Mercurial > pidgin.yaz
changeset 14049:8294485b79db
[gaim-migrate @ 16662]
Enhanced protocol testing tools, primarily by designing a more useful interface for sending customized packets.
committer: Tailor Script <tailor@pidgin.im>
author | Mark Huetsch <markhuetsch> |
---|---|
date | Mon, 07 Aug 2006 06:17:13 +0000 |
parents | 9c4bec886220 |
children | 6342ffdeb3ac |
files | src/protocols/qq/qq.c src/protocols/qq/recv_core.c src/protocols/qq/send_core.h src/protocols/qq/utils.c src/protocols/qq/utils.h |
diffstat | 5 files changed, 167 insertions(+), 55 deletions(-) [+] |
line wrap: on
line diff
--- a/src/protocols/qq/qq.c Mon Aug 07 03:24:39 2006 +0000 +++ b/src/protocols/qq/qq.c Mon Aug 07 06:17:13 2006 +0000 @@ -28,6 +28,7 @@ #include "accountopt.h" #include "debug.h" +#include "gtkroomlist.h" #include "notify.h" #include "prefs.h" #include "prpl.h" @@ -586,12 +587,10 @@ } */ -/* static void _qq_menu_search_or_add_permanent_group(GaimPluginAction * action) { gaim_gtk_roomlist_dialog_show(); } -*/ /* static void _qq_menu_create_permanent_group(GaimPluginAction * action) @@ -659,57 +658,160 @@ // } } */ -/* -static void _qq_send_custom_packet(GaimConnection *gc, const gchar *packet) + +static gboolean _qq_parse_custom_packet_field(GaimRequestFields *fields, + const gchar *id, guint8 **value) { - guint16 cmd; - guint8 *buffer; - gint len; + GaimRequestField *field; + const gchar *str; + gint len, i; + gboolean success; + + success = FALSE; + field = gaim_request_fields_get_field(fields, id); + str = gaim_request_field_string_get_value(field); + if (str) { + success = TRUE; + if (strcmp(id, "uid") != 0) { + *value = hex_str_to_bytes(str, &len); + if (!*value || len != 2) + success = FALSE; + } else { + for (i = 0; i < strlen(str); i++) { + if (!g_ascii_isdigit(str[i])) { + success = FALSE; + break; + } + } + if (success) { + *(guint32 *) value = strtoul(str, NULL, 10); + if (errno == ERANGE) + success = FALSE; + } + } + } + if (!success) + gaim_debug(GAIM_DEBUG_ERROR, "QQ", "Invalid entry: %s\n", id); + return success; +} - if (!packet) { - gaim_debug(GAIM_DEBUG_ERROR, "QQ", "Null packet inputted!\n"); - return; +static gboolean _qq_parse_custom_packet_fields(GaimRequestFields *fields, + guint8 **client, guint8 **cmd, guint8 **seq, guint32 *uid, + guint8 **body, gint *body_len) +{ + GaimRequestField *field; + gboolean success; + + success = TRUE; + *client = *cmd = *seq = *body = NULL; + *uid = 0; + success = _qq_parse_custom_packet_field(fields, "client", client); + if (success) + success = _qq_parse_custom_packet_field(fields, "cmd", cmd); + if (success) + success = _qq_parse_custom_packet_field(fields, "uid", (guint8 **) uid); + if (success) + success = _qq_parse_custom_packet_field(fields, "seq", seq); + if (success) { + field = gaim_request_fields_get_field(fields, "body"); + *body = hex_str_to_bytes(gaim_request_field_string_get_value(field), + body_len); + } else { + if (*client) + g_free(*client); + if (*cmd) + g_free(*cmd); + if (*seq) + g_free(*seq); } - if (strlen(packet) > MAX_PACKET_SIZE * 2) { - gaim_debug(GAIM_DEBUG_ERROR, "QQ", "Packet inputted is too large!\n"); - return; - } - if (strlen(packet) < 4) { - gaim_debug(GAIM_DEBUG_ERROR, "QQ", "Packet is impossibly short!\n"); + return success; +} + +static void _qq_send_custom_packet_cb(GaimConnection *gc, GaimRequestFields *fields) +{ + guint32 uid; + guint8 *buf, *client, *cmd, *seq, *body, *cursor; + gint bytes, len; + qq_data *qd; + gboolean success; + + qd = (qq_data *) gc->proto_data; + + success = _qq_parse_custom_packet_fields(fields, &client, &cmd, + &seq, &uid, &body, &len); + if (!success) { + gaim_notify_error(gc, _("Error"), _("Invalid packet entry"), NULL); return; } - buffer = hex_str_to_bytes(packet); - if (!buffer) { - gaim_debug(GAIM_DEBUG_ERROR, "QQ", "Invalid packet inputted!\n"); - return; - } - // big endian - cmd = 256 * buffer[0] + buffer[1]; - gaim_debug(GAIM_DEBUG_INFO, "QQ", "Inputted CMD: %d\n", cmd); + if (body) + g_return_if_fail(len+12 <= MAX_PACKET_SIZE); - len = strlen(buffer) - 2; - packet = buffer + 2; + bytes = 0; + buf = g_newa(guint8, MAX_PACKET_SIZE); + cursor = buf; + /* QQ TCP packet has two bytes in the beginning to define packet length + * so I leave room here for size */ + if (qd->use_tcp) + bytes += create_packet_w(buf, &cursor, 0x0000); + bytes += create_packet_b(buf, &cursor, QQ_PACKET_TAG); + bytes += create_packet_w(buf, &cursor, *(guint16 *) client); + bytes += create_packet_w(buf, &cursor, *(guint16 *) cmd); + bytes += create_packet_w(buf, &cursor, *(guint16 *) seq); + bytes += create_packet_dw(buf, &cursor, uid); + if (body) { + bytes += create_packet_data(buf, &cursor, body, len); + g_free(body); + } + bytes += create_packet_b(buf, &cursor, QQ_PACKET_TAIL); - qq_send_cmd(gc, cmd, TRUE, 0, TRUE, packet, len); - - g_free(buffer); + gaim_debug(GAIM_DEBUG_INFO, "QQ", "Custom packet of length %i\n", bytes); + _qq_show_packet("Outgoing custom packet", buf, bytes); + + _qq_send_packet(gc, buf, bytes, *(guint16 *) cmd); + g_free(client); + g_free(cmd); + g_free(seq); } -*/ /* send a custom packet to the server - for protocol testing */ -/* static void _qq_menu_send_custom_packet(GaimPluginAction *action) { - GaimConnection *gc = (GaimConnection *) action->context; - g_return_if_fail(gc != NULL); - gaim_request_input(gc, _("Send Custom Packet"), - _("Enter the packet in hex here"), - _("Include the command and everything following"), - NULL, FALSE, FALSE, NULL, - _("Send"), G_CALLBACK(_qq_send_custom_packet), _("Cancel"), NULL, gc); + GaimConnection *gc; + GaimRequestFields *fields; + GaimRequestFieldGroup *group; + GaimRequestField *field; + gchar *tmp; + qq_data *qd; + + gc = (GaimConnection *) action->context; + qd = (qq_data *) gc->proto_data; + g_return_if_fail(gc != NULL && qd != NULL); + + fields = gaim_request_fields_new(); + group = gaim_request_field_group_new(_("Packet Elements")); + gaim_request_fields_add_group(fields, group); + tmp = g_strdup_printf("%04X", QQ_CLIENT); + field = gaim_request_field_string_new("client", _("Client (hex)"), tmp, FALSE); + g_free(tmp); + gaim_request_field_group_add_field(group, field); + field = gaim_request_field_string_new("cmd", _("Command (hex)"), "0000", FALSE); + gaim_request_field_group_add_field(group, field); + field = gaim_request_field_string_new("seq", _("Sequence (hex)"), "0000", FALSE); + gaim_request_field_group_add_field(group, field); + tmp = g_strdup_printf("%u", qd->uid); + field = gaim_request_field_string_new("uid", _("QQ Number (decimal)"), tmp, FALSE); + g_free(tmp); + gaim_request_field_group_add_field(group, field); + field = gaim_request_field_string_new("body", _("Body (hex)"), NULL, FALSE); + gaim_request_field_group_add_field(group, field); + + gaim_request_fields(gc, _("Send a custom packet"), + _("Send a custom packet"), NULL, fields, + _("Send"), G_CALLBACK(_qq_send_custom_packet_cb), + _("Cancel"), NULL, + gc); } -*/ /* protocol related menus */ static GList *_qq_actions(GaimPlugin *plugin, gpointer context) @@ -727,7 +829,7 @@ act = gaim_plugin_action_new(_("Show Login Information"), _qq_menu_show_login_info); m = g_list_append(m, act); - /* + /* act = gaim_plugin_action_new(_("Send Custom Packet"), _qq_menu_send_custom_packet); m = g_list_append(m, act); */ @@ -737,7 +839,7 @@ m = g_list_append(m, act); */ - /* XXX the old group gtk code needs to moved to the gaim UI before this can be used + /* act = gaim_plugin_action_new(_("Qun: Search a permanent Qun"), _qq_menu_search_or_add_permanent_group); m = g_list_append(m, act);
--- a/src/protocols/qq/recv_core.c Mon Aug 07 03:24:39 2006 +0000 +++ b/src/protocols/qq/recv_core.c Mon Aug 07 06:17:13 2006 +0000 @@ -90,6 +90,7 @@ data = g_newa(guint8, len); msg_utf8 = NULL; + _qq_show_packet("Processing unknown packet", buf, len); if (qq_crypt(DECRYPT, buf, buf_len, qd->session_key, data, &len)) { gaim_debug(GAIM_DEBUG_WARNING, "QQ", ">>> [%d] %s, %d bytes -> [default] decrypt and dump\n%s",
--- a/src/protocols/qq/send_core.h Mon Aug 07 03:24:39 2006 +0000 +++ b/src/protocols/qq/send_core.h Mon Aug 07 06:17:13 2006 +0000 @@ -28,9 +28,10 @@ #define QQ_CLIENT 0x0E1B +/* #define QQ_CLIENT 0x0F3F */ -gint -qq_send_cmd(GaimConnection *gc, - guint16 cmd, gboolean is_auto_seq, guint16 seq, gboolean need_ack, guint8 *data, gint len); +gint qq_send_cmd(GaimConnection *gc, guint16 cmd, gboolean is_auto_seq, guint16 seq, + gboolean need_ack, guint8 *data, gint len); +gint _qq_send_packet(GaimConnection * gc, guint8 *buf, gint len, guint16 cmd); #endif
--- a/src/protocols/qq/utils.c Mon Aug 07 03:24:39 2006 +0000 +++ b/src/protocols/qq/utils.c Mon Aug 07 06:17:13 2006 +0000 @@ -199,6 +199,8 @@ gchar *ret; int i; + g_return_val_if_fail(buffer != NULL, NULL); + stripped = g_string_new(""); for (i=0; i<strlen(buffer); i++) { if ((int) buffer[i] != 32) { @@ -214,12 +216,14 @@ /* Dumps an ASCII hex string to a string of bytes. The return should be freed later. * Returns NULL if a string with an odd number of nibbles is passed in or if buffer * isn't a valid hex string */ -guint8 *hex_str_to_bytes(const gchar *buffer) +guint8 *hex_str_to_bytes(const gchar *buffer, gint *out_len) { gchar *hex_str, *hex_buffer, *cursor, tmp; guint8 *bytes, nibble1, nibble2; - gint index, len; + gint index; + g_return_val_if_fail(buffer != NULL, NULL); + hex_buffer = strstrip(buffer); if (strlen(hex_buffer) % 2 != 0) { @@ -233,10 +237,11 @@ g_free(hex_buffer); index = 0; for (cursor = hex_str; cursor < hex_str + sizeof(gchar) * (strlen(hex_str)) - 1; cursor++) { - if (g_ascii_isdigit(*cursor)) {tmp = *cursor; nibble1 = atoi(&tmp); } - else if (g_ascii_isalpha(*cursor) && (gint) *cursor - 87 < 16) + if (g_ascii_isdigit(*cursor)) { + tmp = *cursor; nibble1 = atoi(&tmp); + } else if (g_ascii_isalpha(*cursor) && (gint) *cursor - 87 < 16) { nibble1 = (gint) *cursor - 87; - else { + } else { gaim_debug(GAIM_DEBUG_WARNING, "QQ", "Invalid char found in hex string!\n"); g_free(hex_str); @@ -244,18 +249,21 @@ } nibble1 = nibble1 << 4; cursor++; - if (g_ascii_isdigit(*cursor)) {tmp = *cursor; nibble2 = atoi(&tmp); } - else if (g_ascii_isalpha(*cursor) && (gint) (*cursor - 87) < 16) + if (g_ascii_isdigit(*cursor)) { + tmp = *cursor; nibble2 = atoi(&tmp); + } else if (g_ascii_isalpha(*cursor) && (gint) (*cursor - 87) < 16) { nibble2 = (gint) *cursor - 87; - else { + } else { + gaim_debug(GAIM_DEBUG_WARNING, "QQ", + "Invalid char found in hex string!\n"); g_free(hex_str); return NULL; } bytes[index++] = nibble1 + nibble2; } - len = strlen(hex_str) / 2; + *out_len = strlen(hex_str) / 2; g_free(hex_str); - return g_memdup(bytes, len); + return g_memdup(bytes, *out_len); } /* Dumps a chunk of raw data into an ASCII hex string. The return should be freed later. */
--- a/src/protocols/qq/utils.h Mon Aug 07 03:24:39 2006 +0000 +++ b/src/protocols/qq/utils.h Mon Aug 07 06:17:13 2006 +0000 @@ -43,7 +43,7 @@ void try_dump_as_gbk(guint8 *data, gint len); -guint8 *hex_str_to_bytes(const gchar *buf); +guint8 *hex_str_to_bytes(const gchar *buf, gint *out_len); gchar *hex_dump_to_str(const guint8 *buf, gint buf_len); #endif