PageRenderTime 52ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/pidgin-2.7.3/libpurple/protocols/qq/group_internal.c

https://github.com/jrcjc/chimein
C | 434 lines | 332 code | 70 blank | 32 comment | 95 complexity | 3cac2badcb95b617774f28a296a0e5af MD5 | raw file
  1. /**
  2. * @file group_internal.c
  3. *
  4. * purple
  5. *
  6. * Purple is the legal property of its developers, whose names are too numerous
  7. * to list here. Please refer to the COPYRIGHT file distributed with this
  8. * source distribution.
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation; either version 2 of the License, or
  13. * (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program; if not, write to the Free Software
  22. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
  23. */
  24. #include "internal.h"
  25. #include "blist.h"
  26. #include "debug.h"
  27. #include "buddy_opt.h"
  28. #include "group_internal.h"
  29. #include "utils.h"
  30. static qq_room_data *room_data_new(guint32 id, guint32 ext_id, const gchar *title)
  31. {
  32. qq_room_data *rmd;
  33. purple_debug_info("QQ", "Created room data: %s, ext id %u, id %u\n",
  34. title == NULL ? "(NULL)" : title,
  35. ext_id, id);
  36. rmd = g_new0(qq_room_data, 1);
  37. rmd->my_role = QQ_ROOM_ROLE_NO;
  38. rmd->id = id;
  39. rmd->ext_id = ext_id;
  40. rmd->type8 = 0x01; /* assume permanent Qun */
  41. rmd->creator_uid = 10000; /* assume by QQ admin */
  42. rmd->category = 0x01;
  43. rmd->auth_type = 0x02; /* assume need auth */
  44. rmd->title_utf8 = g_strdup(title == NULL ? "" : title);
  45. rmd->desc_utf8 = g_strdup("");
  46. rmd->notice_utf8 = g_strdup("");
  47. rmd->members = NULL;
  48. rmd->is_got_buddies = FALSE;
  49. return rmd;
  50. }
  51. /* create a qq_room_data from hashtable */
  52. static qq_room_data *room_data_new_by_hashtable(PurpleConnection *gc, GHashTable *data)
  53. {
  54. qq_room_data *rmd;
  55. guint32 id, ext_id;
  56. gchar *value;
  57. value = g_hash_table_lookup(data, QQ_ROOM_KEY_INTERNAL_ID);
  58. id = value ? strtoul(value, NULL, 10) : 0;
  59. value = g_hash_table_lookup(data, QQ_ROOM_KEY_EXTERNAL_ID);
  60. ext_id = value ? strtoul(value, NULL, 10) : 0;
  61. value = g_hash_table_lookup(data, QQ_ROOM_KEY_TITLE_UTF8);
  62. rmd = room_data_new(id, ext_id, value);
  63. rmd->my_role = QQ_ROOM_ROLE_YES;
  64. return rmd;
  65. }
  66. /* gracefully free all members in a room */
  67. static void room_buddies_free(qq_room_data *rmd)
  68. {
  69. gint i;
  70. GList *list;
  71. qq_buddy_data *bd;
  72. g_return_if_fail(rmd != NULL);
  73. i = 0;
  74. while (NULL != (list = rmd->members)) {
  75. bd = (qq_buddy_data *) list->data;
  76. i++;
  77. rmd->members = g_list_remove(rmd->members, bd);
  78. qq_buddy_data_free(bd);
  79. }
  80. rmd->members = NULL;
  81. }
  82. /* gracefully free the memory for one qq_room_data */
  83. static void room_data_free(qq_room_data *rmd)
  84. {
  85. g_return_if_fail(rmd != NULL);
  86. room_buddies_free(rmd);
  87. g_free(rmd->title_utf8);
  88. g_free(rmd->desc_utf8);
  89. g_free(rmd->notice_utf8);
  90. g_free(rmd);
  91. }
  92. void qq_room_update_chat_info(PurpleChat *chat, qq_room_data *rmd)
  93. {
  94. GHashTable *components;
  95. if (rmd->title_utf8 != NULL && strlen(rmd->title_utf8) > 0) {
  96. purple_blist_alias_chat(chat, rmd->title_utf8);
  97. }
  98. components = purple_chat_get_components(chat);
  99. g_hash_table_replace(components,
  100. g_strdup(QQ_ROOM_KEY_INTERNAL_ID),
  101. g_strdup_printf("%u", rmd->id));
  102. g_hash_table_replace(components,
  103. g_strdup(QQ_ROOM_KEY_EXTERNAL_ID),
  104. g_strdup_printf("%u", rmd->ext_id));
  105. g_hash_table_replace(components,
  106. g_strdup(QQ_ROOM_KEY_TITLE_UTF8), g_strdup(rmd->title_utf8));
  107. }
  108. static PurpleChat *chat_new(PurpleConnection *gc, qq_room_data *rmd)
  109. {
  110. GHashTable *components;
  111. PurpleGroup *g;
  112. PurpleChat *chat;
  113. purple_debug_info("QQ", "Add new chat: id %u, ext id %u, title %s\n",
  114. rmd->id, rmd->ext_id,
  115. rmd->title_utf8 == NULL ? "(NULL)" : rmd->title_utf8);
  116. components = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
  117. g_hash_table_insert(components,
  118. g_strdup(QQ_ROOM_KEY_INTERNAL_ID), g_strdup_printf("%u", rmd->id));
  119. g_hash_table_insert(components, g_strdup(QQ_ROOM_KEY_EXTERNAL_ID),
  120. g_strdup_printf("%u", rmd->ext_id));
  121. g_hash_table_insert(components, g_strdup(QQ_ROOM_KEY_TITLE_UTF8), g_strdup(rmd->title_utf8));
  122. chat = purple_chat_new(purple_connection_get_account(gc), rmd->title_utf8, components);
  123. g = qq_group_find_or_new(PURPLE_GROUP_QQ_QUN);
  124. purple_blist_add_chat(chat, g, NULL);
  125. return chat;
  126. }
  127. PurpleChat *qq_room_find_or_new(PurpleConnection *gc, guint32 id, guint32 ext_id)
  128. {
  129. qq_data *qd;
  130. qq_room_data *rmd;
  131. PurpleChat *chat;
  132. gchar *num_str;
  133. g_return_val_if_fail (gc != NULL && gc->proto_data != NULL, NULL);
  134. qd = (qq_data *) gc->proto_data;
  135. g_return_val_if_fail(id != 0 && ext_id != 0, NULL);
  136. purple_debug_info("QQ", "Find or add new room: id %u, ext id %u\n", id, ext_id);
  137. rmd = qq_room_data_find(gc, id);
  138. if (rmd == NULL) {
  139. rmd = room_data_new(id, ext_id, NULL);
  140. g_return_val_if_fail(rmd != NULL, NULL);
  141. rmd->my_role = QQ_ROOM_ROLE_YES;
  142. qd->groups = g_list_append(qd->groups, rmd);
  143. }
  144. num_str = g_strdup_printf("%u", ext_id);
  145. chat = purple_blist_find_chat(purple_connection_get_account(gc), num_str);
  146. g_free(num_str);
  147. if (chat) {
  148. return chat;
  149. }
  150. return chat_new(gc, rmd);
  151. }
  152. void qq_room_remove(PurpleConnection *gc, guint32 id)
  153. {
  154. qq_data *qd;
  155. PurpleChat *chat;
  156. qq_room_data *rmd;
  157. gchar *num_str;
  158. guint32 ext_id;
  159. g_return_if_fail (gc != NULL && gc->proto_data != NULL);
  160. qd = (qq_data *) gc->proto_data;
  161. purple_debug_info("QQ", "Find and remove room data, id %u\n", id);
  162. rmd = qq_room_data_find(gc, id);
  163. g_return_if_fail (rmd != NULL);
  164. ext_id = rmd->ext_id;
  165. qd->groups = g_list_remove(qd->groups, rmd);
  166. room_data_free(rmd);
  167. purple_debug_info("QQ", "Find and remove chat, ext_id %u\n", ext_id);
  168. num_str = g_strdup_printf("%u", ext_id);
  169. chat = purple_blist_find_chat(purple_connection_get_account(gc), num_str);
  170. g_free(num_str);
  171. g_return_if_fail (chat != NULL);
  172. purple_blist_remove_chat(chat);
  173. }
  174. /* find a qq_buddy_data by uid, called by im.c */
  175. qq_buddy_data *qq_room_buddy_find(qq_room_data *rmd, guint32 uid)
  176. {
  177. GList *list;
  178. qq_buddy_data *bd;
  179. g_return_val_if_fail(rmd != NULL && uid > 0, NULL);
  180. list = rmd->members;
  181. while (list != NULL) {
  182. bd = (qq_buddy_data *) list->data;
  183. if (bd->uid == uid)
  184. return bd;
  185. else
  186. list = list->next;
  187. }
  188. return NULL;
  189. }
  190. /* remove a qq_buddy_data by uid, called by qq_group_opt.c */
  191. void qq_room_buddy_remove(qq_room_data *rmd, guint32 uid)
  192. {
  193. GList *list;
  194. qq_buddy_data *bd;
  195. g_return_if_fail(rmd != NULL && uid > 0);
  196. list = rmd->members;
  197. while (list != NULL) {
  198. bd = (qq_buddy_data *) list->data;
  199. if (bd->uid == uid) {
  200. rmd->members = g_list_remove(rmd->members, bd);
  201. return;
  202. } else {
  203. list = list->next;
  204. }
  205. }
  206. }
  207. qq_buddy_data *qq_room_buddy_find_or_new(PurpleConnection *gc, qq_room_data *rmd, guint32 member_uid)
  208. {
  209. qq_buddy_data *member, *bd;
  210. PurpleBuddy *buddy;
  211. g_return_val_if_fail(rmd != NULL && member_uid > 0, NULL);
  212. member = qq_room_buddy_find(rmd, member_uid);
  213. if (member == NULL) { /* first appear during my session */
  214. member = g_new0(qq_buddy_data, 1);
  215. member->uid = member_uid;
  216. buddy = purple_find_buddy(purple_connection_get_account(gc), uid_to_purple_name(member_uid));
  217. if (buddy != NULL) {
  218. const gchar *alias = NULL;
  219. bd = purple_buddy_get_protocol_data(buddy);
  220. if (bd != NULL && bd->nickname != NULL)
  221. member->nickname = g_strdup(bd->nickname);
  222. else if ((alias = purple_buddy_get_alias(buddy)) != NULL)
  223. member->nickname = g_strdup(alias);
  224. }
  225. rmd->members = g_list_append(rmd->members, member);
  226. }
  227. return member;
  228. }
  229. qq_room_data *qq_room_data_find(PurpleConnection *gc, guint32 room_id)
  230. {
  231. GList *list;
  232. qq_room_data *rmd;
  233. qq_data *qd;
  234. qd = (qq_data *) gc->proto_data;
  235. if (qd->groups == NULL || room_id <= 0)
  236. return 0;
  237. list = qd->groups;
  238. while (list != NULL) {
  239. rmd = (qq_room_data *) list->data;
  240. if (rmd->id == room_id) {
  241. return rmd;
  242. }
  243. list = list->next;
  244. }
  245. return NULL;
  246. }
  247. guint32 qq_room_get_next(PurpleConnection *gc, guint32 room_id)
  248. {
  249. GList *list;
  250. qq_room_data *rmd;
  251. qq_data *qd;
  252. gboolean is_find = FALSE;
  253. qd = (qq_data *) gc->proto_data;
  254. if (qd->groups == NULL) {
  255. return 0;
  256. }
  257. if (room_id <= 0) {
  258. rmd = (qq_room_data *) qd->groups->data;
  259. return rmd->id;
  260. }
  261. list = qd->groups;
  262. while (list != NULL) {
  263. rmd = (qq_room_data *) list->data;
  264. list = list->next;
  265. if (rmd->id == room_id) {
  266. is_find = TRUE;
  267. break;
  268. }
  269. }
  270. g_return_val_if_fail(is_find, 0);
  271. if (list == NULL) return 0; /* be the end */
  272. rmd = (qq_room_data *) list->data;
  273. g_return_val_if_fail(rmd != NULL, 0);
  274. return rmd->id;
  275. }
  276. guint32 qq_room_get_next_conv(PurpleConnection *gc, guint32 room_id)
  277. {
  278. GList *list;
  279. qq_room_data *rmd;
  280. qq_data *qd;
  281. gboolean is_find;
  282. qd = (qq_data *) gc->proto_data;
  283. list = qd->groups;
  284. if (room_id > 0) {
  285. /* search next room */
  286. is_find = FALSE;
  287. while (list != NULL) {
  288. rmd = (qq_room_data *) list->data;
  289. list = list->next;
  290. if (rmd->id == room_id) {
  291. is_find = TRUE;
  292. break;
  293. }
  294. }
  295. g_return_val_if_fail(is_find, 0);
  296. }
  297. while (list != NULL) {
  298. rmd = (qq_room_data *) list->data;
  299. g_return_val_if_fail(rmd != NULL, 0);
  300. if (rmd->my_role == QQ_ROOM_ROLE_YES || rmd->my_role == QQ_ROOM_ROLE_ADMIN) {
  301. if (NULL != purple_find_conversation_with_account(
  302. PURPLE_CONV_TYPE_CHAT,rmd->title_utf8, purple_connection_get_account(gc))) {
  303. /* In convseration*/
  304. return rmd->id;
  305. }
  306. }
  307. list = list->next;
  308. }
  309. return 0;
  310. }
  311. /* this should be called upon signin, even when we did not open group chat window */
  312. void qq_room_data_initial(PurpleConnection *gc)
  313. {
  314. PurpleAccount *account;
  315. PurpleChat *chat;
  316. PurpleGroup *purple_group;
  317. PurpleBlistNode *node;
  318. qq_data *qd;
  319. qq_room_data *rmd;
  320. gint count;
  321. account = purple_connection_get_account(gc);
  322. qd = (qq_data *) gc->proto_data;
  323. purple_debug_info("QQ", "Initial QQ Qun configurations\n");
  324. purple_group = purple_find_group(PURPLE_GROUP_QQ_QUN);
  325. if (purple_group == NULL) {
  326. purple_debug_info("QQ", "We have no QQ Qun\n");
  327. return;
  328. }
  329. count = 0;
  330. for (node = purple_blist_node_get_first_child((PurpleBlistNode *)purple_group);
  331. node != NULL;
  332. node = purple_blist_node_get_sibling_next(node))
  333. {
  334. if ( !PURPLE_BLIST_NODE_IS_CHAT(node)) {
  335. continue;
  336. }
  337. /* got one */
  338. chat = (PurpleChat *) node;
  339. if (account != purple_chat_get_account(chat)) /* not qq account*/
  340. continue;
  341. rmd = room_data_new_by_hashtable(gc, purple_chat_get_components(chat));
  342. qd->groups = g_list_append(qd->groups, rmd);
  343. count++;
  344. }
  345. purple_debug_info("QQ", "Load %d QQ Qun configurations\n", count);
  346. }
  347. void qq_room_data_free_all(PurpleConnection *gc)
  348. {
  349. qq_data *qd;
  350. qq_room_data *rmd;
  351. gint count;
  352. g_return_if_fail (gc != NULL && gc->proto_data != NULL);
  353. qd = (qq_data *) gc->proto_data;
  354. count = 0;
  355. while (qd->groups != NULL) {
  356. rmd = (qq_room_data *) qd->groups->data;
  357. qd->groups = g_list_remove(qd->groups, rmd);
  358. room_data_free(rmd);
  359. count++;
  360. }
  361. if (count > 0) {
  362. purple_debug_info("QQ", "%d rooms are freed\n", count);
  363. }
  364. }