| 121 bytes += qq_put32(raw_data + bytes, position); |
118 bytes += qq_put32(raw_data + bytes, position); |
| 122 |
119 |
| 123 qq_send_cmd(qd, QQ_CMD_GET_ALL_LIST_WITH_GROUP, raw_data, bytes); |
120 qq_send_cmd(qd, QQ_CMD_GET_ALL_LIST_WITH_GROUP, raw_data, bytes); |
| 124 } |
121 } |
| 125 |
122 |
| 126 static void _qq_buddies_online_reply_dump_unclear(qq_friends_online_entry *fe) |
123 /* parse the data into qq_buddy_status */ |
| 127 { |
124 static gint get_buddy_status(qq_buddy_status *bs, guint8 *data) |
| 128 GString *dump; |
125 { |
| 129 |
126 gint bytes = 0; |
| 130 g_return_if_fail(fe != NULL); |
127 |
| 131 |
128 g_return_val_if_fail(data != NULL && bs != NULL, -1); |
| 132 qq_buddy_status_dump_unclear(fe->s); |
129 |
| 133 |
130 /* 000-003: uid */ |
| 134 dump = g_string_new(""); |
131 bytes += qq_get32(&bs->uid, data + bytes); |
| 135 g_string_append_printf(dump, "unclear fields for [%d]:\n", fe->s->uid); |
132 /* 004-004: 0x01 */ |
| 136 g_string_append_printf(dump, "031-032: %04x (unknown)\n", fe->unknown1); |
133 bytes += qq_get8(&bs->unknown1, data + bytes); |
| 137 g_string_append_printf(dump, "033: %02x (flag1)\n", fe->flag1); |
134 /* this is no longer the IP, it seems QQ (as of 2006) no longer sends |
| 138 g_string_append_printf(dump, "034: %02x (comm_flag)\n", fe->comm_flag); |
135 * the buddy's IP in this packet. all 0s */ |
| 139 g_string_append_printf(dump, "035-036: %04x (unknown)\n", fe->unknown2); |
136 /* 005-008: ip */ |
| 140 |
137 bytes += qq_getIP(&bs->ip, data + bytes); |
| 141 purple_debug(PURPLE_DEBUG_INFO, "QQ", "Online buddy entry, %s", dump->str); |
138 /* port info is no longer here either */ |
| 142 g_string_free(dump, TRUE); |
139 /* 009-010: port */ |
| 143 } |
140 bytes += qq_get16(&bs->port, data + bytes); |
| |
141 /* 011-011: 0x00 */ |
| |
142 bytes += qq_get8(&bs->unknown2, data + bytes); |
| |
143 /* 012-012: status */ |
| |
144 bytes += qq_get8(&bs->status, data + bytes); |
| |
145 /* 013-014: client_version */ |
| |
146 bytes += qq_get16(&bs->unknown3, data + bytes); |
| |
147 /* 015-030: unknown key */ |
| |
148 bytes += qq_getdata(&(bs->unknown_key[0]), QQ_KEY_LENGTH, data + bytes); |
| |
149 |
| |
150 purple_debug(PURPLE_DEBUG_INFO, "QQ_STATUS", |
| |
151 "uid: %d, U1: %d, ip: %s:%d, U2:%d, status:%d, U3:%04X\n", |
| |
152 bs->uid, bs->unknown1, inet_ntoa(bs->ip), bs->port, |
| |
153 bs->unknown2, bs->status, bs->unknown3); |
| |
154 |
| |
155 return bytes; |
| |
156 } |
| |
157 |
| |
158 #define QQ_ONLINE_BUDDY_ENTRY_LEN 38 |
| 144 |
159 |
| 145 /* process the reply packet for get_buddies_online packet */ |
160 /* process the reply packet for get_buddies_online packet */ |
| 146 void qq_process_get_buddies_online_reply(guint8 *buf, gint buf_len, PurpleConnection *gc) |
161 guint8 qq_process_get_buddies_online_reply(guint8 *buf, gint buf_len, PurpleConnection *gc) |
| 147 { |
162 { |
| 148 qq_data *qd; |
163 qq_data *qd; |
| 149 gint len, bytes, bytes_buddy; |
164 gint len, bytes, bytes_buddy; |
| 150 gint count; |
165 gint count; |
| 151 guint8 *data, position; |
166 guint8 *data, position; |
| 152 PurpleBuddy *b; |
167 PurpleBuddy *b; |
| 153 qq_buddy *q_bud; |
168 qq_buddy *q_bud; |
| 154 qq_friends_online_entry *fe; |
169 qq_buddy_online bo; |
| 155 |
170 |
| 156 g_return_if_fail(buf != NULL && buf_len != 0); |
171 g_return_val_if_fail(buf != NULL && buf_len != 0, -1); |
| 157 |
172 |
| 158 qd = (qq_data *) gc->proto_data; |
173 qd = (qq_data *) gc->proto_data; |
| 159 len = buf_len; |
174 len = buf_len; |
| 160 data = g_newa(guint8, len); |
175 data = g_newa(guint8, len); |
| 161 |
176 |
| 162 purple_debug(PURPLE_DEBUG_INFO, "QQ", "processing get_buddies_online_reply\n"); |
177 purple_debug(PURPLE_DEBUG_INFO, "QQ", "processing get_buddies_online_reply\n"); |
| 163 |
178 |
| 164 if (!qq_decrypt(buf, buf_len, qd->session_key, data, &len)) { |
179 if (!qq_decrypt(buf, buf_len, qd->session_key, data, &len)) { |
| 165 purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Error decrypt buddies online"); |
180 purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Error decrypt buddies online"); |
| 166 return; |
181 return -1; |
| 167 } |
182 } |
| 168 |
183 |
| 169 qq_show_packet("Get buddies online reply packet", data, len); |
184 /* qq_show_packet("Get buddies online reply packet", data, len); */ |
| 170 |
185 |
| 171 bytes = 0; |
186 bytes = 0; |
| 172 bytes += qq_get8(&position, data + bytes); |
187 bytes += qq_get8(&position, data + bytes); |
| 173 |
188 |
| 174 fe = g_newa(qq_friends_online_entry, 1); |
|
| 175 fe->s = g_newa(qq_buddy_status, 1); |
|
| 176 |
|
| 177 count = 0; |
189 count = 0; |
| 178 while (bytes < len) { |
190 while (bytes < len) { |
| |
191 if (len - bytes < QQ_ONLINE_BUDDY_ENTRY_LEN) { |
| |
192 purple_debug(PURPLE_DEBUG_ERROR, "QQ", |
| |
193 "[buddies online] only %d, need %d", |
| |
194 (len - bytes), QQ_ONLINE_BUDDY_ENTRY_LEN); |
| |
195 break; |
| |
196 } |
| |
197 memset(&bo, 0 ,sizeof(bo)); |
| |
198 |
| 179 /* set flag */ |
199 /* set flag */ |
| 180 bytes_buddy = bytes; |
200 bytes_buddy = bytes; |
| 181 /* based on one online buddy entry */ |
201 /* based on one online buddy entry */ |
| 182 /* ATTTENTION! NEWED in the sub function, but FREED here */ |
|
| 183 /* 000-030 qq_buddy_status */ |
202 /* 000-030 qq_buddy_status */ |
| 184 bytes += qq_buddy_status_read(fe->s, data + bytes); |
203 bytes += get_buddy_status(&(bo.bs), data + bytes); |
| 185 /* 031-032: unknown4 */ |
204 /* 031-032: */ |
| 186 bytes += qq_get16(&fe->unknown1, data + bytes); |
205 bytes += qq_get16(&bo.unknown1, data + bytes); |
| 187 /* 033-033: flag1 */ |
206 /* 033-033: ext_flag */ |
| 188 bytes += qq_get8(&fe->flag1, data + bytes); |
207 bytes += qq_get8(&bo.ext_flag, data + bytes); |
| 189 /* 034-034: comm_flag */ |
208 /* 034-034: comm_flag */ |
| 190 bytes += qq_get8(&fe->comm_flag, data + bytes); |
209 bytes += qq_get8(&bo.comm_flag, data + bytes); |
| 191 /* 035-036: */ |
210 /* 035-036: */ |
| 192 bytes += qq_get16(&fe->unknown2, data + bytes); |
211 bytes += qq_get16(&bo.unknown2, data + bytes); |
| 193 /* 037-037: */ |
212 /* 037-037: */ |
| 194 bytes += qq_get8(&fe->ending, data + bytes); /* 0x00 */ |
213 bytes += qq_get8(&bo.ending, data + bytes); /* 0x00 */ |
| 195 |
214 |
| 196 if (fe->s->uid == 0 || (bytes - bytes_buddy) != QQ_ONLINE_BUDDY_ENTRY_LEN) { |
215 if (bo.bs.uid == 0 || (bytes - bytes_buddy) != QQ_ONLINE_BUDDY_ENTRY_LEN) { |
| 197 purple_debug(PURPLE_DEBUG_ERROR, "QQ", |
216 purple_debug(PURPLE_DEBUG_ERROR, "QQ", |
| 198 "uid=0 or entry complete len(%d) != %d", |
217 "uid=0 or entry complete len(%d) != %d", |
| 199 (bytes - bytes_buddy), QQ_ONLINE_BUDDY_ENTRY_LEN); |
218 (bytes - bytes_buddy), QQ_ONLINE_BUDDY_ENTRY_LEN); |
| 200 g_free(fe->s->ip); |
|
| 201 g_free(fe->s->unknown_key); |
|
| 202 continue; |
219 continue; |
| 203 } /* check if it is a valid entry */ |
220 } /* check if it is a valid entry */ |
| 204 |
221 |
| 205 if (QQ_DEBUG) { |
222 /* update buddy information */ |
| 206 _qq_buddies_online_reply_dump_unclear(fe); |
223 b = purple_find_buddy(purple_connection_get_account(gc), |
| |
224 uid_to_purple_name(bo.bs.uid) ); |
| |
225 q_bud = (b == NULL) ? NULL : (qq_buddy *) b->proto_data; |
| |
226 if (q_bud == NULL) { |
| |
227 purple_debug(PURPLE_DEBUG_ERROR, "QQ", |
| |
228 "Got an online buddy %d, but not in my buddy list\n", bo.bs.uid); |
| |
229 continue; |
| 207 } |
230 } |
| 208 |
231 /* we find one and update qq_buddy */ |
| 209 /* update buddy information */ |
232 /* |
| 210 b = purple_find_buddy(purple_connection_get_account(gc), uid_to_purple_name(fe->s->uid)); |
233 if(0 != fe->s->client_version) |
| 211 q_bud = (b == NULL) ? NULL : (qq_buddy *) b->proto_data; |
234 q_bud->client_version = fe->s->client_version; |
| 212 |
235 */ |
| 213 if (q_bud != NULL) { /* we find one and update qq_buddy */ |
236 q_bud->ip.s_addr = bo.bs.ip.s_addr; |
| 214 if(0 != fe->s->client_version) |
237 q_bud->port = bo.bs.port; |
| 215 q_bud->client_version = fe->s->client_version; |
238 q_bud->status = bo.bs.status; |
| 216 g_memmove(q_bud->ip, fe->s->ip, 4); |
239 q_bud->ext_flag = bo.ext_flag; |
| 217 q_bud->port = fe->s->port; |
240 q_bud->comm_flag = bo.comm_flag; |
| 218 q_bud->status = fe->s->status; |
241 qq_update_buddy_contact(gc, q_bud); |
| 219 q_bud->flag1 = fe->flag1; |
242 count++; |
| 220 q_bud->comm_flag = fe->comm_flag; |
|
| 221 qq_update_buddy_contact(gc, q_bud); |
|
| 222 count++; |
|
| 223 } else { |
|
| 224 purple_debug(PURPLE_DEBUG_ERROR, "QQ", |
|
| 225 "Got an online buddy %d, but not in my buddy list\n", fe->s->uid); |
|
| 226 } |
|
| 227 |
|
| 228 g_free(fe->s->ip); |
|
| 229 g_free(fe->s->unknown_key); |
|
| 230 } |
243 } |
| 231 |
244 |
| 232 if(bytes > len) { |
245 if(bytes > len) { |
| 233 purple_debug(PURPLE_DEBUG_ERROR, "QQ", |
246 purple_debug(PURPLE_DEBUG_ERROR, "QQ", |
| 234 "qq_process_get_buddies_online_reply: Dangerous error! maybe protocol changed, notify developers!\n"); |
247 "qq_process_get_buddies_online_reply: Dangerous error! maybe protocol changed, notify developers!\n"); |
| 235 } |
248 } |
| 236 |
249 |
| 237 purple_debug(PURPLE_DEBUG_INFO, "QQ", "Received %d online buddies, nextposition=%u\n", |
250 purple_debug(PURPLE_DEBUG_INFO, "QQ", "Received %d online buddies, nextposition=%u\n", |
| 238 count, (guint) position); |
251 count, (guint) position); |
| 239 if (position != QQ_FRIENDS_ONLINE_POSITION_END |
252 return position; |
| 240 && position != QQ_FRIENDS_ONLINE_POSITION_START) { |
|
| 241 purple_debug(PURPLE_DEBUG_INFO, "QQ", "Requesting for more online buddies\n"); |
|
| 242 qq_send_packet_get_buddies_online(gc, position); |
|
| 243 } else { |
|
| 244 purple_debug(PURPLE_DEBUG_INFO, "QQ", "All online buddies received\n"); |
|
| 245 qq_send_packet_get_buddies_levels(gc); |
|
| 246 qq_refresh_all_buddy_status(gc); |
|
| 247 } |
|
| 248 } |
253 } |
| 249 |
254 |
| 250 |
255 |
| 251 /* process reply for get_buddies_list */ |
256 /* process reply for get_buddies_list */ |
| 252 void qq_process_get_buddies_list_reply(guint8 *buf, gint buf_len, PurpleConnection *gc) |
257 guint16 qq_process_get_buddies_list_reply(guint8 *buf, gint buf_len, PurpleConnection *gc) |
| 253 { |
258 { |
| 254 qq_data *qd; |
259 qq_data *qd; |
| 255 qq_buddy *q_bud; |
260 qq_buddy *q_bud; |
| 256 gint len, bytes_expected, count; |
261 gint len, bytes_expected, count; |
| 257 gint bytes, buddy_bytes; |
262 gint bytes, buddy_bytes; |
| 258 guint16 position, unknown; |
263 guint16 position, unknown; |
| 259 guint8 *data, pascal_len; |
264 guint8 *data, pascal_len; |
| 260 gchar *name; |
265 gchar *name; |
| 261 PurpleBuddy *b; |
266 PurpleBuddy *b; |
| 262 |
267 |
| 263 g_return_if_fail(buf != NULL && buf_len != 0); |
268 g_return_val_if_fail(buf != NULL && buf_len != 0, -1); |
| 264 |
269 |
| 265 qd = (qq_data *) gc->proto_data; |
270 qd = (qq_data *) gc->proto_data; |
| 266 len = buf_len; |
271 len = buf_len; |
| 267 data = g_newa(guint8, len); |
272 data = g_newa(guint8, len); |
| 268 |
273 |
| 269 if (!qq_decrypt(buf, buf_len, qd->session_key, data, &len)) { |
274 if (!qq_decrypt(buf, buf_len, qd->session_key, data, &len)) { |
| 270 purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Error decrypt buddies list"); |
275 purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Error decrypt buddies list"); |
| 271 return; |
276 return -1; |
| 272 } |
277 } |
| 273 bytes = 0; |
278 bytes = 0; |
| 274 bytes += qq_get16(&position, data + bytes); |
279 bytes += qq_get16(&position, data + bytes); |
| 275 /* the following data is buddy list in this packet */ |
280 /* the following data is buddy list in this packet */ |
| 276 count = 0; |
281 count = 0; |
| 427 if(bytes > len) { |
416 if(bytes > len) { |
| 428 purple_debug(PURPLE_DEBUG_ERROR, "QQ", |
417 purple_debug(PURPLE_DEBUG_ERROR, "QQ", |
| 429 "qq_process_get_all_list_with_group_reply: Dangerous error! maybe protocol changed, notify developers!"); |
418 "qq_process_get_all_list_with_group_reply: Dangerous error! maybe protocol changed, notify developers!"); |
| 430 } |
419 } |
| 431 |
420 |
| 432 purple_debug(PURPLE_DEBUG_INFO, "QQ", "Get all list done, %d buddies and %d Quns\n", i, j); |
|
| 433 purple_debug(PURPLE_DEBUG_INFO, "QQ", "Received %d buddies and %d groups, nextposition=%u\n", i, j, (guint) position); |
421 purple_debug(PURPLE_DEBUG_INFO, "QQ", "Received %d buddies and %d groups, nextposition=%u\n", i, j, (guint) position); |
| 434 |
422 return position; |
| 435 if (position != QQ_FRIENDS_ALL_LIST_POSITION_START |
423 } |
| 436 && position != QQ_FRIENDS_ALL_LIST_POSITION_END) { |
424 |
| 437 purple_debug(PURPLE_DEBUG_INFO, "QQ", "Requesting for more buddies and groups\n"); |
425 #define QQ_MISC_STATUS_HAVING_VIIDEO 0x00000001 |
| 438 qq_send_packet_get_all_list_with_group(gc, position); |
426 #define QQ_CHANGE_ONLINE_STATUS_REPLY_OK 0x30 /* ASCII value of "0" */ |
| |
427 |
| |
428 /* TODO: figure out what's going on with the IP region. Sometimes I get valid IP addresses, |
| |
429 * but the port number's weird, other times I get 0s. I get these simultaneously on the same buddy, |
| |
430 * using different accounts to get info. */ |
| |
431 |
| |
432 /* check if status means online or offline */ |
| |
433 gboolean is_online(guint8 status) |
| |
434 { |
| |
435 switch(status) { |
| |
436 case QQ_BUDDY_ONLINE_NORMAL: |
| |
437 case QQ_BUDDY_ONLINE_AWAY: |
| |
438 case QQ_BUDDY_ONLINE_INVISIBLE: |
| |
439 return TRUE; |
| |
440 case QQ_BUDDY_ONLINE_OFFLINE: |
| |
441 return FALSE; |
| |
442 } |
| |
443 return FALSE; |
| |
444 } |
| |
445 |
| |
446 /* Help calculate the correct icon index to tell the server. */ |
| |
447 gint get_icon_offset(PurpleConnection *gc) |
| |
448 { |
| |
449 PurpleAccount *account; |
| |
450 PurplePresence *presence; |
| |
451 |
| |
452 account = purple_connection_get_account(gc); |
| |
453 presence = purple_account_get_presence(account); |
| |
454 |
| |
455 if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_INVISIBLE)) { |
| |
456 return 2; |
| |
457 } else if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_AWAY) |
| |
458 || purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_EXTENDED_AWAY) |
| |
459 || purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_UNAVAILABLE)) { |
| |
460 return 1; |
| 439 } else { |
461 } else { |
| 440 purple_debug(PURPLE_DEBUG_INFO, "QQ", "All buddies and groups received\n"); |
462 return 0; |
| 441 } |
463 } |
| 442 } |
464 } |
| |
465 |
| |
466 /* send a packet to change my online status */ |
| |
467 void qq_send_packet_change_status(PurpleConnection *gc) |
| |
468 { |
| |
469 qq_data *qd; |
| |
470 guint8 raw_data[16] = {0}; |
| |
471 gint bytes = 0; |
| |
472 guint8 away_cmd; |
| |
473 guint32 misc_status; |
| |
474 gboolean fake_video; |
| |
475 PurpleAccount *account; |
| |
476 PurplePresence *presence; |
| |
477 |
| |
478 account = purple_connection_get_account(gc); |
| |
479 presence = purple_account_get_presence(account); |
| |
480 |
| |
481 qd = (qq_data *) gc->proto_data; |
| |
482 if (!qd->logged_in) |
| |
483 return; |
| |
484 |
| |
485 if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_INVISIBLE)) { |
| |
486 away_cmd = QQ_BUDDY_ONLINE_INVISIBLE; |
| |
487 } else if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_AWAY) |
| |
488 || purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_EXTENDED_AWAY) |
| |
489 || purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_UNAVAILABLE)) { |
| |
490 away_cmd = QQ_BUDDY_ONLINE_AWAY; |
| |
491 } else { |
| |
492 away_cmd = QQ_BUDDY_ONLINE_NORMAL; |
| |
493 } |
| |
494 |
| |
495 misc_status = 0x00000000; |
| |
496 fake_video = purple_prefs_get_bool("/plugins/prpl/qq/show_fake_video"); |
| |
497 if (fake_video) |
| |
498 misc_status |= QQ_MISC_STATUS_HAVING_VIIDEO; |
| |
499 |
| |
500 bytes = 0; |
| |
501 bytes += qq_put8(raw_data + bytes, away_cmd); |
| |
502 bytes += qq_put32(raw_data + bytes, misc_status); |
| |
503 |
| |
504 qq_send_cmd(qd, QQ_CMD_CHANGE_ONLINE_STATUS, raw_data, bytes); |
| |
505 } |
| |
506 |
| |
507 /* parse the reply packet for change_status */ |
| |
508 void qq_process_change_status_reply(guint8 *buf, gint buf_len, PurpleConnection *gc) |
| |
509 { |
| |
510 qq_data *qd; |
| |
511 gint len, bytes; |
| |
512 guint8 *data, reply; |
| |
513 PurpleBuddy *b; |
| |
514 qq_buddy *q_bud; |
| |
515 gchar *name; |
| |
516 |
| |
517 g_return_if_fail(buf != NULL && buf_len != 0); |
| |
518 |
| |
519 qd = (qq_data *) gc->proto_data; |
| |
520 len = buf_len; |
| |
521 data = g_newa(guint8, len); |
| |
522 |
| |
523 if ( !qq_decrypt(buf, buf_len, qd->session_key, data, &len) ) { |
| |
524 purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Error decrypt chg status reply\n"); |
| |
525 return; |
| |
526 } |
| |
527 |
| |
528 bytes = 0; |
| |
529 bytes = qq_get8(&reply, data + bytes); |
| |
530 if (reply != QQ_CHANGE_ONLINE_STATUS_REPLY_OK) { |
| |
531 purple_debug(PURPLE_DEBUG_WARNING, "QQ", "Change status fail 0x%02X\n", reply); |
| |
532 return; |
| |
533 } |
| |
534 |
| |
535 /* purple_debug(PURPLE_DEBUG_INFO, "QQ", "Change status OK\n"); */ |
| |
536 name = uid_to_purple_name(qd->uid); |
| |
537 b = purple_find_buddy(gc->account, name); |
| |
538 g_free(name); |
| |
539 q_bud = (b == NULL) ? NULL : (qq_buddy *) b->proto_data; |
| |
540 if (q_bud != NULL) { |
| |
541 qq_update_buddy_contact(gc, q_bud); |
| |
542 } |
| |
543 } |
| |
544 |
| |
545 /* it is a server message indicating that one of my buddies has changed its status */ |
| |
546 void qq_process_buddy_change_status(guint8 *buf, gint buf_len, PurpleConnection *gc) |
| |
547 { |
| |
548 qq_data *qd; |
| |
549 gint bytes; |
| |
550 guint32 my_uid; |
| |
551 guint8 *data; |
| |
552 gint data_len; |
| |
553 PurpleBuddy *b; |
| |
554 qq_buddy *q_bud; |
| |
555 qq_buddy_status bs; |
| |
556 gchar *name; |
| |
557 |
| |
558 g_return_if_fail(buf != NULL && buf_len != 0); |
| |
559 |
| |
560 qd = (qq_data *) gc->proto_data; |
| |
561 data_len = buf_len; |
| |
562 data = g_newa(guint8, data_len); |
| |
563 |
| |
564 if ( !qq_decrypt(buf, buf_len, qd->session_key, data, &data_len) ) { |
| |
565 purple_debug(PURPLE_DEBUG_ERROR, "QQ", "[buddy status change] Failed decrypt\n"); |
| |
566 return; |
| |
567 } |
| |
568 |
| |
569 if (data_len < 35) { |
| |
570 purple_debug(PURPLE_DEBUG_ERROR, "QQ", "[buddy status change] only %d, need 35 bytes\n", data_len); |
| |
571 return; |
| |
572 } |
| |
573 |
| |
574 memset(&bs, 0, sizeof(bs)); |
| |
575 bytes = 0; |
| |
576 /* 000-030: qq_buddy_status */ |
| |
577 bytes += get_buddy_status(&bs, data + bytes); |
| |
578 /* 031-034: Unknow, maybe my uid */ |
| |
579 /* This has a value of 0 when we've changed our status to |
| |
580 * QQ_BUDDY_ONLINE_INVISIBLE */ |
| |
581 bytes += qq_get32(&my_uid, data + bytes); |
| |
582 |
| |
583 name = uid_to_purple_name(bs.uid); |
| |
584 b = purple_find_buddy(gc->account, name); |
| |
585 g_free(name); |
| |
586 q_bud = (b == NULL) ? NULL : (qq_buddy *) b->proto_data; |
| |
587 if (q_bud == NULL) { |
| |
588 purple_debug(PURPLE_DEBUG_ERROR, "QQ", |
| |
589 "got information of unknown buddy %d\n", bs.uid); |
| |
590 return; |
| |
591 } |
| |
592 |
| |
593 purple_debug(PURPLE_DEBUG_INFO, "QQ", "status:.uid = %d, q_bud->uid = %d\n", bs.uid , q_bud->uid); |
| |
594 if(bs.ip.s_addr != 0) { |
| |
595 q_bud->ip.s_addr = bs.ip.s_addr; |
| |
596 q_bud->port = bs.port; |
| |
597 } |
| |
598 q_bud->status =bs.status; |
| |
599 |
| |
600 if (q_bud->status == QQ_BUDDY_ONLINE_NORMAL) { |
| |
601 qq_send_packet_get_level(gc, q_bud->uid); |
| |
602 } |
| |
603 qq_update_buddy_contact(gc, q_bud); |
| |
604 } |
| |
605 |
| |
606 /*TODO: maybe this should be qq_update_buddy_status() ?*/ |
| |
607 void qq_update_buddy_contact(PurpleConnection *gc, qq_buddy *q_bud) |
| |
608 { |
| |
609 gchar *name; |
| |
610 PurpleBuddy *bud; |
| |
611 gchar *status_id; |
| |
612 |
| |
613 g_return_if_fail(q_bud != NULL); |
| |
614 |
| |
615 name = uid_to_purple_name(q_bud->uid); |
| |
616 bud = purple_find_buddy(gc->account, name); |
| |
617 |
| |
618 if (bud == NULL) { |
| |
619 purple_debug(PURPLE_DEBUG_ERROR, "QQ", "unknown buddy: %d\n", q_bud->uid); |
| |
620 g_free(name); |
| |
621 return; |
| |
622 } |
| |
623 |
| |
624 purple_blist_server_alias_buddy(bud, q_bud->nickname); /* server */ |
| |
625 q_bud->last_refresh = time(NULL); |
| |
626 |
| |
627 /* purple supports signon and idle time |
| |
628 * but it is not much use for QQ, I do not use them */ |
| |
629 /* serv_got_update(gc, name, online, 0, q_bud->signon, q_bud->idle, bud->uc); */ |
| |
630 status_id = "available"; |
| |
631 switch(q_bud->status) { |
| |
632 case QQ_BUDDY_OFFLINE: |
| |
633 status_id = "offline"; |
| |
634 break; |
| |
635 case QQ_BUDDY_ONLINE_NORMAL: |
| |
636 status_id = "available"; |
| |
637 break; |
| |
638 case QQ_BUDDY_ONLINE_OFFLINE: |
| |
639 status_id = "offline"; |
| |
640 break; |
| |
641 case QQ_BUDDY_ONLINE_AWAY: |
| |
642 status_id = "away"; |
| |
643 break; |
| |
644 case QQ_BUDDY_ONLINE_INVISIBLE: |
| |
645 status_id = "invisible"; |
| |
646 break; |
| |
647 default: |
| |
648 status_id = "invisible"; |
| |
649 purple_debug(PURPLE_DEBUG_ERROR, "QQ", "unknown status: %x\n", q_bud->status); |
| |
650 break; |
| |
651 } |
| |
652 purple_debug(PURPLE_DEBUG_INFO, "QQ", "buddy %d %s\n", q_bud->uid, status_id); |
| |
653 purple_prpl_got_user_status(gc->account, name, status_id, NULL); |
| |
654 |
| |
655 if (q_bud->comm_flag & QQ_COMM_FLAG_MOBILE && q_bud->status != QQ_BUDDY_OFFLINE) |
| |
656 purple_prpl_got_user_status(gc->account, name, "mobile", NULL); |
| |
657 else |
| |
658 purple_prpl_got_user_status_deactive(gc->account, name, "mobile"); |
| |
659 |
| |
660 if (q_bud->comm_flag & QQ_COMM_FLAG_VIDEO && q_bud->status != QQ_BUDDY_OFFLINE) |
| |
661 purple_prpl_got_user_status(gc->account, name, "video", NULL); |
| |
662 else |
| |
663 purple_prpl_got_user_status_deactive(gc->account, name, "video"); |
| |
664 |
| |
665 g_free(name); |
| |
666 } |
| |
667 |
| |
668 /* refresh all buddies online/offline, |
| |
669 * after receiving reply for get_buddies_online packet */ |
| |
670 void qq_refresh_all_buddy_status(PurpleConnection *gc) |
| |
671 { |
| |
672 time_t now; |
| |
673 GList *list; |
| |
674 qq_data *qd; |
| |
675 qq_buddy *q_bud; |
| |
676 |
| |
677 qd = (qq_data *) (gc->proto_data); |
| |
678 now = time(NULL); |
| |
679 list = qd->buddies; |
| |
680 |
| |
681 while (list != NULL) { |
| |
682 q_bud = (qq_buddy *) list->data; |
| |
683 if (q_bud != NULL && now > q_bud->last_refresh + QQ_UPDATE_ONLINE_INTERVAL |
| |
684 && q_bud->status != QQ_BUDDY_ONLINE_INVISIBLE) { |
| |
685 q_bud->status = QQ_BUDDY_ONLINE_OFFLINE; |
| |
686 qq_update_buddy_contact(gc, q_bud); |
| |
687 } |
| |
688 list = list->next; |
| |
689 } |
| |
690 } |