Mercurial > pidgin
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 |