static gint send_room_cmd(PurpleConnection *gc, guint8 room_cmd, guint32 room_id, guint8 *data, gint data_len, UPDCLS update_class, guint32 ship32) { qq_data *qd; guint8 *buf; gint buf_len; guint8 *encrypted; gint encrypted_len; gint bytes_sent; guint16 seq; g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, -1); qd = (qq_data *) gc->proto_data; buf = g_newa(guint8, MAX_PACKET_SIZE); memset(buf, 0, MAX_PACKET_SIZE); /* encap room_cmd and room id to buf*/ buf_len = 0; buf_len += qq_put8(buf + buf_len, room_cmd); if (room_id != 0) { /* id 0 is for QQ Demo Group, now they are closed*/ buf_len += qq_put32(buf + buf_len, room_id); } if (data != NULL && data_len > 0) { buf_len += qq_putdata(buf + buf_len, data, data_len); } qd->send_seq++; seq = qd->send_seq; /* Encrypt to encrypted with session_key */ /* at most 17 bytes more */ encrypted = g_newa(guint8, buf_len + 17); encrypted_len = qq_encrypt(encrypted, buf, buf_len, qd->session_key); if (encrypted_len < 16) { purple_debug_error("QQ_ENCRYPT", "Error len %d: [%05d] %s (0x%02X)\n", encrypted_len, seq, qq_get_room_cmd_desc(room_cmd), room_cmd); return -1; } bytes_sent = packet_send_out(gc, QQ_CMD_ROOM, seq, encrypted, encrypted_len); #if 1 /* qq_show_packet("send_room_cmd", buf, buf_len); */ purple_debug_info("QQ", "<== [%05d] %s (0x%02X) to room %d, datalen %d\n", seq, qq_get_room_cmd_desc(room_cmd), room_cmd, room_id, buf_len); #endif qq_trans_add_room_cmd(gc, seq, room_cmd, room_id, encrypted, encrypted_len, update_class, ship32); return bytes_sent; }
static void process_room_cmd_notify(PurpleConnection *gc, guint8 room_cmd, guint8 room_id, guint8 reply, guint8 *data, gint data_len) { gchar *prim; gchar *msg, *msg_utf8; g_return_if_fail(data != NULL && data_len > 0); msg = g_strndup((gchar *) data, data_len); /* it will append 0x00 */ msg_utf8 = qq_to_utf8(msg, QQ_CHARSET_DEFAULT); g_free(msg); prim = g_strdup_printf(_("Error reply of %s(0x%02X)\nRoom %u, reply 0x%02X"), qq_get_room_cmd_desc(room_cmd), room_cmd, room_id, reply); purple_notify_error(gc, _("QQ Qun Command"), prim, msg_utf8); g_free(prim); g_free(msg_utf8); }
void qq_proc_room_cmds(PurpleConnection *gc, guint16 seq, guint8 room_cmd, guint32 room_id, guint8 *rcved, gint rcved_len, guint32 update_class, guintptr ship_value) { qq_data *qd; guint8 *data; gint data_len; qq_room_data *rmd; gint bytes; guint8 reply_cmd, reply; g_return_if_fail (gc != NULL && gc->proto_data != NULL); qd = (qq_data *) gc->proto_data; data = g_newa(guint8, rcved_len); data_len = qq_decrypt(data, rcved, rcved_len, qd->session_key); if (data_len < 0) { purple_debug_warning("QQ", "Can not decrypt room cmd by session key, [%05d], 0x%02X %s for %d, len %d\n", seq, room_cmd, qq_get_room_cmd_desc(room_cmd), room_id, rcved_len); qq_show_packet("Can not decrypted", rcved, rcved_len); return; } if (room_id <= 0) { purple_debug_warning("QQ", "room id is 0, [%05d], 0x%02X %s for %d, len %d\n", seq, room_cmd, qq_get_room_cmd_desc(room_cmd), room_id, rcved_len); /* Some room cmd has no room id, like QQ_ROOM_CMD_SEARCH */ } if (data_len <= 2) { purple_debug_warning("QQ", "Invaild len of room cmd decrypted, [%05d], 0x%02X %s for %d, len %d\n", seq, room_cmd, qq_get_room_cmd_desc(room_cmd), room_id, rcved_len); return; } bytes = 0; bytes += qq_get8(&reply_cmd, data + bytes); bytes += qq_get8(&reply, data + bytes); if (reply_cmd != room_cmd) { purple_debug_warning("QQ", "Missing room cmd in reply 0x%02X %s, [%05d], 0x%02X %s for %d, len %d\n", reply_cmd, qq_get_room_cmd_desc(reply_cmd), seq, room_cmd, qq_get_room_cmd_desc(room_cmd), room_id, rcved_len); } /* now process the packet */ if (reply != QQ_ROOM_CMD_REPLY_OK) { switch (reply) { /* this should be all errors */ case QQ_ROOM_CMD_REPLY_NOT_MEMBER: rmd = qq_room_data_find(gc, room_id); if (rmd == NULL) { purple_debug_warning("QQ", "Missing room id in [%05d], 0x%02X %s for %d, len %d\n", seq, room_cmd, qq_get_room_cmd_desc(room_cmd), room_id, rcved_len); } else { purple_debug_warning("QQ", "Not a member of room \"%s\"\n", rmd->name); rmd->my_role = QQ_ROOM_ROLE_NO; } break; case QQ_ROOM_CMD_REPLY_SEARCH_ERROR: if (qd->roomlist != NULL) { if (purple_roomlist_get_in_progress(qd->roomlist)) purple_roomlist_set_in_progress(qd->roomlist, FALSE); } default: process_room_cmd_notify(gc, reply_cmd, room_id, reply, data + bytes, data_len - bytes); } return; } /* seems ok so far, so we process the reply according to sub_cmd */ switch (reply_cmd) { case QQ_ROOM_CMD_GET_QUN_LIST: qq_process_room_cmd_get_qun_list(data + bytes, data_len - bytes, gc); break; case QQ_ROOM_CMD_GET_INFO: qq_process_room_cmd_get_info(data + bytes, data_len - bytes, ship_value, gc); break; case QQ_ROOM_CMD_CREATE: qq_group_process_create_group_reply(data + bytes, data_len - bytes, gc); break; case QQ_ROOM_CMD_CHANGE_INFO: qq_group_process_modify_info_reply(data + bytes, data_len - bytes, gc); break; case QQ_ROOM_CMD_MEMBER_OPT: qq_group_process_modify_members_reply(data + bytes, data_len - bytes, gc); break; case QQ_ROOM_CMD_ACTIVATE: qq_group_process_activate_group_reply(data + bytes, data_len - bytes, gc); break; case QQ_ROOM_CMD_SEARCH: qq_process_room_search(gc, data + bytes, data_len - bytes, ship_value); break; case QQ_ROOM_CMD_JOIN: qq_process_group_cmd_join_group(data + bytes, data_len - bytes, gc); break; case QQ_ROOM_CMD_AUTH: qq_process_group_cmd_join_group_auth(data + bytes, data_len - bytes, gc); break; case QQ_ROOM_CMD_QUIT: qq_process_group_cmd_exit_group(data + bytes, data_len - bytes, gc); break; case QQ_ROOM_CMD_SEND_IM: qq_process_room_send_im(gc, data + bytes, data_len - bytes); break; case QQ_ROOM_CMD_GET_ONLINES: qq_process_room_cmd_get_onlines(data + bytes, data_len - bytes, gc); break; case QQ_ROOM_CMD_GET_MEMBERS_INFO: qq_process_room_cmd_get_members_info(data + bytes, data_len - bytes, ship_value, gc); break; default: purple_debug_warning("QQ", "Unknown room cmd 0x%02X %s\n", reply_cmd, qq_get_room_cmd_desc(reply_cmd)); } if (update_class == QQ_CMD_CLASS_NONE) return; if (update_class == QQ_CMD_CLASS_UPDATE_ALL) { qq_update_all_rooms(gc, room_cmd, room_id); return; } if (update_class == QQ_CMD_CLASS_UPDATE_ONLINE) { update_all_rooms_online(gc, room_cmd, room_id); return; } if (update_class == QQ_CMD_CLASS_UPDATE_ROOM) { qq_update_room(gc, room_cmd, room_id); } }