# HG changeset patch # User Yoshiki Yazawa # Date 1265180449 -32400 # Node ID e3031e5785a315e7203d9ef65bd2422e8a88d245 # Parent 06740353bfc7d7d3db001cfadbe42cc57b949273# Parent 4d50162d809e4916722d9d5d53024eda7afb9615 merged with im.pidgin.pidgin diff -r 06740353bfc7 -r e3031e5785a3 COPYRIGHT --- a/COPYRIGHT Fri Jan 29 13:00:26 2010 +0900 +++ b/COPYRIGHT Wed Feb 03 16:00:49 2010 +0900 @@ -379,6 +379,7 @@ R. Ramkumar Mart Raudsepp Etan Reisner +Luoh Ren-Shan Kristian Rietveld Pekka Riikonen Tim Ringenbach @@ -390,6 +391,7 @@ Luciano Miguel Ferreira Rocha Andrew Rodland Miguel Rodríguez (migrax) +Adi Roiban Martin Rosinski Bob Rossi Jason Roth diff -r 06740353bfc7 -r e3031e5785a3 ChangeLog --- a/ChangeLog Fri Jan 29 13:00:26 2010 +0900 +++ b/ChangeLog Wed Feb 03 16:00:49 2010 +0900 @@ -31,6 +31,8 @@ offline. * Wrap XHTML messages in

