PageRenderTime 57ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 1ms

/cl.c

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