# HG changeset patch # User Mark Doliner # Date 1154756427 0 # Node ID c070fdec12a3f97813f5b8dea9badc7d596b70c6 # Parent 49e020487c82f774d9697a1f550e0c0f55808c7d [gaim-migrate @ 16635] Make Yahoo! packet parsing not allocate stuff twice. Who wrote this?? committer: Tailor Script diff -r 49e020487c82 -r c070fdec12a3 src/protocols/yahoo/yahoo_packet.c --- a/src/protocols/yahoo/yahoo_packet.c Sat Aug 05 04:07:52 2006 +0000 +++ b/src/protocols/yahoo/yahoo_packet.c Sat Aug 05 05:40:27 2006 +0000 @@ -43,7 +43,7 @@ struct yahoo_pair *pair = g_new0(struct yahoo_pair, 1); pair->key = key; pair->value = g_strdup(value); - pkt->hash = g_slist_append(pkt->hash, pair); + pkt->hash = g_slist_prepend(pkt->hash, pair); } void yahoo_packet_hash_int(struct yahoo_packet *pkt, int key, int value) @@ -52,7 +52,7 @@ pair->key = key; pair->value = g_strdup_printf("%d", value); - pkt->hash = g_slist_append(pkt->hash, pair); + pkt->hash = g_slist_prepend(pkt->hash, pair); } void yahoo_packet_hash(struct yahoo_packet *pkt, const char *fmt, ...) @@ -105,17 +105,16 @@ return len; } -void yahoo_packet_read(struct yahoo_packet *pkt, guchar *data, int len) +void yahoo_packet_read(struct yahoo_packet *pkt, const guchar *data, int len) { int pos = 0; + char key[64], *delimiter, *esc; + gboolean accept; + int x; + struct yahoo_pair *pair; - while (pos + 1 < len) { - char key[64], *value = NULL, *esc; - int accept; - int x; - - struct yahoo_pair *pair = g_new0(struct yahoo_pair, 1); - + while (pos + 1 < len) + { /* this is weird, and in one of the chat packets, and causes us to * think all the values are keys and all the keys are values after * this point if we don't handle it */ @@ -126,10 +125,11 @@ pos++; } pos += 2; - g_free(pair); continue; } + pair = g_new0(struct yahoo_pair, 1); + x = 0; while (pos + 1 < len) { if (data[pos] == 0xc0 && data[pos + 1] == 0x80) @@ -151,25 +151,29 @@ if (len - pos + 1 <= 0) { /* Truncated. Garbage or something. */ - accept = 0; + accept = FALSE; } if (accept) { - value = g_malloc(len - pos + 1); - x = 0; - while (pos + 1 < len) { - if (data[pos] == 0xc0 && data[pos + 1] == 0x80) - break; - value[x++] = data[pos++]; + delimiter = strstr((char *)&data[pos], "\xc0\x80"); + if (delimiter == NULL) + { + /* Malformed packet! (it doesn't end in 0xc0 0x80) */ + g_free(pair); + pos = len; + continue; } - value[x] = 0; - pair->value = g_strdup(value); - g_free(value); - pkt->hash = g_slist_append(pkt->hash, pair); + x = (guint64)delimiter - (guint64)data; + pair->value = g_strndup((const gchar *)&data[pos], x - pos); + pos = x; + pkt->hash = g_slist_prepend(pkt->hash, pair); + +#ifdef DEBUG esc = g_strescape(pair->value, NULL); gaim_debug(GAIM_DEBUG_MISC, "yahoo", "Key: %d \tValue: %s\n", pair->key, esc); g_free(esc); +#endif } else { g_free(pair); } @@ -179,6 +183,16 @@ if (data[0] == '9' && data[pos] == 0x01) pos++; } + + /* + * Originally this function used g_slist_append(). I changed + * it to use g_slist_prepend() for improved performance. + * Ideally the Yahoo! PRPL code would be indifferent to the + * order of the key/value pairs, but I don't know if this is + * the case for all incoming messages. To be on the safe side + * we reverse the list. + */ + pkt->hash = g_slist_reverse(pkt->hash); } void yahoo_packet_write(struct yahoo_packet *pkt, guchar *data)