comparison libpurple/protocols/qq/qq_process.c @ 23878:967344bc404d

applied changes from f12c8903079425d7850fa183df0b3f937b2952be through 8cebefbc6cd5d84acb69c74e69e8821f11dd225d Backport of 8cebefbc6cd5d84acb69c74e69e8821f11dd225d to avoid having other changes overwritten. 2008.08.16 - ccpaging <ecc_hy(at)hotmail.com> * Rename group to room. If you used pidginqq before, this may create a new room with same title, you may delete old one * Replace purple_debug with purple_debug_info, purple_debug_warning, purple_debug_error * Add server notice and server new, and two options to turn on/off * Minor modify for reducing transaction's debug infor * Minor modifies for system notice and QQ news. * Add 4 new strings need translate compare with p10. committer: Daniel Atallah <daniel.atallah@gmail.com>
author SHiNE CsyFeK <csyfek@gmail.com>
date Mon, 15 Sep 2008 02:59:23 +0000
parents 5f454b975a99
children 23cec4360d4a
comparison
equal deleted inserted replaced
23695:5f454b975a99 23878:967344bc404d
24 24
25 #include "cipher.h" 25 #include "cipher.h"
26 #include "debug.h" 26 #include "debug.h"
27 #include "internal.h" 27 #include "internal.h"
28 28
29 #ifdef _WIN32
30 #define random rand
31 #define srandom srand
32 #endif
33
34 #include "buddy_info.h" 29 #include "buddy_info.h"
35 #include "buddy_list.h" 30 #include "buddy_list.h"
36 #include "buddy_opt.h" 31 #include "buddy_opt.h"
37 #include "group_info.h" 32 #include "group_info.h"
38 #include "group_free.h" 33 #include "group_free.h"
86 purple_notify_info(gc, NULL, msg_utf8, NULL); 81 purple_notify_info(gc, NULL, msg_utf8, NULL);
87 g_free(msg_utf8); 82 g_free(msg_utf8);
88 } 83 }
89 } 84 }
90 85
91 void qq_proc_cmd_server(PurpleConnection *gc, 86 void qq_proc_cmd_server(PurpleConnection *gc, guint16 cmd, guint16 seq, guint8 *rcved, gint rcved_len)
92 guint16 cmd, guint16 seq, guint8 *rcved, gint rcved_len)
93 { 87 {
94 qq_data *qd; 88 qq_data *qd;
95 89
96 guint8 *data; 90 guint8 *data;
97 gint data_len; 91 gint data_len;
100 qd = (qq_data *) gc->proto_data; 94 qd = (qq_data *) gc->proto_data;
101 95
102 data = g_newa(guint8, rcved_len); 96 data = g_newa(guint8, rcved_len);
103 data_len = qq_decrypt(data, rcved, rcved_len, qd->session_key); 97 data_len = qq_decrypt(data, rcved, rcved_len, qd->session_key);
104 if (data_len < 0) { 98 if (data_len < 0) {
105 purple_debug(PURPLE_DEBUG_WARNING, "QQ", 99 purple_debug_warning("QQ",
106 "Can not decrypt server cmd by session key, [%05d], 0x%04X %s, len %d\n", 100 "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); 101 seq, cmd, qq_get_cmd_desc(cmd), rcved_len);
108 qq_show_packet("Can not decrypted", rcved, rcved_len); 102 qq_show_packet("Can not decrypted", rcved, rcved_len);
109 return; 103 return;
110 } 104 }
111 105
112 if (data_len <= 0) { 106 if (data_len <= 0) {
113 purple_debug(PURPLE_DEBUG_WARNING, "QQ", 107 purple_debug_warning("QQ",
114 "Server cmd decrypted is empty, [%05d], 0x%04X %s, len %d\n", 108 "Server cmd decrypted is empty, [%05d], 0x%04X %s, len %d\n",
115 seq, cmd, qq_get_cmd_desc(cmd), rcved_len); 109 seq, cmd, qq_get_cmd_desc(cmd), rcved_len);
116 return; 110 return;
117 } 111 }
118 112
119 /* now process the packet */ 113 /* now process the packet */
120 switch (cmd) { 114 switch (cmd) {
121 case QQ_CMD_RECV_IM: 115 case QQ_CMD_RECV_IM:
122 qq_process_recv_im(data, data_len, seq, gc); 116 qq_process_recv_im(data, data_len, seq, gc);
123 break; 117 break;
124 case QQ_CMD_RECV_MSG_SYS: 118 case QQ_CMD_RECV_MSG_SYS:
125 qq_process_msg_sys(data, data_len, seq, gc); 119 qq_process_msg_sys(data, data_len, seq, gc);
126 break; 120 break;
127 case QQ_CMD_RECV_MSG_BUDDY_CHANGE_STATUS: 121 case QQ_CMD_BUDDY_CHANGE_STATUS:
128 qq_process_buddy_change_status(data, data_len, gc); 122 qq_process_buddy_change_status(data, data_len, gc);
129 break; 123 break;
130 default: 124 default:
131 process_cmd_unknow(gc, "Unknow SERVER CMD", data, data_len, cmd, seq); 125 process_cmd_unknow(gc, "Unknow SERVER CMD", data, data_len, cmd, seq);
132 break; 126 break;
133 } 127 }
134 } 128 }
135 129
136 static void process_cmd_login(PurpleConnection *gc, guint8 *data, gint data_len) 130 static void process_room_cmd_notify(PurpleConnection *gc,
137 { 131 guint8 room_cmd, guint8 room_id, guint8 reply, guint8 *data, gint data_len)
138 qq_data *qd;
139 guint ret_8;
140
141 g_return_if_fail (gc != NULL && gc->proto_data != NULL);
142
143 qd = (qq_data *) gc->proto_data;
144
145 ret_8 = qq_process_login_reply(data, data_len, gc);
146 if (ret_8 == QQ_LOGIN_REPLY_OK) {
147 purple_debug(PURPLE_DEBUG_INFO, "QQ", "Login repliess OK; everything is fine\n");
148
149 purple_connection_set_state(gc, PURPLE_CONNECTED);
150 qd->logged_in = TRUE; /* must be defined after sev_finish_login */
151
152 /* now initiate QQ Qun, do it first as it may take longer to finish */
153 qq_group_init(gc);
154
155 /* Now goes on updating my icon/nickname, not showing info_window */
156 qd->modifying_face = FALSE;
157
158 qq_send_packet_get_info(gc, qd->uid, FALSE);
159 /* grab my level */
160 qq_send_packet_get_level(gc, qd->uid);
161
162 qq_send_packet_change_status(gc);
163
164 /* refresh buddies */
165 qq_send_packet_get_buddies_list(gc, 0);
166
167 /* refresh groups */
168 qq_send_packet_get_buddies_and_rooms(gc, 0);
169
170 return;
171 }
172
173 if (ret_8 == QQ_LOGIN_REPLY_REDIRECT) {
174 qd->is_redirect = TRUE;
175 /*
176 purple_debug(PURPLE_DEBUG_WARNING, "QQ",
177 "Redirected to new server: %s:%d\n", qd->real_hostname, qd->real_port);
178 */
179 return;
180 }
181
182 if (ret_8 == QQ_LOGIN_REPLY_ERR_PWD) {
183 if (!purple_account_get_remember_password(gc->account)) {
184 purple_account_set_password(gc->account, NULL);
185 }
186 purple_connection_error_reason(gc,
187 PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, _("Incorrect password."));
188 return;
189 }
190
191 if (ret_8 == QQ_LOGIN_REPLY_ERR_MISC) {
192 if (purple_debug_is_enabled())
193 purple_connection_error_reason(gc,
194 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to login. Check debug log."));
195 else
196 purple_connection_error_reason(gc,
197 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to login"));
198 return;
199 }
200 }
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 { 132 {
205 gchar *msg, *msg_utf8; 133 gchar *msg, *msg_utf8;
206 g_return_if_fail(data != NULL && data_len > 0); 134 g_return_if_fail(data != NULL && data_len > 0);
207 135
208 msg = g_strndup((gchar *) data, data_len); /* it will append 0x00 */ 136 msg = g_strndup((gchar *) data, data_len); /* it will append 0x00 */
209 msg_utf8 = qq_to_utf8(msg, QQ_CHARSET_DEFAULT); 137 msg_utf8 = qq_to_utf8(msg, QQ_CHARSET_DEFAULT);
210 g_free(msg); 138 g_free(msg);
211 139
212 msg = g_strdup_printf(_( 140 msg = g_strdup_printf(_("Command %s(0x%02X) id %d, reply [0x%02X]:\n%s"),
213 "Reply %s(0x%02X )\n" 141 qq_get_room_cmd_desc(room_cmd), room_cmd, room_id, reply, msg_utf8);
214 "Sent %s(0x%02X )\n" 142
215 "Room id %d, reply [0x%02X]: \n" 143 purple_notify_error(gc, NULL, _("Invalid QQ Qun reply"), msg);
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); 144 g_free(msg);
223 g_free(msg_utf8); 145 g_free(msg_utf8);
224 } 146 }
225 147
226 void qq_proc_room_cmd_reply(PurpleConnection *gc, 148 void qq_room_update(PurpleConnection *gc, guint8 room_cmd, guint32 room_id)
227 guint16 seq, guint8 room_cmd, guint32 room_id, guint8 *rcved, gint rcved_len) 149 {
150 qq_data *qd;
151 qq_group *group;
152 gint ret;
153
154 g_return_if_fail (gc != NULL && gc->proto_data != NULL);
155 qd = (qq_data *) gc->proto_data;
156
157 group = qq_room_search_id(gc, room_id);
158 if (group == NULL && room_id <= 0) {
159 purple_debug_info("QQ", "No room, nothing update\n");
160 return;
161 }
162 if (group == NULL ) {
163 purple_debug_warning("QQ", "Failed search room id [%d]\n", room_id);
164 return;
165 }
166
167 switch (room_cmd) {
168 case 0:
169 qq_send_room_cmd_mess(gc, QQ_ROOM_CMD_GET_INFO, group->id, NULL, 0,
170 QQ_CMD_CLASS_UPDATE_ROOM, 0);
171 break;
172 case QQ_ROOM_CMD_GET_INFO:
173 ret = qq_request_room_get_buddies(gc, group, QQ_CMD_CLASS_UPDATE_ROOM);
174 if (ret <= 0) {
175 qq_send_room_cmd_mess(gc, QQ_ROOM_CMD_GET_ONLINES, group->id, NULL, 0,
176 QQ_CMD_CLASS_UPDATE_ROOM, 0);
177 }
178 break;
179 case QQ_ROOM_CMD_GET_BUDDIES:
180 qq_send_room_cmd_mess(gc, QQ_ROOM_CMD_GET_ONLINES, group->id, NULL, 0,
181 QQ_CMD_CLASS_UPDATE_ROOM, 0);
182 break;
183 case QQ_ROOM_CMD_GET_ONLINES:
184 /* last command */
185 default:
186 break;
187 }
188 }
189
190 static void update_all_rooms(PurpleConnection *gc, guint8 room_cmd, guint32 room_id)
191 {
192 qq_data *qd;
193 gboolean is_new_turn = FALSE;
194 qq_group *next_group;
195
196 g_return_if_fail (gc != NULL && gc->proto_data != NULL);
197 qd = (qq_data *) gc->proto_data;
198
199 next_group = qq_room_get_next(gc, room_id);
200 if (next_group == NULL && room_id <= 0) {
201 purple_debug_info("QQ", "No room, nothing update\n");
202 qd->is_finish_update = TRUE;
203 return;
204 }
205 if (next_group == NULL ) {
206 is_new_turn = TRUE;
207 next_group = qq_room_get_next(gc, 0);
208 g_return_if_fail(next_group != NULL);
209 }
210
211 switch (room_cmd) {
212 case 0:
213 qq_send_room_cmd_mess(gc, QQ_ROOM_CMD_GET_INFO, next_group->id, NULL, 0,
214 QQ_CMD_CLASS_UPDATE_ALL, 0);
215 break;
216 case QQ_ROOM_CMD_GET_INFO:
217 if (!is_new_turn) {
218 qq_send_room_cmd_mess(gc, QQ_ROOM_CMD_GET_INFO, next_group->id, NULL, 0,
219 QQ_CMD_CLASS_UPDATE_ALL, 0);
220 } else {
221 qq_request_room_get_buddies(gc, next_group, QQ_CMD_CLASS_UPDATE_ALL);
222 }
223 break;
224 case QQ_ROOM_CMD_GET_BUDDIES:
225 /* last command */
226 if (!is_new_turn) {
227 qq_request_room_get_buddies(gc, next_group, QQ_CMD_CLASS_UPDATE_ALL);
228 } else {
229 qd->is_finish_update = TRUE;
230 }
231 break;
232 default:
233 break;
234 }
235 }
236
237 void qq_update_all(PurpleConnection *gc, guint16 cmd)
238 {
239 qq_data *qd;
240
241 g_return_if_fail (gc != NULL && gc->proto_data != NULL);
242 qd = (qq_data *) gc->proto_data;
243
244 switch (cmd) {
245 case 0:
246 qq_request_buddy_info(gc, qd->uid, QQ_CMD_CLASS_UPDATE_ALL, QQ_BUDDY_INFO_UPDATE_ONLY);
247 break;
248 case QQ_CMD_GET_USER_INFO:
249 qq_request_change_status(gc, QQ_CMD_CLASS_UPDATE_ALL);
250 break;
251 case QQ_CMD_CHANGE_STATUS:
252 qq_request_get_buddies_list(gc, 0, QQ_CMD_CLASS_UPDATE_ALL);
253 break;
254 case QQ_CMD_GET_BUDDIES_LIST:
255 qq_request_get_buddies_and_rooms(gc, 0, QQ_CMD_CLASS_UPDATE_ALL);
256 break;
257 case QQ_CMD_GET_BUDDIES_AND_ROOMS:
258 qq_request_get_buddies_levels(gc, QQ_CMD_CLASS_UPDATE_ALL);
259 break;
260 case QQ_CMD_GET_LEVEL:
261 qq_request_get_buddies_online(gc, 0, QQ_CMD_CLASS_UPDATE_ALL);
262 break;
263 case QQ_CMD_GET_BUDDIES_ONLINE:
264 /* last command */
265 update_all_rooms(gc, 0, 0);
266 break;
267 default:
268 break;
269 }
270 }
271
272 static void update_all_rooms_online(PurpleConnection *gc, guint8 room_cmd, guint32 room_id)
273 {
274 qq_data *qd;
275 qq_group *next_group;
276
277 g_return_if_fail (gc != NULL && gc->proto_data != NULL);
278 qd = (qq_data *) gc->proto_data;
279
280 next_group = qq_room_get_next_conv(gc, room_id);
281 if (next_group == NULL && room_id <= 0) {
282 purple_debug_info("QQ", "No room, no update online buddies\n");
283 return;
284 }
285 if (next_group == NULL ) {
286 purple_debug_info("QQ", "finished update online buddies\n");
287 return;
288 }
289
290 switch (room_cmd) {
291 case 0:
292 qq_send_room_cmd_mess(gc, QQ_ROOM_CMD_GET_ONLINES, next_group->id, NULL, 0,
293 QQ_CMD_CLASS_UPDATE_ALL, 0);
294 break;
295 case QQ_ROOM_CMD_GET_ONLINES:
296 qq_send_room_cmd_mess(gc, QQ_ROOM_CMD_GET_ONLINES, next_group->id, NULL, 0,
297 QQ_CMD_CLASS_UPDATE_ALL, 0);
298 break;
299 default:
300 break;
301 }
302 }
303
304 void qq_update_online(PurpleConnection *gc, guint16 cmd)
305 {
306 switch (cmd) {
307 case 0:
308 qq_request_get_buddies_online(gc, 0, QQ_CMD_CLASS_UPDATE_ONLINE);
309 break;
310 case QQ_CMD_GET_BUDDIES_ONLINE:
311 /* last command */
312 update_all_rooms_online(gc, 0, 0);
313 break;
314 default:
315 break;
316 }
317 }
318
319 void qq_proc_room_cmd_reply(PurpleConnection *gc, guint16 seq,
320 guint8 room_cmd, guint32 room_id, guint8 *rcved, gint rcved_len,
321 gint update_class, guint32 ship32)
228 { 322 {
229 qq_data *qd; 323 qq_data *qd;
230 guint8 *data; 324 guint8 *data;
231 gint data_len; 325 gint data_len;
232 qq_group *group; 326 qq_group *group;
237 qd = (qq_data *) gc->proto_data; 331 qd = (qq_data *) gc->proto_data;
238 332
239 data = g_newa(guint8, rcved_len); 333 data = g_newa(guint8, rcved_len);
240 data_len = qq_decrypt(data, rcved, rcved_len, qd->session_key); 334 data_len = qq_decrypt(data, rcved, rcved_len, qd->session_key);
241 if (data_len < 0) { 335 if (data_len < 0) {
242 purple_debug(PURPLE_DEBUG_WARNING, "QQ", 336 purple_debug_warning("QQ",
243 "Can not decrypt room cmd by session key, [%05d], 0x%02X %s for %d, len %d\n", 337 "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); 338 seq, room_cmd, qq_get_room_cmd_desc(room_cmd), room_id, rcved_len);
245 qq_show_packet("Can not decrypted", rcved, rcved_len); 339 qq_show_packet("Can not decrypted", rcved, rcved_len);
246 return; 340 return;
247 } 341 }
248 342
249 if (room_id <= 0) { 343 if (room_id <= 0) {
250 purple_debug(PURPLE_DEBUG_WARNING, "QQ", 344 purple_debug_warning("QQ",
251 "Invaild room id, [%05d], 0x%02X %s for %d, len %d\n", 345 "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); 346 seq, room_cmd, qq_get_room_cmd_desc(room_cmd), room_id, rcved_len);
253 return; 347 return;
254 } 348 }
255 349
256 if (data_len <= 2) { 350 if (data_len <= 2) {
257 purple_debug(PURPLE_DEBUG_WARNING, "QQ", 351 purple_debug_warning("QQ",
258 "Invaild len of room cmd decrypted, [%05d], 0x%02X %s for %d, len %d\n", 352 "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); 353 seq, room_cmd, qq_get_room_cmd_desc(room_cmd), room_id, rcved_len);
260 return; 354 return;
261 } 355 }
262 356
263 group = qq_room_search_id(gc, room_id); 357 group = qq_room_search_id(gc, room_id);
264 if (group == NULL) { 358 if (group == NULL) {
265 purple_debug(PURPLE_DEBUG_WARNING, "QQ", 359 purple_debug_warning("QQ",
266 "Missing room id in [%05d], 0x%02X %s for %d, len %d\n", 360 "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); 361 seq, room_cmd, qq_get_room_cmd_desc(room_cmd), room_id, rcved_len);
268 } 362 }
269 363
270 bytes = 0; 364 bytes = 0;
271 bytes += qq_get8(&reply_cmd, data + bytes); 365 bytes += qq_get8(&reply_cmd, data + bytes);
272 bytes += qq_get8(&reply, data + bytes); 366 bytes += qq_get8(&reply, data + bytes);
273 367
274 if (reply_cmd != room_cmd) { 368 if (reply_cmd != room_cmd) {
275 purple_debug(PURPLE_DEBUG_WARNING, "QQ", 369 purple_debug_warning("QQ",
276 "Missing room cmd in reply 0x%02X %s, [%05d], 0x%02X %s for %d, len %d\n", 370 "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), 371 reply_cmd, qq_get_room_cmd_desc(reply_cmd),
278 seq, room_cmd, qq_get_room_cmd_desc(room_cmd), room_id, rcved_len); 372 seq, room_cmd, qq_get_room_cmd_desc(room_cmd), room_id, rcved_len);
279 } 373 }
280 374
281 /* now process the packet */ 375 /* now process the packet */
282 if (reply != QQ_ROOM_CMD_REPLY_OK) { 376 if (reply != QQ_ROOM_CMD_REPLY_OK) {
283 if (group != NULL) { 377 if (group != NULL) {
284 qq_set_pending_id(&qd->joining_groups, group->ext_id, FALSE); 378 qq_set_pending_id(&qd->joining_groups, group->ext_id, FALSE);
285 } 379 }
286 380
287 switch (reply) { /* this should be all errors */ 381 switch (reply) { /* this should be all errors */
288 case QQ_ROOM_CMD_REPLY_NOT_MEMBER: 382 case QQ_ROOM_CMD_REPLY_NOT_MEMBER:
289 if (group != NULL) { 383 if (group != NULL) {
290 purple_debug(PURPLE_DEBUG_WARNING, 384 purple_debug_warning("QQ",
291 "QQ", 385 _("You are not a member of QQ Qun \"%s\"\n"), group->title_utf8);
292 _("You are not a member of group \"%s\"\n"), group->group_name_utf8); 386 group->my_role = QQ_ROOM_ROLE_NO;
293 group->my_status = QQ_GROUP_MEMBER_STATUS_NOT_MEMBER;
294 qq_group_refresh(gc, group); 387 qq_group_refresh(gc, group);
295 } 388 }
296 break; 389 break;
297 case QQ_ROOM_CMD_REPLY_SEARCH_ERROR: 390 case QQ_ROOM_CMD_REPLY_SEARCH_ERROR:
298 if (qd->roomlist != NULL) { 391 if (qd->roomlist != NULL) {
299 if (purple_roomlist_get_in_progress(qd->roomlist)) 392 if (purple_roomlist_get_in_progress(qd->roomlist))
300 purple_roomlist_set_in_progress(qd->roomlist, FALSE); 393 purple_roomlist_set_in_progress(qd->roomlist, FALSE);
301 } 394 }
302 default: 395 default:
303 process_room_cmd_notify(gc, room_cmd, room_id, reply_cmd, reply, data + bytes, data_len - bytes); 396 process_room_cmd_notify(gc, reply_cmd, room_id, reply, data + bytes, data_len - bytes);
304 } 397 }
305 return; 398 return;
306 } 399 }
307 400
308 /* seems ok so far, so we process the reply according to sub_cmd */ 401 /* seems ok so far, so we process the reply according to sub_cmd */
309 switch (reply_cmd) { 402 switch (reply_cmd) {
310 case QQ_ROOM_CMD_GET_INFO: 403 case QQ_ROOM_CMD_GET_INFO:
311 qq_process_room_cmd_get_info(data + bytes, data_len - bytes, gc); 404 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; 405 break;
317 case QQ_ROOM_CMD_CREATE: 406 case QQ_ROOM_CMD_CREATE:
318 qq_group_process_create_group_reply(data + bytes, data_len - bytes, gc); 407 qq_group_process_create_group_reply(data + bytes, data_len - bytes, gc);
319 break; 408 break;
320 case QQ_ROOM_CMD_CHANGE_INFO: 409 case QQ_ROOM_CMD_CHANGE_INFO:
344 case QQ_ROOM_CMD_GET_ONLINES: 433 case QQ_ROOM_CMD_GET_ONLINES:
345 qq_process_room_cmd_get_onlines(data + bytes, data_len - bytes, gc); 434 qq_process_room_cmd_get_onlines(data + bytes, data_len - bytes, gc);
346 if (group != NULL) 435 if (group != NULL)
347 qq_group_conv_refresh_online_member(gc, group); 436 qq_group_conv_refresh_online_member(gc, group);
348 break; 437 break;
349 case QQ_ROOM_CMD_GET_MEMBER_INFO: 438 case QQ_ROOM_CMD_GET_BUDDIES:
350 qq_process_room_cmd_get_members(data + bytes, data_len - bytes, gc); 439 qq_process_room_cmd_get_buddies(data + bytes, data_len - bytes, gc);
351 if (group != NULL) 440 if (group != NULL)
352 qq_group_conv_refresh_online_member(gc, group); 441 qq_group_conv_refresh_online_member(gc, group);
353 break; 442 break;
354 default: 443 default:
355 purple_debug(PURPLE_DEBUG_WARNING, "QQ", 444 purple_debug_warning("QQ", "Unknow room cmd 0x%02X %s\n",
356 "Unknow room cmd 0x%02X %s\n",
357 reply_cmd, qq_get_room_cmd_desc(reply_cmd)); 445 reply_cmd, qq_get_room_cmd_desc(reply_cmd));
358 } 446 }
359 } 447
360 448 purple_debug_info("QQ", "Update class %d\n", update_class);
361 void qq_proc_cmd_reply(PurpleConnection *gc, 449 if (update_class == QQ_CMD_CLASS_UPDATE_ALL) {
362 guint16 cmd, guint16 seq, guint8 *rcved, gint rcved_len) 450 update_all_rooms(gc, room_cmd, room_id);
451 return;
452 }
453 if (update_class == QQ_CMD_CLASS_UPDATE_ONLINE) {
454 update_all_rooms_online(gc, room_cmd, room_id);
455 return;
456 }
457 if (update_class == QQ_CMD_CLASS_UPDATE_ROOM) {
458 qq_room_update(gc, room_cmd, room_id);
459 }
460 }
461
462 void qq_proc_cmd_login(PurpleConnection *gc, guint8 *rcved, gint rcved_len)
463 {
464 qq_data *qd;
465 guint8 *data;
466 gint data_len;
467 guint ret_8;
468
469 g_return_if_fail (gc != NULL && gc->proto_data != NULL);
470 qd = (qq_data *) gc->proto_data;
471
472 data = g_newa(guint8, rcved_len);
473 /* May use password_twice_md5 in the past version like QQ2005*/
474 data_len = qq_decrypt(data, rcved, rcved_len, qd->inikey);
475 if (data_len >= 0) {
476 purple_debug_warning("QQ",
477 "Decrypt login reply packet with inikey, %d bytes\n", data_len);
478 } else {
479 data_len = qq_decrypt(data, rcved, rcved_len, qd->password_twice_md5);
480 if (data_len >= 0) {
481 purple_debug_warning("QQ",
482 "Decrypt login reply packet with password_twice_md5, %d bytes\n", data_len);
483 } else {
484 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
485 _("Can not decrypt login reply"));
486 return;
487 }
488 }
489
490 ret_8 = qq_process_login_reply(gc, data, data_len);
491 if (ret_8 != QQ_LOGIN_REPLY_OK) {
492 return;
493 }
494
495 purple_debug_info("QQ", "Login repliess OK; everything is fine\n");
496
497 purple_connection_set_state(gc, PURPLE_CONNECTED);
498 qd->is_login = TRUE; /* must be defined after sev_finish_login */
499
500 /* now initiate QQ Qun, do it first as it may take longer to finish */
501 qq_group_init(gc);
502
503 /* Now goes on updating my icon/nickname, not showing info_window */
504 qd->modifying_face = FALSE;
505
506 qq_update_all(gc, 0);
507 return;
508 }
509
510 void qq_proc_cmd_reply(PurpleConnection *gc, guint16 cmd, guint16 seq,
511 guint8 *rcved, gint rcved_len, gint update_class, guint32 ship32)
363 { 512 {
364 qq_data *qd; 513 qq_data *qd;
365 514
366 guint8 *data; 515 guint8 *data;
367 gint data_len; 516 gint data_len;
368 517
369 gboolean ret_bool = FALSE; 518 gboolean ret_bool = FALSE;
370 guint8 ret_8 = 0; 519 guint8 ret_8 = 0;
371 guint16 ret_16 = 0; 520 guint16 ret_16 = 0;
372 guint32 ret_32 = 0; 521 guint32 ret_32 = 0;
373 gchar *error_msg = NULL; 522 gboolean is_unknow = FALSE;
374 523
375 g_return_if_fail(rcved_len > 0); 524 g_return_if_fail(rcved_len > 0);
376 525
377 g_return_if_fail (gc != NULL && gc->proto_data != NULL); 526 g_return_if_fail (gc != NULL && gc->proto_data != NULL);
378 qd = (qq_data *) gc->proto_data; 527 qd = (qq_data *) gc->proto_data;
379 528
380 data = g_newa(guint8, rcved_len); 529 data = g_newa(guint8, rcved_len);
381 if (cmd == QQ_CMD_TOKEN) { 530 data_len = qq_decrypt(data, rcved, rcved_len, qd->session_key);
382 g_memmove(data, rcved, rcved_len); 531 if (data_len < 0) {
383 data_len = rcved_len; 532 purple_debug_warning("QQ",
384 } else if (cmd == QQ_CMD_LOGIN) { 533 "Reply can not be decrypted by session key, [%05d], 0x%04X %s, len %d\n",
385 /* May use password_twice_md5 in the past version like QQ2005*/ 534 seq, cmd, qq_get_cmd_desc(cmd), rcved_len);
386 data_len = qq_decrypt(data, rcved, rcved_len, qd->inikey); 535 qq_show_packet("Can not decrypted", rcved, rcved_len);
387 if (data_len >= 0) { 536 return;
388 purple_debug(PURPLE_DEBUG_WARNING, "QQ", 537 }
389 "Decrypt login reply packet with inikey, %d bytes\n", data_len); 538
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) { 539 if (data_len <= 0) {
413 purple_debug(PURPLE_DEBUG_WARNING, "QQ", 540 purple_debug_warning("QQ",
414 "Reply decrypted is empty, [%05d], 0x%04X %s, len %d\n", 541 "Reply decrypted is empty, [%05d], 0x%04X %s, len %d\n",
415 seq, cmd, qq_get_cmd_desc(cmd), rcved_len); 542 seq, cmd, qq_get_cmd_desc(cmd), rcved_len);
416 return; 543 return;
417 } 544 }
418 545
419 switch (cmd) { 546 switch (cmd) {
420 case QQ_CMD_TOKEN:
421 ret_8 = qq_process_token_reply(gc, error_msg, data, data_len);
422 if (ret_8 != QQ_TOKEN_REPLY_OK) {
423 if (error_msg == NULL) {
424 error_msg = g_strdup_printf( _("Invalid token reply code, 0x%02X"), ret_8);
425 }
426 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, error_msg);
427 g_free(error_msg);
428 return;
429 }
430
431 qq_send_packet_login(gc);
432 break;
433 case QQ_CMD_LOGIN:
434 process_cmd_login(gc, data, data_len);
435 break;
436 case QQ_CMD_UPDATE_INFO: 547 case QQ_CMD_UPDATE_INFO:
437 qq_process_modify_info_reply(data, data_len, gc); 548 qq_process_modify_info_reply(data, data_len, gc);
438 break; 549 break;
439 case QQ_CMD_ADD_BUDDY_WO_AUTH: 550 case QQ_CMD_ADD_BUDDY_WO_AUTH:
440 qq_process_add_buddy_reply(data, data_len, seq, gc); 551 qq_process_add_buddy_reply(data, data_len, seq, gc);
449 qq_process_add_buddy_auth_reply(data, data_len, gc); 560 qq_process_add_buddy_auth_reply(data, data_len, gc);
450 break; 561 break;
451 case QQ_CMD_GET_USER_INFO: 562 case QQ_CMD_GET_USER_INFO:
452 qq_process_get_info_reply(data, data_len, gc); 563 qq_process_get_info_reply(data, data_len, gc);
453 break; 564 break;
454 case QQ_CMD_CHANGE_ONLINE_STATUS: 565 case QQ_CMD_CHANGE_STATUS:
455 qq_process_change_status_reply(data, data_len, gc); 566 qq_process_change_status_reply(data, data_len, gc);
456 break; 567 break;
457 case QQ_CMD_SEND_IM: 568 case QQ_CMD_SEND_IM:
458 qq_process_send_im_reply(data, data_len, gc); 569 qq_process_send_im_reply(data, data_len, gc);
459 break; 570 break;
461 qq_process_keep_alive(data, data_len, gc); 572 qq_process_keep_alive(data, data_len, gc);
462 break; 573 break;
463 case QQ_CMD_GET_BUDDIES_ONLINE: 574 case QQ_CMD_GET_BUDDIES_ONLINE:
464 ret_8 = qq_process_get_buddies_online_reply(data, data_len, gc); 575 ret_8 = qq_process_get_buddies_online_reply(data, data_len, gc);
465 if (ret_8 > 0 && ret_8 < 0xff) { 576 if (ret_8 > 0 && ret_8 < 0xff) {
466 purple_debug(PURPLE_DEBUG_INFO, "QQ", "Requesting for more online buddies\n"); 577 purple_debug_info("QQ", "Requesting for more online buddies\n");
467 qq_send_packet_get_buddies_online(gc, ret_8); 578 qq_request_get_buddies_online(gc, ret_8, update_class);
468 } else { 579 return;
469 purple_debug(PURPLE_DEBUG_INFO, "QQ", "All online buddies received\n"); 580 }
470 /* Fixme: this should not be called once*/ 581 purple_debug_info("QQ", "All online buddies received\n");
471 qq_send_packet_get_buddies_levels(gc); 582 qq_refresh_all_buddy_status(gc);
472
473 qq_refresh_all_buddy_status(gc);
474 }
475 break; 583 break;
476 case QQ_CMD_GET_LEVEL: 584 case QQ_CMD_GET_LEVEL:
477 qq_process_get_level_reply(data, data_len, gc); 585 qq_process_get_level_reply(data, data_len, gc);
478 break; 586 break;
479 case QQ_CMD_GET_BUDDIES_LIST: 587 case QQ_CMD_GET_BUDDIES_LIST:
480 ret_16 = qq_process_get_buddies_list_reply(data, data_len, gc); 588 ret_16 = qq_process_get_buddies_list_reply(data, data_len, gc);
481 if (ret_16 > 0 && ret_16 < 0xffff) { 589 if (ret_16 > 0 && ret_16 < 0xffff) {
482 purple_debug(PURPLE_DEBUG_INFO, "QQ", "Requesting for more buddies\n"); 590 purple_debug_info("QQ", "Requesting for more buddies\n");
483 qq_send_packet_get_buddies_list(gc, ret_16); 591 qq_request_get_buddies_list(gc, ret_16, update_class);
484 } else { 592 return;
485 purple_debug(PURPLE_DEBUG_INFO, "QQ", "All buddies received. Requesting buddies' levels\n"); 593 }
486 qq_send_packet_get_buddies_online(gc, 0); 594 purple_debug_info("QQ", "All buddies received. Requesting buddies' levels\n");
487 }
488 break; 595 break;
489 case QQ_CMD_GET_BUDDIES_AND_ROOMS: 596 case QQ_CMD_GET_BUDDIES_AND_ROOMS:
490 ret_32 = qq_process_get_buddies_and_rooms(data, data_len, gc); 597 ret_32 = qq_process_get_buddies_and_rooms(data, data_len, gc);
491 if (ret_32 > 0 && ret_32 < 0xffffffff) { 598 if (ret_32 > 0 && ret_32 < 0xffffffff) {
492 purple_debug(PURPLE_DEBUG_INFO, "QQ", "Requesting for more buddies and groups\n"); 599 purple_debug_info("QQ", "Requesting for more buddies and groups\n");
493 qq_send_packet_get_buddies_and_rooms(gc, ret_32); 600 qq_request_get_buddies_and_rooms(gc, ret_32, update_class);
494 } else { 601 return;
495 purple_debug(PURPLE_DEBUG_INFO, "QQ", "All buddies and groups received\n"); 602 }
496 } 603 purple_debug_info("QQ", "All buddies and groups received\n");
497 break; 604 break;
498 default: 605 default:
499 process_cmd_unknow(gc, "Unknow reply CMD", data, data_len, cmd, seq); 606 process_cmd_unknow(gc, "Unknow reply CMD", data, data_len, cmd, seq);
500 break; 607 is_unknow = TRUE;
501 } 608 break;
502 } 609 }
503 610 if (is_unknow)
611 return;
612
613 if (update_class == QQ_CMD_CLASS_NONE)
614 return;
615
616 purple_debug_info("QQ", "Update class %d\n", update_class);
617 if (update_class == QQ_CMD_CLASS_UPDATE_ALL) {
618 qq_update_all(gc, cmd);
619 return;
620 }
621 if (update_class == QQ_CMD_CLASS_UPDATE_ONLINE) {
622 qq_update_online(gc, cmd);
623 return;
624 }
625 }
626