/cl.c
C | 1348 lines | 1203 code | 85 blank | 60 comment | 222 complexity | 5518c38f7917712dad7a4cb89c505f4c MD5 | raw file
1/* This file is part of mrim-prpl. 2 * 3 * mrim-prpl is free software: you can redistribute it and/or modify 4 * it under the terms of the GNU General Public License as published by 5 * the Free Software Foundation, either version 2 of the License, or 6 * (at your option) any later version. 7 * 8 * mrim-prpl is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 * 13 * You should have received a copy of the GNU General Public License 14 * along with mrim-prpl. If not, see <http://www.gnu.org/licenses/>. 15 */ 16 17#include "mrim.h" 18#include "package.h" 19#include "statuses.h" 20#include "cl.h" 21#include "util.h" 22#include "message.h" 23 24/* Contact list */ 25 26void mrim_cl_skip(MrimPackage *pack, gchar *mask) { 27 while (*mask) { 28 switch (*mask) { 29 case 's': 30 g_free(mrim_package_read_LPSA(pack)); 31 break; 32 case 'z': 33 case 'u': 34 mrim_package_read_UL(pack); 35 break; 36 } 37 mask++; 38 } 39} 40 41static MrimBuddy *mrim_cl_load_buddy(MrimData *mrim, MrimPackage *pack, gchar *mask) { 42 MrimBuddy *mb = g_new0(MrimBuddy, 1); 43 mb->mrim = mrim; 44 mb->flags = mrim_package_read_UL(pack); 45 mb->group_id = mrim_package_read_UL(pack); 46 mb->email = mrim_package_read_LPSA(pack); 47 mb->alias = mrim_package_read_LPSW(pack); 48 mb->s_flags = mrim_package_read_UL(pack); 49 mb->phones = g_new0(gchar*, 4); 50 { 51 guint32 status_id = mrim_package_read_UL(pack); 52 { 53 gchar *phones = mrim_package_read_LPSA(pack); 54 if (phones) { 55 gchar **phones_splitted = g_strsplit(phones, ",", 3); 56 guint i = 0; 57 while (phones_splitted[i]) { 58 gchar *phone; 59 if ((!phones_splitted[i][0]) || (phones_splitted[i][0] == '+')) { 60 phone = g_strdup(phones_splitted[i]); 61 } else { 62 phone = g_strdup_printf("+%s", phones_splitted[i]); 63 } 64 mb->phones[i] = phone; 65 i++; 66 } 67 g_strfreev(phones_splitted); 68 } 69 } 70 { 71 gchar *status_uri = mrim_package_read_LPSA(pack); 72 gchar *tmp = mrim_package_read_LPSW(pack); 73 gchar *status_title = purple_markup_escape_text(tmp, -1); 74 g_free(tmp); 75 tmp = mrim_package_read_LPSW(pack); 76 gchar *status_desc = purple_markup_escape_text(tmp, -1); 77 g_free(tmp); 78 mb->status = make_mrim_status(status_id, status_uri, status_title, status_desc); 79 } 80 } 81 mb->com_support = mrim_package_read_UL(pack); 82 mb->user_agent = mrim_package_read_LPSA(pack); 83 mrim_package_read_UL(pack); 84 mrim_package_read_UL(pack); 85 mrim_package_read_UL(pack); 86 { 87 gchar *tmp = mrim_package_read_LPSW(pack); 88 mb->microblog = purple_markup_escape_text(tmp, -1); 89 g_free(tmp); 90 } 91 mrim_cl_skip(pack, mask + 16); 92 mb->authorized = !(mb->s_flags & CONTACT_INTFLAG_NOT_AUTHORIZED); 93 return mb; 94} 95 96void mrim_avatar_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data, const gchar *url_text, gsize len, const gchar *error_message) { 97 purple_debug_info("mrim-prpl", "[%s]\n", __func__); 98 PurpleBuddy* buddy = user_data; 99 if(url_text && len) { 100 purple_buddy_icons_set_for_user(purple_buddy_get_account(buddy), purple_buddy_get_name(buddy), g_memdup(url_text, len), len, NULL); 101 } 102} 103 104void mrim_fetch_avatar(PurpleBuddy *buddy) { 105 g_return_if_fail(buddy != NULL); 106 g_return_if_fail(buddy->name != NULL); 107 g_return_if_fail(is_myworld_able(buddy->name) == TRUE); 108 purple_debug_info("mrim-prpl", "[%s] Fetch avatar for buddy '%s'\n", __func__, buddy->name); 109 //if (!is_valid_email(buddy->name)) return; 110 if ((!buddy->icon) && buddy->name) { 111 gchar** split_1 = g_strsplit(buddy->name,"@",2); 112 gchar* email_name=split_1[0]; 113 gchar* domain; 114 gchar** split_2; 115 if (split_1[1]) { 116 split_2 = g_strsplit(split_1[1],".ru\0",2); 117 domain = split_2[0]; 118 if (g_strcmp0(domain, "corp.mail") == 0) { 119 domain = g_strdup("corp"); 120 } 121 } else { 122 g_strfreev(split_1); 123 return; 124 } 125 gchar* url = g_strdup_printf("http://obraz.foto.mail.ru/%s/%s/_mrimavatar", domain, email_name); 126 g_strfreev(split_2); 127 g_strfreev(split_1); 128 purple_util_fetch_url(url, TRUE, NULL, TRUE, mrim_avatar_cb, buddy); 129 g_free(url); 130 } 131} 132 133void mrim_cl_load(MrimPackage *pack, MrimData *mrim) { 134 guint32 group_count = mrim_package_read_UL(pack); 135 gchar *group_mask = mrim_package_read_LPSA(pack); 136 gchar *buddy_mask = mrim_package_read_LPSA(pack); 137 /* GROUPS */ 138 purple_debug_info("mrim-prpl", "[%s] Group count = %i, group mask = '%s', contact mask = '%s'\n", __func__, group_count, group_mask, buddy_mask); 139 { 140 guint32 i; 141 for (i = 0; i < group_count; i++) { 142 guint32 flags = mrim_package_read_UL(pack); 143 gchar *name = mrim_package_read_LPSW(pack); 144 purple_debug_info("mrim-prpl", "[%s] New group: name = '%s', flags = 0x%x\n", __func__, name, flags); 145 new_mrim_group(mrim, i, name, flags); 146 mrim_cl_skip(pack, group_mask + 2); 147 g_free(name); 148 } 149 } 150 g_free(group_mask); 151 { 152 guint32 id = 20; 153 while (pack->cur < pack->data_size) { 154 MrimBuddy *mb = mrim_cl_load_buddy(mrim, pack, buddy_mask); 155 if (!mb) 156 break; 157 158 mb->id = id++; 159 160 if (mb->flags & CONTACT_FLAG_REMOVED) { 161 purple_debug_info("mrim-prpl", "[%s] Buddy '%s' removed\n", __func__, mb->email); 162 free_mrim_buddy(mb); 163 continue; 164 } 165 /* CHATS */ 166 if (mb->flags & CONTACT_FLAG_MULTICHAT) { 167 PurpleGroup *group = get_mrim_group(mrim, mb->group_id)->group; 168 PurpleChat *pc = NULL; 169 PurpleChat *old_pc = purple_blist_find_chat(mrim->account, mb->email); 170 if (old_pc) { 171 pc = old_pc; 172 purple_debug_info("mrim-prpl", "[%s] update chat: %s \n", __func__, mb->email); 173 } else { 174 purple_debug_info("mrim-prpl", "[%s] New chat: %s \n", __func__, mb->email); 175 GHashTable *defaults = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free); 176 g_hash_table_insert(defaults, "room", g_strdup(mb->email)); 177 pc = purple_chat_new(mrim->account, mb->email, defaults); 178 179 purple_blist_add_chat(pc, group, NULL); 180 } 181 purple_blist_alias_chat(pc, mb->alias); 182 } else { 183 /* BUDDIES */ 184 purple_debug_info("mrim-prpl", "[%s] New buddy: email = '%s', nick = '%s', flags = 0x%x, status = '%s', UA = '%s', microblog = '%s'\n", 185 __func__, mb->email, mb->alias, mb->flags, mb->status->purple_id, mb->user_agent, mb->microblog); 186 PurpleGroup *group = get_mrim_group(mrim, mb->group_id)->group; 187 PurpleBuddy *buddy = purple_find_buddy(mrim->account, mb->email); 188 if (buddy) { 189 purple_blist_alias_buddy(buddy, mb->alias); 190 } else { 191 buddy = purple_buddy_new(mrim->account, mb->email, mb->alias); 192 purple_blist_add_buddy(buddy, NULL, group, NULL); 193 } 194 purple_buddy_set_protocol_data(buddy, mb); 195 mb->buddy = buddy; 196 update_buddy_status(buddy); 197 if (purple_account_get_bool(mrim->gc->account, "fetch_avatars", TRUE)) { 198 if (!(mb->flags & CONTACT_FLAG_PHONE)) { 199 mrim_fetch_avatar(buddy); 200 } 201 } 202 } 203 } /* while */ 204 } 205 g_free(buddy_mask); 206 /* Purge all obsolete buddies. */ 207 { 208 GSList *buddies = purple_find_buddies(mrim->gc->account, NULL); 209 GSList *first = buddies; 210 while (buddies) { 211 PurpleBuddy *buddy = (PurpleBuddy*)buddies->data; 212 if (buddy) { 213 if (!(buddy->proto_data)) { 214 purple_blist_remove_buddy(buddy); 215 } 216 } 217 buddies = g_slist_next(buddies); 218 } 219 g_slist_free(first); 220 } 221 /* TODO: Purge all obsolete chats. */ 222 purple_blist_show(); 223} 224 225/* Groups */ 226 227void mrim_modify_group_ack(MrimData *mrim, gpointer user_data, MrimPackage *pack) { 228 guint32 status = mrim_package_read_UL(pack); 229 purple_debug_info("mrim-prpl", "[%s] Status is %i\n", __func__, status); 230 g_return_if_fail(status == CONTACT_OPER_SUCCESS); 231} 232 233void mrim_rename_group(PurpleConnection *gc, const char *old_name, PurpleGroup *group, GList *moved_buddies) { 234 MrimData *mrim = gc->proto_data; 235 g_return_if_fail(mrim != NULL); 236 MrimGroup *gr = get_mrim_group_by_name(mrim, group->name); 237 g_free(gr->name); 238 gr->name = g_strdup(group->name); 239 MrimPackage *pack = mrim_package_new(mrim->seq++, MRIM_CS_MODIFY_CONTACT); 240 mrim_package_add_UL(pack, gr->id); 241 mrim_package_add_UL(pack, gr->flags); 242 mrim_package_add_UL(pack, 0); 243 mrim_package_add_LPSA(pack, NULL); 244 mrim_package_add_LPSW(pack, gr->name); 245 mrim_package_add_LPSA(pack, NULL); 246 mrim_add_ack_cb(mrim, pack->header->seq, mrim_modify_group_ack, NULL); 247 mrim_package_send(pack, mrim); 248} 249 250void mrim_remove_group(PurpleConnection *gc, PurpleGroup *group) { 251 MrimData *mrim = gc->proto_data; 252 g_return_if_fail(mrim != NULL); 253 MrimGroup *gr = get_mrim_group_by_name(mrim, group->name); 254 g_return_if_fail(gr != NULL); 255 MrimPackage *pack = mrim_package_new(mrim->seq++, MRIM_CS_MODIFY_CONTACT); 256 mrim_package_add_UL(pack, gr->id); 257 mrim_package_add_UL(pack, gr->flags & CONTACT_FLAG_REMOVED); 258 mrim_package_add_UL(pack, 0); 259 mrim_package_add_LPSA(pack, NULL); 260 mrim_package_add_LPSW(pack, gr->name); 261 mrim_package_add_LPSA(pack, NULL); 262 mrim_add_ack_cb(mrim, pack->header->seq, mrim_modify_group_ack, NULL); 263 mrim_package_send(pack, mrim); 264} 265 266MrimGroup *new_mrim_group(MrimData *mrim, guint32 id, gchar *name, guint32 flags) { 267 MrimGroup *group = g_new0(MrimGroup, 1); 268 group->id = id; 269 group->name = g_strdup(name); 270 group->flags = flags; 271 group->group = purple_find_group(name); 272 if (!group->group) { 273 group->group = purple_group_new(name); 274 purple_blist_add_group(group->group, NULL); 275 } 276 g_hash_table_insert(mrim->groups, GUINT_TO_POINTER(id), group); 277 return group; 278} 279 280void free_mrim_group(MrimGroup *group) { 281 if (group) { 282 if (group->name) { 283 g_free(group->name); 284 } 285 g_free(group); 286 } 287} 288 289MrimGroup *get_mrim_group(MrimData *mrim, guint32 id) { 290 MrimGroup *group = g_hash_table_lookup(mrim->groups, GUINT_TO_POINTER(id)); 291 g_return_val_if_fail(group != NULL, g_hash_table_lookup(mrim->groups, GUINT_TO_POINTER(0))); 292 return group; 293} 294 295MrimGroup *get_mrim_group_by_name(MrimData *mrim, gchar *name) { 296 if (!name) { 297 purple_debug_info("mrim-prpl", "[%s] name = NULL!\n", __func__); 298 return NULL; 299 } else { 300 purple_debug_info("mrim-prpl", "[%s] name = '%s'\n", __func__, name); 301 }; 302 GList *g = g_list_first(g_hash_table_get_values(mrim->groups)); 303 MrimGroup *group; 304 while (g) { 305 group = g->data; 306 if (!group) { 307 purple_debug_info("mrim-prpl", "[%s] g->data FAIL!\n", __func__); 308 } else if (!group->name) { 309 purple_debug_info("mrim-prpl", "[%s] NONAME group (id, flags) = (%u,%u)\n", __func__, group->id, group->flags); 310 } else { 311 purple_debug_info("mrim-prpl", "[%s] group info: (id, flags) = (%u,%u)\n", __func__, group->id, group->flags); 312 purple_debug_info("mrim-prpl", "[%s] group->name = '%s'\n", __func__, group->name); 313 if (g_strcmp0(group->name, name) == 0) { 314 g_list_free(g); 315 return group; 316 }; 317 }; 318 g = g_list_next(g); 319 }; 320 g_list_free(g); 321 return NULL; 322} 323 324void mrim_add_group_ack(MrimData *mrim, gpointer user_data, MrimPackage *pack) { 325 guint32 status = mrim_package_read_UL(pack); 326 purple_debug_info("mrim-prpl", "[%s] Status = %i\n", __func__, status); 327 g_return_if_fail(status == CONTACT_OPER_SUCCESS); 328 guint32 id = mrim_package_read_UL(pack); 329 AddContactInfo *info = user_data; 330 new_mrim_group(mrim, id, info->group->name, 0); 331 if (info->buddy) { 332 if (info->move) { 333 mrim_add_buddy(mrim->gc, info->buddy, info->group); 334 } else { 335 mrim_move_buddy(mrim->gc, info->buddy->name, NULL, info->group->name); 336 } 337 } 338} 339 340void cl_add_group(MrimData *mrim, gchar *name, AddContactInfo *info) { 341 purple_debug_info("mrim-prpl", "[%s] Add group with name '%s'\n", __func__, name); 342 guint32 groups_count = g_hash_table_size(mrim->groups); 343 MrimPackage *pack = mrim_package_new(mrim->seq++, MRIM_CS_ADD_CONTACT); 344 mrim_package_add_UL(pack, CONTACT_FLAG_GROUP | (groups_count << 24)); 345 mrim_package_add_UL(pack, 0); 346 mrim_package_add_LPSA(pack, NULL); 347 mrim_package_add_LPSW(pack, name); 348 mrim_package_add_LPSA(pack, NULL); 349 mrim_package_add_UL(pack, 0); 350 mrim_package_add_UL(pack, 0); 351 if (!info) { 352 info = g_new0(AddContactInfo, 1); 353 info->group = purple_find_group(name); 354 } 355 mrim_add_ack_cb(mrim, pack->header->seq, mrim_add_group_ack, info); 356 mrim_package_send(pack, mrim); 357} 358 359/* Buddies */ 360 361void mrim_add_contact_ack(MrimData *mrim, gpointer user_data, MrimPackage *pack) { 362 guint32 status = mrim_package_read_UL(pack); 363 purple_debug_info("mrim-prpl", "[%s] Status is %i\n", __func__, status); 364 g_return_if_fail(status == CONTACT_OPER_SUCCESS); 365 guint32 id = mrim_package_read_UL(pack); 366 BuddyAddInfo *info = user_data; 367 PurpleBuddy *buddy = info->buddy; 368 MrimBuddy *mb = buddy->proto_data; 369 mb->id = id; 370} 371 372void mrim_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group) { 373 purple_debug_info("mrim-prpl", "[%s]\n", __func__); 374 g_return_if_fail(buddy != NULL); 375 g_return_if_fail(group != NULL); 376 g_return_if_fail(gc != NULL); 377 g_return_if_fail(gc->state == PURPLE_CONNECTED); 378 purple_debug_info("mrim-prpl", "[%s] Add buddy '%s' to group '%s'\n", __func__, buddy->name, group->name); 379 { 380 const gchar *normalized_name = mrim_normalize(gc->account, (const gchar*)buddy->name); 381 g_free(buddy->name); 382 buddy->name = (gchar*)normalized_name; 383 } 384 PurpleBuddy *old_buddy = purple_find_buddy(gc->account, buddy->name); 385 MrimData *mrim = gc->proto_data; 386 MrimBuddy *mb; 387 if (old_buddy != NULL && old_buddy != buddy) { 388 purple_blist_remove_buddy(buddy); 389 buddy = old_buddy; 390 mb = (MrimBuddy*)(buddy->proto_data); 391 if (mb) { 392 mb->buddy = buddy; 393 purple_blist_alias_buddy(buddy, mb->alias); 394 update_buddy_status(buddy); 395 } 396 } else if (is_valid_email(buddy->name) || is_valid_phone(buddy->name)) { 397 purple_debug_info("mrim-prpl", "[%s] Buddy has a valid email or phone '%s'\n", __func__, buddy->name); 398 MrimGroup *gr = get_mrim_group_by_name(mrim, group->name); 399 gint group_id = gr ? gr->id : -1; 400 if (group_id == -1) { 401 purple_debug_info("mrim-prpl", "[%s] Group '%s' not exists - creating\n", __func__, group->name); 402 AddContactInfo *info = g_new(AddContactInfo, 1); 403 info->buddy = buddy; 404 info->group = group; 405 info->move = FALSE; 406 cl_add_group(mrim, group->name, info); 407 } else { 408 mb = g_new0(MrimBuddy, 1); 409 mb->email = g_strdup(buddy->name); 410 mb->alias = g_strdup(buddy->alias ? buddy->alias : buddy->name); 411 buddy->proto_data = mb; 412 mb->group_id = group_id; 413 mb->phones = g_new0(gchar*, 4); 414 if (is_valid_phone(buddy->name)) { 415 mb->flags |= CONTACT_FLAG_PHONE; 416 mb->authorized = TRUE; 417 mb->status = make_mrim_status(STATUS_ONLINE, NULL, NULL, NULL); 418 } else { 419 mb->authorized = FALSE; 420 mb->status = make_mrim_status(STATUS_OFFLINE, NULL, NULL, NULL); 421 } 422 purple_debug_info("mrim-prpl", "[%s] Adding buddy with email = '%s' alias = '%s', flags = 0x%x\n", __func__, 423 mb->email, mb->alias, mb->flags); 424 MrimPackage *pack = mrim_package_new(mrim->seq++, MRIM_CS_ADD_CONTACT); 425 mrim_package_add_UL(pack, mb->flags); 426 mrim_package_add_UL(pack, mb->group_id); 427 mrim_package_add_LPSA(pack, mb->email); 428 mrim_package_add_LPSW(pack, mb->alias); 429 { 430 gchar *str = g_strjoinv(",", mb->phones); 431 mrim_package_add_LPSA(pack, str); 432 g_free(str); 433 } 434 mrim_package_add_LPSA(pack, " "); 435 mrim_package_add_UL(pack, 0); 436 { 437 BuddyAddInfo *info = g_new(BuddyAddInfo, 1); 438 info->buddy = buddy; 439 mrim_add_ack_cb(mrim, pack->header->seq, mrim_add_contact_ack, info); 440 } 441 mrim_package_send(pack, mrim); 442 if (!(mb->flags & CONTACT_FLAG_PHONE)) { 443 mrim_fetch_avatar(buddy); 444 } 445 } 446 } else { 447 purple_debug_info("mrim-prpl", "[%s] '%s' is not valid email or phone number!\n", __func__, buddy->name); 448 gchar *msg = g_strdup_printf(_("Unable to add the buddy \"%s\" because the username is invalid. Usernames must be a valid email address(in mail.ru bk.ru list.ru corp.mail.ru inbox.ru domains), valid ICQ UIN in NNNN@uin.icq format or valid phone number (start with + and contain only numbers, spaces and \'-\'."), buddy->name); 449 purple_notify_error(gc, NULL, _("Unable to Add"), msg); 450 g_free(msg); 451 purple_blist_remove_buddy(buddy); 452 } 453 purple_blist_show(); 454} 455 456void mrim_modify_buddy_ack(MrimData *mrim, gpointer user_data, MrimPackage *pack) { 457 guint32 status = mrim_package_read_UL(pack); 458 purple_debug_info("mrim-prpl", "[%s] Status is %i\n", __func__, status); 459 g_return_if_fail(status == CONTACT_OPER_SUCCESS); 460} 461 462void mrim_modify_buddy(MrimData *mrim, PurpleBuddy *buddy) { 463 MrimBuddy *mb = buddy->proto_data; 464 MrimPackage *pack = mrim_package_new(mrim->seq++, MRIM_CS_MODIFY_CONTACT); 465 mrim_package_add_UL(pack, mb->id); 466 mrim_package_add_UL(pack, mb->flags); 467 mrim_package_add_UL(pack, mb->group_id); 468 mrim_package_add_LPSA(pack, mb->flags & CONTACT_FLAG_PHONE ? "phone" : mb->email); 469 mrim_package_add_LPSW(pack, mb->alias); 470 { 471 gchar *str = g_strjoinv(",", mb->phones); 472 mrim_package_add_LPSA(pack, str); 473 g_free(str); 474 } 475 mrim_add_ack_cb(mrim, pack->header->seq, mrim_modify_buddy_ack, NULL); 476 mrim_package_send(pack, mrim); 477} 478 479void mrim_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group) { 480 MrimData *mrim = gc->proto_data; 481 MrimBuddy *mb = buddy->proto_data; 482 purple_debug_info("mrim-prpl", "[%s] Removing buddy '%s' from buddy list\n", __func__, buddy->name); 483 mb->flags |= CONTACT_FLAG_REMOVED; 484 mrim_modify_buddy(mrim, buddy); 485} 486 487void free_mrim_buddy(MrimBuddy *mb) { 488 if (mb) { 489 g_free(mb->email); 490 g_free(mb->alias); 491 g_strfreev(mb->phones); 492 g_free(mb->user_agent); 493 g_free(mb->microblog); 494 free_mrim_status(mb->status); 495 g_free(mb); 496 } 497} 498 499void mrim_free_buddy(PurpleBuddy *buddy) { 500 if (buddy->proto_data) { 501 MrimBuddy *mb = buddy->proto_data; 502 free_mrim_buddy(mb); 503 } 504} 505 506void mrim_alias_buddy(PurpleConnection *gc, const char *who, const char *alias) { 507 PurpleBuddy *buddy = purple_find_buddy(gc->account, (gchar*)who); 508 g_return_if_fail(buddy != NULL); 509 MrimData *mrim = gc->proto_data; 510 MrimBuddy *mb = buddy->proto_data; 511 g_return_if_fail(mb != NULL); 512 g_free(mb->alias); 513 mb->alias = g_strdup(alias); 514 mrim_modify_buddy(mrim, buddy); 515} 516 517void mrim_move_buddy(PurpleConnection *gc, const char *who, const char *old_group, const char *new_group) { 518 purple_debug_info("mrim-prpl", "[%s] Moving '%s' to group '%s'\n", __func__, who, new_group); 519 PurpleBuddy *buddy = purple_find_buddy(gc->account, (gchar*)who); 520 g_return_if_fail(buddy != NULL); 521 MrimData *mrim = gc->proto_data; 522 MrimBuddy *mb = buddy->proto_data; 523 g_return_if_fail(mb != NULL); 524 MrimGroup *group_found = get_mrim_group_by_name(mrim, (gchar*)new_group); 525 gint group_id = group_found ? group_found->id : -1; 526 if (!group_found) { 527 purple_debug_info("mrim-prpl", "[%s] Group '%s' not exists - creating\n", __func__, new_group); 528 AddContactInfo *info = g_new(AddContactInfo, 1); 529 info->buddy = buddy; 530 info->group = purple_find_group((gchar*)new_group); 531 info->move = TRUE; 532 cl_add_group(mrim, (gchar*)new_group, info); 533 } else { 534 mb->group_id = group_id; 535 mrim_modify_buddy(mrim, buddy); 536 } 537 g_free(group_found); 538} 539 540const char *mrim_normalize(const PurpleAccount *account, const char *who) { 541 return g_ascii_strdown((gchar*)who, -1); 542} 543 544/* User actions */ 545 546void blist_authorize_menu_item(PurpleBlistNode *node, gpointer userdata) { /* Request auth message */ 547 PurpleBuddy *buddy = (PurpleBuddy*)node; 548 g_return_if_fail(buddy != NULL); 549 MrimBuddy *mb = buddy->proto_data; 550 g_return_if_fail(mb != NULL); 551 MrimData *mrim = (MrimData*)userdata; 552 g_return_if_fail(mrim != NULL); 553 purple_debug_info("mrim", "[%s] Asking authorization of '%s'\n", __func__, mb->email); 554 mrim_send_authorize(mrim, mb->email, NULL); 555} 556 557#ifdef ENABLE_GTK 558 559void update_sms_char_counter(GObject *object, gpointer user_data) { 560 SmsDialogParams *params = user_data; 561 gchar *original_text, *new_text; 562 GtkTextBuffer *buffer = gtk_text_view_get_buffer(params->message_text); 563 { 564 GtkTextIter start, end; 565 gtk_text_buffer_get_start_iter(buffer, &start); 566 gtk_text_buffer_get_end_iter(buffer, &end); 567 original_text = gtk_text_buffer_get_text(buffer, &start, &end, FALSE); 568 } 569 if (gtk_toggle_button_get_active((GtkToggleButton*)params->translit)) { 570 new_text = transliterate_text(original_text); 571 } else { 572 new_text = g_strdup(original_text); 573 } 574 g_free(original_text); 575 g_free(params->sms_text); 576 params->sms_text = new_text; 577 gint count = g_utf8_strlen(new_text, -1); 578 gchar *buf = g_strdup_printf(_("Symbols: %d"), count); 579 gtk_label_set_text(params->char_counter, buf); 580 g_free(buf); 581} 582 583void sms_dialog_response(GtkDialog *dialog, gint response_id, gpointer user_data) { 584 SmsDialogParams *params = user_data; 585 switch (response_id) { 586 case GTK_RESPONSE_ACCEPT: 587 { 588 MrimBuddy *mb = params->mb; 589 MrimData *mrim = params->mrim; 590 update_sms_char_counter(NULL, params); //?? ??????, ???? ????? ????????? ?????????????? ???????????? ??? ?? ??????? ????? 591 gchar *text = params->sms_text; 592 gint phone_index = gtk_combo_box_get_active(params->phone); 593 if (phone_index > -1) { 594 gchar *phone = mb->phones[phone_index]; 595 mrim_send_sms(mrim, phone, text); 596 } 597 break; 598 } 599 case GTK_RESPONSE_REJECT: 600 break; 601 } 602 gtk_widget_destroy((GtkWidget*)dialog); 603} 604 605void sms_dialog_destroy(GtkDialog *dialog, gpointer user_data) { 606 SmsDialogParams *params = user_data; 607 g_free(params->sms_text); 608 g_free(params); 609} 610 611void sms_dialog_edit_phones(GtkButton *button, gpointer user_data) { 612 SmsDialogParams *params = user_data; 613 blist_edit_phones_menu_item((PurpleBlistNode*)params->buddy, params->mrim); 614 gtk_combo_box_remove_text(params->phone, 2); 615 gtk_combo_box_remove_text(params->phone, 1); 616 gtk_combo_box_remove_text(params->phone, 0); 617 gtk_combo_box_append_text(params->phone, params->mb->phones[0]); 618 gtk_combo_box_append_text(params->phone, params->mb->phones[1]); 619 gtk_combo_box_append_text(params->phone, params->mb->phones[2]); 620 gtk_combo_box_set_active(params->phone, 0); 621} 622 623void blist_gtk_sms_menu_item(PurpleBlistNode *node, gpointer userdata) { 624 PurpleBuddy *buddy = (PurpleBuddy *) node; 625 MrimData *mrim = userdata; 626 g_return_if_fail(buddy != NULL); 627 g_return_if_fail(mrim != NULL); 628 MrimBuddy *mb = buddy->proto_data; 629 g_return_if_fail(mb != NULL); 630 631 /* ?????? */ 632 GtkWidget *dialog = gtk_dialog_new_with_buttons(_("Send SMS"), NULL, GTK_DIALOG_DESTROY_WITH_PARENT, 633 GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, NULL); 634 gtk_window_set_default_size((GtkWindow*)dialog, 320, 240); 635 GtkWidget *content_area = gtk_dialog_get_content_area((GtkDialog*)dialog); 636 GtkWidget *hbox; 637 //gtk_container_set_border_width(content_area, 8); // ?? ??????? ?????? ?? ????????. ???? ?????-?????? ?????????? - ?????? ????????? ??????? 638 gtk_container_set_border_width((GtkContainer*)dialog, 6); 639 gtk_box_set_spacing((GtkBox*)content_area, 6); 640 /* ????????? */ 641 GtkWidget *buddy_name = gtk_label_new(mb->alias); 642 gtk_box_pack_start((GtkBox*)content_area, buddy_name, FALSE, TRUE, 0); 643 /* ??????? */ 644 hbox = gtk_hbox_new(FALSE, 6); 645 gtk_box_pack_start((GtkBox*)content_area, hbox, FALSE, TRUE, 0); 646 GtkWidget *phone_combo_box = gtk_combo_box_new_text(); 647 gtk_combo_box_append_text((GtkComboBox*)phone_combo_box, mb->phones[0]); 648 gtk_combo_box_append_text((GtkComboBox*)phone_combo_box, mb->phones[1]); 649 gtk_combo_box_append_text((GtkComboBox*)phone_combo_box, mb->phones[2]); 650 gtk_combo_box_set_active((GtkComboBox*)phone_combo_box, 0); 651 gtk_box_pack_start((GtkBox*)hbox, gtk_label_new(_("Phone:")), FALSE, TRUE, 0); 652 gtk_box_pack_start((GtkBox*)hbox, phone_combo_box, TRUE, TRUE, 0); 653 GtkWidget *edit_phones_button = gtk_button_new_from_stock(GTK_STOCK_EDIT); 654 gtk_box_pack_end((GtkBox*)hbox, edit_phones_button, FALSE, TRUE, 0); 655 /* ????? ????????? */ 656 GtkWidget *scrolled_wnd = gtk_scrolled_window_new(NULL, NULL); 657 gtk_scrolled_window_set_policy((GtkScrolledWindow*)scrolled_wnd, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); 658 GtkWidget *message_text = gtk_text_view_new(); 659 gtk_container_add((GtkContainer*)scrolled_wnd, message_text); 660 gtk_box_pack_start((GtkBox*)content_area, scrolled_wnd, TRUE, TRUE, 0); 661 gtk_text_view_set_wrap_mode((GtkTextView*)message_text, GTK_WRAP_WORD); 662 /* ?????? ?????????????? ? ??????? ???????? */ 663 hbox = gtk_hbutton_box_new(); 664 gtk_button_box_set_spacing((GtkBox*)hbox, 6); 665 gtk_button_box_set_layout((GtkButtonBox*)hbox, GTK_BUTTONBOX_EDGE); 666 GtkWidget *translit = gtk_check_button_new_with_label(_("Translit")); 667 gtk_container_add((GtkContainer*)hbox, translit); 668 GtkWidget *char_counter = gtk_label_new(""); 669 gtk_container_add((GtkContainer*)hbox, char_counter); 670 gtk_box_pack_end((GtkBox*)content_area, hbox, FALSE, TRUE, 0); 671 /* ???????? ?????? ?????? ???????? */ 672 SmsDialogParams *params = g_new0(SmsDialogParams, 1); 673 params->buddy = buddy; 674 params->mrim = mrim; 675 params->mb = mb; 676 params->message_text = (GtkTextView*)message_text; 677 params->translit = (GtkCheckButton*)translit; 678 params->char_counter = (GtkLabel*)char_counter; 679 params->phone = (GtkComboBox*)phone_combo_box; 680 params->sms_text = NULL; 681 /* ????????? ??????????? ???????? */ 682 g_signal_connect(G_OBJECT(dialog), "destroy", G_CALLBACK(sms_dialog_destroy), params); 683 { 684 GtkTextBuffer *buffer = gtk_text_view_get_buffer((GtkTextView*)message_text); 685 g_signal_connect(G_OBJECT(buffer), "changed", G_CALLBACK(update_sms_char_counter), params); 686 update_sms_char_counter(G_OBJECT(buffer), params); 687 } 688 g_signal_connect(G_OBJECT(translit), "toggled", G_CALLBACK(update_sms_char_counter), params); 689 g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(sms_dialog_response), params); 690 g_signal_connect(G_OBJECT(edit_phones_button), "clicked", G_CALLBACK(sms_dialog_edit_phones), params); 691 /* ?????????? ?????? */ 692 gtk_widget_show_all(dialog); 693 /* ???? ??????? ?????? ?? ???????????? ?????????????? - ???????? ??? ??????? */ 694 if (g_strcmp0("translit-table", _("translit-table")) == 0) { 695 gtk_widget_hide(translit); 696 } 697 /* ?????? ???????? ????? ???? ????? ????????? */ 698 gtk_widget_grab_focus(message_text); 699} 700 701#endif 702 703void blist_send_sms(PurpleConnection *gc, PurpleRequestFields *fields) { 704 g_return_if_fail(gc); 705 PurpleRequestField *RadioBoxField = purple_request_fields_get_field(fields, "combobox"); 706 int index = RadioBoxField->u.choice.value; 707 GList *list = RadioBoxField->u.choice.labels; 708 while (index-- && list) 709 list = list->next; 710 gchar *message = (gchar*)purple_request_fields_get_string(fields, "message_box"); 711 mrim_send_sms((MrimData*)gc->proto_data, list->data, message); 712} 713 714void blist_sms_menu_item(PurpleBlistNode *node, gpointer userdata) { 715 PurpleBuddy *buddy = (PurpleBuddy *) node; 716 MrimData *mrim = userdata; 717 g_return_if_fail(buddy != NULL); 718 g_return_if_fail(mrim != NULL); 719 MrimBuddy *mb = buddy->proto_data; 720 g_return_if_fail(mb != NULL); 721 PurpleRequestFields *fields; 722 PurpleRequestFieldGroup *group; 723 PurpleRequestField *field; 724 fields = purple_request_fields_new(); 725 group = purple_request_field_group_new(NULL); 726 purple_request_fields_add_group(fields, group); 727 field = purple_request_field_choice_new("combobox", _("Choose phone number"), 0); 728 purple_request_field_choice_add(field, mb->phones[0]); 729 purple_request_field_choice_add(field, mb->phones[1]); 730 purple_request_field_choice_add(field, mb->phones[2]); 731 purple_request_field_group_add_field(group, field); 732 field = purple_request_field_string_new("message_box",_("SMS message text"),"",TRUE); 733 purple_request_field_group_add_field(group, field); 734 purple_request_fields(mrim->gc, _("Send SMS"), NULL, _("SMS message should contain not\nmore than 135 symbols in latin\nor 35 in cyrillic."), 735 fields, _("_Send"), G_CALLBACK(blist_send_sms), _("_Cancel"), NULL, mrim->account, buddy->name, NULL, mrim->gc); 736} 737 738void blist_edit_phones(PurpleBuddy *buddy, PurpleRequestFields *fields) { 739 g_return_if_fail(buddy); 740 MrimBuddy *mb = buddy->proto_data; 741 g_return_if_fail(mb); 742 PurpleAccount *account = purple_buddy_get_account(buddy); 743 PurpleConnection *gc = purple_account_get_connection(account); 744 MrimData *mrim = purple_connection_get_protocol_data(gc); 745 PurpleRequestFieldGroup *group = fields->groups->data; 746 mb->phones[0] = g_strdup(purple_request_fields_get_string(fields, "phone1")); 747 mb->phones[1] = g_strdup(purple_request_fields_get_string(fields, "phone2")); 748 mb->phones[2] = g_strdup(purple_request_fields_get_string(fields, "phone3")); 749 guint i = 0; 750 while (mb->phones[i]) { 751 if (mb->phones[i][0] && (mb->phones[i][0] != '+')) { 752 gchar *phone = g_strdup_printf("+%s", mb->phones[i]); 753 g_free(mb->phones[i]); 754 mb->phones[i] = phone; 755 } 756 i++; 757 } 758 mrim_modify_buddy(mrim, buddy); 759} 760 761void blist_edit_phones_menu_item(PurpleBlistNode *node, gpointer userdata) { 762 PurpleBuddy *buddy = (PurpleBuddy*)node; 763 MrimData *mrim = userdata; 764 g_return_if_fail(buddy != NULL); 765 g_return_if_fail(mrim != NULL); 766 MrimBuddy *mb = buddy->proto_data; 767 g_return_if_fail(mb != NULL); 768 if (!mb->phones) { /* ??? ?? ?????? ???? */ 769 mb->phones = g_new0(char *, 4); 770 } 771 PurpleRequestFields *fields; 772 PurpleRequestFieldGroup *group; 773 PurpleRequestField *field; 774 fields = purple_request_fields_new(); 775 group = purple_request_field_group_new(mb->email); 776 purple_request_fields_add_group(fields, group); 777 field = purple_request_field_string_new("phone1", _("_Main number"), mb->phones[0], FALSE); 778 purple_request_field_group_add_field(group, field); 779 field = purple_request_field_string_new("phone2", _("S_econd number"), mb->phones[1], FALSE); 780 purple_request_field_group_add_field(group, field); 781 field = purple_request_field_string_new("phone3", _("_Third number"), mb->phones[2], FALSE); 782 purple_request_field_group_add_field(group, field); 783 purple_request_fields(mrim->gc, _("Phone numbers"), _("Phone numbers"), _("Specify numbers as shown: +71234567890"), fields, 784 _("_OK"), G_CALLBACK(blist_edit_phones), 785 _("_Cancel"), NULL, 786 mrim->account, buddy->name, NULL, buddy); 787} 788 789void mrim_url_menu_action(PurpleBlistNode *node, gpointer userdata) { 790 PurpleBuddy *buddy = (PurpleBuddy*)node; 791 PurpleAccount *account = purple_buddy_get_account(buddy); 792 MrimData *mrim = account->gc->proto_data; 793 g_return_if_fail(mrim != NULL); 794 mrim_open_myworld_url(mrim, buddy->name, userdata); 795} 796 797void blist_toggle_visible(PurpleBlistNode *node, gpointer userdata) { 798 PurpleBuddy *buddy = (PurpleBuddy*)node; 799 MrimData *mrim = userdata; 800 g_return_if_fail(buddy != NULL); 801 g_return_if_fail(mrim != NULL); 802 MrimBuddy *mb = buddy->proto_data; 803 g_return_if_fail(mb != NULL); 804 mb->flags ^= CONTACT_FLAG_VISIBLE; 805 mrim_modify_buddy(mrim, buddy); 806} 807 808void blist_toggle_invisible(PurpleBlistNode *node, gpointer userdata) { 809 PurpleBuddy *buddy = (PurpleBuddy*)node; 810 MrimData *mrim = userdata; 811 g_return_if_fail(buddy != NULL); 812 g_return_if_fail(mrim != NULL); 813 MrimBuddy *mb = buddy->proto_data; 814 g_return_if_fail(mb != NULL); 815 mb->flags ^= CONTACT_FLAG_INVISIBLE; 816 mrim_modify_buddy(mrim, buddy); 817} 818 819GList *mrim_user_actions(PurpleBlistNode *node) { 820 purple_debug_info("mrim-prpl", "[%s]\n", __func__); 821 if (!PURPLE_BLIST_NODE_IS_BUDDY(node)) return NULL; 822 PurpleBuddy *buddy = (PurpleBuddy*)node; 823 MrimBuddy *mb = buddy->proto_data; 824 MrimData *mrim = purple_buddy_get_account(buddy)->gc->proto_data; 825 if (mb) { 826 PurpleMenuAction *action; 827 GList *list = NULL;//g_list_append(NULL, NULL); 828 if (!mb->authorized) { 829 action = purple_menu_action_new(_("Request authorization"), PURPLE_CALLBACK(blist_authorize_menu_item), mrim, NULL); 830 list = g_list_append(list, action); 831 } 832 if (mb->phones && mb->phones[0]) { 833#ifdef ENABLE_GTK 834 if (mrim->use_gtk) { 835 action = purple_menu_action_new(_("Send an SMS..."), PURPLE_CALLBACK(blist_gtk_sms_menu_item), mrim, NULL); 836 } else { 837#endif 838 action = purple_menu_action_new(_("Send an SMS..."), PURPLE_CALLBACK(blist_sms_menu_item), mrim, NULL); 839#ifdef ENABLE_GTK 840 } 841#endif 842 list = g_list_append(list, action); 843 } 844 action = purple_menu_action_new(_("Edit phone numbers..."), PURPLE_CALLBACK(blist_edit_phones_menu_item), mrim, NULL); 845 list = g_list_append(list, action); 846 if (is_valid_email(mb->email)) { 847 list = g_list_append(list, NULL); 848 action = purple_menu_action_new(_("MyWorld@Mail.ru"), PURPLE_CALLBACK(mrim_url_menu_action), 849 "http://r.mail.ru/cln3587/my.mail.ru/%s/%s", NULL); 850 list = g_list_append(list, action); 851 action = purple_menu_action_new(_("Photo@Mail.ru"), PURPLE_CALLBACK(mrim_url_menu_action), 852 "http://r.mail.ru/cln3565/foto.mail.ru/%s/%s", NULL); 853 list = g_list_append(list, action); 854 action = purple_menu_action_new(_("Video@Mail.ru"), PURPLE_CALLBACK(mrim_url_menu_action), 855 "http://r.mail.ru/cln3567/video.mail.ru/%s/%s", NULL); 856 list = g_list_append(list, action); 857 action = purple_menu_action_new(_("Blogs@Mail.ru"), PURPLE_CALLBACK(mrim_url_menu_action), 858 "http://r.mail.ru/cln3566/blogs.mail.ru/%s/%s", NULL); 859 list = g_list_append(list, action); 860 list = g_list_append(list, NULL); 861 } 862 { 863 GList *submenu = NULL; 864 action = purple_menu_action_new((mb->flags & CONTACT_FLAG_VISIBLE) ? _("Remove from 'Visible to' list") : 865 _("Add to 'Visible to' list"), PURPLE_CALLBACK(blist_toggle_visible), mrim, NULL); 866 submenu = g_list_append(submenu, action); 867 action = purple_menu_action_new((mb->flags & CONTACT_FLAG_INVISIBLE) ? _("Remove from 'Invisible to' list") : 868 _("Add to 'Invisible to' list"), PURPLE_CALLBACK(blist_toggle_invisible), mrim, NULL); 869 submenu = g_list_append(submenu, action); 870 action = purple_menu_action_new(_("Visibility settings"), NULL, mrim, submenu); 871 list = g_list_append(list, action); 872 } 873 return list; 874 } else { //??? ???? ?????? ?? ?? ?????? 875 return NULL; 876 } 877} 878 879/* User info */ 880 881MrimSearchResult *mrim_parse_search_result(MrimPackage *pack) { 882 guint32 status = mrim_package_read_UL(pack); 883 purple_debug_info("mrim-prpl", "[%s] Status is %i\n", __func__, status); 884 if (status != MRIM_ANKETA_INFO_STATUS_OK) { 885 switch (status) { 886 case MRIM_ANKETA_INFO_STATUS_NOUSER: 887 purple_notify_warning(mrim_plugin, _("Encountered an error while working on user details!"), 888 _("Encountered an error while working on user details!"), _("User not found.")); 889 break; 890 case MRIM_ANKETA_INFO_STATUS_DBERR: 891 purple_notify_warning(mrim_plugin, _("Encountered an error while working on user details!"), 892 _("Encountered an error while working on user details!"), _("DBERR error. Please try later.")); 893 break; 894 case MRIM_ANKETA_INFO_STATUS_RATELIMERR: 895 purple_notify_warning(mrim_plugin, _("Encountered an error while working on user details!"), 896 _("Encountered an error while working on user details!"), _("MRIM_ANKETA_INFO_STATUS_RATELIMERR")); 897 break; 898 default: 899 purple_notify_warning(mrim_plugin, _("Encountered an error while working on user details!"), 900 _("Encountered an error while working on user details!"), _("unknown error")); 901 break; 902 } 903 return NULL; 904 } 905 MrimSearchResult *result = g_new0(MrimSearchResult, 1); 906 result->column_count = mrim_package_read_UL(pack); 907 result->row_count = mrim_package_read_UL(pack); 908 guint32 date = mrim_package_read_UL(pack); 909 purple_debug_info("mrim-prpl", "[%s] Column count is %i, row count is %i\n", __func__, result->column_count, result->row_count); 910 result->columns = g_new0(MrimSearchResultColumn, result->column_count); 911 result->rows = g_new0(gchar**, result->row_count); 912 guint i; 913 for (i = 0; i < result->column_count; i++) { 914 result->columns[i].title = mrim_package_read_LPSA(pack); 915 if (g_strcmp0(result->columns[i].title, "Username") == 0) { 916 result->username_index = i; 917 } else if (g_strcmp0(result->columns[i].title, "Domain") == 0) { 918 result->domain_index = i; 919 } 920 if ((g_strcmp0(result->columns[i].title, "Username") == 0) || (g_strcmp0(result->columns[i].title, "Domain") == 0) || 921 (g_strcmp0(result->columns[i].title, "City_id") == 0) || (g_strcmp0(result->columns[i].title, "Country_id") == 0) || 922 (g_strcmp0(result->columns[i].title, "BMonth") == 0) || (g_strcmp0(result->columns[i].title, "BDay") == 0) /*|| 923 (g_strcmp0(result->columns[i].title, "mrim_status") == 0)*/) { 924 result->columns[i].skip = TRUE; 925 } else { 926 result->columns[i].skip = FALSE; 927 } 928 if ((g_strcmp0(result->columns[i].title, "Nickname") == 0) || (g_strcmp0(result->columns[i].title, "FirstName") == 0) || 929 (g_strcmp0(result->columns[i].title, "LastName") == 0) || (g_strcmp0(result->columns[i].title, "Location") == 0) || 930 (g_strcmp0(result->columns[i].title, "status_title") == 0) || (g_strcmp0(result->columns[i].title, "status_desc") == 0)) { 931 result->columns[i].unicode = TRUE; 932 } else { 933 result->columns[i].unicode = FALSE; 934 } 935 } 936 937 for (guint i = 0; i < result->row_count; i++) { 938 if (pack->cur >= pack->data_size) break; 939 result->rows[i] = g_new0(gchar*, result->column_count); 940 for (guint j = 0; j < result->column_count; j++) { 941 if (result->columns[j].unicode) { 942 result->rows[i][j] = mrim_package_read_LPSW(pack); 943 } else { 944 result->rows[i][j] = mrim_package_read_LPSA(pack); 945 } 946 if ((!result->rows[i][j]) || (!result->rows[i][j][0])) { 947 g_free(result->rows[i][j]); 948 result->rows[i][j] = g_strdup(" "); 949 } 950 if (g_strcmp0(result->columns[j].title, "Sex") == 0) { 951 gchar *value = (atoi(result->rows[i][j]) == 1) ? g_strdup(_("Male")) : g_strdup(_("Female")); 952 g_free(result->rows[i][j]); 953 result->rows[i][j] = value; 954 } else if (g_strcmp0(result->columns[j].title, "Zodiac") == 0) { 955 guint index = atoi(result->rows[i][j]) - 1; 956 if (index < ARRAY_SIZE(zodiac)) { 957 g_free(result->rows[i][j]); 958 result->rows[i][j] = g_strdup(_(zodiac[index])); 959 } 960 } 961 } 962 }; 963 // Detecting if search results contain birthday column so we can determine age then: 964 purple_debug_info("mrim-prpl", "[%s] Looking for BDay...\n", __func__); 965 guint bday_col_index = result->column_count; 966 for (guint i = 0; i < result->column_count; i++) { 967 if (g_strcmp0(result->columns[i].title, "Birthday") == 0) { 968 bday_col_index = i; 969 break; 970 }; 971 }; 972 if (bday_col_index < result->column_count) { 973 guint age_col_index = result->column_count++; 974 result->columns = g_renew(MrimSearchResultColumn, result->columns, result->column_count); 975 result->columns[age_col_index].title = "Age"; 976 result->columns[age_col_index].skip = FALSE; 977 result->columns[age_col_index].unicode = FALSE; 978 979 for (guint row_id = 0; row_id < result->row_count; row_id++) { 980 gchar **old_row = result->rows[row_id]; 981 if (!old_row) { 982 break; 983 } else { 984 result->rows[row_id] = g_new0(gchar*, result->column_count); 985 for (guint col_id = 0; col_id < age_col_index; col_id++) { 986 result->rows[row_id][col_id] = g_strdup(old_row[col_id]); 987 g_free(old_row[col_id]); 988 } 989 gchar *BDay_Str = g_strdup(result->rows[row_id][bday_col_index]); 990 gchar *buddy_age = g_strdup("0"); 991 if ( g_strcmp0(BDay_Str, " ") == 0 ) { 992 g_free(buddy_age); 993 buddy_age = g_strdup(_("Not specified")); 994 } else { 995 int bd_year=0, bd_mon=0, bd_day=0; 996 int ret = sscanf(BDay_Str, "%u-%u-%u", &bd_year, &bd_mon, &bd_day); 997 purple_debug_info("mrim-prpl", "[%s] Birthday parsed (ret=%i) is %i-%i-%i.\n", __func__, ret, bd_year, bd_mon, bd_day); 998 999#if GLIB_MINOR_VERSION < 26 1000 // Age calculation for GLib <= 2.26 1001 GTimeVal *gTimeReal = g_new0(GTimeVal, 1); 1002 GDate *gCurDate = g_new0(GDate, 1); 1003 g_get_current_time (gTimeReal); 1004 g_date_set_time_val (gCurDate, gTimeReal); 1005 g_date_subtract_years (gCurDate, bd_year); 1006 g_date_subtract_months (gCurDate, bd_mon % 12); 1007 g_date_subtract_days (gCurDate, bd_day); 1008 g_free(buddy_age); 1009 int full_years = g_date_get_year(gCurDate); 1010 int full_months = g_date_get_month(gCurDate) % 12; 1011 1012 g_free(gTimeReal); 1013 g_free(gCurDate); 1014 // End GLib < 2.26 1015#else 1016 // Used for GLib >= 2.26 1017 GDateTime *TimeNow = g_date_time_new_now_local(); 1018 GDateTime *LifeTime; 1019 LifeTime = g_date_time_add_full(TimeNow, -bd_year, -bd_mon, -bd_day, 0, 0, 0); 1020 g_free(buddy_age); 1021 int full_years = g_date_time_get_year(LifeTime); 1022 int full_months = g_date_time_get_month(LifeTime) % 12; 1023 g_date_time_unref(TimeNow); 1024 g_date_time_unref(LifeTime); 1025 // End GLib >= 2.26 1026#endif 1027 if (!full_months) { 1028 buddy_age = g_strdup_printf(_("%i full years"), full_years); 1029 } else { 1030 buddy_age = g_strdup_printf(_("%i years, %i months"), full_years, full_months); 1031 } 1032 } 1033 result->rows[row_id][age_col_index] = buddy_age; 1034 } 1035 } 1036 }; 1037 // Age guessing end. 1038 purple_debug_info("mrim-prpl", "[%s] Search result parsed OK (%i rows)\n", __func__, i); 1039 return result; 1040} 1041 1042void mrim_get_info_ack(MrimData *mrim, gpointer user_data, MrimPackage *pack) { 1043 gchar *user_name = user_data; 1044 MrimSearchResult *result = mrim_parse_search_result(pack); 1045 if (result) { 1046 guint i; 1047 PurpleNotifyUserInfo *info = purple_notify_user_info_new(); 1048 purple_notify_user_info_add_pair(info, _("E-mail"), user_name); 1049 for (i = 0; i < result->column_count; i++) { 1050 if (!result->columns[i].skip) { 1051 purple_notify_user_info_add_pair(info, _(result->columns[i].title), result->rows[0][i]); 1052 } 1053 } 1054 PurpleBuddy *buddy = purple_find_buddy(mrim->account, user_name); 1055 if (buddy) { 1056 MrimBuddy *mb = buddy->proto_data; 1057 if (mb) { 1058 if (mb->user_agent) { 1059 gchar *tmp = mrim_get_ua_alias(mrim, mb->user_agent); 1060 purple_notify_user_info_add_pair(info, _("User agent"), tmp); 1061 g_free(tmp); 1062 } 1063 if (mb->microblog) { 1064 purple_notify_user_info_add_pair(info, _("Microblog"), mb->microblog); 1065 } 1066 } 1067 } 1068 purple_notify_userinfo(mrim->gc, user_name, info, NULL, NULL); 1069 } 1070} 1071 1072void mrim_get_info(PurpleConnection *gc, const char *username) { 1073 purple_debug_info("mrim-prpl", "[%s]\n", __func__); 1074 g_return_if_fail(username); 1075 g_return_if_fail(gc); 1076 MrimData *mrim = gc->proto_data; 1077 g_return_if_fail(mrim != NULL); 1078 purple_debug_info("mrim-prpl", "[%s] Fetching info for user '%s'\n", __func__, username); 1079 if (!is_valid_email((gchar*)username)) { 1080 PurpleNotifyUserInfo *info = purple_notify_user_info_new(); 1081 purple_notify_user_info_add_pair(info, _("UserInfo is not available for conferences and phones"), ""); 1082 purple_notify_userinfo(gc, username, info, NULL, NULL); 1083 } else { 1084 gchar** split = g_strsplit(username, "@", 2); 1085 gchar *user = split[0]; 1086 gchar *domain = split[1]; 1087 MrimPackage *pack = mrim_package_new(mrim->seq++, MRIM_CS_WP_REQUEST); 1088 mrim_package_add_UL(pack, MRIM_CS_WP_REQUEST_PARAM_USER); 1089 mrim_package_add_LPSA(pack, user); 1090 mrim_package_add_UL(pack, MRIM_CS_WP_REQUEST_PARAM_DOMAIN); 1091 mrim_package_add_LPSA(pack, domain); 1092 g_strfreev(split); 1093 mrim_add_ack_cb(mrim, pack->header->seq, mrim_get_info_ack, g_strdup(username)); 1094 mrim_package_send(pack, mrim); 1095 } 1096} 1097 1098void mrim_searchresults_add_buddy(PurpleConnection *gc, GList *row, void *user_data) { 1099 MrimData *mrim = user_data; 1100 purple_debug_info("mrim-prpl","[%s] %s\n", __func__, mrim->account->username); 1101 if (!purple_find_buddy(mrim->account, g_list_nth_data(row, 0))) { 1102 purple_blist_request_add_buddy(mrim->account, g_list_nth_data(row, 0), NULL, NULL); // TODO Propose alias automatically. 1103 } 1104} 1105 1106void mrim_search_ack(MrimData *mrim, gpointer user_data, MrimPackage *pack) { 1107 MrimSearchResult *result = mrim_parse_search_result(pack); 1108 if (result) { 1109 purple_debug_info("mrim-prpl", "[%s]\n", __func__); 1110 PurpleNotifySearchResults *results = purple_notify_searchresults_new(); 1111 PurpleNotifySearchColumn *column = purple_notify_searchresults_column_new(_("E-mail")); 1112 purple_notify_searchresults_column_add(results, column); 1113 guint32 i; 1114 for (i = 0; i < result->column_count; i++) { 1115 if (!result->columns[i].skip) { 1116 column = purple_notify_searchresults_column_new(g_strdup(_(result->columns[i].title))); 1117 purple_notify_searchresults_column_add(results, column); 1118 } 1119 } 1120 purple_notify_searchresults_button_add(results, PURPLE_NOTIFY_BUTTON_ADD, 1121 mrim_searchresults_add_buddy); 1122 for (i = 0; i < result->row_count; i++) { 1123 if (result->rows[i]) { 1124 guint32 j; 1125 GList *row = g_list_append(NULL, g_strdup_printf("%s@%s", 1126 result->rows[i][result->username_index], 1127 result->rows[i][result->domain_index])); 1128 for (j = 0; j < result->column_count; j++) { 1129 if (!result->columns[j].skip) { 1130 row = g_list_append(row, result->rows[i][j]); 1131 } 1132 } 1133 purple_notify_searchresults_row_add(results, row); 1134 } else { 1135 break; 1136 } 1137 } 1138 purple_notify_searchresults(mrim->gc, NULL, _("Search results"), NULL, results, NULL, NULL); 1139 } 1140} 1141 1142/* Tooltip */ 1143 1144void mrim_tooltip_text(PurpleBuddy *buddy, PurpleNotifyUserInfo *info, gboolean full) { 1145 purple_debug_info("mrim-prpl","[%s]\n",__func__); 1146 g_return_if_fail(buddy); 1147 if (buddy->alias) { 1148 purple_notify_user_info_add_pair(info, _("Name"), buddy->alias); 1149 } 1150 MrimBuddy *mb = buddy->proto_data; 1151 if (mb) { 1152 MrimData *mrim = mb->mrim; 1153 if (mb->flags & CONTACT_FLAG_MULTICHAT) { 1154 purple_notify_user_info_add_pair(info, _("Account"), buddy->account->username); 1155 purple_notify_user_info_add_pair(info, _("Room"), mb->email); 1156 purple_notify_user_info_add_pair(info, _("Alias"), mb->alias); 1157 return; 1158 } 1159 if (mb->status->id != STATUS_OFFLINE) { 1160 //if (mb->listening) { 1161 purple_notify_user_info_add_pair(info, _("Status"), mb->status->title); 1162 //} else { 1163 // purple_notify_user_info_add_pair(info, _("Status"), mb->status->display_str); 1164 //} 1165 } 1166 if (mb->listening) { 1167 purple_notify_user_info_add_pair(info, _("Listening"), mb->listening); 1168 } else if (mb->status && mb->status->desc) { 1169 purple_notify_user_info_add_pair(info, _("Comment"), mb->status->desc); 1170 } 1171 if (mb->user_agent) { 1172 gchar *tmp = mrim_get_ua_alias(mrim, mb->user_agent); 1173 purple_notify_user_info_add_pair(info, _("User agent"), tmp); 1174 g_free(tmp); 1175 } 1176 if (mb->microblog) { 1177 purple_notify_user_info_add_pair(info, _("Microblog"), mb->microblog); 1178 } 1179 } 1180 purple_debug_info("mrim-prpl","[%s] end.\n",__func__); 1181} 1182 1183/* Authorization */ 1184 1185void mrim_authorization_yes(gpointer va_data) { 1186 MrimAuthData *data = va_data; 1187 MrimData *mrim = data->mrim; 1188 purple_debug_info("mrim-prpl","[%s] Authorization request from '%s' acepted\n", __func__, data->from); 1189 MrimPackage *pack = mrim_package_new(data->seq, MRIM_CS_AUTHORIZE); 1190 mrim_package_add_LPSA(pack, data->from); 1191 mrim_package_send(pack, mrim); 1192 PurpleBuddy *buddy = purple_find_buddy(mrim->account, data->from); 1193 if (buddy && buddy->proto_data) { 1194 MrimBuddy *mb = buddy->proto_data; 1195 if (!mb->authorized) { 1196 mrim_send_authorize(mrim, data->from, NULL); /* TODO: Request auth message */ 1197 } 1198 } 1199 g_free(data->from); 1200 g_free(data); 1201} 1202 1203void mrim_authorization_no(gpointer va_data) { 1204 purple_debug_info("mrim-prpl", "[%s]\n", __func__); 1205 MrimAuthData *data = va_data; 1206 g_free(data->from); 1207 g_free(data); 1208} 1209 1210void mrim_send_authorize(MrimData *mrim, gchar *email, gchar *message) { /* TODO: Auth message */ 1211 purple_debug_info("mrim-prpl", "[%s] Send auhtorization request to '%s' with message '%s'\n", __func__, email, message); 1212 MrimPackage *pack = mrim_package_new(mrim->seq++, MRIM_CS_MESSAGE); 1213 mrim_package_add_UL(pack, MESSAGE_FLAG_AUTHORIZE | MESSAGE_FLAG_NORECV); 1214 mrim_package_add_LPSA(pack, email); 1215 mrim_package_add_base64(pack, "uss", 2, mrim->nick, message ? message : " "); 1216 mrim_package_add_UL(pack, 0); 1217 mrim_package_send(pack, mrim); 1218} 1219 1220/* 1221* CHATS 1222*/ 1223 1224// handle MULTICHAT_GET_MEMBERS 1225void mrim_chat_blist(MrimData *mrim, gpointer data, MrimPackage *pack) 1226{ 1227 purple_debug_info("mrim-prpl", "[%s] room=<%s>\n", __func__, (gchar*) data); 1228 PurpleConversation *conv = purple_find_chat(mrim->gc, get_chat_id(data)); 1229 PurpleConvChat *chat = PURPLE_CONV_CHAT(conv); 1230 1231 mrim_package_read_UL(pack); // todo: wtf?? 0x62 1232 mrim_package_read_UL(pack); // todo: wtf?? 0x02 == MULTICHAT_MEMBERS 1233 gchar *topic = mrim_package_read_LPSW(pack); 1234 mrim_package_read_UL(pack); // todo: wtf?? 0x4c 1235 // Set Topic 1236 purple_conv_chat_set_topic(chat, NULL, topic); 1237 /// 1238 /// Add users 1239 int n = mrim_package_read_UL(pack); 1240 for (int i = 0; i<n ; i++) 1241 { 1242 gchar *username = mrim_package_read_LPSA(pack); 1243 purple_conv_chat_add_user(chat, username, NULL, PURPLE_CBFLAGS_NONE, TRUE); 1244 } 1245} 1246 1247 1248void mrim_chat_join(PurpleConnection *gc, GHashTable *components) 1249{ 1250 gchar *room = g_hash_table_lookup(components, "room"); 1251 if (! is_valid_chat(room)) 1252 { 1253 char *buf = g_strdup_printf(_("%s is not a valid room name"), room); 1254 purple_notify_error(gc, _("Invalid Room Name"), _("Invalid Room Name"), buf); 1255 purple_serv_got_join_chat_failed(gc, components); 1256 g_free(buf); 1257 return; 1258 } 1259 1260 const char *username = gc->account->username; 1261 MrimData *mrim = gc->proto_data; 1262 PurpleChat *pchat = purple_blist_find_chat(gc->account, room); 1263 if (pchat == NULL) // TODO 1264 { 1265 // add chat 1266 purple_debug_info("mrim-prpl", "[%s] New chat: %s \n", __func__, room); 1267 GHashTable *defaults = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free); 1268 g_hash_table_insert(defaults, "room", g_strdup(room)); 1269 PurpleChat *pc = purple_chat_new(mrim->account, room, defaults); 1270 1271 purple_blist_add_chat(pc, get_mrim_group(mrim, 0)->group, NULL); // add to "?????????" // TODO // TODO move to ack? 1272 1273 MrimPackage *pack = mrim_package_new(mrim->seq, MRIM_CS_ADD_CONTACT); 1274 mrim_package_add_UL(pack, CONTACT_FLAG_MULTICHAT); 1275 mrim_package_add_UL(pack, 0); 1276 mrim_package_add_UL(pack, 0); 1277 mrim_package_add_LPSW(pack, "THIS IS TOPIC"); // TODO 1278 mrim_package_add_UL(pack, 0); 1279 mrim_package_add_UL(pack, 0); 1280 mrim_package_add_UL(pack, 0); 1281 1282 mrim_package_add_UL(pack, 0); // UL 34h 50h 21h 1283 mrim_package_add_UL(pack, 0); // UL 30h 1fh 1284 // UL count 1285 // count ???? LPS email 1286 mrim_package_send(pack, mrim); 1287 1288 } 1289 1290 if (!purple_find_chat(gc, get_chat_id(room))) { 1291 purple_debug_info("mrim-prpl", "[%s] %s is joining chat room %s\n", __func__, username, room); 1292 1293 serv_got_joined_chat(gc, get_chat_id(room), room); 1294 // Get users list 1295 mrim_add_ack_cb(mrim, mrim->seq, mrim_chat_blist, g_strdup(room)); 1296 1297 MrimPackage *pack = mrim_package_new(mrim->seq++, MRIM_CS_MESSAGE); 1298 mrim_package_add_UL(pack, MESSAGE_FLAG_MULTICHAT ); 1299 mrim_package_add_LPSA(pack, room); 1300 mrim_package_add_UL(pack, 0); 1301 mrim_package_add_UL(pack, 0); 1302 mrim_package_add_UL(pack, 4); 1303 mrim_package_add_UL(pack, MULTICHAT_GET_MEMBERS); 1304 mrim_package_send(pack, mrim); 1305 } 1306} 1307 1308void mrim_reject_chat(PurpleConnection *gc, GHashTable *components) 1309{ 1310 const char *room = g_hash_table_lookup(components, "room"); 1311 purple_debug_info("mrim-prpl", "[%s] room = %s\n", __func__, room); 1312} 1313 1314char *mrim_get_chat_name(GHashTable *components) 1315{ 1316 purple_debug_info("mrim", "[%s]\n", __func__); 1317 const char *str = g_hash_table_lookup(components, "room"); 1318 return (char*)str; 1319} 1320 1321 1322void mrim_chat_invite(PurpleConnection *gc, int id, const char *message, const char *who) 1323{ 1324 purple_debug_info("mrim-prpl", "[%s]\n", __func__); 1325 MrimData *mrim = gc->proto_data; 1326 PurpleConversation *conv = purple_find_chat(gc, id); 1327 const char *room = conv->name; 1328 1329 purple_debug_info("mrim-prpl", "[%s] %s is invited to join chat room %s\n", __func__, who, room); 1330 1331 MrimPackage *pack = mrim_package_new(mrim->seq++, MRIM_CS_MESSAGE); 1332 mrim_package_add_UL(pack, CONTACT_FLAG_MULTICHAT ); 1333 mrim_package_add_LPSA(pack, room); 1334 mrim_package_add_UL(pack, 0); // message 1335 mrim_package_add_UL(pack, 0); // rtf 1336 mrim_package_add_UL(pack, 0); // 0x27 ??? 1337 mrim_package_add_UL(pack, MULTICHAT_ADD_MEMBERS); 1338 mrim_package_add_UL(pack, 0); // 0x1f 1339 mrim_package_add_UL(pack, 1); // CLPS? 1340 mrim_package_add_LPSA(pack, who); 1341 mrim_package_send(pack, mrim); 1342} 1343 1344void mrim_chat_leave(PurpleConnection *gc, int id) 1345{ 1346 PurpleConversation *conv = purple_find_chat(gc, id); 1347 purple_debug_info("mrim-prpl", "[%s] %s is leaving chat room %s\n", __func__, gc->account->username, conv->name); 1348}