static void request_change_memo(PurpleConnection *gc, guint32 bd_uid, gchar **segments) { gint bytes; /* Attention, length of each segment must be guint8(0~255), * so length of memo string is limited. * convert it to guint8 first before putting data */ guint seg_len; gint index; guint8 raw_data[MAX_PACKET_SIZE - 16] = {0}; purple_debug_info( "QQ", "request_change_memo\n" ); g_return_if_fail(NULL != gc && NULL != segments); bytes = 0; bytes += qq_put8(raw_data+bytes, QQ_BUDDY_MEMO_MODIFY); bytes += qq_put8(raw_data+bytes, 0x00); bytes += qq_put32(raw_data+bytes, (guint32)bd_uid); bytes += qq_put8(raw_data+bytes, 0x00); for (index = 0; index < QQ_MEMO_SIZE; index++) { seg_len = strlen(segments[index]); seg_len = seg_len & 0xff; bytes += qq_put8(raw_data+bytes, (guint8)seg_len); bytes += qq_putdata(raw_data+bytes, (const guint8 *)segments[index], (guint8)seg_len); } /* debug */ /* qq_show_packet("MEMO MODIFY", raw_data, bytes); */ qq_send_cmd(gc, QQ_CMD_BUDDY_MEMO, raw_data, bytes); }
/* this buddy needs authentication, text conversion is done at lowest level */ static void request_add_buddy_auth(PurpleConnection *gc, guint32 uid, const gchar response, const gchar *text) { guint8 raw_data[MAX_PACKET_SIZE - 16]; gint bytes; gchar *msg, uid_str[11]; guint8 bar; g_return_if_fail(uid != 0); g_snprintf(uid_str, sizeof(uid_str), "%u", uid); bar = 0x1f; bytes = 0; bytes += qq_putdata(raw_data + bytes, (guint8 *) uid_str, strlen(uid_str)); bytes += qq_put8(raw_data + bytes, bar); bytes += qq_put8(raw_data + bytes, response); if (text != NULL) { msg = utf8_to_qq(text, QQ_CHARSET_DEFAULT); bytes += qq_put8(raw_data + bytes, bar); bytes += qq_putdata(raw_data + bytes, (guint8 *) msg, strlen(msg)); g_free(msg); } qq_send_cmd(gc, QQ_CMD_ADD_BUDDY_AUTH, raw_data, bytes); }
static void request_add_buddy_auth_ex(PurpleConnection *gc, guint32 uid, const gchar *text, guint8 *auth, guint8 auth_len) { guint8 raw_data[MAX_PACKET_SIZE - 16]; gint bytes = 0; g_return_if_fail(uid != 0); bytes = 0; bytes += qq_put8(raw_data + bytes, 0x02); bytes += qq_put32(raw_data + bytes, uid); bytes += qq_put16(raw_data + bytes, 0); bytes += qq_put8(raw_data + bytes, 0); if (auth == NULL || auth_len <= 0) { bytes += qq_put8(raw_data + bytes, 0); } else { bytes += qq_put8(raw_data + bytes, auth_len); bytes += qq_putdata(raw_data + bytes, auth, auth_len); } bytes += qq_put8(raw_data + bytes, 1); /* ALLOW ADD ME FLAG */ bytes += qq_put8(raw_data + bytes, 0); /* group number? */ bytes += qq_put_vstr(raw_data + bytes, text, QQ_CHARSET_DEFAULT); qq_send_cmd(gc, QQ_CMD_ADD_BUDDY_AUTH_EX, raw_data, bytes); }
/* send an IM to uid_to */ static void request_send_im(PurpleConnection *gc, guint32 uid_to, gint type, qq_im_format *fmt, gchar *msg, guint8 id, guint8 frag_count, guint8 frag_index) { qq_data *qd; guint8 raw_data[MAX_PACKET_SIZE - 16]; guint16 im_type; gint bytes; time_t now; qd = (qq_data *) gc->proto_data; im_type = QQ_NORMAL_IM_TEXT; /* purple_debug_info("QQ", "Send IM %d-%d\n", frag_count, frag_index); */ bytes = 0; /* 000-003: receiver uid */ bytes += qq_put32(raw_data + bytes, qd->uid); /* 004-007: sender uid */ bytes += qq_put32(raw_data + bytes, uid_to); /* 008-009: sender client version */ bytes += qq_put16(raw_data + bytes, qd->client_tag); /* 010-013: receiver uid */ bytes += qq_put32(raw_data + bytes, qd->uid); /* 014-017: sender uid */ bytes += qq_put32(raw_data + bytes, uid_to); /* 018-033: md5 of (uid+session_key) */ bytes += qq_putdata(raw_data + bytes, qd->session_md5, 16); /* 034-035: message type */ bytes += qq_put16(raw_data + bytes, QQ_NORMAL_IM_TEXT); /* 036-037: sequence number */ bytes += qq_put16(raw_data + bytes, qd->send_seq); /* 038-041: send time */ now = time(NULL); bytes += qq_put32(raw_data + bytes, (guint32) now); /* 042-043: sender icon */ bytes += qq_put16(raw_data + bytes, qd->my_icon); /* 044-046: always 0x00 */ bytes += qq_put16(raw_data + bytes, 0x0000); bytes += qq_put8(raw_data + bytes, 0x00); /* 047-047: always use font attr */ bytes += qq_put8(raw_data + bytes, 0x01); /* 048-051: always 0x00 */ /* Fixme: frag_count, frag_index not working now */ bytes += qq_put8(raw_data + bytes, frag_count); bytes += qq_put8(raw_data + bytes, frag_index); bytes += qq_put8(raw_data + bytes, id); bytes += qq_put8(raw_data + bytes, 0); /* 052-052: text message type (normal/auto-reply) */ bytes += qq_put8(raw_data + bytes, type); /* 053- : msg ends with 0x00 */ bytes += qq_putdata(raw_data + bytes, (guint8 *)msg, strlen(msg)); if (frag_count == frag_index + 1) { bytes += qq_put8(raw_data + bytes, 0x20); /* add extra SPACE */ } bytes += qq_put_im_tail(raw_data + bytes, fmt); /* qq_show_packet("QQ_CMD_SEND_IM", raw_data, bytes); */ qq_send_cmd(gc, QQ_CMD_SEND_IM, raw_data, bytes); }
void qq_request_get_level_2007(PurpleConnection *gc, guint32 uid) { guint8 buf[16] = {0}; gint bytes = 0; bytes += qq_put8(buf + bytes, 0x08); bytes += qq_put32(buf + bytes, uid); bytes += qq_put8(buf + bytes, 0x00); qq_send_cmd(gc, QQ_CMD_GET_LEVEL, buf, bytes); }
/* send logout packets to QQ server */ void qq_send_packet_logout(PurpleConnection *gc) { gint i; qq_data *qd; qd = (qq_data *) gc->proto_data; for (i = 0; i < 4; i++) qq_send_cmd(gc, QQ_CMD_LOGOUT, FALSE, 0xffff, FALSE, qd->pwkey, QQ_KEY_LENGTH); qd->logged_in = FALSE; /* update login status AFTER sending logout packets */ }
void qq_request_get_level(PurpleConnection *gc, guint32 uid) { qq_data *qd = (qq_data *) gc->proto_data; guint8 buf[16] = {0}; gint bytes = 0; if (qd->client_version >= 2007) { bytes += qq_put8(buf + bytes, 0x02); } else { bytes += qq_put8(buf + bytes, 0x00); } bytes += qq_put32(buf + bytes, uid); qq_send_cmd(gc, QQ_CMD_GET_LEVEL, buf, bytes); }
/* send keep-alive packet to QQ server (it is a heart-beat) */ void qq_send_packet_keep_alive(GaimConnection *gc) { qq_data *qd; guint8 *raw_data, *cursor; qd = (qq_data *) gc->proto_data; raw_data = g_newa(guint8, 4); cursor = raw_data; /* In fact, we can send whatever we like to server * with this command, server return the same result including * the amount of online QQ users, my ip and port */ create_packet_dw(raw_data, &cursor, qd->uid); qq_send_cmd(gc, QQ_CMD_KEEP_ALIVE, TRUE, 0, TRUE, raw_data, 4); }
/* get all list, buddies & Quns with groupsid support */ void qq_send_packet_get_all_list_with_group(GaimConnection *gc, guint32 position) { guint8 *raw_data, *cursor; gint data_len; data_len = 10; raw_data = g_newa(guint8, data_len); cursor = raw_data; /* 0x01 download, 0x02, upload */ create_packet_b(raw_data, &cursor, 0x01); /* unknown 0x02 */ create_packet_b(raw_data, &cursor, 0x02); /* unknown 00 00 00 00 */ create_packet_dw(raw_data, &cursor, 0x00000000); create_packet_dw(raw_data, &cursor, position); qq_send_cmd(gc, QQ_CMD_GET_ALL_LIST_WITH_GROUP, TRUE, 0, TRUE, raw_data, data_len); }
/* position starts with 0x0000, * server may return a position tag if list is too long for one packet */ void qq_send_packet_get_buddies_list(GaimConnection *gc, guint16 position) { guint8 *raw_data, *cursor; gint data_len; data_len = 3; raw_data = g_newa(guint8, data_len); cursor = raw_data; /* 000-001 starting position, can manually specify */ create_packet_w(raw_data, &cursor, position); /* before Mar 18, 2004, any value can work, and we sent 00 * I do not know what data QQ server is expecting, as QQ2003iii 0304 itself * even can sending packets 00 and get no response. * Now I tested that 00,00,00,00,00,01 work perfectly * March 22, found the 00,00,00 starts to work as well */ create_packet_b(raw_data, &cursor, 0x00); qq_send_cmd(gc, QQ_CMD_GET_FRIENDS_LIST, TRUE, 0, TRUE, raw_data, data_len); }
static void request_buddy_check_code(PurpleConnection *gc, gchar *from, guint8 *code, gint code_len) { guint8 *raw_data; gint bytes; guint32 uid; g_return_if_fail(code != NULL && code_len > 0 && from != NULL); uid = strtoul(from, NULL, 10); raw_data = g_newa(guint8, code_len + 16); bytes = 0; bytes += qq_put8(raw_data + bytes, 0x03); bytes += qq_put8(raw_data + bytes, 0x01); bytes += qq_put32(raw_data + bytes, uid); bytes += qq_put16(raw_data + bytes, code_len); bytes += qq_putdata(raw_data + bytes, code, code_len); qq_send_cmd(gc, QQ_CMD_BUDDY_CHECK_CODE, raw_data, bytes); }
static void request_add_buddy_by_question(PurpleConnection *gc, guint32 uid, guint8 *code, guint16 code_len) { guint8 raw_data[MAX_PACKET_SIZE - 16]; gint bytes = 0; g_return_if_fail(uid != 0 && code_len > 0); bytes = 0; bytes += qq_put8(raw_data + bytes, 0x10); bytes += qq_put32(raw_data + bytes, uid); bytes += qq_put16(raw_data + bytes, 0); bytes += qq_put8(raw_data + bytes, 0); bytes += qq_put8(raw_data + bytes, 0); /* no auth code */ bytes += qq_put16(raw_data + bytes, code_len); bytes += qq_putdata(raw_data + bytes, code, code_len); bytes += qq_put8(raw_data + bytes, 1); /* ALLOW ADD ME FLAG */ bytes += qq_put8(raw_data + bytes, 0); /* group number? */ qq_send_cmd(gc, QQ_CMD_ADD_BUDDY_AUTH_EX, raw_data, bytes); }
/* send packet to modify personal information */ static void request_change_info(PurpleConnection *gc, gchar **segments) { gint bytes = 0; guint8 raw_data[MAX_PACKET_SIZE - 128] = {0}; guint8 bar; gchar *join; g_return_if_fail(segments != NULL); bar = 0x1f; bytes += qq_put8(raw_data + bytes, bar); bytes += qq_put8(raw_data + bytes, bar); /* important! skip the first uid entry */ join = g_strjoinv("\x1f", segments + 1); bytes += qq_putdata(raw_data + bytes, (guint8 *)join, strlen(join)); g_free(join); bytes += qq_put8(raw_data + bytes, bar); /* qq_show_packet("request_modify_info", raw_data, bytes); */ qq_send_cmd(gc, QQ_CMD_UPDATE_INFO, raw_data, bytes); }
/* get a list of online_buddies */ void qq_send_packet_get_buddies_online(GaimConnection *gc, guint8 position) { qq_data *qd; guint8 *raw_data, *cursor; qd = (qq_data *) gc->proto_data; raw_data = g_newa(guint8, 5); cursor = raw_data; /* 000-000 get online friends cmd * only 0x02 and 0x03 returns info from server, other valuse all return 0xff * I can also only send the first byte (0x02, or 0x03) * and the result is the same */ create_packet_b(raw_data, &cursor, QQ_GET_ONLINE_BUDDY_02); /* 001-001 seems it supports 255 online buddies at most */ create_packet_b(raw_data, &cursor, position); /* 002-002 */ create_packet_b(raw_data, &cursor, 0x00); /* 003-004 */ create_packet_w(raw_data, &cursor, 0x0000); qq_send_cmd(gc, QQ_CMD_GET_FRIENDS_ONLINE, TRUE, 0, TRUE, raw_data, 5); qd->last_get_online = time(NULL); }