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: