diff src/protocols/qq/qq.c @ 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 80891029f5dd
children f78289db8977
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);