Mercurial > pidgin.yaz
comparison libpurple/protocols/qq/qq_process.c @ 23753:5f454b975a99
2008.08.10 - csyfek <csyfek(at)gmail.com>
* Commit to Pidgin
2008.08.06 - ccpaging <ecc_hy(at)hotmail.com>
* Rename names of variables, Group, to Room
* Functions of group_network merged into qq_network and qq_process
* Canceled managing glist of group packet, add sub_cmdd and room_id to transaction
* Fixed error of demo group:
If 'room list' and 'room infor' are not setup, response received from server will emits
'room_id = 0' packet.
2008.08.04 - ccpaging <ecc_hy(at)hotmail.com>
* Use new crypt/decrypt functions
* Rename crypt.c/h to qq_crypt.c/h
* Clean code of decrypt functions
* Fixed decryption failure
2008.08.04 - csyfek <csyfek(at)gmail.com>
* Update AUTHORS
author | SHiNE CsyFeK <csyfek@gmail.com> |
---|---|
date | Sun, 10 Aug 2008 04:32:14 +0000 |
parents | eba700811832 |
children | 967344bc404d e16982ad923f |
comparison
equal
deleted
inserted
replaced
23748:107166bb2a64 | 23753:5f454b975a99 |
---|---|
35 #include "buddy_list.h" | 35 #include "buddy_list.h" |
36 #include "buddy_opt.h" | 36 #include "buddy_opt.h" |
37 #include "group_info.h" | 37 #include "group_info.h" |
38 #include "group_free.h" | 38 #include "group_free.h" |
39 #include "char_conv.h" | 39 #include "char_conv.h" |
40 #include "crypt.h" | 40 #include "qq_crypt.h" |
41 #include "group_network.h" | 41 |
42 #include "group_conv.h" | |
43 #include "group_find.h" | |
44 #include "group_internal.h" | |
45 #include "group_im.h" | |
46 #include "group_info.h" | |
47 #include "group_join.h" | |
48 #include "group_opt.h" | |
49 #include "group_search.h" | |
50 | |
42 #include "header_info.h" | 51 #include "header_info.h" |
43 #include "qq_base.h" | 52 #include "qq_base.h" |
44 #include "im.h" | 53 #include "im.h" |
45 #include "qq_process.h" | 54 #include "qq_process.h" |
46 #include "packet_parse.h" | 55 #include "packet_parse.h" |
47 #include "qq_network.h" | 56 #include "qq_network.h" |
48 #include "qq_trans.h" | 57 #include "qq_trans.h" |
49 #include "sys_msg.h" | 58 #include "sys_msg.h" |
50 #include "utils.h" | 59 #include "utils.h" |
51 | 60 |
61 enum { | |
62 QQ_ROOM_CMD_REPLY_OK = 0x00, | |
63 QQ_ROOM_CMD_REPLY_SEARCH_ERROR = 0x02, | |
64 QQ_ROOM_CMD_REPLY_NOT_MEMBER = 0x0a | |
65 }; | |
66 | |
52 /* default process, decrypt and dump */ | 67 /* default process, decrypt and dump */ |
53 static void process_cmd_unknow(PurpleConnection *gc,gchar *title, guint8 *buf, gint buf_len, guint16 cmd, guint16 seq) | 68 static void process_cmd_unknow(PurpleConnection *gc,gchar *title, guint8 *data, gint data_len, guint16 cmd, guint16 seq) |
54 { | 69 { |
55 qq_data *qd; | 70 qq_data *qd; |
56 guint8 *data; | |
57 gint data_len; | |
58 gchar *msg_utf8 = NULL; | 71 gchar *msg_utf8 = NULL; |
59 | 72 |
60 g_return_if_fail(buf != NULL && buf_len != 0); | 73 g_return_if_fail(data != NULL && data_len != 0); |
61 | 74 |
62 qq_show_packet(title, buf, buf_len); | 75 qq_show_packet(title, data, data_len); |
63 | 76 |
64 qd = (qq_data *) gc->proto_data; | 77 qd = (qq_data *) gc->proto_data; |
65 | 78 |
66 data_len = buf_len; | |
67 data = g_newa(guint8, data_len); | |
68 memset(data, 0, data_len); | |
69 if ( !qq_decrypt(buf, buf_len, qd->session_key, data, &data_len )) { | |
70 purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Fail decrypt packet with default process\n"); | |
71 return; | |
72 } | |
73 | |
74 qq_hex_dump(PURPLE_DEBUG_WARNING, "QQ", | 79 qq_hex_dump(PURPLE_DEBUG_WARNING, "QQ", |
75 data, data_len, | 80 data, data_len, |
76 ">>> [%d] %s -> [default] decrypt and dump", | 81 ">>> [%d] %s -> [default] decrypt and dump", |
77 seq, qq_get_cmd_desc(cmd)); | 82 seq, qq_get_cmd_desc(cmd)); |
78 | 83 |
79 msg_utf8 = try_dump_as_gbk(data, data_len); | 84 msg_utf8 = try_dump_as_gbk(data, data_len); |
80 if (msg_utf8) { | 85 if (msg_utf8) { |
86 purple_notify_info(gc, NULL, msg_utf8, NULL); | |
81 g_free(msg_utf8); | 87 g_free(msg_utf8); |
82 } | 88 } |
83 } | 89 } |
84 | 90 |
85 void qq_proc_cmd_server(PurpleConnection *gc, | 91 void qq_proc_cmd_server(PurpleConnection *gc, |
86 guint16 cmd, guint16 seq, guint8 *data, gint data_len) | 92 guint16 cmd, guint16 seq, guint8 *rcved, gint rcved_len) |
87 { | 93 { |
94 qq_data *qd; | |
95 | |
96 guint8 *data; | |
97 gint data_len; | |
98 | |
99 g_return_if_fail (gc != NULL && gc->proto_data != NULL); | |
100 qd = (qq_data *) gc->proto_data; | |
101 | |
102 data = g_newa(guint8, rcved_len); | |
103 data_len = qq_decrypt(data, rcved, rcved_len, qd->session_key); | |
104 if (data_len < 0) { | |
105 purple_debug(PURPLE_DEBUG_WARNING, "QQ", | |
106 "Can not decrypt server cmd by session key, [%05d], 0x%04X %s, len %d\n", | |
107 seq, cmd, qq_get_cmd_desc(cmd), rcved_len); | |
108 qq_show_packet("Can not decrypted", rcved, rcved_len); | |
109 return; | |
110 } | |
111 | |
112 if (data_len <= 0) { | |
113 purple_debug(PURPLE_DEBUG_WARNING, "QQ", | |
114 "Server cmd decrypted is empty, [%05d], 0x%04X %s, len %d\n", | |
115 seq, cmd, qq_get_cmd_desc(cmd), rcved_len); | |
116 return; | |
117 } | |
118 | |
88 /* now process the packet */ | 119 /* now process the packet */ |
89 switch (cmd) { | 120 switch (cmd) { |
90 case QQ_CMD_RECV_IM: | 121 case QQ_CMD_RECV_IM: |
91 qq_process_recv_im(data, data_len, seq, gc); | 122 qq_process_recv_im(data, data_len, seq, gc); |
92 break; | 123 break; |
132 | 163 |
133 /* refresh buddies */ | 164 /* refresh buddies */ |
134 qq_send_packet_get_buddies_list(gc, 0); | 165 qq_send_packet_get_buddies_list(gc, 0); |
135 | 166 |
136 /* refresh groups */ | 167 /* refresh groups */ |
137 qq_send_packet_get_all_list_with_group(gc, 0); | 168 qq_send_packet_get_buddies_and_rooms(gc, 0); |
138 | 169 |
139 return; | 170 return; |
140 } | 171 } |
141 | 172 |
142 if (ret_8 == QQ_LOGIN_REPLY_REDIRECT) { | 173 if (ret_8 == QQ_LOGIN_REPLY_REDIRECT) { |
166 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to login")); | 197 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to login")); |
167 return; | 198 return; |
168 } | 199 } |
169 } | 200 } |
170 | 201 |
202 static void process_room_cmd_notify(PurpleConnection *gc, | |
203 guint8 room_cmd, guint8 room_id, guint8 reply_cmd, guint8 reply, guint8 *data, gint data_len) | |
204 { | |
205 gchar *msg, *msg_utf8; | |
206 g_return_if_fail(data != NULL && data_len > 0); | |
207 | |
208 msg = g_strndup((gchar *) data, data_len); /* it will append 0x00 */ | |
209 msg_utf8 = qq_to_utf8(msg, QQ_CHARSET_DEFAULT); | |
210 g_free(msg); | |
211 | |
212 msg = g_strdup_printf(_( | |
213 "Reply %s(0x%02X )\n" | |
214 "Sent %s(0x%02X )\n" | |
215 "Room id %d, reply [0x%02X]: \n" | |
216 "%s"), | |
217 qq_get_room_cmd_desc(reply_cmd), reply_cmd, | |
218 qq_get_room_cmd_desc(room_cmd), room_cmd, | |
219 room_id, reply, msg_utf8); | |
220 | |
221 purple_notify_error(gc, NULL, _("Failed room reply"), msg); | |
222 g_free(msg); | |
223 g_free(msg_utf8); | |
224 } | |
225 | |
226 void qq_proc_room_cmd_reply(PurpleConnection *gc, | |
227 guint16 seq, guint8 room_cmd, guint32 room_id, guint8 *rcved, gint rcved_len) | |
228 { | |
229 qq_data *qd; | |
230 guint8 *data; | |
231 gint data_len; | |
232 qq_group *group; | |
233 gint bytes; | |
234 guint8 reply_cmd, reply; | |
235 | |
236 g_return_if_fail (gc != NULL && gc->proto_data != NULL); | |
237 qd = (qq_data *) gc->proto_data; | |
238 | |
239 data = g_newa(guint8, rcved_len); | |
240 data_len = qq_decrypt(data, rcved, rcved_len, qd->session_key); | |
241 if (data_len < 0) { | |
242 purple_debug(PURPLE_DEBUG_WARNING, "QQ", | |
243 "Can not decrypt room cmd by session key, [%05d], 0x%02X %s for %d, len %d\n", | |
244 seq, room_cmd, qq_get_room_cmd_desc(room_cmd), room_id, rcved_len); | |
245 qq_show_packet("Can not decrypted", rcved, rcved_len); | |
246 return; | |
247 } | |
248 | |
249 if (room_id <= 0) { | |
250 purple_debug(PURPLE_DEBUG_WARNING, "QQ", | |
251 "Invaild room id, [%05d], 0x%02X %s for %d, len %d\n", | |
252 seq, room_cmd, qq_get_room_cmd_desc(room_cmd), room_id, rcved_len); | |
253 return; | |
254 } | |
255 | |
256 if (data_len <= 2) { | |
257 purple_debug(PURPLE_DEBUG_WARNING, "QQ", | |
258 "Invaild len of room cmd decrypted, [%05d], 0x%02X %s for %d, len %d\n", | |
259 seq, room_cmd, qq_get_room_cmd_desc(room_cmd), room_id, rcved_len); | |
260 return; | |
261 } | |
262 | |
263 group = qq_room_search_id(gc, room_id); | |
264 if (group == NULL) { | |
265 purple_debug(PURPLE_DEBUG_WARNING, "QQ", | |
266 "Missing room id in [%05d], 0x%02X %s for %d, len %d\n", | |
267 seq, room_cmd, qq_get_room_cmd_desc(room_cmd), room_id, rcved_len); | |
268 } | |
269 | |
270 bytes = 0; | |
271 bytes += qq_get8(&reply_cmd, data + bytes); | |
272 bytes += qq_get8(&reply, data + bytes); | |
273 | |
274 if (reply_cmd != room_cmd) { | |
275 purple_debug(PURPLE_DEBUG_WARNING, "QQ", | |
276 "Missing room cmd in reply 0x%02X %s, [%05d], 0x%02X %s for %d, len %d\n", | |
277 reply_cmd, qq_get_room_cmd_desc(reply_cmd), | |
278 seq, room_cmd, qq_get_room_cmd_desc(room_cmd), room_id, rcved_len); | |
279 } | |
280 | |
281 /* now process the packet */ | |
282 if (reply != QQ_ROOM_CMD_REPLY_OK) { | |
283 if (group != NULL) { | |
284 qq_set_pending_id(&qd->joining_groups, group->ext_id, FALSE); | |
285 } | |
286 | |
287 switch (reply) { /* this should be all errors */ | |
288 case QQ_ROOM_CMD_REPLY_NOT_MEMBER: | |
289 if (group != NULL) { | |
290 purple_debug(PURPLE_DEBUG_WARNING, | |
291 "QQ", | |
292 _("You are not a member of group \"%s\"\n"), group->group_name_utf8); | |
293 group->my_status = QQ_GROUP_MEMBER_STATUS_NOT_MEMBER; | |
294 qq_group_refresh(gc, group); | |
295 } | |
296 break; | |
297 case QQ_ROOM_CMD_REPLY_SEARCH_ERROR: | |
298 if (qd->roomlist != NULL) { | |
299 if (purple_roomlist_get_in_progress(qd->roomlist)) | |
300 purple_roomlist_set_in_progress(qd->roomlist, FALSE); | |
301 } | |
302 default: | |
303 process_room_cmd_notify(gc, room_cmd, room_id, reply_cmd, reply, data + bytes, data_len - bytes); | |
304 } | |
305 return; | |
306 } | |
307 | |
308 /* seems ok so far, so we process the reply according to sub_cmd */ | |
309 switch (reply_cmd) { | |
310 case QQ_ROOM_CMD_GET_INFO: | |
311 qq_process_room_cmd_get_info(data + bytes, data_len - bytes, gc); | |
312 if (group != NULL) { | |
313 qq_send_cmd_group_get_members_info(gc, group); | |
314 qq_send_cmd_group_get_online_members(gc, group); | |
315 } | |
316 break; | |
317 case QQ_ROOM_CMD_CREATE: | |
318 qq_group_process_create_group_reply(data + bytes, data_len - bytes, gc); | |
319 break; | |
320 case QQ_ROOM_CMD_CHANGE_INFO: | |
321 qq_group_process_modify_info_reply(data + bytes, data_len - bytes, gc); | |
322 break; | |
323 case QQ_ROOM_CMD_MEMBER_OPT: | |
324 qq_group_process_modify_members_reply(data + bytes, data_len - bytes, gc); | |
325 break; | |
326 case QQ_ROOM_CMD_ACTIVATE: | |
327 qq_group_process_activate_group_reply(data + bytes, data_len - bytes, gc); | |
328 break; | |
329 case QQ_ROOM_CMD_SEARCH: | |
330 qq_process_group_cmd_search_group(data + bytes, data_len - bytes, gc); | |
331 break; | |
332 case QQ_ROOM_CMD_JOIN: | |
333 qq_process_group_cmd_join_group(data + bytes, data_len - bytes, gc); | |
334 break; | |
335 case QQ_ROOM_CMD_AUTH: | |
336 qq_process_group_cmd_join_group_auth(data + bytes, data_len - bytes, gc); | |
337 break; | |
338 case QQ_ROOM_CMD_QUIT: | |
339 qq_process_group_cmd_exit_group(data + bytes, data_len - bytes, gc); | |
340 break; | |
341 case QQ_ROOM_CMD_SEND_MSG: | |
342 qq_process_group_cmd_im(data + bytes, data_len - bytes, gc); | |
343 break; | |
344 case QQ_ROOM_CMD_GET_ONLINES: | |
345 qq_process_room_cmd_get_onlines(data + bytes, data_len - bytes, gc); | |
346 if (group != NULL) | |
347 qq_group_conv_refresh_online_member(gc, group); | |
348 break; | |
349 case QQ_ROOM_CMD_GET_MEMBER_INFO: | |
350 qq_process_room_cmd_get_members(data + bytes, data_len - bytes, gc); | |
351 if (group != NULL) | |
352 qq_group_conv_refresh_online_member(gc, group); | |
353 break; | |
354 default: | |
355 purple_debug(PURPLE_DEBUG_WARNING, "QQ", | |
356 "Unknow room cmd 0x%02X %s\n", | |
357 reply_cmd, qq_get_room_cmd_desc(reply_cmd)); | |
358 } | |
359 } | |
360 | |
171 void qq_proc_cmd_reply(PurpleConnection *gc, | 361 void qq_proc_cmd_reply(PurpleConnection *gc, |
172 guint16 cmd, guint16 seq, guint8 *data, gint data_len) | 362 guint16 cmd, guint16 seq, guint8 *rcved, gint rcved_len) |
173 { | 363 { |
364 qq_data *qd; | |
365 | |
366 guint8 *data; | |
367 gint data_len; | |
368 | |
369 gboolean ret_bool = FALSE; | |
174 guint8 ret_8 = 0; | 370 guint8 ret_8 = 0; |
175 guint16 ret_16 = 0; | 371 guint16 ret_16 = 0; |
176 guint32 ret_32 = 0; | 372 guint32 ret_32 = 0; |
177 gchar *error_msg = NULL; | 373 gchar *error_msg = NULL; |
374 | |
375 g_return_if_fail(rcved_len > 0); | |
376 | |
377 g_return_if_fail (gc != NULL && gc->proto_data != NULL); | |
378 qd = (qq_data *) gc->proto_data; | |
379 | |
380 data = g_newa(guint8, rcved_len); | |
381 if (cmd == QQ_CMD_TOKEN) { | |
382 g_memmove(data, rcved, rcved_len); | |
383 data_len = rcved_len; | |
384 } else if (cmd == QQ_CMD_LOGIN) { | |
385 /* May use password_twice_md5 in the past version like QQ2005*/ | |
386 data_len = qq_decrypt(data, rcved, rcved_len, qd->inikey); | |
387 if (data_len >= 0) { | |
388 purple_debug(PURPLE_DEBUG_WARNING, "QQ", | |
389 "Decrypt login reply packet with inikey, %d bytes\n", data_len); | |
390 } else { | |
391 data_len = qq_decrypt(data, rcved, rcved_len, qd->password_twice_md5); | |
392 if (data_len >= 0) { | |
393 purple_debug(PURPLE_DEBUG_WARNING, "QQ", | |
394 "Decrypt login reply packet with password_twice_md5, %d bytes\n", data_len); | |
395 } else { | |
396 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, | |
397 _("Can not decrypt login reply")); | |
398 return; | |
399 } | |
400 } | |
401 } else { | |
402 data_len = qq_decrypt(data, rcved, rcved_len, qd->session_key); | |
403 if (data_len < 0) { | |
404 purple_debug(PURPLE_DEBUG_WARNING, "QQ", | |
405 "Can not reply by session key, [%05d], 0x%04X %s, len %d\n", | |
406 seq, cmd, qq_get_cmd_desc(cmd), rcved_len); | |
407 qq_show_packet("Can not decrypted", rcved, rcved_len); | |
408 return; | |
409 } | |
410 } | |
411 | |
412 if (data_len <= 0) { | |
413 purple_debug(PURPLE_DEBUG_WARNING, "QQ", | |
414 "Reply decrypted is empty, [%05d], 0x%04X %s, len %d\n", | |
415 seq, cmd, qq_get_cmd_desc(cmd), rcved_len); | |
416 return; | |
417 } | |
178 | 418 |
179 switch (cmd) { | 419 switch (cmd) { |
180 case QQ_CMD_TOKEN: | 420 case QQ_CMD_TOKEN: |
181 ret_8 = qq_process_token_reply(gc, error_msg, data, data_len); | 421 ret_8 = qq_process_token_reply(gc, error_msg, data, data_len); |
182 if (ret_8 != QQ_TOKEN_REPLY_OK) { | 422 if (ret_8 != QQ_TOKEN_REPLY_OK) { |
244 } else { | 484 } else { |
245 purple_debug(PURPLE_DEBUG_INFO, "QQ", "All buddies received. Requesting buddies' levels\n"); | 485 purple_debug(PURPLE_DEBUG_INFO, "QQ", "All buddies received. Requesting buddies' levels\n"); |
246 qq_send_packet_get_buddies_online(gc, 0); | 486 qq_send_packet_get_buddies_online(gc, 0); |
247 } | 487 } |
248 break; | 488 break; |
249 case QQ_CMD_GROUP_CMD: | 489 case QQ_CMD_GET_BUDDIES_AND_ROOMS: |
250 qq_process_group_cmd_reply(data, data_len, seq, gc); | 490 ret_32 = qq_process_get_buddies_and_rooms(data, data_len, gc); |
251 break; | |
252 case QQ_CMD_GET_ALL_LIST_WITH_GROUP: | |
253 ret_32 = qq_process_get_all_list_with_group_reply(data, data_len, gc); | |
254 if (ret_32 > 0 && ret_32 < 0xffffffff) { | 491 if (ret_32 > 0 && ret_32 < 0xffffffff) { |
255 purple_debug(PURPLE_DEBUG_INFO, "QQ", "Requesting for more buddies and groups\n"); | 492 purple_debug(PURPLE_DEBUG_INFO, "QQ", "Requesting for more buddies and groups\n"); |
256 qq_send_packet_get_all_list_with_group(gc, ret_32); | 493 qq_send_packet_get_buddies_and_rooms(gc, ret_32); |
257 } else { | 494 } else { |
258 purple_debug(PURPLE_DEBUG_INFO, "QQ", "All buddies and groups received\n"); | 495 purple_debug(PURPLE_DEBUG_INFO, "QQ", "All buddies and groups received\n"); |
259 } | 496 } |
260 break; | 497 break; |
261 default: | 498 default: |