# HG changeset patch # User Jeffrey Connelly # Date 1180752223 0 # Node ID 37499e926a42166be7663cf55e73f2fea4648467 # Parent 9ecd2bb0ecc10ff2fd537fdccb7700b818be1813 Add new MsimMessage element type, MSIM_TYPE_RAW, for fields in incoming protocol messages that don't have any type information associated with them. These elements will be unescaped if used as strings, in msim_msg_get_string(), and won't be escaped if serialized into a protocol message in msim_msg_element_pack(). On the other hand, MSIM_TYPE_STRING will be escaped when packed. Previously, everything was MSIM_TYPE_STRING, leading to more complicated escaping. Now, an instant message "foo/bar\baz" will be represented as follows: bm(raw): 1 f(raw): 180301984 cv(raw): 673 msg(raw): foo/1bar/2baz And it will be interpreted by the receiving client correctly-- msim_msg_get_string(..., "msg") will be "foo/bar\baz". diff -r 9ecd2bb0ecc1 -r 37499e926a42 libpurple/protocols/myspace/message.c --- a/libpurple/protocols/myspace/message.c Fri Jun 01 06:20:23 2007 +0000 +++ b/libpurple/protocols/myspace/message.c Sat Jun 02 02:43:43 2007 +0000 @@ -25,7 +25,7 @@ static void msim_msg_free_element(gpointer data, gpointer user_data); static void msim_msg_debug_string_element(gpointer data, gpointer user_data); static gchar *msim_msg_pack_using(MsimMessage *msg, GFunc gf, gchar *sep, gchar *begin, gchar *end); -static gchar *msim_msg_element_as_string(MsimMessageElement *elem); +static gchar *msim_msg_element_pack(MsimMessageElement *elem); MsimMessage *msim_msg_new(void) { @@ -47,6 +47,7 @@ /* Integer value stored in gpointer - no need to free(). */ break; + case MSIM_TYPE_RAW: /* Fall through */ case MSIM_TYPE_STRING: /* Always free strings - caller should have g_strdup()'d if * string was static or temporary and not to be freed. */ @@ -197,6 +198,8 @@ * * * MSIM_TYPE_STRING: gchar *. The data WILL BE FREED - use g_strdup() if needed. * + * * MSIM_TYPE_RAW: gchar *. The data WILL BE FREED - use g_strdup() if needed. + * * * MSIM_TYPE_BINARY: g_string_new_len(data, length). The data AND GString will be freed. * * * MSIM_TYPE_DICTIONARY: TODO @@ -272,6 +275,10 @@ string = g_strdup_printf("%s(integer): %d", elem->name, GPOINTER_TO_UINT(elem->data)); break; + case MSIM_TYPE_RAW: + string = g_strdup_printf("%s(raw): %s", elem->name, (gchar *)elem->data); + break; + case MSIM_TYPE_STRING: string = g_strdup_printf("%s(string): %s", elem->name, (gchar *)elem->data); break; @@ -321,17 +328,25 @@ return msim_msg_pack_using(msg, msim_msg_debug_string_element, "\n", ""); } -/** Return a message element data as a new string, converting from other types (integer, etc.) if necessary. +/** Return a message element data as a new string for a raw protocol message, converting from other types (integer, etc.) if necessary. * * @return gchar * The data as a string, or NULL. Caller must g_free(). + * + * Returns a string suitable for inclusion in a raw protocol message, not necessarily + * optimal for human consumption. For example, strings are escaped. Use + * msim_msg_get_string() if you want a string, which in some cases is same as this. */ -static gchar *msim_msg_element_as_string(MsimMessageElement *elem) +static gchar *msim_msg_element_pack(MsimMessageElement *elem) { switch (elem->type) { case MSIM_TYPE_INTEGER: return g_strdup_printf("%d", GPOINTER_TO_UINT(elem->data)); + case MSIM_TYPE_RAW: + /* Not un-escaped - this is a raw element, already escaped if necessary. */ + return (gchar *)elem->data; + case MSIM_TYPE_STRING: /* Strings get escaped. msim_escape() creates a new string. */ return msim_escape((gchar *)elem->data); @@ -383,12 +398,13 @@ elem = (MsimMessageElement *)data; items = user_data; - data_string = msim_msg_element_as_string(elem); + data_string = msim_msg_element_pack(elem); switch (elem->type) { - /* These types are represented by key name/value pairs. */ + /* These types are represented by key name/value pairs (converted above). */ case MSIM_TYPE_INTEGER: + case MSIM_TYPE_RAW: case MSIM_TYPE_STRING: case MSIM_TYPE_BINARY: case MSIM_TYPE_DICTIONARY: @@ -477,13 +493,12 @@ if (i % 2) { /* Odd-numbered ordinal is a value. */ + value = token; - /* Note: returns a new string. */ - value = msim_unescape(token); - - /* Always append strings, since protocol has no incoming - * type information for each field. */ - msg = msim_msg_append(msg, g_strdup(key), MSIM_TYPE_STRING, value); + /* Incoming protocol messages get tagged as MSIM_TYPE_RAW, which + * represents an untyped piece of data. msim_msg_get_* will + * convert to appropriate types for caller, and handle unescaping if needed. */ + msg = msim_msg_append(msg, g_strdup(key), MSIM_TYPE_RAW, g_strdup(value)); #ifdef MSIM_DEBUG_PARSE purple_debug_info("msim", "insert string: |%s|=|%s|\n", key, value); #endif @@ -596,7 +611,11 @@ * * @param name Name of element. * - * @return gchar * The message string. Caller must g_free(). + * @return gchar * The data as a string. Caller must g_free(). + * + * Note that msim_msg_element_pack() is similar, but returns a string + * for inclusion into a raw protocol string (escaped and everything). + * This function unescapes the string for you, if needed. */ gchar *msim_msg_get_string(MsimMessage *msg, gchar *name) { @@ -606,7 +625,25 @@ if (!elem) return NULL; - return msim_msg_element_as_string(elem); + switch (elem->type) + { + case MSIM_TYPE_INTEGER: + return g_strdup_printf("%d", GPOINTER_TO_UINT(elem->data)); + + case MSIM_TYPE_RAW: + /* Raw element from incoming message - if its a string, it'll + * be escaped. */ + return msim_unescape((gchar *)elem->data); + + case MSIM_TYPE_STRING: + /* Already unescaped. */ + return (gchar *)elem->data; + + default: + purple_debug_info("msim", "msim_msg_get_string: type %d unknown, name %s\n", + elem->type, name); + return NULL; + } } /** Return the data of an element of a given name, as an integer. @@ -630,6 +667,7 @@ case MSIM_TYPE_INTEGER: return GPOINTER_TO_UINT(elem->data); + case MSIM_TYPE_RAW: case MSIM_TYPE_STRING: /* TODO: find out if we need larger integers */ return (guint)atoi((gchar *)elem->data); @@ -655,24 +693,26 @@ switch (elem->type) { - case MSIM_TYPE_STRING: - /* Currently, incoming messages get stored as MSIM_TYPE_STRING. - * This is fine for integers and strings, since they can easily be - * converted in msim_get_*, as desirable. However, it may not work + case MSIM_TYPE_RAW: + /* Incoming messages are tagged with MSIM_TYPE_RAW, and + * converted appropriately. They can still be "strings", just they won't + * be tagged as MSIM_TYPE_STRING (as MSIM_TYPE_STRING is intended to be used + * by msimprpl code for things like instant messages - stuff that should be + * escaped if needed). DWIM. + */ + + /* Previously, incoming messages were stored as MSIM_TYPE_STRING. + * This was fine for integers and strings, since they can easily be + * converted in msim_get_*, as desirable. However, it does not work * well for binary strings. Consider: * - * Incoming base64'd elements get tagged as MSIM_TYPE_STRING. + * If incoming base64'd elements were tagged as MSIM_TYPE_STRING. * msim_msg_get_binary() sees MSIM_TYPE_STRING, base64 decodes, returns. * everything is fine. * But then, msim_send() is called on the incoming message, which has * a base64'd MSIM_TYPE_STRING that really is encoded binary. The values * will be escaped since strings are escaped, and / becomes /2; no good. * - * TODO: Make incoming messages be tagged with MSIM_TYPE_UNKNOWN, and - * converted appropriately. They can still be "strings", just they won't - * be tagged as MSIM_TYPE_STRING (as MSIM_TYPE_STRING is intended to be used - * by msimprpl code for things like instant messages - stuff that should be - * escaped if needed). DWIM. */ *binary_data = (gchar *)purple_base64_decode((const gchar *)elem->data, binary_length); return TRUE; @@ -699,6 +739,8 @@ * return (GString *)elem->data; */ default: + purple_debug_info("msim", "msim_msg_get_binary: unhandled type %d for key %s\n", + elem->type, name); return FALSE; } } diff -r 9ecd2bb0ecc1 -r 37499e926a42 libpurple/protocols/myspace/message.h --- a/libpurple/protocols/myspace/message.h Fri Jun 01 06:20:23 2007 +0000 +++ b/libpurple/protocols/myspace/message.h Sat Jun 02 02:43:43 2007 +0000 @@ -36,6 +36,7 @@ typedef gchar MsimMessageType; /* Protocol field types */ +#define MSIM_TYPE_RAW '-' #define MSIM_TYPE_INTEGER 'i' #define MSIM_TYPE_STRING 's' #define MSIM_TYPE_BINARY 'b'