Mercurial > pidgin
changeset 29808:59510eac0bdf
propagate from branch 'im.pidgin.pidgin' (head 8c322571bfb4f2d00c9126e59746445f877be296)
to branch 'im.pidgin.cpw.malu.ft_thumbnails' (head d5d8bd0b5e09c6539bde372c51d209284f19e321)
author | Marcus Lundblad <ml@update.uu.se> |
---|---|
date | Tue, 03 Nov 2009 18:27:07 +0000 |
parents | 28d73d34d792 (diff) d0730ad1c7df (current diff) |
children | b0f1698c52f8 |
files | pidgin/gtkrequest.c |
diffstat | 31 files changed, 600 insertions(+), 306 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog Mon Oct 26 22:16:32 2009 +0000 +++ b/ChangeLog Tue Nov 03 18:27:07 2009 +0000 @@ -11,6 +11,10 @@ * Fix DNS TXT query resolution. * Always rejoin open chats after an account reconnects. + AIM and ICQ: + * Better rate limit calculations and other improvements. (Aman Gupta) + * More detailed error messages when messages fail to send. (Aman Gupta) + MSN: * Don't forget display names for buddies. * Fix a random crash that might occur when idle. @@ -45,6 +49,10 @@ * Add a hold button to the media window. * Tooltips for custom smileys should work now. * Users with unread messages are again bolded in the Buddy List. + * Minor reworking of the Preferences window's Network tab to make it need + less vertical space. + * The global "Use remote DNS with SOCKS4 proxies" preference no longer + disappears when the preference value changes in certain ways. version 2.6.3 (10/16/2009): General:
--- a/autogen.sh Mon Oct 26 22:16:32 2009 +0000 +++ b/autogen.sh Tue Nov 03 18:27:07 2009 +0000 @@ -83,7 +83,7 @@ OUTPUT=`mktemp autogen-XXXXXX` - printf "%s" "running ${CMD} ${@}... " + printf "running %s %s... " ${CMD} "$*" ${CMD} ${@} >${OUTPUT} 2>&1 if [ $? != 0 ] ; then @@ -99,9 +99,17 @@ fi } +cleanup () { + rm -f autogen-?????? + echo + exit 2 +} + ############################################################################### # We really start here, yes, very sneaky! ############################################################################### +trap cleanup 2 + FIGLET=`which figlet 2> /dev/null` if [ x"${FIGLET}" != x"" ] ; then ${FIGLET} -f small ${PACKAGE} @@ -143,7 +151,7 @@ run_or_die ${INTLTOOLIZE} ${INTLTOOLIZE_FLAGS:-"-c -f --automake"} # This call to sed is needed to work around an annoying bug in intltool 0.40.6 # See http://developer.pidgin.im/ticket/9520 for details -run_or_die ${SED} "s:'\^\$\$lang\$\$':\^\$\$lang\$\$:g" -i po/Makefile.in.in +run_or_die ${SED} -i.bak -e "s:'\^\$\$lang\$\$':\^\$\$lang\$\$:g" po/Makefile.in.in run_or_die ${ACLOCAL} ${ACLOCAL_FLAGS:-"-I m4macros"} run_or_die ${AUTOHEADER} ${AUTOHEADER_FLAGS} run_or_die ${AUTOMAKE} ${AUTOMAKE_FLAGS:-"-a -c --gnu"}
--- a/finch/libgnt/gntentry.c Mon Oct 26 22:16:32 2009 +0000 +++ b/finch/libgnt/gntentry.c Tue Nov 03 18:27:07 2009 +0000 @@ -1044,8 +1044,11 @@ snprintf(entry->start, len + 1, "%s", text); entry->end = entry->start + len; - entry->scroll = entry->start + scroll; - entry->cursor = entry->end - cursor; + if ((entry->scroll = entry->start + scroll) > entry->end) + entry->scroll = entry->end; + + if ((entry->cursor = entry->end - cursor) > entry->end) + entry->cursor = entry->end; if (GNT_WIDGET_IS_FLAG_SET(GNT_WIDGET(entry), GNT_WIDGET_MAPPED)) entry_redraw(GNT_WIDGET(entry));
--- a/finch/libgnt/gnttextview.c Mon Oct 26 22:16:32 2009 +0000 +++ b/finch/libgnt/gnttextview.c Tue Nov 03 18:27:07 2009 +0000 @@ -67,6 +67,12 @@ static void reset_text_view(GntTextView *view); +static gboolean +text_view_contains(GntTextView *view, const char *str) +{ + return (str >= view->string->str && str < view->string->str + view->string->len); +} + static void gnt_text_view_draw(GntWidget *widget) { @@ -109,7 +115,7 @@ char back = *end; chtype fl = seg->flags; *end = '\0'; - if (select_start < view->string->str + seg->start && select_end > view->string->str + seg->end) { + if (select_start && select_start < view->string->str + seg->start && select_end > view->string->str + seg->end) { fl |= A_REVERSE; wattrset(widget->window, fl); wprintw(widget->window, "%s", (view->string->str + seg->start)); @@ -326,9 +332,10 @@ select_start = gnt_text_view_get_p(GNT_TEXT_VIEW(widget), x - widget->priv.x, y - widget->priv.y); g_timeout_add(500, too_slow, NULL); } else if (event == GNT_MOUSE_UP) { - if (select_start) { + GntTextView *view = GNT_TEXT_VIEW(widget); + if (text_view_contains(view, select_start)) { GString *clip; - select_end = gnt_text_view_get_p(GNT_TEXT_VIEW(widget), x - widget->priv.x, y - widget->priv.y); + select_end = gnt_text_view_get_p(view, x - widget->priv.x, y - widget->priv.y); if (select_end < select_start) { gchar *t = select_start; select_start = select_end; @@ -336,7 +343,7 @@ } if (select_start == select_end) { if (double_click) { - clip = select_word_text(GNT_TEXT_VIEW(widget), select_start); + clip = select_word_text(view, select_start); double_click = FALSE; } else { double_click = TRUE;
--- a/libpurple/dnsquery.c Mon Oct 26 22:16:32 2009 +0000 +++ b/libpurple/dnsquery.c Tue Nov 03 18:27:07 2009 +0000 @@ -172,6 +172,7 @@ return FALSE; } +#ifdef USE_IDN static gboolean dns_str_is_ascii(const char *name) { @@ -183,6 +184,7 @@ return TRUE; } +#endif #if defined(PURPLE_DNSQUERY_USE_FORK) @@ -293,12 +295,11 @@ rc = purple_network_convert_idn_to_ascii(dns_params.hostname, &hostname); if (rc != 0) { write_to_parent(child_out, &rc, sizeof(rc)); - close(child_out); if (show_debug) fprintf(stderr, "dns[%d] Error: IDN conversion returned " "%d\n", getpid(), rc); dns_params.hostname[0] = '\0'; - continue; + break; } } else /* intentional to execute the g_strdup */ #endif @@ -323,14 +324,13 @@ rc = getaddrinfo(hostname, servname, &hints, &res); write_to_parent(child_out, &rc, sizeof(rc)); if (rc != 0) { - close(child_out); if (show_debug) printf("dns[%d] Error: getaddrinfo returned %d\n", getpid(), rc); dns_params.hostname[0] = '\0'; g_free(hostname); hostname = NULL; - continue; + break; } tmp = res; while (res) {
--- a/libpurple/dnssrv.c Mon Oct 26 22:16:32 2009 +0000 +++ b/libpurple/dnssrv.c Tue Nov 03 18:27:07 2009 +0000 @@ -248,6 +248,7 @@ return list; } +#ifdef USE_IDN static gboolean dns_str_is_ascii(const char *name) { @@ -259,8 +260,60 @@ return TRUE; } +#endif #ifndef _WIN32 +static void +write_to_parent(int in, int out, gconstpointer data, gsize size) +{ + const guchar *buf = data; + gssize w; + + do { + w = write(out, buf, size); + if (w > 0) { + buf += w; + size -= w; + } else if (w < 0 && errno == EINTR) { + /* Let's try some more; */ + w = 1; + } + } while (size > 0 && w > 0); + + if (size != 0) { + /* An error occurred */ + close(out); + close(in); + _exit(0); + } +} + +/* Read size bytes to data. Dies if an error occurs. */ +static void +read_from_parent(int in, int out, gpointer data, gsize size) +{ + guchar *buf = data; + gssize r; + + do { + r = read(in, data, size); + if (r > 0) { + buf += r; + size -= r; + } else if (r < 0 && errno == EINTR) { + /* Let's try some more; */ + r = 1; + } + } while (size > 0 && r > 0); + + if (size != 0) { + /* An error occurred */ + close(out); + close(in); + _exit(0); + } +} + G_GNUC_NORETURN static void resolve(int in, int out) @@ -279,16 +332,12 @@ purple_restore_default_signal_handlers(); #endif - if (read(in, &query, sizeof(query)) <= 0) { - close(out); - close(in); - _exit(0); - } + read_from_parent(in, out, &query, sizeof(query)); size = res_query( query.query, C_IN, query.type, (u_char*)&answer, sizeof( answer)); if (size == -1) { - write(out, &(query.type), sizeof(query.type)); - write(out, &size, sizeof(int)); + write_to_parent(in, out, &(query.type), sizeof(query.type)); + write_to_parent(in, out, &size, sizeof(size)); close(out); close(in); _exit(0); @@ -353,19 +402,17 @@ if (query.type == T_SRV) ret = purple_srv_sort(ret); - /* TODO: Check return value */ - write(out, &(query.type), sizeof(query.type)); - write(out, &size, sizeof(size)); + write_to_parent(in, out, &(query.type), sizeof(query.type)); + write_to_parent(in, out, &size, sizeof(size)); while (ret != NULL) { - /* TODO: Check return value */ if (query.type == T_SRV) - write(out, ret->data, sizeof(PurpleSrvResponse)); + write_to_parent(in, out, ret->data, sizeof(PurpleSrvResponse)); if (query.type == T_TXT) { PurpleTxtResponse *response = ret->data; gsize l = strlen(response->content) + 1 /* null byte */; - write(out, &l, sizeof(l)); - write(out, response->content, l); + write_to_parent(in, out, &l, sizeof(l)); + write_to_parent(in, out, response->content, l); } g_free(ret->data);
--- a/libpurple/plugins/perl/Makefile.mingw Mon Oct 26 22:16:32 2009 +0000 +++ b/libpurple/plugins/perl/Makefile.mingw Tue Nov 03 18:27:07 2009 +0000 @@ -7,10 +7,12 @@ PIDGIN_TREE_TOP := ../../.. include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak +DEFINES := $(subst -DWIN32_LEAN_AND_MEAN,,$(DEFINES)) + TARGET = perl # Perl headers with /* /* */ type comments.. Turn off warnings. -CFLAGS += -Wno-comment +GCCWARNINGS += -Wno-comment ## ## INCLUDE PATHS
--- a/libpurple/plugins/perl/common/Makefile.mingw Mon Oct 26 22:16:32 2009 +0000 +++ b/libpurple/plugins/perl/common/Makefile.mingw Tue Nov 03 18:27:07 2009 +0000 @@ -5,9 +5,12 @@ # PIDGIN_TREE_TOP := ../../../.. -GCCWARNINGS := -Wno-comment -Waggregate-return -Wcast-align -Wdeclaration-after-statement -Werror-implicit-function-declaration -Wextra -Wno-sign-compare -Wno-unused-parameter -Winit-self -Wmissing-declarations -Wmissing-prototypes -Wpointer-arith -Wundef -Wno-unused include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak +GCCWARNINGS += -Wno-comment -Wno-unused -Wno-nested-externs + +DEFINES := $(subst -DWIN32_LEAN_AND_MEAN,,$(DEFINES)) + TARGET = Purple AUTOSPLIT = lib/auto/Purple/autosplit.ix EXTUTILS ?= C:/perl/lib/ExtUtils
--- a/libpurple/protocols/msn/msn.c Mon Oct 26 22:16:32 2009 +0000 +++ b/libpurple/protocols/msn/msn.c Tue Nov 03 18:27:07 2009 +0000 @@ -634,9 +634,14 @@ MsnSession *session = gc->proto_data; if (session) { MsnUser *user = msn_userlist_find_user(session->userlist, who); - if (user) + if (user) { /* Include these too: MSN_CLIENT_CAP_MSNMOBILE|MSN_CLIENT_CAP_MSNDIRECT ? */ - ret = (user->clientid & MSN_CLIENT_CAP_WEBMSGR) == 0; + if ((user->clientid & MSN_CLIENT_CAP_WEBMSGR) || + user->networkid == MSN_NETWORK_YAHOO) + ret = FALSE; + else + ret = TRUE; + } } else ret = FALSE; }
--- a/libpurple/protocols/msn/notification.c Mon Oct 26 22:16:32 2009 +0000 +++ b/libpurple/protocols/msn/notification.c Tue Nov 03 18:27:07 2009 +0000 @@ -670,7 +670,7 @@ "User %s is on both Allow and Block list; " "removing from Allow list.\n", user->passport); - msn_userlist_rem_buddy_from_list(session->userlist, user->passport, MSN_LIST_AL); + msn_user_unset_op(user, MSN_LIST_AL_OP); } if (user->networkid != MSN_NETWORK_UNKNOWN) { @@ -840,17 +840,48 @@ MsnSession *session; PurpleAccount *account; PurpleConnection *gc; - char *adl = g_strndup(payload, len); - char *reason = g_strdup_printf(_("Unknown error (%d): %s"), - GPOINTER_TO_INT(cmd->payload_cbdata), adl); - g_free(adl); + int error = GPOINTER_TO_INT(cmd->payload_cbdata); session = cmdproc->session; account = session->account; gc = purple_account_get_connection(account); - purple_notify_error(gc, NULL, _("Unable to add user"), reason); - g_free(reason); + if (error == 241) { + /* khc: some googling suggests that error 241 means the buddy is somehow + in the local list, but not the server list, and that we should add + those buddies to the addressbook. For now I will just notify the user + about the raw payload, because I am lazy */ + xmlnode *adl = xmlnode_from_str(payload, len); + GString *emails = g_string_new(NULL); + + xmlnode *domain = xmlnode_get_child(adl, "d"); + while (domain) { + const char *domain_str = xmlnode_get_attrib(domain, "n"); + xmlnode *contact = xmlnode_get_child(domain, "c"); + while (contact) { + g_string_append_printf(emails, "%s@%s\n", + xmlnode_get_attrib(contact, "n"), domain_str); + contact = xmlnode_get_next_twin(contact); + } + domain = xmlnode_get_next_twin(domain); + } + + purple_notify_error(gc, NULL, + _("The following users are missing from your addressbook"), + emails->str); + g_string_free(emails, TRUE); + xmlnode_free(adl); + } + else + { + char *adl = g_strndup(payload, len); + char *reason = g_strdup_printf(_("Unknown error (%d): %s"), + error, adl); + g_free(adl); + + purple_notify_error(gc, NULL, _("Unable to add user"), reason); + g_free(reason); + } } static void @@ -878,50 +909,49 @@ } static void -adl_241_error_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload, - size_t len) +rml_error_parse(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload, size_t len) { - /* khc: some googling suggests that error 241 means the buddy is somehow - in the local list, but not the server list, and that we should add - those buddies to the addressbook. For now I will just notify the user - about the raw payload, because I am lazy */ MsnSession *session; PurpleAccount *account; PurpleConnection *gc; - xmlnode *adl; - xmlnode *domain; - GString *emails; + char *adl, *reason; + int error = GPOINTER_TO_INT(cmd->payload_cbdata); session = cmdproc->session; account = session->account; gc = purple_account_get_connection(account); - adl = xmlnode_from_str(payload, len); - emails = g_string_new(NULL); + adl = g_strndup(payload, len); + reason = g_strdup_printf(_("Unknown error (%d): %s"), + error, adl); + g_free(adl); - domain = xmlnode_get_child(adl, "d"); - while (domain) { - const char *domain_str = xmlnode_get_attrib(domain, "n"); - xmlnode *contact = xmlnode_get_child(domain, "c"); - while (contact) { - g_string_append_printf(emails, "%s@%s\n", - xmlnode_get_attrib(contact, "n"), domain_str); - contact = xmlnode_get_next_twin(contact); - } - domain = xmlnode_get_next_twin(domain); - } - - purple_notify_error(gc, NULL, - _("The following users are missing from your addressbook"), emails->str); - g_string_free(emails, TRUE); - xmlnode_free(adl); + purple_notify_error(gc, NULL, _("Unable to remove user"), reason); + g_free(reason); } static void -adl_241_error_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) +rml_error(MsnCmdProc *cmdproc, MsnTransaction *trans, int error) { - cmdproc->last_cmd->payload_cb = adl_241_error_cmd_post; - cmd->payload_len = atoi(cmd->params[1]); + MsnSession *session; + PurpleAccount *account; + PurpleConnection *gc; + MsnCommand *cmd = cmdproc->last_cmd; + + session = cmdproc->session; + account = session->account; + gc = purple_account_get_connection(account); + + purple_debug_error("msn", "RML error\n"); + if (cmd->param_count > 1) { + cmd->payload_cb = rml_error_parse; + cmd->payload_len = atoi(cmd->params[1]); + cmd->payload_cbdata = GINT_TO_POINTER(error); + } else { + char *reason = g_strdup_printf(_("Unknown error (%d)"), error); + purple_notify_error(gc, NULL, _("Unable to remove user"), reason); + g_free(reason); + } } static void @@ -1068,7 +1098,17 @@ /* Where'd this come from? */ return; - if (cmd->param_count == 7) { + if (cmd->param_count == 8) { + /* Yahoo! Buddy, looks like */ + networkid = atoi(cmd->params[3]); + friendly = g_strdup(purple_url_decode(cmd->params[4])); + clientid = strtoul(cmd->params[5], NULL, 10); + + /* cmd->params[7] seems to be a URL to a Yahoo! icon: + https://sec.yimg.com/i/us/nt/b/purpley.1.0.png + ... and it's purple, HAH! + */ + } else if (cmd->param_count == 7) { /* MSNP14+ with Display Picture object */ networkid = atoi(cmd->params[3]); friendly = g_strdup(purple_url_decode(cmd->params[4])); @@ -2095,9 +2135,8 @@ msn_table_add_cmd(cbs_table, "fallback", "XFR", xfr_cmd); - msn_table_add_cmd(cbs_table, NULL, "241", adl_241_error_cmd); - msn_table_add_error(cbs_table, "ADL", adl_error); + msn_table_add_error(cbs_table, "RML", rml_error); msn_table_add_error(cbs_table, "FQY", fqy_error); msn_table_add_error(cbs_table, "USR", usr_error);
--- a/libpurple/protocols/oscar/family_icbm.c Mon Oct 26 22:16:32 2009 +0000 +++ b/libpurple/protocols/oscar/family_icbm.c Tue Nov 03 18:27:07 2009 +0000 @@ -151,6 +151,55 @@ return AIM_CLIENTTYPE_UNKNOWN; } +/* + * Subtype 0x0001 - Error + */ +static int +error(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) +{ + int ret = 0; + aim_rxcallback_t userfunc; + aim_snac_t *snac2; + guint16 reason, errcode = 0; + char *bn; + GSList *tlvlist; + + if (!(snac2 = aim_remsnac(od, snac->id))) { + purple_debug_misc("oscar", "icbm error: received response from unknown request!\n"); + return 0; + } + + if (snac2->family != SNAC_FAMILY_ICBM) { + purple_debug_misc("oscar", "icbm error: received response from invalid request! %d\n", snac2->family); + g_free(snac2->data); + g_free(snac2); + return 0; + } + + if (!(bn = snac2->data)) { + purple_debug_misc("oscar", "icbm error: received response from request without a buddy name!\n"); + g_free(snac2); + return 0; + } + + reason = byte_stream_get16(bs); + + tlvlist = aim_tlvlist_read(bs); + if (aim_tlv_gettlv(tlvlist, 0x0008, 1)) + errcode = aim_tlv_get16(tlvlist, 0x0008, 1); + aim_tlvlist_free(tlvlist); + + /* Notify the user that the message wasn't delivered */ + if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) + ret = userfunc(od, conn, frame, reason, errcode, bn); + + if (snac2) + g_free(snac2->data); + g_free(snac2); + + return ret; +} + /** * Subtype 0x0002 - Set ICBM parameters. * @@ -2789,7 +2838,9 @@ static int snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { - if (snac->subtype == 0x0005) + if (snac->subtype == 0x0001) + return error(od, conn, mod, frame, snac, bs); + else if (snac->subtype == 0x0005) return aim_im_paraminfo(od, conn, mod, frame, snac, bs); else if (snac->subtype == 0x0006) return outgoingim(od, conn, mod, frame, snac, bs);
--- a/libpurple/protocols/oscar/family_oservice.c Mon Oct 26 22:16:32 2009 +0000 +++ b/libpurple/protocols/oscar/family_oservice.c Tue Nov 03 18:27:07 2009 +0000 @@ -319,7 +319,10 @@ for (i = 0; i < numclasses; i++) { struct rateclass *rateclass; + guint32 delta; + struct timeval now; + gettimeofday(&now, NULL); rateclass = g_new0(struct rateclass, 1); rateclass->classid = byte_stream_get16(bs); @@ -339,11 +342,24 @@ * the new version hardcoded here. */ if (mod->version >= 3) - byte_stream_getrawbuf(bs, rateclass->unknown, sizeof(rateclass->unknown)); + { + rateclass->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; + } rateclass->members = g_hash_table_new(g_direct_hash, g_direct_equal); - rateclass->last.tv_sec = 0; - rateclass->last.tv_usec = 0; conn->rateclasses = g_slist_prepend(conn->rateclasses, rateclass); } conn->rateclasses = g_slist_reverse(conn->rateclasses); @@ -383,8 +399,7 @@ */ /* - * Last step in the conn init procedure is to acknowledge that we - * agree to these draconian limitations. + * Subscribe to rate change information for all rate classes. */ aim_srv_rates_addparam(od, conn); @@ -451,7 +466,10 @@ aim_rxcallback_t userfunc; guint16 code, classid; struct rateclass *rateclass; + guint32 delta; + struct timeval now; + gettimeofday(&now, NULL); code = byte_stream_get16(bs); classid = byte_stream_get16(bs); @@ -468,8 +486,29 @@ rateclass->current = byte_stream_get32(bs); rateclass->max = byte_stream_get32(bs); - if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) - ret = userfunc(od, conn, frame, code, classid, rateclass->windowsize, rateclass->clear, rateclass->alert, rateclass->limit, rateclass->disconnect, rateclass->current, rateclass->max); + if (mod->version >= 3) + { + rateclass->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; + } + + 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); + } return ret; }
--- a/libpurple/protocols/oscar/flap_connection.c Mon Oct 26 22:16:32 2009 +0000 +++ b/libpurple/protocols/oscar/flap_connection.c Tue Nov 03 18:27:07 2009 +0000 @@ -131,11 +131,13 @@ rateclass_get_new_current(FlapConnection *conn, struct rateclass *rateclass, struct timeval *now) { unsigned long timediff; /* In milliseconds */ + guint32 current; 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 the joscar API docs. Preesh. */ - return MIN(((rateclass->current * (rateclass->windowsize - 1)) + timediff) / rateclass->windowsize, rateclass->max); + /* This formula is taken from http://dev.aol.com/aim/oscar/#RATELIMIT */ + return MIN(current, rateclass->max); } /* @@ -161,8 +163,7 @@ new_current = rateclass_get_new_current(conn, rateclass, &now); - /* (Add 100ms padding to account for inaccuracies in the calculation) */ - if (new_current < rateclass->alert + 100) + if (rateclass->dropping_snacs || new_current <= rateclass->alert) /* Not ready to send this SNAC yet--keep waiting. */ return FALSE; @@ -245,10 +246,9 @@ gettimeofday(&now, NULL); new_current = rateclass_get_new_current(conn, rateclass, &now); - /* (Add 100ms padding to account for inaccuracies in the calculation) */ - if (new_current < rateclass->alert + 100) + if (rateclass->dropping_snacs || new_current <= rateclass->alert) { - purple_debug_info("oscar", "Current rate for conn %p would be %u, but we alert at %u; enqueueing\n", conn, new_current, (rateclass->alert + 100)); + purple_debug_info("oscar", "Current rate for conn %p would be %u, but we alert at %u; enqueueing\n", conn, new_current, rateclass->alert); enqueue = TRUE; }
--- a/libpurple/protocols/oscar/oscar.c Mon Oct 26 22:16:32 2009 +0000 +++ b/libpurple/protocols/oscar/oscar.c Tue Nov 03 18:27:07 2009 +0000 @@ -144,6 +144,26 @@ }; static const int msgerrreasonlen = G_N_ELEMENTS(msgerrreason); +static const char * const errcodereason[] = { + N_("Invalid error"), + N_("Not logged in"), + N_("Cannot receive IM due to parental controls"), + N_("Cannot send SMS without accepting terms"), + N_("Cannot send SMS"), /* SMS_WITHOUT_DISCLAIMER is weird */ + N_("Cannot send SMS to this country"), + N_("Unknown error"), /* Undocumented */ + N_("Unknown error"), /* Undocumented */ + N_("Cannot send SMS to unknown country"), + N_("Bot accounts cannot initiate IMs"), + N_("Bot account cannot IM this user"), + N_("Bot account reached IM limit"), + N_("Bot account reached daily IM limit"), + N_("Bot account reached monthly IM limit"), + N_("Unable to receive offline messages"), + N_("Offline message store full") +}; +static const int errcodereasonlen = G_N_ELEMENTS(errcodereason); + /* All the libfaim->purple callback functions */ /* Only used when connecting with the old-style BUCP login */ @@ -1877,7 +1897,7 @@ break; case 0x18: /* username connecting too frequently */ - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, _("You have been connecting and disconnecting too frequently. Wait ten minutes and try again. If you continue to try, you will need to wait even longer.")); + purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, _("Your username has been connecting and disconnecting too frequently. Wait ten minutes and try again. If you continue to try, you will need to wait even longer.")); break; case 0x1c: { @@ -1889,7 +1909,7 @@ } case 0x1d: /* IP address connecting too frequently */ - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, _("You have been connecting and disconnecting too frequently. Wait a minute and try again. If you continue to try, you will need to wait even longer.")); + purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, _("Your IP address has been connecting and disconnecting too frequently. Wait a minute and try again. If you continue to try, you will need to wait even longer.")); break; default: purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, _("Unknown reason")); @@ -2876,7 +2896,7 @@ if (text) { /* Read the number of contacts that we were sent */ errno = 0; - num = strtoul(text[0], NULL, 10); + num = text[0] ? strtoul(text[0], NULL, 10) : 0; if (num > 0 && errno == 0) { for (i=0; i<num; i++) { @@ -3217,17 +3237,18 @@ PurpleXfer *xfer; #endif va_list ap; - guint16 reason; - char *data, *buf; + guint16 reason, errcode; + char *data, *reason_str, *buf, *error; va_start(ap, fr); reason = (guint16)va_arg(ap, unsigned int); + errcode = (guint16)va_arg(ap, unsigned int); data = va_arg(ap, char *); va_end(ap); purple_debug_error("oscar", - "Message error with data %s and reason %hu\n", - (data != NULL ? data : ""), reason); + "Message error with data %s and reason %hu and errcode %hu\n", + (data != NULL ? data : ""), reason, errcode); if ((data == NULL) || (*data == '\0')) /* We can't do anything if data is empty */ @@ -3242,14 +3263,21 @@ #endif /* Data is assumed to be the destination bn */ - buf = g_strdup_printf(_("Unable to send message: %s"), (reason < msgerrreasonlen) ? _(msgerrreason[reason]) : _("Unknown reason.")); + reason_str = g_strdup((reason < msgerrreasonlen) ? _(msgerrreason[reason]) : _("Unknown reason")); + if (errcode != 0 && errcode < errcodereasonlen) { + error = g_strdup_printf("%s: %s", reason_str, _(errcodereason[errcode])); + g_free(reason_str); + } else + error = reason_str; + + buf = g_strdup_printf(_("Unable to send message: %s"), error); if (!purple_conv_present_error(data, purple_connection_get_account(gc), buf)) { g_free(buf); buf = g_strdup_printf(_("Unable to send message to %s:"), data ? data : "(unknown)"); - purple_notify_error(od->gc, NULL, buf, - (reason < msgerrreasonlen) ? _(msgerrreason[reason]) : _("Unknown reason.")); + purple_notify_error(od->gc, NULL, buf, error); } g_free(buf); + g_free(error); return 1; } @@ -3740,7 +3768,8 @@ }; va_list ap; guint16 code, rateclass; - guint32 windowsize, clear, alert, limit, disconnect, currentavg, maxavg; + guint32 windowsize, clear, alert, limit, disconnect, currentavg, maxavg, delta; + guint8 dropping_snacs; va_start(ap, fr); code = (guint16)va_arg(ap, unsigned int); @@ -3752,23 +3781,28 @@ 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 (window size = %u)\n", + "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, - windowsize); + 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.")); + "Please wait 10 seconds and try again.\n")); } return 1; @@ -5276,7 +5310,7 @@ for (curitem=od->ssi.local; curitem; curitem=curitem->next) { if ((curitem->name == NULL) || (g_utf8_validate(curitem->name, -1, NULL))) switch (curitem->type) { - case 0x0000: { /* Buddy */ + case AIM_SSI_TYPE_BUDDY: { /* Buddy */ if (curitem->name) { struct aim_ssi_item *groupitem; char *gname, *gname_utf8, *alias, *alias_utf8; @@ -5342,7 +5376,7 @@ } } break; - case 0x0001: { /* Group */ + case AIM_SSI_TYPE_GROUP: { /* Group */ char *gname; char *gname_utf8; @@ -5362,7 +5396,7 @@ g_free(gname_utf8); } break; - case 0x0002: { /* Permit buddy */ + case AIM_SSI_TYPE_PERMIT: { /* Permit buddy */ if (curitem->name) { /* if (!find_permdeny_by_name(gc->permit, curitem->name)) { AAA */ GSList *list; @@ -5375,7 +5409,7 @@ } } break; - case 0x0003: { /* Deny buddy */ + case AIM_SSI_TYPE_DENY: { /* Deny buddy */ if (curitem->name) { GSList *list; for (list=account->deny; (list && oscar_util_name_compare(curitem->name, list->data)); list=list->next); @@ -5387,7 +5421,7 @@ } } break; - case 0x0004: { /* Permit/deny setting */ + case AIM_SSI_TYPE_PDINFO: { /* Permit/deny setting */ /* * We don't inherit the permit/deny setting from the server * for ICQ because, for ICQ, this setting controls who can @@ -5405,7 +5439,7 @@ } } break; - case 0x0005: { /* Presence setting */ + case AIM_SSI_TYPE_PRESENCEPREFS: { /* Presence setting */ /* We don't want to change Purple's setting because it applies to all accounts */ } break; } /* End of switch on curitem->type */
--- a/libpurple/protocols/oscar/oscar.h Mon Oct 26 22:16:32 2009 +0000 +++ b/libpurple/protocols/oscar/oscar.h Tue Nov 03 18:27:07 2009 +0000 @@ -1685,7 +1685,8 @@ guint32 disconnect; guint32 current; guint32 max; - guint8 unknown[5]; /* only present in versions >= 3 */ + 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. */
--- a/libpurple/protocols/silc/Makefile.mingw Mon Oct 26 22:16:32 2009 +0000 +++ b/libpurple/protocols/silc/Makefile.mingw Tue Nov 03 18:27:07 2009 +0000 @@ -7,6 +7,8 @@ PIDGIN_TREE_TOP := ../../.. include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak +DEFINES := $(subst -DWIN32_LEAN_AND_MEAN,,$(DEFINES)) + TARGET = libsilc NEEDED_DLLS = $(SILC_TOOLKIT)/bin/libsilc-1-1-2.dll \ $(SILC_TOOLKIT)/bin/libsilcclient-1-1-2.dll @@ -79,7 +81,7 @@ $(OBJECTS): $(PURPLE_CONFIG_H) $(TARGET).dll: $(PURPLE_DLL).a $(OBJECTS) - $(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -Wl,--image-base,0x64000000 -o $(TARGET).dll + $(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -Wl,--image-base,0x74000000 -o $(TARGET).dll ## ## CLEAN RULES
--- a/libpurple/protocols/silc10/Makefile.mingw Mon Oct 26 22:16:32 2009 +0000 +++ b/libpurple/protocols/silc10/Makefile.mingw Tue Nov 03 18:27:07 2009 +0000 @@ -7,6 +7,8 @@ PIDGIN_TREE_TOP := ../../.. include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak +DEFINES := $(subst -DWIN32_LEAN_AND_MEAN,,$(DEFINES)) + TARGET = libsilc NEEDED_DLLS = $(SILC_TOOLKIT)/lib/silc.dll \ $(SILC_TOOLKIT)/lib/silcclient.dll
--- a/libpurple/protocols/yahoo/libyahoo.c Mon Oct 26 22:16:32 2009 +0000 +++ b/libpurple/protocols/yahoo/libyahoo.c Tue Nov 03 18:27:07 2009 +0000 @@ -249,7 +249,7 @@ yahoo_roomlist_get_list, yahoo_roomlist_cancel, yahoo_roomlist_expand_category, - NULL, /* can_receive_file */ + yahoo_can_receive_file, /* can_receive_file */ yahoo_send_file, yahoo_new_xfer, yahoo_offline_message, /* offline_message */
--- a/libpurple/protocols/yahoo/libymsg.c Mon Oct 26 22:16:32 2009 +0000 +++ b/libpurple/protocols/yahoo/libymsg.c Tue Nov 03 18:27:07 2009 +0000 @@ -154,6 +154,7 @@ gboolean unicode = FALSE; char *message = NULL; YahooFederation fed = YAHOO_FEDERATION_NONE; + char *fedname = NULL; if (pkt->service == YAHOO_SERVICE_LOGOFF && pkt->status == -1) { if (!purple_account_get_remember_password(account)) @@ -194,18 +195,20 @@ break; if (p->key == 241) { fed = strtol(p->value, NULL, 10); + g_free(fedname); switch (fed) { case YAHOO_FEDERATION_MSN: - name = g_strconcat("msn/", name, NULL); + name = fedname = g_strconcat("msn/", name, NULL); break; case YAHOO_FEDERATION_OCS: - name = g_strconcat("ocs/", name, NULL); + name = fedname = g_strconcat("ocs/", name, NULL); break; case YAHOO_FEDERATION_IBM: - name = g_strconcat("ibm/", name, NULL); + name = fedname = g_strconcat("ibm/", name, NULL); break; case YAHOO_FEDERATION_NONE: default: + fedname = NULL; break; } break; @@ -390,6 +393,7 @@ yahoo_update_status(gc, name, f); } + g_free(fedname); } static void yahoo_do_group_check(PurpleAccount *account, GHashTable *ht, const char *name, const char *group) @@ -3995,7 +3999,7 @@ } - if (f && f->status != YAHOO_STATUS_OFFLINE) { + if (f && f->status != YAHOO_STATUS_OFFLINE && f->fed == YAHOO_FEDERATION_NONE) { if (!yd->wm) { act = purple_menu_action_new(_("Join in Chat"), PURPLE_CALLBACK(yahoo_chat_goto_menu), @@ -4035,10 +4039,12 @@ build_presence_submenu(f, gc)); m = g_list_append(m, act); - act = purple_menu_action_new(_("Start Doodling"), - PURPLE_CALLBACK(yahoo_doodle_blist_node), - NULL, NULL); - m = g_list_append(m, act); + if (f->fed == YAHOO_FEDERATION_NONE) { + act = purple_menu_action_new(_("Start Doodling"), + PURPLE_CALLBACK(yahoo_doodle_blist_node), + NULL, NULL); + m = g_list_append(m, act); + } act = purple_menu_action_new(_("Set User Info..."), PURPLE_CALLBACK(yahoo_userinfo_blist_node), @@ -4363,17 +4369,7 @@ } } - if (who[3] == '/') { - if (!g_ascii_strncasecmp(who, "msn/", 4)) { - fed = YAHOO_FEDERATION_MSN; - } - else if (!g_ascii_strncasecmp(who, "ocs/", 4)) { - fed = YAHOO_FEDERATION_OCS; - } - else if (!g_ascii_strncasecmp(who, "ibm/", 4)) { - fed = YAHOO_FEDERATION_IBM; - } - } + fed = yahoo_get_federation_from_name(who); if (who[0] == '+') { /* we have an sms to be sent */ @@ -4505,17 +4501,7 @@ YahooFederation fed = YAHOO_FEDERATION_NONE; struct yahoo_packet *pkt = NULL; - if (who[3] == '/') { - if (!g_ascii_strncasecmp(who, "msn/", 4)) { - fed = YAHOO_FEDERATION_MSN; - } - else if (!g_ascii_strncasecmp(who, "ocs/", 4)) { - fed = YAHOO_FEDERATION_OCS; - } - else if (!g_ascii_strncasecmp(who, "ibm/", 4)) { - fed = YAHOO_FEDERATION_IBM; - } - } + fed = yahoo_get_federation_from_name(who); /* Don't do anything if sms is being typed */ if( strncmp(who, "+", 1) == 0 ) @@ -4807,18 +4793,9 @@ return; f = yahoo_friend_find(gc, bname); - if (bname[3] == '/') { + fed = yahoo_get_federation_from_name(bname); + if (fed != YAHOO_FEDERATION_NONE) fed_bname += 4; - if (!g_ascii_strncasecmp(bname, "msn/", 4)) { - fed = YAHOO_FEDERATION_MSN; - } - else if (!g_ascii_strncasecmp(bname, "ocs/", 4)) { - fed = YAHOO_FEDERATION_OCS; - } - else if (!g_ascii_strncasecmp(bname, "ibm/", 4)) { - fed = YAHOO_FEDERATION_IBM; - } - } g = purple_buddy_get_group(buddy); if (g) @@ -4930,18 +4907,8 @@ if (!who || who[0] == '\0') return; - if (who[3] == '/') { - if (!g_ascii_strncasecmp(who, "msn/", 4)) { - fed = YAHOO_FEDERATION_MSN; - } - else if (!g_ascii_strncasecmp(who, "ocs/", 4)) { - fed = YAHOO_FEDERATION_OCS; - } - else if (!g_ascii_strncasecmp(who, "ibm/", 4)) { - fed = YAHOO_FEDERATION_IBM; - } - } - + fed = yahoo_get_federation_from_name(who); + pkt = yahoo_packet_new(YAHOO_SERVICE_IGNORECONTACT, YAHOO_STATUS_AVAILABLE, yd->session_id); if(fed) @@ -4962,17 +4929,8 @@ if (!who || who[0] == '\0') return; - if (who[3] == '/') { - if (!g_ascii_strncasecmp(who, "msn/", 4)) { - fed = YAHOO_FEDERATION_MSN; - } - else if (!g_ascii_strncasecmp(who, "ocs/", 4)) { - fed = YAHOO_FEDERATION_OCS; - } - else if (!g_ascii_strncasecmp(who, "ibm/", 4)) { - fed = YAHOO_FEDERATION_IBM; - } - } + fed = yahoo_get_federation_from_name(who); + pkt = yahoo_packet_new(YAHOO_SERVICE_IGNORECONTACT, YAHOO_STATUS_AVAILABLE, yd->session_id); if(fed)
--- a/libpurple/protocols/yahoo/libymsg.h Mon Oct 26 22:16:32 2009 +0000 +++ b/libpurple/protocols/yahoo/libymsg.h Tue Nov 03 18:27:07 2009 +0000 @@ -346,6 +346,7 @@ char *yahoo_convert_to_numeric(const char *str); +YahooFederation yahoo_get_federation_from_name(const char *who); /* yahoo_profile.c */ void yahoo_get_info(PurpleConnection *gc, const char *name);
--- a/libpurple/protocols/yahoo/util.c Mon Oct 26 22:16:32 2009 +0000 +++ b/libpurple/protocols/yahoo/util.c Tue Nov 03 18:27:07 2009 +0000 @@ -916,3 +916,18 @@ return g_string_free(dest, FALSE); } + +YahooFederation yahoo_get_federation_from_name(const char *who) +{ + YahooFederation fed = YAHOO_FEDERATION_NONE; + if (who[3] == '/') { + if (!g_ascii_strncasecmp(who, "msn", 3)) + fed = YAHOO_FEDERATION_MSN; + else if (!g_ascii_strncasecmp(who, "ocs", 3)) + fed = YAHOO_FEDERATION_OCS; + else if (!g_ascii_strncasecmp(who, "ibm", 3)) + fed = YAHOO_FEDERATION_IBM; + } + return fed; +} +
--- a/libpurple/protocols/yahoo/yahoo_filexfer.c Mon Oct 26 22:16:32 2009 +0000 +++ b/libpurple/protocols/yahoo/yahoo_filexfer.c Tue Nov 03 18:27:07 2009 +0000 @@ -1070,6 +1070,13 @@ yahoo_packet_send_and_free(pkt, yd); } +gboolean yahoo_can_receive_file(PurpleConnection *gc, const char *who) +{ + if (!who || yahoo_get_federation_from_name(who) != YAHOO_FEDERATION_NONE) + return FALSE; + return TRUE; +} + void yahoo_send_file(PurpleConnection *gc, const char *who, const char *file) { struct yahoo_xfer_data *xfer_data;
--- a/libpurple/protocols/yahoo/yahoo_filexfer.h Mon Oct 26 22:16:32 2009 +0000 +++ b/libpurple/protocols/yahoo/yahoo_filexfer.h Tue Nov 03 18:27:07 2009 +0000 @@ -43,6 +43,18 @@ PurpleXfer *yahoo_new_xfer(PurpleConnection *gc, const char *who); /** + * Returns TRUE if the buddy can receive file, FALSE otherwise. + * Federated users cannot receive files. So this will return FALSE only + * for them. + * + * @param gc The connection + * @param who The name of the remote user + * + * @return TRUE or FALSE + */ +gboolean yahoo_can_receive_file(PurpleConnection *gc, const char *who); + +/** * Send a file. * * @param gc The PurpleConnection handle.
--- a/libpurple/win32/global.mak Mon Oct 26 22:16:32 2009 +0000 +++ b/libpurple/win32/global.mak Tue Nov 03 18:27:07 2009 +0000 @@ -85,7 +85,7 @@ DEFINES += -DHAVE_CYRUS_SASL endif -DEFINES += -DHAVE_CONFIG_H +DEFINES += -DHAVE_CONFIG_H -DWIN32_LEAN_AND_MEAN # Use -g flag when building debug version of Pidgin (including plugins). # Use -fnative-struct instead of -mms-bitfields when using mingw 1.1
--- a/pidgin/Makefile.mingw Mon Oct 26 22:16:32 2009 +0000 +++ b/pidgin/Makefile.mingw Tue Nov 03 18:27:07 2009 +0000 @@ -7,6 +7,8 @@ PIDGIN_TREE_TOP := .. include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak +DEFINES := $(subst -DWIN32_LEAN_AND_MEAN,,$(DEFINES)) + NEEDED_DLLS = $(GTKSPELL_TOP)/gtkspell/libgtkspell.dll ## @@ -55,12 +57,12 @@ ## PIDGIN_C_SRC = \ gtkaccount.c \ - gtkblist.c \ + gtkblist-theme-loader.c \ gtkblist-theme.c \ - gtkblist-theme-loader.c \ - gtkcertmgr.c \ + gtkblist.c \ gtkcellrendererexpander.c \ gtkcellrendererprogress.c \ + gtkcertmgr.c \ gtkconn.c \ gtkconv.c \ gtkdebug.c \ @@ -70,8 +72,8 @@ gtkeventloop.c \ gtkexpander.c \ gtkft.c \ + gtkicon-theme-loader.c \ gtkicon-theme.c \ - gtkicon-theme-loader.c \ gtkidle.c \ gtkimhtml.c \ gtkimhtmltoolbar.c \
--- a/pidgin/gtkmain.c Mon Oct 26 22:16:32 2009 +0000 +++ b/pidgin/gtkmain.c Tue Nov 03 18:27:07 2009 +0000 @@ -744,7 +744,7 @@ } #if GLIB_CHECK_VERSION(2,2,0) - g_set_application_name(_("Pidgin")); + g_set_application_name(PIDGIN_NAME); #endif /* glib-2.0 >= 2.2.0 */ #ifdef _WIN32
--- a/pidgin/gtkprefs.c Mon Oct 26 22:16:32 2009 +0000 +++ b/pidgin/gtkprefs.c Tue Nov 03 18:27:07 2009 +0000 @@ -77,6 +77,7 @@ static GtkListStore *smiley_theme_store = NULL; static GtkTreeSelection *smiley_theme_sel = NULL; static GtkWidget *prefs_proxy_frame = NULL; +static GtkWidget *prefs_proxy_subframe = NULL; static GtkWidget *prefs = NULL; static GtkWidget *debugbutton = NULL; @@ -1887,23 +1888,27 @@ pidgin_prefs_checkbox(_("_Enable automatic router port forwarding"), "/purple/network/map_ports", vbox); - ports_checkbox = pidgin_prefs_checkbox(_("_Manually specify range of ports to listen on"), - "/purple/network/ports_range_use", vbox); - - spin_button = pidgin_prefs_labeled_spin_button(vbox, _("_Start port:"), + hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); + + ports_checkbox = pidgin_prefs_checkbox(_("_Manually specify range of ports to listen on:"), + "/purple/network/ports_range_use", hbox); + + spin_button = pidgin_prefs_labeled_spin_button(hbox, _("_Start:"), "/purple/network/ports_range_start", 0, 65535, sg); if (!purple_prefs_get_bool("/purple/network/ports_range_use")) gtk_widget_set_sensitive(GTK_WIDGET(spin_button), FALSE); g_signal_connect(G_OBJECT(ports_checkbox), "clicked", G_CALLBACK(pidgin_toggle_sensitive), spin_button); - spin_button = pidgin_prefs_labeled_spin_button(vbox, _("_End port:"), + spin_button = pidgin_prefs_labeled_spin_button(hbox, _("_End:"), "/purple/network/ports_range_end", 0, 65535, sg); if (!purple_prefs_get_bool("/purple/network/ports_range_use")) gtk_widget_set_sensitive(GTK_WIDGET(spin_button), FALSE); g_signal_connect(G_OBJECT(ports_checkbox), "clicked", G_CALLBACK(pidgin_toggle_sensitive), spin_button); + pidgin_add_widget_to_vbox(GTK_BOX(vbox), NULL, NULL, hbox, TRUE, NULL); + g_object_unref(sg); /* TURN server */ @@ -1922,9 +1927,9 @@ pidgin_prefs_labeled_spin_button(hbox, _("_Port:"), "/purple/network/turn_port", 0, 65535, NULL); - hbox = pidgin_prefs_labeled_entry(vbox, _("_Username:"), + hbox = pidgin_prefs_labeled_entry(vbox, _("Use_rname:"), "/purple/network/turn_username", sg); - pidgin_prefs_labeled_password(hbox, _("_Password:"), + pidgin_prefs_labeled_password(hbox, _("Pass_word:"), "/purple/network/turn_password", NULL); if (purple_running_gnome()) { @@ -1968,9 +1973,15 @@ gtk_widget_show(browser_button); } else { vbox = pidgin_make_frame(ret, _("Proxy Server")); - prefs_proxy_frame = gtk_vbox_new(FALSE, 0); - - pidgin_prefs_dropdown(vbox, _("Proxy _type:"), PURPLE_PREF_STRING, + prefs_proxy_frame = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); + prefs_proxy_subframe = gtk_vbox_new(FALSE, 0); + + /* This is a global option that affects SOCKS4 usage even with account-specific proxy settings */ + pidgin_prefs_checkbox(_("Use remote _DNS with SOCKS4 proxies"), + "/purple/proxy/socks4_remotedns", prefs_proxy_frame); + gtk_box_pack_start(GTK_BOX(vbox), prefs_proxy_frame, 0, 0, 0); + + pidgin_prefs_dropdown(prefs_proxy_frame, _("Proxy t_ype:"), PURPLE_PREF_STRING, "/purple/proxy/type", _("No proxy"), "none", "SOCKS 4", "socks4", @@ -1978,21 +1989,17 @@ "HTTP", "http", _("Use Environmental Settings"), "envvar", NULL); - gtk_box_pack_start(GTK_BOX(vbox), prefs_proxy_frame, 0, 0, 0); + gtk_box_pack_start(GTK_BOX(prefs_proxy_frame), prefs_proxy_subframe, 0, 0, 0); proxy_info = purple_global_proxy_get_info(); purple_prefs_connect_callback(prefs, "/purple/proxy/type", - proxy_changed_cb, prefs_proxy_frame); - - /* This is a global option that affects SOCKS4 usage even with account-specific proxy settings */ - pidgin_prefs_checkbox(_("Use remote DNS with SOCKS4 proxies"), - "/purple/proxy/socks4_remotedns", prefs_proxy_frame); + proxy_changed_cb, prefs_proxy_subframe); table = gtk_table_new(4, 2, FALSE); gtk_container_set_border_width(GTK_CONTAINER(table), 0); gtk_table_set_col_spacings(GTK_TABLE(table), 5); gtk_table_set_row_spacings(GTK_TABLE(table), 10); - gtk_container_add(GTK_CONTAINER(prefs_proxy_frame), table); + gtk_container_add(GTK_CONTAINER(prefs_proxy_subframe), table); label = gtk_label_new_with_mnemonic(_("_Host:")); @@ -2013,11 +2020,11 @@ gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); pidgin_set_accessible_label (entry, label); - label = gtk_label_new_with_mnemonic(_("_Port:")); + label = gtk_label_new_with_mnemonic(_("P_ort:")); gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5); gtk_table_attach(GTK_TABLE(table), label, 2, 3, 0, 1, GTK_FILL, 0, 0, 0); - entry = gtk_entry_new(); + entry = gtk_spin_button_new_with_range(0, 65535, 1); gtk_label_set_mnemonic_widget(GTK_LABEL(label), entry); gtk_table_attach(GTK_TABLE(table), entry, 3, 4, 0, 1, GTK_FILL, 0, 0, 0); g_signal_connect(G_OBJECT(entry), "changed", @@ -2032,7 +2039,7 @@ } pidgin_set_accessible_label (entry, label); - label = gtk_label_new_with_mnemonic(_("_User:")); + label = gtk_label_new_with_mnemonic(_("User_name:")); gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5); gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, GTK_FILL, 0, 0, 0);
--- a/pidgin/gtkrequest.c Mon Oct 26 22:16:32 2009 +0000 +++ b/pidgin/gtkrequest.c Tue Nov 03 18:27:07 2009 +0000 @@ -82,6 +82,33 @@ } PidginRequestData; static void +pidgin_widget_decorate_account(GtkWidget *cont, PurpleAccount *account) +{ + GtkWidget *image; + GdkPixbuf *pixbuf; + GtkTooltips *tips; + + if (!account) + return; + + pixbuf = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_SMALL); + image = gtk_image_new_from_pixbuf(pixbuf); + g_object_unref(G_OBJECT(pixbuf)); + + tips = gtk_tooltips_new(); + gtk_tooltips_set_tip(tips, image, purple_account_get_username(account), NULL); + + if (GTK_IS_DIALOG(cont)) { + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(cont)->action_area), image, FALSE, TRUE, 0); + gtk_box_reorder_child(GTK_BOX(GTK_DIALOG(cont)->action_area), image, 0); + } else if (GTK_IS_HBOX(cont)) { + gtk_misc_set_alignment(GTK_MISC(image), 0, 0); + gtk_box_pack_end(GTK_BOX(cont), image, FALSE, TRUE, 0); + } + gtk_widget_show(image); +} + +static void generic_response_start(PidginRequestData *data) { g_return_if_fail(data != NULL); @@ -348,6 +375,8 @@ gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 0); + pidgin_widget_decorate_account(hbox, account); + /* Descriptive label */ primary_esc = (primary != NULL) ? g_markup_escape_text(primary, -1) : NULL; secondary_esc = (secondary != NULL) ? g_markup_escape_text(secondary, -1) : NULL; @@ -516,6 +545,8 @@ gtk_misc_set_alignment(GTK_MISC(img), 0, 0); gtk_box_pack_start(GTK_BOX(hbox), img, FALSE, FALSE, 0); + pidgin_widget_decorate_account(hbox, account); + /* Vertical box */ vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BORDER); gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0); @@ -659,6 +690,8 @@ vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BORDER); gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0); + pidgin_widget_decorate_account(hbox, account); + /* Descriptive label */ primary_esc = (primary != NULL) ? g_markup_escape_text(primary, -1) : NULL; secondary_esc = (secondary != NULL) ? g_markup_escape_text(secondary, -1) : NULL; @@ -1174,6 +1207,8 @@ GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT); gtk_window_set_default(GTK_WINDOW(win), button); + pidgin_widget_decorate_account(hbox, account); + /* Setup the vbox */ vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BORDER); gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 0);
--- a/pidgin/gtkstatusbox.c Mon Oct 26 22:16:32 2009 +0000 +++ b/pidgin/gtkstatusbox.c Tue Nov 03 18:27:07 2009 +0000 @@ -79,8 +79,8 @@ static void pidgin_status_box_pulse_typing(PidginStatusBox *status_box); static void pidgin_status_box_refresh(PidginStatusBox *status_box); -static void status_menu_refresh_iter(PidginStatusBox *status_box); -static void pidgin_status_box_regenerate(PidginStatusBox *status_box); +static void status_menu_refresh_iter(PidginStatusBox *status_box, gboolean status_changed); +static void pidgin_status_box_regenerate(PidginStatusBox *status_box, gboolean status_changed); static void pidgin_status_box_changed(PidginStatusBox *box); static void pidgin_status_box_size_request (GtkWidget *widget, GtkRequisition *requisition); static void pidgin_status_box_size_allocate (GtkWidget *widget, GtkAllocation *allocation); @@ -304,7 +304,7 @@ if (status_box->account == account) update_to_reflect_account_status(status_box, account, newstatus); else if (status_box->token_status_account == account) - status_menu_refresh_iter(status_box); + status_menu_refresh_iter(status_box, TRUE); } static gboolean @@ -312,6 +312,7 @@ { if (event->button == 3) { GtkWidget *menu_item; + const char *path; if (box->icon_box_menu) gtk_widget_destroy(box->icon_box_menu); @@ -325,7 +326,8 @@ menu_item = pidgin_new_item_from_stock(box->icon_box_menu, _("Remove"), GTK_STOCK_REMOVE, G_CALLBACK(remove_buddy_icon_cb), box, 0, 0, NULL); - if (purple_prefs_get_path(PIDGIN_PREFS_ROOT "/accounts/buddyicon") == NULL) + if (!(path = purple_prefs_get_path(PIDGIN_PREFS_ROOT "/accounts/buddyicon")) + || !*path) gtk_widget_set_sensitive(menu_item, FALSE); gtk_menu_popup(GTK_MENU(box->icon_box_menu), NULL, NULL, NULL, NULL, @@ -559,7 +561,7 @@ else statusbox->token_status_account = check_active_accounts_for_identical_statuses(); - pidgin_status_box_regenerate(statusbox); + pidgin_status_box_regenerate(statusbox, TRUE); break; default: @@ -821,7 +823,7 @@ * keyboard signals instead of the changed signal? */ static void -status_menu_refresh_iter(PidginStatusBox *status_box) +status_menu_refresh_iter(PidginStatusBox *status_box, gboolean status_changed) { PurpleSavedStatus *saved_status; PurpleStatusPrimitive primitive; @@ -912,18 +914,15 @@ } else status_box->active_row = NULL; - message = purple_savedstatus_get_message(saved_status); - if (!purple_savedstatus_is_transient(saved_status) || !message || !*message) - { - status_box->imhtml_visible = FALSE; - gtk_widget_hide_all(status_box->vbox); - } - else - { - status_box->imhtml_visible = TRUE; - gtk_widget_show_all(status_box->vbox); + if (status_changed) { + message = purple_savedstatus_get_message(saved_status); /* + * If we are going to hide the imhtml, don't retain the + * message because showing the old message later is + * confusing. If we are going to set the message to a pre-set, + * then we need to do this anyway + * * Suppress the "changed" signal because the status * was changed programmatically. */ @@ -931,12 +930,24 @@ gtk_imhtml_clear(GTK_IMHTML(status_box->imhtml)); gtk_imhtml_clear_formatting(GTK_IMHTML(status_box->imhtml)); - gtk_imhtml_append_text(GTK_IMHTML(status_box->imhtml), message, 0); + + if (!purple_savedstatus_is_transient(saved_status) || !message || !*message) + { + status_box->imhtml_visible = FALSE; + gtk_widget_hide_all(status_box->vbox); + } + else + { + status_box->imhtml_visible = TRUE; + gtk_widget_show_all(status_box->vbox); + + gtk_imhtml_append_text(GTK_IMHTML(status_box->imhtml), message, 0); + } + gtk_widget_set_sensitive(GTK_WIDGET(status_box->imhtml), TRUE); + update_size(status_box); } - update_size(status_box); - /* Stop suppressing the "changed" signal. */ gtk_widget_set_sensitive(GTK_WIDGET(status_box), TRUE); } @@ -996,50 +1007,50 @@ * statuses and a token account if they do */ static PurpleAccount* check_active_accounts_for_identical_statuses(void) { - PurpleAccount *acct = NULL, *acct2; - GList *tmp, *tmp2, *active_accts = purple_accounts_get_all_active(); - GList *s, *s1, *s2; - - for (tmp = active_accts; tmp; tmp = tmp->next) { - acct = tmp->data; - s = purple_account_get_status_types(acct); - for (tmp2 = tmp->next; tmp2; tmp2 = tmp2->next) { - acct2 = tmp2->data; - - /* Only actually look at the statuses if the accounts use the same prpl */ - if (strcmp(purple_account_get_protocol_id(acct), purple_account_get_protocol_id(acct2))) { - acct = NULL; - break; - } - - s2 = purple_account_get_status_types(acct2); - - s1 = s; - while (s1 && s2) { - PurpleStatusType *st1 = s1->data, *st2 = s2->data; - /* TODO: Are these enough to consider the statuses identical? */ - if (purple_status_type_get_primitive(st1) != purple_status_type_get_primitive(st2) - || strcmp(purple_status_type_get_id(st1), purple_status_type_get_id(st2)) - || strcmp(purple_status_type_get_name(st1), purple_status_type_get_name(st2))) { - acct = NULL; - break; - } - - s1 = s1->next; - s2 = s2->next; - } - - if (s1 != s2) {/* Will both be NULL if matched */ - acct = NULL; + GList *iter, *active_accts = purple_accounts_get_all_active(); + PurpleAccount *acct1 = NULL; + const char *prpl1 = NULL; + + if (active_accts) { + acct1 = active_accts->data; + prpl1 = purple_account_get_protocol_id(acct1); + } else { + /* there's no enabled account */ + return NULL; + } + + /* start at the second account */ + for (iter = active_accts->next; iter; iter = iter->next) { + PurpleAccount *acct2 = iter->data; + GList *s1, *s2; + + if (!g_str_equal(prpl1, purple_account_get_protocol_id(acct2))) { + acct1 = NULL; + break; + } + + for (s1 = purple_account_get_status_types(acct1), + s2 = purple_account_get_status_types(acct2); s1 && s2; + s1 = s1->next, s2 = s2->next) { + PurpleStatusType *st1 = s1->data, *st2 = s2->data; + /* TODO: Are these enough to consider the statuses identical? */ + if (purple_status_type_get_primitive(st1) != purple_status_type_get_primitive(st2) + || strcmp(purple_status_type_get_id(st1), purple_status_type_get_id(st2)) + || strcmp(purple_status_type_get_name(st1), purple_status_type_get_name(st2))) { + acct1 = NULL; break; } } - if (!acct) + + if (s1 != s2) {/* Will both be NULL if matched */ + acct1 = NULL; break; + } } + g_list_free(active_accts); - return acct; + return acct1; } static void @@ -1068,7 +1079,7 @@ } static void -pidgin_status_box_regenerate(PidginStatusBox *status_box) +pidgin_status_box_regenerate(PidginStatusBox *status_box, gboolean status_changed) { GtkIconSize icon_size; @@ -1104,7 +1115,7 @@ pidgin_status_box_add(PIDGIN_STATUS_BOX(status_box), PIDGIN_STATUS_BOX_TYPE_CUSTOM, NULL, _("New status..."), NULL, NULL); pidgin_status_box_add(PIDGIN_STATUS_BOX(status_box), PIDGIN_STATUS_BOX_TYPE_SAVED, NULL, _("Saved statuses..."), NULL, NULL); - status_menu_refresh_iter(status_box); + status_menu_refresh_iter(status_box, status_changed); pidgin_status_box_refresh(status_box); } else { @@ -1156,7 +1167,7 @@ update_to_reflect_account_status(status_box, status_box->account, purple_account_get_active_status(status_box->account)); else { - status_menu_refresh_iter(status_box); + status_menu_refresh_iter(status_box, TRUE); pidgin_status_box_refresh(status_box); } return TRUE; @@ -1229,7 +1240,7 @@ /* Regenerate the list if it has changed */ if (initial_token_acct != status_box->token_status_account) { - pidgin_status_box_regenerate(status_box); + pidgin_status_box_regenerate(status_box, TRUE); } } @@ -1238,13 +1249,14 @@ current_savedstatus_changed_cb(PurpleSavedStatus *now, PurpleSavedStatus *old, PidginStatusBox *status_box) { /* Make sure our current status is added to the list of popular statuses */ - pidgin_status_box_regenerate(status_box); + pidgin_status_box_regenerate(status_box, TRUE); } static void saved_status_updated_cb(PurpleSavedStatus *status, PidginStatusBox *status_box) { - pidgin_status_box_regenerate(status_box); + pidgin_status_box_regenerate(status_box, + purple_savedstatus_get_current() == status); } static void @@ -1919,7 +1931,7 @@ status_box->token_status_account = check_active_accounts_for_identical_statuses(); cache_pixbufs(status_box); - pidgin_status_box_regenerate(status_box); + pidgin_status_box_regenerate(status_box, TRUE); purple_signal_connect(purple_savedstatuses_get_handle(), "savedstatus-changed", status_box, @@ -2324,18 +2336,6 @@ pidgin_status_box_refresh(status_box); } -static gboolean -message_changed(const char *one, const char *two) -{ - if (one == NULL && two == NULL) - return FALSE; - - if (one == NULL || two == NULL) - return TRUE; - - return (g_utf8_collate(one, two) != 0); -} - static void activate_currently_selected_status(PidginStatusBox *status_box) { @@ -2386,6 +2386,7 @@ if (status_box->account == NULL) { PurpleStatusType *acct_status_type = NULL; + const char *id = NULL; /* id of acct_status_type */ PurpleStatusPrimitive primitive = GPOINTER_TO_INT(data); /* Global */ /* Save the newly selected status to prefs.xml and status.xml */ @@ -2394,7 +2395,6 @@ if (status_box->token_status_account) { gint active; PurpleStatus *status; - const char *id = NULL; GtkTreePath *path = gtk_tree_row_reference_get_path(status_box->active_row); active = gtk_tree_path_get_indices(path)[0]; @@ -2402,37 +2402,35 @@ status = purple_account_get_active_status(status_box->token_status_account); - acct_status_type = find_status_type_by_index(status_box->token_status_account, active); + acct_status_type = find_status_type_by_index(status_box->token_status_account, active); id = purple_status_type_get_id(acct_status_type); - if (strncmp(id, purple_status_get_id(status), strlen(id)) == 0) + if (g_str_equal(id, purple_status_get_id(status)) && + purple_strequal(message, purple_status_get_attr_string(status, "message"))) { /* Selected status and previous status is the same */ - if (!message_changed(message, purple_status_get_attr_string(status, "message"))) - { - PurpleSavedStatus *ss = purple_savedstatus_get_current(); - /* Make sure that statusbox displays the correct thing. - * It can get messed up if the previous selection was a - * saved status that wasn't supported by this account */ - if ((purple_savedstatus_get_type(ss) == primitive) - && purple_savedstatus_is_transient(ss) - && purple_savedstatus_has_substatuses(ss)) - changed = FALSE; - } + PurpleSavedStatus *ss = purple_savedstatus_get_current(); + /* Make sure that statusbox displays the correct thing. + * It can get messed up if the previous selection was a + * saved status that wasn't supported by this account */ + if ((purple_savedstatus_get_type(ss) == primitive) + && purple_savedstatus_is_transient(ss) + && purple_savedstatus_has_substatuses(ss)) + changed = FALSE; } } else { saved_status = purple_savedstatus_get_current(); if (purple_savedstatus_get_type(saved_status) == primitive && - !purple_savedstatus_has_substatuses(saved_status)) + !purple_savedstatus_has_substatuses(saved_status) && + purple_strequal(purple_savedstatus_get_message(saved_status), message)) { - if (!message_changed(purple_savedstatus_get_message(saved_status), message)) - changed = FALSE; + changed = FALSE; } } if (changed) { - /* Manually find the appropriate transient acct */ + /* Manually find the appropriate transient status */ if (status_box->token_status_account) { GList *iter = purple_savedstatuses_get_all(); GList *tmp, *active_accts = purple_accounts_get_all_active(); @@ -2440,27 +2438,31 @@ for (; iter != NULL; iter = iter->next) { PurpleSavedStatus *ss = iter->data; const char *ss_msg = purple_savedstatus_get_message(ss); + /* find a known transient status that is the same as the + * new selected one */ if ((purple_savedstatus_get_type(ss) == primitive) && purple_savedstatus_is_transient(ss) && purple_savedstatus_has_substatuses(ss) && /* Must have substatuses */ - !message_changed(ss_msg, message)) + purple_strequal(ss_msg, message)) { gboolean found = FALSE; - /* The currently enabled accounts must have substatuses for all the active accts */ + /* this status must have substatuses for all the active accts */ for(tmp = active_accts; tmp != NULL; tmp = tmp->next) { PurpleAccount *acct = tmp->data; PurpleSavedStatusSub *sub = purple_savedstatus_get_substatus(ss, acct); if (sub) { const PurpleStatusType *sub_type = purple_savedstatus_substatus_get_type(sub); const char *subtype_status_id = purple_status_type_get_id(sub_type); - if (subtype_status_id && !strcmp(subtype_status_id, - purple_status_type_get_id(acct_status_type))) + if (purple_strequal(subtype_status_id, id)) { found = TRUE; + break; + } } } - if (!found) - continue; - saved_status = ss; - break; + + if (found) { + saved_status = ss; + break; + } } } @@ -2503,11 +2505,11 @@ status_type = find_status_type_by_index(status_box->account, active); id = purple_status_type_get_id(status_type); - if (strncmp(id, purple_status_get_id(status), strlen(id)) == 0) + if (g_str_equal(id, purple_status_get_id(status)) && + purple_strequal(message, purple_status_get_attr_string(status, "message"))) { /* Selected status and previous status is the same */ - if (!message_changed(message, purple_status_get_attr_string(status, "message"))) - changed = FALSE; + changed = FALSE; } if (changed) @@ -2597,7 +2599,7 @@ if (status_box->typing == 0) { /* Nothing has changed, so we don't need to do anything */ - status_menu_refresh_iter(status_box); + status_menu_refresh_iter(status_box, FALSE); return; } @@ -2655,14 +2657,14 @@ pidgin_status_editor_show(FALSE, purple_savedstatus_is_transient(saved_status) ? saved_status : NULL); - status_menu_refresh_iter(status_box); + status_menu_refresh_iter(status_box, FALSE); return; } if (type == PIDGIN_STATUS_BOX_TYPE_SAVED) { pidgin_status_window_show(); - status_menu_refresh_iter(status_box); + status_menu_refresh_iter(status_box, FALSE); return; } }
--- a/pidgin/plugins/perl/common/Makefile.mingw Mon Oct 26 22:16:32 2009 +0000 +++ b/pidgin/plugins/perl/common/Makefile.mingw Tue Nov 03 18:27:07 2009 +0000 @@ -5,9 +5,12 @@ # PIDGIN_TREE_TOP := ../../../.. -GCCWARNINGS := -Wno-comment -Waggregate-return -Wcast-align -Wdeclaration-after-statement -Werror-implicit-function-declaration -Wextra -Wno-sign-compare -Wno-unused-parameter -Winit-self -Wmissing-declarations -Wmissing-prototypes -Wpointer-arith -Wundef -Wno-unused include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak +GCCWARNINGS += -Wno-comment -Wno-unused -Wno-nested-externs + +DEFINES := $(subst -DWIN32_LEAN_AND_MEAN,,$(DEFINES)) + TARGET = Pidgin EXTUTILS ?= C:/perl/lib/ExtUtils
--- a/pidgin/plugins/win32/winprefs/Makefile.mingw Mon Oct 26 22:16:32 2009 +0000 +++ b/pidgin/plugins/win32/winprefs/Makefile.mingw Tue Nov 03 18:27:07 2009 +0000 @@ -8,6 +8,7 @@ include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak TARGET = winprefs +DEFINES := $(subst -DWIN32_LEAN_AND_MEAN,,$(DEFINES)) DEFINES += -DWINVER=0x500 ##