00001
00023
00024
00025 #include "conversation.h"
00026 #include "debug.h"
00027 #include "internal.h"
00028 #include "md5.h"
00029 #include "notify.h"
00030 #include "server.h"
00031 #include "util.h"
00032
00033 #include "utils.h"
00034 #include "packet_parse.h"
00035 #include "buddy_info.h"
00036 #include "buddy_list.h"
00037 #include "buddy_opt.h"
00038 #include "char_conv.h"
00039 #include "crypt.h"
00040 #include "group_im.h"
00041 #include "header_info.h"
00042 #include "im.h"
00043 #include "send_core.h"
00044 #include "qq.h"
00045 #include "send_file.h"
00046
00047 #define QQ_SEND_IM_REPLY_OK 0x00
00048 #define DEFAULT_FONT_NAME_LEN 4
00049
00050
00051 void _qq_show_packet(gchar * desc, gchar * buf, gint len);
00052
00053 enum
00054 {
00055 QQ_NORMAL_IM_TEXT = 0x000b,
00056 QQ_NORMAL_IM_FILE_REQUEST = 0x0035,
00057 QQ_NORMAL_IM_FILE_APPROVE_UDP = 0x0037,
00058 QQ_NORMAL_IM_FILE_APPROVE_TCP = 0x0003,
00059 QQ_NORMAL_IM_FILE_REJECT_UDP = 0x0039,
00060 QQ_NORMAL_IM_FILE_REJECT_TCP = 0x0005,
00061 QQ_NORMAL_IM_FILE_NOTIFY = 0x003b,
00062 QQ_NORMAL_IM_FILE_CANCEL = 0x0049,
00063 QQ_NORMAL_IM_FILE_PASV = 0x003f,
00064 };
00065
00066 enum {
00067 QQ_RECV_SYS_IM_KICK_OUT = 0x01,
00068 };
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083 typedef struct _qq_recv_im_header qq_recv_im_header;
00084 typedef struct _qq_recv_normal_im_text qq_recv_normal_im_text;
00085 typedef struct _qq_recv_normal_im_common qq_recv_normal_im_common;
00086 typedef struct _qq_recv_normal_im_unprocessed qq_recv_normal_im_unprocessed;
00087
00088 struct _qq_recv_normal_im_common {
00089
00090 guint16 sender_ver;
00091 guint32 sender_uid;
00092 guint32 receiver_uid;
00093 guint8 *session_md5;
00094 guint16 normal_im_type;
00095 };
00096
00097 struct _qq_recv_normal_im_text {
00098 qq_recv_normal_im_common *common;
00099
00100 guint16 msg_seq;
00101 guint32 send_time;
00102 guint8 unknown1;
00103 guint8 sender_icon;
00104 guint8 unknown2[3];
00105 guint8 is_there_font_attr;
00106 guint8 unknown3[4];
00107 guint8 msg_type;
00108 guint8 *msg;
00109 guint8 *font_attr;
00110 gint font_attr_len;
00111 };
00112
00113 struct _qq_recv_normal_im_unprocessed {
00114 qq_recv_normal_im_common *common;
00115
00116 guint8 *unknown;
00117 gint length;
00118 };
00119
00120 struct _qq_recv_im_header {
00121 guint32 sender_uid;
00122 guint32 receiver_uid;
00123 guint32 server_im_seq;
00124 guint8 sender_ip[4];
00125 guint16 sender_port;
00126 guint16 im_type;
00127 };
00128
00129 #define QQ_SEND_IM_AFTER_MSG_HEADER_LEN 8
00130 #define DEFAULT_FONT_NAME "\0xcb\0xce\0xcc\0xe5"
00131
00132 guint8 *qq_get_send_im_tail(const gchar * font_color,
00133 const gchar * font_size,
00134 const gchar * font_name,
00135 gboolean is_bold, gboolean is_italic, gboolean is_underline, guint tail_len)
00136 {
00137 gchar *s1, *s2;
00138 unsigned char *rgb;
00139 guint font_name_len;
00140 guint8 *send_im_tail;
00141 const guint8 simsun[] = { 0xcb, 0xce, 0xcc, 0xe5 };
00142
00143 if (font_name) {
00144 font_name_len = strlen(font_name);
00145 } else {
00146 font_name_len = DEFAULT_FONT_NAME_LEN;
00147 font_name = simsun;
00148 }
00149
00150 send_im_tail = g_new0(guint8, tail_len);
00151
00152 g_strlcpy(send_im_tail + QQ_SEND_IM_AFTER_MSG_HEADER_LEN,
00153 font_name, tail_len - QQ_SEND_IM_AFTER_MSG_HEADER_LEN);
00154 send_im_tail[tail_len - 1] = tail_len;
00155
00156 send_im_tail[0] = 0x00;
00157 if (font_size) {
00158 send_im_tail[1] = (guint8) (atoi(font_size) * 3 + 1);
00159 } else {
00160 send_im_tail[1] = 10;
00161 }
00162 if (is_bold)
00163 send_im_tail[1] |= 0x20;
00164 if (is_italic)
00165 send_im_tail[1] |= 0x40;
00166 if (is_underline)
00167 send_im_tail[1] |= 0x80;
00168
00169 if (font_color) {
00170 s1 = g_strndup(font_color + 1, 6);
00171
00172
00173
00174 s2 = g_strdup_printf("%sH", s1);
00175 gaim_base16_decode(s2, &rgb);
00176 g_free(s1);
00177 g_free(s2);
00178 memcpy(send_im_tail + 2, rgb, 3);
00179 g_free(rgb);
00180 } else {
00181 send_im_tail[2] = send_im_tail[3] = send_im_tail[4] = 0;
00182 }
00183
00184 send_im_tail[5] = 0x00;
00185 send_im_tail[6] = 0x86;
00186 send_im_tail[7] = 0x22;
00187 _qq_show_packet("QQ_MESG", send_im_tail, tail_len);
00188 return (guint8 *) send_im_tail;
00189 }
00190
00191
00192 const gchar *qq_get_recv_im_type_str(gint type)
00193 {
00194 switch (type) {
00195 case QQ_RECV_IM_TO_BUDDY:
00196 return "QQ_RECV_IM_TO_BUDDY";
00197 case QQ_RECV_IM_TO_UNKNOWN:
00198 return "QQ_RECV_IM_TO_UNKNOWN";
00199 case QQ_RECV_IM_UNKNOWN_GROUP_IM:
00200 return "QQ_RECV_IM_UNKNOWN_GROUP_IM";
00201 case QQ_RECV_IM_ADD_TO_GROUP:
00202 return "QQ_RECV_IM_ADD_TO_GROUP";
00203 case QQ_RECV_IM_DEL_FROM_GROUP:
00204 return "QQ_RECV_IM_DEL_FROM_GROUP";
00205 case QQ_RECV_IM_APPLY_ADD_TO_GROUP:
00206 return "QQ_RECV_IM_APPLY_ADD_TO_GROUP";
00207 case QQ_RECV_IM_CREATE_GROUP:
00208 return "QQ_RECV_IM_CREATE_GROUP";
00209 case QQ_RECV_IM_SYS_NOTIFICATION:
00210 return "QQ_RECV_IM_SYS_NOTIFICATION";
00211 case QQ_RECV_IM_APPROVE_APPLY_ADD_TO_GROUP:
00212 return "QQ_RECV_IM_APPROVE_APPLY_ADD_TO_GROUP";
00213 case QQ_RECV_IM_REJCT_APPLY_ADD_TO_GROUP:
00214 return "QQ_RECV_IM_REJCT_APPLY_ADD_TO_GROUP";
00215 case QQ_RECV_IM_TEMP_GROUP_IM:
00216 return "QQ_RECV_IM_TEMP_GROUP_IM";
00217 case QQ_RECV_IM_GROUP_IM:
00218 return "QQ_RECV_IM_GROUP_IM";
00219 default:
00220 return "QQ_RECV_IM_UNKNOWN";
00221 }
00222 }
00223
00224
00225
00226 gchar *_gen_session_md5(gint uid, gchar * session_key)
00227 {
00228 gchar *src, md5_str[QQ_KEY_LENGTH];
00229 guint8 *cursor;
00230 md5_state_t ctx;
00231
00232 src = g_newa(gchar, 20);
00233 cursor = src;
00234 create_packet_dw(src, &cursor, uid);
00235 create_packet_data(src, &cursor, session_key, QQ_KEY_LENGTH);
00236
00237 md5_init(&ctx);
00238 md5_append(&ctx, src, 20);
00239 md5_finish(&ctx, (md5_byte_t *) md5_str);
00240
00241 return g_memdup(md5_str, QQ_KEY_LENGTH);
00242 }
00243
00244
00245
00246
00247 void _qq_send_packet_recv_im_ack(GaimConnection * gc, guint16 seq, guint8 * data) {
00248 qq_send_cmd(gc, QQ_CMD_RECV_IM, FALSE, seq, FALSE, data, 16);
00249 }
00250
00251
00252
00253
00254 gint _qq_normal_im_common_read(guint8 * data, guint8 ** cursor, gint len, qq_recv_normal_im_common * common) {
00255
00256 gint bytes;
00257 g_return_val_if_fail(data != NULL && len != 0 && common != NULL, -1);
00258
00259 bytes = 0;
00260
00261 bytes += read_packet_w(data, cursor, len, &(common->sender_ver));
00262 bytes += read_packet_dw(data, cursor, len, &(common->sender_uid));
00263 bytes += read_packet_dw(data, cursor, len, &(common->receiver_uid));
00264
00265 common->session_md5 = g_memdup(*cursor, QQ_KEY_LENGTH);
00266 bytes += QQ_KEY_LENGTH;
00267 *cursor += QQ_KEY_LENGTH;
00268
00269 bytes += read_packet_w(data, cursor, len, &(common->normal_im_type));
00270
00271 if (bytes != 28) {
00272 gaim_debug(GAIM_DEBUG_ERROR, "QQ", "Expect 28 bytes, read %d bytes\n", bytes);
00273 return -1;
00274 }
00275
00276 return bytes;
00277 }
00278
00279
00280
00281 void _qq_process_recv_normal_im_text
00282 (guint8 * data, guint8 ** cursor, gint len, qq_recv_normal_im_common * common, GaimConnection * gc) {
00283 guint16 gaim_msg_type;
00284 gchar *name;
00285 gchar *msg_with_gaim_smiley;
00286 gchar *msg_utf8_encoded;
00287 qq_data *qd;
00288 qq_recv_normal_im_text *im_text;
00289
00290 g_return_if_fail(gc != NULL && gc->proto_data != NULL && common != NULL);
00291 qd = (qq_data *) gc->proto_data;
00292
00293
00294 if (*cursor >= (data + len - 1)) {
00295 gaim_debug(GAIM_DEBUG_WARNING, "QQ", "Received normal IM text is empty\n");
00296 return;
00297 } else
00298 im_text = g_newa(qq_recv_normal_im_text, 1);
00299
00300 im_text->common = common;
00301
00302
00303 read_packet_w(data, cursor, len, &(im_text->msg_seq));
00304 read_packet_dw(data, cursor, len, &(im_text->send_time));
00305 read_packet_b(data, cursor, len, &(im_text->unknown1));
00306 read_packet_b(data, cursor, len, &(im_text->sender_icon));
00307 read_packet_data(data, cursor, len, (guint8 *) & (im_text->unknown2), 3);
00308 read_packet_b(data, cursor, len, &(im_text->is_there_font_attr));
00309 read_packet_data(data, cursor, len, (guint8 *) & (im_text->unknown3), 4);
00310 read_packet_b(data, cursor, len, &(im_text->msg_type));
00311
00312
00313
00314
00315 if (im_text->msg_type == QQ_IM_AUTO_REPLY) {
00316 im_text->is_there_font_attr = 0x00;
00317 im_text->msg = g_strndup(*cursor, data + len - *cursor);
00318 } else {
00319 if (im_text->is_there_font_attr) {
00320 im_text->msg = g_strdup(*cursor);
00321 *cursor += strlen(im_text->msg) + 1;
00322 im_text->font_attr_len = data + len - *cursor;
00323 im_text->font_attr = g_memdup(*cursor, im_text->font_attr_len);
00324 } else
00325 im_text->msg = g_strndup(*cursor, data + len - *cursor);
00326 }
00327 _qq_show_packet("QQ_MESG recv", data, *cursor - data);
00328
00329 name = uid_to_gaim_name(common->sender_uid);
00330 if (gaim_find_buddy(gc->account, name) == NULL)
00331 qq_add_buddy_by_recv_packet(gc, common->sender_uid, FALSE, TRUE);
00332
00333 gaim_msg_type = (im_text->msg_type == QQ_IM_AUTO_REPLY) ? GAIM_CONV_IM_AUTO_RESP : 0;
00334
00335 msg_with_gaim_smiley = qq_smiley_to_gaim(im_text->msg);
00336 msg_utf8_encoded = im_text->is_there_font_attr ?
00337 qq_encode_to_gaim(im_text->font_attr,
00338 im_text->font_attr_len,
00339 msg_with_gaim_smiley) : qq_to_utf8(msg_with_gaim_smiley, QQ_CHARSET_DEFAULT);
00340
00341
00342
00343
00344 serv_got_im(gc, name, msg_utf8_encoded, gaim_msg_type, (time_t) im_text->send_time);
00345
00346 g_free(msg_utf8_encoded);
00347 g_free(msg_with_gaim_smiley);
00348 g_free(name);
00349 g_free(im_text->msg);
00350 if (im_text->is_there_font_attr)
00351 g_free(im_text->font_attr);
00352 }
00353
00354
00355
00356 void _qq_process_recv_normal_im(guint8 * data, guint8 ** cursor, gint len, GaimConnection * gc)
00357 {
00358 gint bytes;
00359 qq_recv_normal_im_common *common;
00360 qq_recv_normal_im_unprocessed *im_unprocessed;
00361
00362 g_return_if_fail (data != NULL && len != 0);
00363
00364 if (*cursor >= (data + len - 1)) {
00365 gaim_debug (GAIM_DEBUG_WARNING, "QQ",
00366 "Received normal IM is empty\n");
00367 return;
00368 }
00369 else
00370 common = g_newa (qq_recv_normal_im_common, 1);
00371
00372 bytes = _qq_normal_im_common_read (data, cursor, len, common);
00373 if (bytes < 0) {
00374 gaim_debug (GAIM_DEBUG_ERROR, "QQ",
00375 "Fail read the common part of normal IM\n");
00376 return;
00377 }
00378
00379 switch (common->normal_im_type) {
00380 case QQ_NORMAL_IM_TEXT:
00381 gaim_debug (GAIM_DEBUG_INFO,
00382 "QQ",
00383 "Normal IM, text type:\n [%d] => [%d], src: %s\n",
00384 common->sender_uid, common->receiver_uid,
00385 qq_get_source_str (common->sender_ver));
00386 _qq_process_recv_normal_im_text (data, cursor, len, common,
00387 gc);
00388 break;
00389 case QQ_NORMAL_IM_FILE_REJECT_UDP:
00390 qq_process_recv_file_reject (data, cursor, len,
00391 common->sender_uid, gc);
00392 break;
00393 case QQ_NORMAL_IM_FILE_APPROVE_UDP:
00394 qq_process_recv_file_accept (data, cursor, len,
00395 common->sender_uid, gc);
00396 break;
00397 case QQ_NORMAL_IM_FILE_REQUEST:
00398 qq_process_recv_file_request (data, cursor, len,
00399 common->sender_uid, gc);
00400 break;
00401 case QQ_NORMAL_IM_FILE_CANCEL:
00402 qq_process_recv_file_cancel (data, cursor, len,
00403 common->sender_uid, gc);
00404 break;
00405 case QQ_NORMAL_IM_FILE_NOTIFY:
00406 qq_process_recv_file_notify (data, cursor, len,
00407 common->sender_uid, gc);
00408 break;
00409 default:
00410 im_unprocessed = g_newa (qq_recv_normal_im_unprocessed, 1);
00411 im_unprocessed->common = common;
00412 im_unprocessed->unknown = *cursor;
00413 im_unprocessed->length = data + len - *cursor;
00414
00415 gaim_debug (GAIM_DEBUG_WARNING, "QQ",
00416 "Normal IM, unprocessed type [0x%04x]\n",
00417 common->normal_im_type);
00418 gaim_debug (GAIM_DEBUG_WARNING, "QQ",
00419 "Dump unknown part.\n%s",
00420 hex_dump_to_str (im_unprocessed->unknown,
00421 im_unprocessed->length));
00422 g_free (common->session_md5);
00423 return;
00424 }
00425
00426 g_free (common->session_md5);
00427 }
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475 void _qq_process_recv_sys_im(guint8 * data, guint8 ** cursor, gint data_len, GaimConnection * gc) {
00476 gint len;
00477 guint8 reply;
00478 gchar **segments, *msg_utf8;
00479
00480 g_return_if_fail(gc != NULL && data != NULL && data_len != 0);
00481
00482 if (*cursor >= (data + data_len - 1)) {
00483 gaim_debug(GAIM_DEBUG_WARNING, "QQ", "Received sys IM is empty\n");
00484 return;
00485 }
00486
00487 len = data + data_len - *cursor;
00488
00489 if (NULL == (segments = split_data(*cursor, len, "\x2f", 2)))
00490 return;
00491
00492 reply = strtol(segments[0], NULL, 10);
00493 if (reply == QQ_RECV_SYS_IM_KICK_OUT)
00494 gaim_debug(GAIM_DEBUG_WARNING, "QQ", "We are kicked out by QQ server\n");
00495 msg_utf8 = qq_to_utf8(segments[1], QQ_CHARSET_DEFAULT);
00496 gaim_notify_warning(gc, NULL, _("System Message"), msg_utf8);
00497
00498 }
00499
00500
00501
00502 void qq_send_packet_im(GaimConnection * gc, guint32 to_uid, gchar * msg, gint type) {
00503 qq_data *qd;
00504 guint8 *cursor, *raw_data;
00505 guint16 client_tag, normal_im_type;
00506 gint msg_len, raw_len, bytes;
00507 time_t now;
00508 gchar *md5, *msg_filtered;
00509 GData *attribs;
00510 gchar *font_size = NULL, *font_color = NULL, *font_name = NULL, *tmp;
00511 gboolean is_bold = FALSE, is_italic = FALSE, is_underline = FALSE;
00512 const gchar *start, *end, *last;
00513
00514 g_return_if_fail(gc != NULL && gc->proto_data != NULL);
00515
00516 qd = (qq_data *) gc->proto_data;
00517 client_tag = QQ_CLIENT;
00518 normal_im_type = QQ_NORMAL_IM_TEXT;
00519
00520 last = msg;
00521 while (gaim_markup_find_tag("font", last, &start, &end, &attribs)) {
00522 tmp = g_datalist_get_data(&attribs, "size");
00523 if (tmp) {
00524 if (font_size)
00525 g_free(font_size);
00526 font_size = g_strdup(tmp);
00527 }
00528 tmp = g_datalist_get_data(&attribs, "color");
00529 if (tmp) {
00530 if (font_color)
00531 g_free(font_color);
00532 font_color = g_strdup(tmp);
00533 }
00534 tmp = g_datalist_get_data(&attribs, "face");
00535 if (tmp) {
00536 if (font_name)
00537 g_free(font_name);
00538 font_name = g_strdup(tmp);
00539 }
00540
00541 g_datalist_clear(&attribs);
00542 last = end + 1;
00543 }
00544
00545 if (gaim_markup_find_tag("b", msg, &start, &end, &attribs)) {
00546 is_bold = TRUE;
00547 g_datalist_clear(&attribs);
00548 }
00549
00550 if (gaim_markup_find_tag("i", msg, &start, &end, &attribs)) {
00551 is_italic = TRUE;
00552 g_datalist_clear(&attribs);
00553 }
00554
00555 if (gaim_markup_find_tag("u", msg, &start, &end, &attribs)) {
00556 is_underline = TRUE;
00557 g_datalist_clear(&attribs);
00558 }
00559
00560 gaim_debug(GAIM_DEBUG_INFO, "QQ_MESG", "send mesg: %s\n", msg);
00561 msg_filtered = gaim_markup_strip_html(msg);
00562 msg_len = strlen(msg_filtered);
00563 now = time(NULL);
00564 md5 = _gen_session_md5(qd->uid, qd->session_key);
00565
00566 guint font_name_len, tail_len;
00567 font_name_len = (font_name) ? strlen(font_name) : DEFAULT_FONT_NAME_LEN;
00568 tail_len = font_name_len + QQ_SEND_IM_AFTER_MSG_HEADER_LEN + 1;
00569
00570 raw_len = QQ_SEND_IM_BEFORE_MSG_LEN + msg_len + tail_len;
00571 raw_data = g_newa(guint8, raw_len);
00572 cursor = raw_data;
00573 bytes = 0;
00574
00575
00576 bytes += create_packet_dw(raw_data, &cursor, qd->uid);
00577
00578 bytes += create_packet_dw(raw_data, &cursor, to_uid);
00579
00580 bytes += create_packet_w(raw_data, &cursor, client_tag);
00581
00582 bytes += create_packet_dw(raw_data, &cursor, qd->uid);
00583
00584 bytes += create_packet_dw(raw_data, &cursor, to_uid);
00585
00586 bytes += create_packet_data(raw_data, &cursor, md5, 16);
00587
00588 bytes += create_packet_w(raw_data, &cursor, normal_im_type);
00589
00590 bytes += create_packet_w(raw_data, &cursor, qd->send_seq);
00591
00592 bytes += create_packet_dw(raw_data, &cursor, (guint32) now);
00593
00594 bytes += create_packet_b(raw_data, &cursor, 0x00);
00595
00596 bytes += create_packet_b(raw_data, &cursor, qd->my_icon);
00597
00598 bytes += create_packet_w(raw_data, &cursor, 0x0000);
00599 bytes += create_packet_b(raw_data, &cursor, 0x00);
00600
00601 bytes += create_packet_b(raw_data, &cursor, 0x01);
00602
00603 bytes += create_packet_dw(raw_data, &cursor, 0x00000000);
00604
00605 bytes += create_packet_b(raw_data, &cursor, type);
00606
00607 bytes += create_packet_data(raw_data, &cursor, msg_filtered, msg_len);
00608 guint8 *send_im_tail = qq_get_send_im_tail(font_color, font_size, font_name, is_bold,
00609 is_italic, is_underline, tail_len);
00610 _qq_show_packet("QQ_MESG debug", send_im_tail, tail_len);
00611 bytes += create_packet_data(raw_data, &cursor, (gchar *) send_im_tail, tail_len);
00612
00613 _qq_show_packet("QQ_MESG raw", raw_data, cursor - raw_data);
00614
00615 if (bytes == raw_len)
00616 qq_send_cmd(gc, QQ_CMD_SEND_IM, TRUE, 0, TRUE, raw_data, cursor - raw_data);
00617 else
00618 gaim_debug(GAIM_DEBUG_ERROR, "QQ",
00619 "Fail creating send_im packet, expect %d bytes, build %d bytes\n", raw_len, bytes);
00620
00621 if (font_color)
00622 g_free(font_color);
00623 if (font_size)
00624 g_free(font_size);
00625 g_free(send_im_tail);
00626 g_free(msg_filtered);
00627 }
00628
00629
00630
00631 void qq_process_send_im_reply(guint8 * buf, gint buf_len, GaimConnection * gc)
00632 {
00633 qq_data *qd;
00634 gint len;
00635 guint8 *data, *cursor, reply;
00636
00637 g_return_if_fail(gc != NULL && gc->proto_data != NULL);
00638 g_return_if_fail(buf != NULL && buf_len != 0);
00639
00640 qd = gc->proto_data;
00641 len = buf_len;
00642 data = g_newa(guint8, len);
00643
00644 if (qq_crypt(DECRYPT, buf, buf_len, qd->session_key, data, &len)) {
00645 cursor = data;
00646 read_packet_b(data, &cursor, len, &reply);
00647 if (reply != QQ_SEND_IM_REPLY_OK)
00648 gaim_debug(GAIM_DEBUG_WARNING, "QQ", "Send IM fail\n");
00649 else
00650 gaim_debug(GAIM_DEBUG_INFO, "QQ", "IM ACK OK\n");
00651 } else
00652 gaim_debug(GAIM_DEBUG_ERROR, "QQ", "Error decrypt send im reply\n");
00653
00654 }
00655
00656
00657
00658
00659 void qq_process_recv_im(guint8 * buf, gint buf_len, guint16 seq, GaimConnection * gc) {
00660 qq_data *qd;
00661 gint len, bytes;
00662 guint8 *data, *cursor;
00663 qq_recv_im_header *im_header;
00664
00665 g_return_if_fail(gc != NULL && gc->proto_data != NULL);
00666 g_return_if_fail(buf != NULL && buf_len != 0);
00667
00668 qd = (qq_data *) gc->proto_data;
00669 len = buf_len;
00670 data = g_newa(guint8, len);
00671
00672 if (qq_crypt(DECRYPT, buf, buf_len, qd->session_key, data, &len)) {
00673 if (len < 16) {
00674 gaim_debug(GAIM_DEBUG_ERROR, "QQ", "IM is too short\n");
00675 return;
00676 } else
00677 _qq_send_packet_recv_im_ack(gc, seq, data);
00678
00679 cursor = data;
00680 bytes = 0;
00681 im_header = g_newa(qq_recv_im_header, 1);
00682 bytes += read_packet_dw(data, &cursor, len, &(im_header->sender_uid));
00683 bytes += read_packet_dw(data, &cursor, len, &(im_header->receiver_uid));
00684 bytes += read_packet_dw(data, &cursor, len, &(im_header->server_im_seq));
00685
00686 bytes += read_packet_data(data, &cursor, len, (guint8 *) & (im_header->sender_ip), 4);
00687 bytes += read_packet_w(data, &cursor, len, &(im_header->sender_port));
00688 bytes += read_packet_w(data, &cursor, len, &(im_header->im_type));
00689
00690 if (bytes != 20) {
00691 gaim_debug(GAIM_DEBUG_ERROR, "QQ",
00692 "Fail read recv IM header, expect 20 bytes, read %d bytes\n", bytes);
00693 return;
00694 }
00695
00696 if (im_header->receiver_uid != qd->uid) {
00697 gaim_debug(GAIM_DEBUG_ERROR, "QQ", "IM to [%d], NOT me\n", im_header->receiver_uid);
00698 return;
00699 }
00700
00701 switch (im_header->im_type) {
00702 case QQ_RECV_IM_TO_BUDDY:
00703 gaim_debug(GAIM_DEBUG_INFO, "QQ",
00704 "IM from buddy [%d], I am in his/her buddy list\n", im_header->sender_uid);
00705 _qq_process_recv_normal_im(data, &cursor, len, gc);
00706 break;
00707 case QQ_RECV_IM_TO_UNKNOWN:
00708 gaim_debug(GAIM_DEBUG_INFO, "QQ",
00709 "IM from buddy [%d], I am a stranger to him/her\n", im_header->sender_uid);
00710 _qq_process_recv_normal_im(data, &cursor, len, gc);
00711 break;
00712 case QQ_RECV_IM_UNKNOWN_GROUP_IM:
00713 case QQ_RECV_IM_TEMP_GROUP_IM:
00714 case QQ_RECV_IM_GROUP_IM:
00715 gaim_debug(GAIM_DEBUG_INFO, "QQ", "IM from group, internal_id [%d]\n", im_header->sender_uid);
00716
00717 qq_process_recv_group_im(data, &cursor, len, im_header->sender_uid, gc, im_header->im_type);
00718 break;
00719 case QQ_RECV_IM_ADD_TO_GROUP:
00720 gaim_debug(GAIM_DEBUG_INFO, "QQ",
00721 "IM from group, added by group internal_id [%d]\n", im_header->sender_uid);
00722
00723
00724 qq_process_recv_group_im_been_added(data, &cursor, len, im_header->sender_uid, gc);
00725 break;
00726 case QQ_RECV_IM_DEL_FROM_GROUP:
00727 gaim_debug(GAIM_DEBUG_INFO, "QQ",
00728 "IM from group, removed by group internal_ID [%d]\n", im_header->sender_uid);
00729
00730 qq_process_recv_group_im_been_removed(data, &cursor, len, im_header->sender_uid, gc);
00731 break;
00732 case QQ_RECV_IM_APPLY_ADD_TO_GROUP:
00733 gaim_debug(GAIM_DEBUG_INFO, "QQ",
00734 "IM from group, apply to join group internal_ID [%d]\n", im_header->sender_uid);
00735
00736 qq_process_recv_group_im_apply_join(data, &cursor, len, im_header->sender_uid, gc);
00737 break;
00738 case QQ_RECV_IM_APPROVE_APPLY_ADD_TO_GROUP:
00739 gaim_debug(GAIM_DEBUG_INFO, "QQ",
00740 "IM for group system info, approved by group internal_id [%d]\n",
00741 im_header->sender_uid);
00742
00743 qq_process_recv_group_im_been_approved(data, &cursor, len, im_header->sender_uid, gc);
00744 break;
00745 case QQ_RECV_IM_REJCT_APPLY_ADD_TO_GROUP:
00746 gaim_debug(GAIM_DEBUG_INFO, "QQ",
00747 "IM for group system info, rejected by group internal_id [%d]\n",
00748 im_header->sender_uid);
00749
00750 qq_process_recv_group_im_been_rejected(data, &cursor, len, im_header->sender_uid, gc);
00751 break;
00752 case QQ_RECV_IM_SYS_NOTIFICATION:
00753 gaim_debug(GAIM_DEBUG_INFO, "QQ",
00754 "IM from [%d], should be a system administrator\n", im_header->sender_uid);
00755 _qq_process_recv_sys_im(data, &cursor, len, gc);
00756 break;
00757 default:
00758 gaim_debug(GAIM_DEBUG_WARNING, "QQ",
00759 "IM from [%d], [0x%02x] %s is not processed\n",
00760 im_header->sender_uid,
00761 im_header->im_type, qq_get_recv_im_type_str(im_header->im_type));
00762 }
00763 } else
00764 gaim_debug(GAIM_DEBUG_ERROR, "QQ", "Error decrypt rev im\n");
00765
00766 }
00767
00768
00769