, as described in XEP-0071, for compatibility with some clients. + * Don't do an SRV lookup for a STUN server associated with the account + if one is already set globally in prefs. Yahoo: * Don't send and tags. (Fartash Faghri) @@ -40,6 +42,7 @@ interior-focus style property is diabled. (Gabriel Schulhof) * Correctly handle a multiline text field being required in a request form. (Thanks to Florian Zeitz for finding this problem) + * Search friends by email-addresses in the buddy list. (Luoh Ren-Shan) version 2.6.5 (01/08/2010): libpurple: diff -r 06740353bfc7 -r e3031e5785a3 libpurple/dnssrv.c --- a/libpurple/dnssrv.c Fri Jan 29 13:00:26 2010 +0900 +++ b/libpurple/dnssrv.c Wed Feb 03 16:00:49 2010 +0900 @@ -366,7 +366,7 @@ cp += 6; GETSHORT(dlen,cp); - if (query.type == T_SRV) { + if (type == T_SRV) { GETSHORT(pref,cp); GETSHORT(weight,cp); @@ -386,7 +386,7 @@ srvres->weight = weight; ret = g_list_prepend(ret, srvres); - } else if (query.type == T_TXT) { + } else if (type == T_TXT) { txtres = g_new0(PurpleTxtResponse, 1); txtres->content = g_strndup((gchar*)(++cp), dlen-1); ret = g_list_append(ret, txtres); diff -r 06740353bfc7 -r e3031e5785a3 libpurple/protocols/jabber/disco.c --- a/libpurple/protocols/jabber/disco.c Fri Jan 29 13:00:26 2010 +0900 +++ b/libpurple/protocols/jabber/disco.c Wed Feb 03 16:00:49 2010 +0900 @@ -22,6 +22,7 @@ */ #include "internal.h" +#include "network.h" #include "prefs.h" #include "debug.h" #include "request.h" @@ -534,8 +535,12 @@ js->googletalk = TRUE; /* autodiscover stun and relays */ - jabber_google_send_jingle_info(js); - } else { + if (purple_network_get_stun_ip() == NULL || + purple_strequal(purple_network_get_stun_ip(), "")) { + jabber_google_send_jingle_info(js); + } + } else if (purple_network_get_stun_ip() == NULL || + purple_strequal(purple_network_get_stun_ip(), "")) { js->srv_query_data = purple_srv_resolve("stun", "udp", js->user->domain, jabber_disco_stun_srv_resolve_cb, js); diff -r 06740353bfc7 -r e3031e5785a3 libpurple/protocols/oscar/family_oservice.c --- a/libpurple/protocols/oscar/family_oservice.c Fri Jan 29 13:00:26 2010 +0900 +++ b/libpurple/protocols/oscar/family_oservice.c Wed Feb 03 16:00:49 2010 +0900 @@ -27,6 +27,24 @@ #include "cipher.h" +/* + * Each time we make a FLAP connection to an oscar server the server gives + * us a list of rate classes. Each rate class has different properties for + * how frequently we can send SNACs in that rate class before we become + * throttled or disconnected. + * + * The server also gives us a list of every available SNAC and tells us which + * rate class it's in. There are a lot of different SNACs, so this list can be + * fairly large. One important characteristic of these rate classes is that + * currently (and since at least 2004) most SNACs are in the same rate class. + * + * One optimization we can do to save memory is to only keep track of SNACs + * that are in classes other than this default rate class. So if we try to + * look up a SNAC and it's not in our hash table then we can assume that it's + * in the default rate class. + */ +#define OSCAR_DEFAULT_RATECLASS 1 + /* Subtype 0x0002 - Client Online */ void aim_srv_clientready(OscarData *od, FlapConnection *conn) @@ -323,7 +341,7 @@ struct timeval now; gettimeofday(&now, NULL); - rateclass = g_new0(struct rateclass, 1); + rateclass = g_new(struct rateclass, 1); rateclass->classid = byte_stream_get16(bs); rateclass->windowsize = byte_stream_get32(bs); @@ -333,34 +351,21 @@ rateclass->disconnect = byte_stream_get32(bs); rateclass->current = byte_stream_get32(bs); rateclass->max = byte_stream_get32(bs); - - /* - * The server will send an extra five bytes of parameters - * depending on the version we advertised in 1/17. If we - * didn't send 1/17 (evil!), then this will crash and you - * die, as it will default to the old version but we have - * the new version hardcoded here. - */ - if (mod->version >= 3) - { - rateclass->delta = byte_stream_get32(bs); + if (mod->version >= 3) { + delta = byte_stream_get32(bs); rateclass->dropping_snacs = byte_stream_get8(bs); - - delta = rateclass->delta; - - rateclass->last.tv_sec = now.tv_sec - delta / 1000; - delta %= 1000; - rateclass->last.tv_usec = now.tv_usec - delta * 1000; - } - else - { - rateclass->delta = rateclass->dropping_snacs = 0; - rateclass->last.tv_sec = now.tv_sec; - rateclass->last.tv_usec = now.tv_usec; + } else { + delta = 0; + rateclass->dropping_snacs = 0; } - rateclass->members = g_hash_table_new(g_direct_hash, g_direct_equal); + rateclass->last.tv_sec = now.tv_sec - delta / 1000; + rateclass->last.tv_usec = now.tv_usec - (delta % 1000) * 1000; + conn->rateclasses = g_slist_prepend(conn->rateclasses, rateclass); + + if (rateclass->classid == OSCAR_DEFAULT_RATECLASS) + conn->default_rateclass = rateclass; } conn->rateclasses = g_slist_reverse(conn->rateclasses); @@ -376,6 +381,15 @@ classid = byte_stream_get16(bs); count = byte_stream_get16(bs); + if (classid == OSCAR_DEFAULT_RATECLASS) { + /* + * Don't bother adding these SNACs to the hash table. See the + * comment for OSCAR_DEFAULT_RATECLASS at the top of this file. + */ + byte_stream_advance(bs, 4 * count); + continue; + } + rateclass = rateclass_find(conn->rateclasses, classid); for (j = 0; j < count; j++) @@ -386,9 +400,9 @@ subtype = byte_stream_get16(bs); if (rateclass != NULL) - g_hash_table_insert(rateclass->members, + g_hash_table_insert(conn->rateclass_members, GUINT_TO_POINTER((group << 16) + subtype), - GUINT_TO_POINTER(TRUE)); + rateclass); } } @@ -462,12 +476,17 @@ static int ratechange(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { - int ret = 0; - aim_rxcallback_t userfunc; guint16 code, classid; struct rateclass *rateclass; guint32 delta; struct timeval now; + static const char *codes[5] = { + "invalid", + "change", + "warning", + "limit", + "limit cleared", + }; gettimeofday(&now, NULL); code = byte_stream_get16(bs); @@ -485,32 +504,32 @@ rateclass->disconnect = byte_stream_get32(bs); rateclass->current = byte_stream_get32(bs); rateclass->max = byte_stream_get32(bs); - - if (mod->version >= 3) - { - rateclass->delta = byte_stream_get32(bs); + if (mod->version >= 3) { + delta = byte_stream_get32(bs); rateclass->dropping_snacs = byte_stream_get8(bs); - - delta = rateclass->delta; - - rateclass->last.tv_sec = now.tv_sec - delta / 1000; - delta %= 1000; - rateclass->last.tv_usec = now.tv_usec - delta * 1000; - } - else - { - rateclass->delta = rateclass->dropping_snacs = 0; - rateclass->last.tv_sec = now.tv_sec; - rateclass->last.tv_usec = now.tv_usec; + } else { + delta = 0; + rateclass->dropping_snacs = 0; } - if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) { - /* Can't pass in guint8 via ... varargs, so we use an unsigned int */ - unsigned int dropping_snacs = rateclass->dropping_snacs; - ret = userfunc(od, conn, frame, code, classid, rateclass->windowsize, rateclass->clear, rateclass->alert, rateclass->limit, rateclass->disconnect, rateclass->current, rateclass->max, rateclass->delta, dropping_snacs); + rateclass->last.tv_sec = now.tv_sec - delta / 1000; + rateclass->last.tv_usec = now.tv_usec - (delta % 1000) * 1000; + + purple_debug_misc("oscar", "rate %s (param ID 0x%04hx): curavg = %u, " + "maxavg = %u, alert at %u, clear warning at %u, limit at %u, " + "disconnect at %u, delta is %u, dropping is %u (window size = %u)\n", + (code < 5) ? codes[code] : codes[0], rateclass->classid, + rateclass->current, rateclass->max, rateclass->alert, + rateclass->clear, rateclass->limit, rateclass->disconnect, + delta, rateclass->dropping_snacs, rateclass->windowsize); + + if (code == AIM_RATE_CODE_LIMIT) { + purple_debug_warning("oscar", _("The last action you attempted " + "could not be performed because you are over the rate " + "limit. Please wait 10 seconds and try again.\n")); } - return ret; + return 1; } /* diff -r 06740353bfc7 -r e3031e5785a3 libpurple/protocols/oscar/flap_connection.c --- a/libpurple/protocols/oscar/flap_connection.c Fri Jan 29 13:00:26 2010 +0900 +++ b/libpurple/protocols/oscar/flap_connection.c Wed Feb 03 16:00:49 2010 +0900 @@ -106,21 +106,15 @@ static struct rateclass * flap_connection_get_rateclass(FlapConnection *conn, guint16 family, guint16 subtype) { - GSList *tmp1; gconstpointer key; + gpointer rateclass; key = GUINT_TO_POINTER((family << 16) + subtype); - - for (tmp1 = conn->rateclasses; tmp1 != NULL; tmp1 = tmp1->next) - { - struct rateclass *rateclass; - rateclass = tmp1->data; + rateclass = g_hash_table_lookup(conn->rateclass_members, key); + if (rateclass != NULL) + return rateclass; - if (g_hash_table_lookup(rateclass->members, key)) - return rateclass; - } - - return NULL; + return conn->default_rateclass; } /* @@ -133,10 +127,10 @@ unsigned long timediff; /* In milliseconds */ guint32 current; + /* This formula is documented at http://dev.aol.com/aim/oscar/#RATELIMIT */ timediff = (now->tv_sec - rateclass->last.tv_sec) * 1000 + (now->tv_usec - rateclass->last.tv_usec) / 1000; current = ((rateclass->current * (rateclass->windowsize - 1)) + timediff) / rateclass->windowsize; - /* This formula is taken from http://dev.aol.com/aim/oscar/#RATELIMIT */ return MIN(current, rateclass->max); } @@ -258,14 +252,6 @@ rateclass->last.tv_sec = now.tv_sec; rateclass->last.tv_usec = now.tv_usec; } - } else { - /* - * It's normal for SNACs 0x0001/0x0006 and 0x0001/0x0017 to be - * sent before we receive rate info from the server, so don't - * bother warning about them. - */ - if (family != 0x0001 || (subtype != 0x0006 && subtype != 0x0017)) - purple_debug_warning("oscar", "No rate class found for family 0x%04hx subtype 0x%04hx\n", family, subtype); } if (enqueue) @@ -354,6 +340,7 @@ conn->fd = -1; conn->subtype = -1; conn->type = type; + conn->rateclass_members = g_hash_table_new(g_direct_hash, g_direct_equal); od->oscar_connections = g_slist_prepend(od->oscar_connections, conn); @@ -421,13 +408,6 @@ conn->buffer_outgoing = NULL; } -static void -flap_connection_destroy_rateclass(struct rateclass *rateclass) -{ - g_hash_table_destroy(rateclass->members); - g_free(rateclass); -} - /** * Free a FlapFrame * @@ -515,10 +495,12 @@ g_slist_free(conn->groups); while (conn->rateclasses != NULL) { - flap_connection_destroy_rateclass(conn->rateclasses->data); + g_free(conn->rateclasses->data); conn->rateclasses = g_slist_delete_link(conn->rateclasses, conn->rateclasses); } + g_hash_table_destroy(conn->rateclass_members); + if (conn->queued_snacs) { while (!g_queue_is_empty(conn->queued_snacs)) { diff -r 06740353bfc7 -r e3031e5785a3 libpurple/protocols/oscar/oscar.c --- a/libpurple/protocols/oscar/oscar.c Fri Jan 29 13:00:26 2010 +0900 +++ b/libpurple/protocols/oscar/oscar.c Wed Feb 03 16:00:49 2010 +0900 @@ -190,7 +190,6 @@ static int purple_icon_parseicon (OscarData *, FlapConnection *, FlapFrame *, ...); static int oscar_icon_req (OscarData *, FlapConnection *, FlapFrame *, ...); static int purple_parse_msgack (OscarData *, FlapConnection *, FlapFrame *, ...); -static int purple_parse_ratechange (OscarData *, FlapConnection *, FlapFrame *, ...); static int purple_parse_evilnotify (OscarData *, FlapConnection *, FlapFrame *, ...); static int purple_parse_searcherror(OscarData *, FlapConnection *, FlapFrame *, ...); static int purple_parse_searchreply(OscarData *, FlapConnection *, FlapFrame *, ...); @@ -1554,7 +1553,6 @@ oscar_data_addhandler(od, SNAC_FAMILY_OSERVICE, 0x000f, purple_selfinfo, 0); oscar_data_addhandler(od, SNAC_FAMILY_OSERVICE, 0x001f, purple_memrequest, 0); oscar_data_addhandler(od, SNAC_FAMILY_OSERVICE, 0x0021, oscar_icon_req,0); - oscar_data_addhandler(od, SNAC_FAMILY_OSERVICE, SNAC_SUBTYPE_OSERVICE_RATECHANGE, purple_parse_ratechange, 0); oscar_data_addhandler(od, SNAC_FAMILY_OSERVICE, SNAC_SUBTYPE_OSERVICE_REDIRECT, purple_handle_redirect, 0); oscar_data_addhandler(od, SNAC_FAMILY_OSERVICE, SNAC_SUBTYPE_OSERVICE_MOTD, purple_parse_motd, 0); oscar_data_addhandler(od, SNAC_FAMILY_OSERVICE, SNAC_SUBTYPE_OSERVICE_EVIL, purple_parse_evilnotify, 0); @@ -3871,56 +3869,6 @@ return 1; } -static int purple_parse_ratechange(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { - static const char *codes[5] = { - "invalid", - "change", - "warning", - "limit", - "limit cleared", - }; - va_list ap; - guint16 code, rateclass; - guint32 windowsize, clear, alert, limit, disconnect, currentavg, maxavg, delta; - guint8 dropping_snacs; - - va_start(ap, fr); - code = (guint16)va_arg(ap, unsigned int); - rateclass= (guint16)va_arg(ap, unsigned int); - windowsize = va_arg(ap, guint32); - clear = va_arg(ap, guint32); - alert = va_arg(ap, guint32); - limit = va_arg(ap, guint32); - disconnect = va_arg(ap, guint32); - currentavg = va_arg(ap, guint32); - maxavg = va_arg(ap, guint32); - delta = va_arg(ap, guint32); - dropping_snacs = (guint8)va_arg(ap, unsigned int); - va_end(ap); - - purple_debug_misc("oscar", - "rate %s (param ID 0x%04hx): curavg = %u, maxavg = %u, alert at %u, " - "clear warning at %u, limit at %u, disconnect at %u, delta is %u, dropping is %u (window size = %u)\n", - (code < 5) ? codes[code] : codes[0], - rateclass, - currentavg, maxavg, - alert, clear, - limit, disconnect, - delta, - dropping_snacs, - windowsize - ); - - if (code == AIM_RATE_CODE_LIMIT) - { - purple_debug_warning("oscar", _("The last action you attempted could not be " - "performed because you are over the rate limit. " - "Please wait 10 seconds and try again.\n")); - } - - return 1; -} - static int purple_parse_evilnotify(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { #ifdef CRAZY_WARNING va_list ap; diff -r 06740353bfc7 -r e3031e5785a3 libpurple/protocols/oscar/oscar.h --- a/libpurple/protocols/oscar/oscar.h Fri Jan 29 13:00:26 2010 +0900 +++ b/libpurple/protocols/oscar/oscar.h Wed Feb 03 16:00:49 2010 +0900 @@ -445,6 +445,8 @@ guint16 seqnum_in; /**< The sequence number of most recently received packet. */ GSList *groups; GSList *rateclasses; /* Contains nodes of struct rateclass. */ + struct rateclass *default_rateclass; + GHashTable *rateclass_members; /* Key is family and subtype, value is pointer to the rateclass struct to use. */ GQueue *queued_snacs; /**< Contains QueuedSnacs. */ GQueue *queued_lowpriority_snacs; /**< Contains QueuedSnacs to send only once queued_snacs is empty */ @@ -1686,9 +1688,7 @@ guint32 disconnect; guint32 current; guint32 max; - guint32 delta; guint8 dropping_snacs; - GHashTable *members; /* Key is family and subtype, value is TRUE. */ struct timeval last; /**< The time when we last sent a SNAC of this rate class. */ }; diff -r 06740353bfc7 -r e3031e5785a3 pidgin/gtkblist.c --- a/pidgin/gtkblist.c Fri Jan 29 13:00:26 2010 +0900 +++ b/pidgin/gtkblist.c Wed Feb 03 16:00:49 2010 +0900 @@ -5622,6 +5622,51 @@ } +static gboolean +pidgin_blist_search_equal_func(GtkTreeModel *model, gint column, + const gchar *key, GtkTreeIter *iter, gpointer data) +{ + PurpleBlistNode *node = NULL; + gboolean res = TRUE; + const char *compare = NULL; + + if (!pidgin_tree_view_search_equal_func(model, column, key, iter, data)) + return FALSE; + + /* If the search string does not match the displayed label, then look + * at the alternate labels for the nodes and search in them. Currently, + * alternate labels that make sense are usernames/email addresses for + * buddies (but only for the ones who don't have a local alias). + */ + + gtk_tree_model_get(model, iter, NODE_COLUMN, &node, -1); + if (!node) + return TRUE; + + compare = NULL; + if (PURPLE_BLIST_NODE_IS_CONTACT(node)) { + PurpleBuddy *b = purple_contact_get_priority_buddy(PURPLE_CONTACT(node)); + if (!purple_buddy_get_local_buddy_alias(b)) + compare = purple_buddy_get_name(b); + } else if (PURPLE_BLIST_NODE_IS_BUDDY(node)) { + if (!purple_buddy_get_local_buddy_alias(PURPLE_BUDDY(node))) + compare = purple_buddy_get_name(PURPLE_BUDDY(node)); + } + + if (compare) { + char *tmp, *enteredstring; + tmp = g_utf8_normalize(key, -1, G_NORMALIZE_DEFAULT); + enteredstring = g_utf8_casefold(tmp, -1); + g_free(tmp); + + if (purple_str_has_prefix(compare, enteredstring)) + res = FALSE; + g_free(enteredstring); + } + + return res; +} + static void pidgin_blist_show(PurpleBuddyList *list) { PidginBuddyListPrivate *priv; @@ -5858,7 +5903,8 @@ /* Enable CTRL+F searching */ gtk_tree_view_set_search_column(GTK_TREE_VIEW(gtkblist->treeview), NAME_COLUMN); - gtk_tree_view_set_search_equal_func(GTK_TREE_VIEW(gtkblist->treeview), pidgin_tree_view_search_equal_func, NULL, NULL); + gtk_tree_view_set_search_equal_func(GTK_TREE_VIEW(gtkblist->treeview), + pidgin_blist_search_equal_func, NULL, NULL); gtk_box_pack_start(GTK_BOX(gtkblist->vbox), sw, TRUE, TRUE, 0); gtk_container_add(GTK_CONTAINER(sw), gtkblist->treeview); diff -r 06740353bfc7 -r e3031e5785a3 pidgin/gtkthemes.c --- a/pidgin/gtkthemes.c Fri Jan 29 13:00:26 2010 +0900 +++ b/pidgin/gtkthemes.c Wed Feb 03 16:00:49 2010 +0900 @@ -309,7 +309,7 @@ while (*i) { char l[64]; int li = 0; - while (!isspace(*i) && li < sizeof(l) - 1) { + while (*i && !isspace(*i) && li < sizeof(l) - 1) { if (*i == '\\' && *(i+1) != '\0') i++; l[li++] = *(i++); diff -r 06740353bfc7 -r e3031e5785a3 pidgin/gtkutils.c --- a/pidgin/gtkutils.c Fri Jan 29 13:00:26 2010 +0900 +++ b/pidgin/gtkutils.c Wed Feb 03 16:00:49 2010 +0900 @@ -1586,8 +1586,8 @@ _("You have dragged an image"), _("You can send this image as a file transfer, " "embed it into this message, or use it as the buddy icon for this user."), - DND_FILE_TRANSFER, "OK", (GCallback)dnd_image_ok_callback, - "Cancel", (GCallback)dnd_image_cancel_callback, + DND_FILE_TRANSFER, _("OK"), (GCallback)dnd_image_ok_callback, + _("Cancel"), (GCallback)dnd_image_cancel_callback, account, who, NULL, data, _("Set as buddy icon"), DND_BUDDY_ICON, @@ -1606,8 +1606,8 @@ (ft ? _("You can send this image as a file transfer, or use it as the buddy icon for this user.") : _("You can insert this image into this message, or use it as the buddy icon for this user")), (ft ? DND_FILE_TRANSFER : DND_IM_IMAGE), - "OK", (GCallback)dnd_image_ok_callback, - "Cancel", (GCallback)dnd_image_cancel_callback, + _("OK"), (GCallback)dnd_image_ok_callback, + _("Cancel"), (GCallback)dnd_image_cancel_callback, account, who, NULL, data, _("Set as buddy icon"), DND_BUDDY_ICON,