Mercurial > pidgin
changeset 26068:f95aa2b14bec
propagate from branch 'im.pidgin.pidgin' (head 96db74f0ccbe2a283893e33f0f7bff5a827f48d9)
to branch 'im.pidgin.pidgin.vv' (head 55aa623e09a7429df54b4e068dcba4c67c5fe779)
author | Mike Ruprecht <maiku@soc.pidgin.im> |
---|---|
date | Fri, 30 Jan 2009 08:58:07 +0000 |
parents | a6e53d23bcbb (current diff) ea9e0fa89c02 (diff) |
children | e6d548856fcd |
files | ChangeLog.API pidgin/gtkblist.c pidgin/gtkmain.c pidgin/gtkprefs.c |
diffstat | 51 files changed, 825 insertions(+), 479 deletions(-) [+] |
line wrap: on
line diff
--- a/AUTHORS Fri Jan 30 08:52:27 2009 +0000 +++ b/AUTHORS Fri Jan 30 08:58:07 2009 +0000 @@ -36,7 +36,6 @@ Crazy Patch Writers: ------------------- Paul Aurich -Felipe 'shx' Contreras Marcus 'malu' Lundblad Dennis 'EvilDennisR' Ristuccia Peter 'Fmoo' Ruibal @@ -57,6 +56,7 @@ Retired Crazy Patch Writers: --------------------------- +Felipe 'shx' Contreras Decklin Foster Peter 'Bleeter' Lawler Robert 'Robot101' McQueen
--- a/COPYRIGHT Fri Jan 30 08:52:27 2009 +0000 +++ b/COPYRIGHT Fri Jan 30 08:58:07 2009 +0000 @@ -63,6 +63,7 @@ Damien Carbery Michael Carlson Keegan Carruthers-Smith +Ludovico Cavedon Steve Cavilia Julien Cegarra Cerulean Studios, LLC @@ -210,6 +211,7 @@ Jaromír Karmazín John Kelm Jochen Kemnade +Yann Kerherve Akuke Kok Kir Kolyshkin Konstantin Korikov @@ -229,6 +231,7 @@ Steve Láposi Daniel Larsson Peter Lawler +Vadim Lebedev Ho-seok Lee Jean-Yves Lefort Moses Lei @@ -441,6 +444,7 @@ Todd Troxell Brad Turcotte Kyle Turman +Jon Turney Junichi Uekawa Igor Vlasenko István Váradi @@ -477,6 +481,7 @@ Dan Winship Michal Witkowski Scott Wolchok +Rogier Wolff The Written Word, Inc. Kevin Wu Won Pui Lam Wong
--- a/ChangeLog Fri Jan 30 08:52:27 2009 +0000 +++ b/ChangeLog Fri Jan 30 08:58:07 2009 +0000 @@ -1,6 +1,19 @@ Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul version 2.5.5 (??/??/????): + libpurple: + * Fix transfer of buddy icons, custom smileys, and files from the + latest Windows Live Messenger 9 official client. (Thomas + Gibson-Robinson) + * Fix a crash when removing an account with an unknown protocol id. + * Large (multi-part) messages on MSN are now correctly re-combined. + * Beta support for SSL connections for AIM and ICQ accounts. To + enable, check the "Use SSL" option from the Advanced tab when + editing your AIM or ICQ account. (Paul Aurich) + * Fix retrieval of ICQ status messages from users of ICQ 6.x, Miranda, + and other libpurple clients (fixes with libpurple users only on + statuses other than Available). (Daniel Ljungborg) + Finch: * Allow rebinding keys to change the focused widget (details in the man-page, look for GntBox::binding)
--- a/ChangeLog.API Fri Jan 30 08:52:27 2009 +0000 +++ b/ChangeLog.API Fri Jan 30 08:58:07 2009 +0000 @@ -6,6 +6,13 @@ * PurpleMedia API * xmlnode_get_parent +version 2.5.5 (??/??/2009): + libpurple: + Changed: + * purple_status_type_new now defaults "saveable" to TRUE. + This was necessary in order to maintain the current behavior + while fixing non-saveable statuses not to be saved. + version 2.5.4 (01/12/2009): perl: Changed:
--- a/doc/finch.1.in Fri Jan 30 08:52:27 2009 +0000 +++ b/doc/finch.1.in Fri Jan 30 08:58:07 2009 +0000 @@ -543,23 +543,26 @@ \fIhttp://developer.pidgin.im/query?status=new&status=assigned&status=reopened&component=finch+%28gnt%2Fncurses%29&order=priority\fR Before sending a bug report, please verify that you have the latest -version of \fBfinch\fR and \fBlibpurple\fR. Many bugs (major and minor) are +version of \fBfinch\fR and libpurple. Many bugs (major and minor) are fixed at each release, and if yours is out of date, the problem may already have been solved. - .SH PATCHES If you fix a bug in \fBfinch\fR (or otherwise enhance it), please submit a -patch (using \fImtn diff > my.diff\fR against the latest version from the -Monotone repository) at -.br -\fIhttp://developer.pidgin.im/newticket\fR +patch (using \fBmtn diff > my.diff\fR against the latest version from the +Monotone repository) at \fIhttp://developer.pidgin.im/simpleticket\fR -You are also encouraged to drop by at \fB#pidgin\fR on \fIirc.freenode.net\fR to -discuss development. +You are also encouraged to drop by at \fB#pidgin\fR on \fIirc.freenode.net\fR +to discuss development. .SH SEE ALSO \fIhttp://pidgin.im/\fR +.br +\fIhttp://developer.pidgin.im/\fR +.br +\fBpurple-remote\fR(1) +.br +\fBpidgin\fR(1) .SH LICENSE This program is free software; you can redistribute it and/or modify
--- a/doc/pidgin.1.in Fri Jan 30 08:52:27 2009 +0000 +++ b/doc/pidgin.1.in Fri Jan 30 08:58:07 2009 +0000 @@ -34,6 +34,9 @@ many common features found in other clients, as well as many unique features. Pidgin is not endorsed by or affiliated with America Online, ICQ, Microsoft, or Yahoo. +.PP +Pidgin can be extended by plugins written in multiple programming languages and +controlled through DBus or \fBpurple-remote\fR. .SH OPTIONS The following options are provided by Pidgin using the standard GNU @@ -556,20 +559,28 @@ .SH BUGS The bug tracker can be reached by visiting \fIhttp://developer.pidgin.im/query\fR -.SH PATCHES -If you fix a bug in Pidgin (or otherwise enhance it), please submit a -patch (using \fImtn diff > my.diff\fR against the latest version from the -Monotone repository) at \fIhttp://developer.pidgin.im/simpleticket\fR - Before sending a bug report, please verify that you have the latest version of Pidgin. Many bugs (major and minor) are fixed at each release, and if yours is out of date, the problem may already have been solved. +.SH PATCHES +If you fix a bug in Pidgin (or otherwise enhance it), please submit a +patch (using \fBmtn diff > my.diff\fR against the latest version from the +Monotone repository) at \fIhttp://developer.pidgin.im/simpleticket\fR + +You are also encouraged to drop by at \fB#pidgin\fR on \fIirc.freenode.net\fR +to discuss development. + + .SH SEE ALSO \fIhttp://pidgin.im/\fR .br \fIhttp://developer.pidgin.im/\fR +.br +\fBpurple-remote\fR(1) +.br +\fBfinch\fR(1) .SH LICENSE This program is free software; you can redistribute it and/or modify @@ -643,8 +654,6 @@ .br Paul Aurich .br - Felipe 'shx' Contreras -.br Marcus 'malu' Lundblad .br Dennis 'EvilDennisR' Ristuccia @@ -687,6 +696,8 @@ Our retired crazy patch writers include: .br + Felipe 'shx' Contreras +.br Decklin Foster .br Peter 'Bleeter' Lawler
--- a/finch/libgnt/gntcolors.c Fri Jan 30 08:52:27 2009 +0000 +++ b/finch/libgnt/gntcolors.c Fri Jan 30 08:58:07 2009 +0000 @@ -208,7 +208,7 @@ key = g_ascii_strdown(key, -1); color = gnt_colors_get_color(key); g_free(key); - if (color == -1) + if (color == -EINVAL) continue; init_color(color, r, g, b); @@ -251,7 +251,7 @@ int bg = gnt_colors_get_color(bgc); g_free(fgc); g_free(bgc); - if (fg == -1 || bg == -1) + if (fg == -EINVAL || bg == -EINVAL) continue; key = g_ascii_strdown(key, -1);
--- a/libpurple/account.c Fri Jan 30 08:52:27 2009 +0000 +++ b/libpurple/account.c Fri Jan 30 08:58:07 2009 +0000 @@ -257,15 +257,20 @@ statuses_to_xmlnode(const PurplePresence *presence) { xmlnode *node, *child; - GList *statuses, *status; + GList *statuses; + PurpleStatus *status; node = xmlnode_new("statuses"); statuses = purple_presence_get_statuses(presence); - for (status = statuses; status != NULL; status = status->next) + for (; statuses != NULL; statuses = statuses->next) { - child = status_to_xmlnode((PurpleStatus *)status->data); - xmlnode_insert_child(node, child); + status = statuses->data; + if (purple_status_type_is_saveable(purple_status_get_type(status))) + { + child = status_to_xmlnode(status); + xmlnode_insert_child(node, child); + } } return node;
--- a/libpurple/blist.c Fri Jan 30 08:52:27 2009 +0000 +++ b/libpurple/blist.c Fri Jan 30 08:58:07 2009 +0000 @@ -1811,7 +1811,7 @@ PurpleGroup *group; struct _purple_hbuddy hb; PurplePlugin *prpl; - PurplePluginProtocolInfo *prpl_info; + PurplePluginProtocolInfo *prpl_info = NULL; g_return_if_fail(buddy != NULL); @@ -1872,7 +1872,8 @@ * can free proto_data */ prpl = purple_find_prpl(purple_account_get_protocol_id(buddy->account)); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); + if (prpl) + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); if (prpl_info && prpl_info->buddy_free) prpl_info->buddy_free(buddy);
--- a/libpurple/certificate.c Fri Jan 30 08:52:27 2009 +0000 +++ b/libpurple/certificate.c Fri Jan 30 08:58:07 2009 +0000 @@ -1546,31 +1546,11 @@ void purple_certificate_uninit(void) { - GList *full_list, *l; - - /* Unregister all Schemes */ - full_list = g_list_copy(cert_schemes); /* Make a working copy */ - for (l = full_list; l; l = l->next) { - purple_certificate_unregister_scheme( - (PurpleCertificateScheme *) l->data ); - } - g_list_free(full_list); - /* Unregister all Verifiers */ - full_list = g_list_copy(cert_verifiers); /* Make a working copy */ - for (l = full_list; l; l = l->next) { - purple_certificate_unregister_verifier( - (PurpleCertificateVerifier *) l->data ); - } - g_list_free(full_list); + g_list_foreach(cert_verifiers, (GFunc)purple_certificate_unregister_verifier, NULL); /* Unregister all Pools */ - full_list = g_list_copy(cert_pools); /* Make a working copy */ - for (l = full_list; l; l = l->next) { - purple_certificate_unregister_pool( - (PurpleCertificatePool *) l->data ); - } - g_list_free(full_list); + g_list_foreach(cert_pools, (GFunc)purple_certificate_unregister_pool, NULL); } gpointer
--- a/libpurple/connection.c Fri Jan 30 08:52:27 2009 +0000 +++ b/libpurple/connection.c Fri Jan 30 08:58:07 2009 +0000 @@ -545,7 +545,7 @@ } if (description == NULL) { - purple_debug_error("connection", "purple_connection_error_reason: check `description != NULL' failed\n"); + purple_debug_error("connection", "purple_connection_error_reason called with NULL description\n"); description = _("Unknown error"); }
--- a/libpurple/core.c Fri Jan 30 08:52:27 2009 +0000 +++ b/libpurple/core.c Fri Jan 30 08:58:07 2009 +0000 @@ -137,7 +137,7 @@ * subsystem right away too. */ purple_plugins_init(); - + /* Initialize all static protocols. */ static_proto_init(); @@ -198,22 +198,40 @@ /* Transmission ends */ purple_connections_disconnect_all(); + /* + * Certificates must be destroyed before the SSL plugins, because + * PurpleCertificates contain pointers to PurpleCertificateSchemes, + * and the PurpleCertificateSchemes will be unregistered when the + * SSL plugin is uninit. + */ + purple_certificate_uninit(); + + /* The SSL plugins must be uninit before they're unloaded */ + purple_ssl_uninit(); + + /* Unload all plugins before the UI because UI plugins might call + * UI-specific functions */ + purple_debug_info("main", "Unloading all plugins\n"); + purple_plugins_destroy_all(); + + /* Shut down the UI before all the subsystems */ + ops = purple_core_get_ui_ops(); + if (ops != NULL && ops->quit != NULL) + ops->quit(); + /* Save .xml files, remove signals, etc. */ purple_smileys_uninit(); purple_idle_uninit(); - purple_ssl_uninit(); purple_pounces_uninit(); purple_blist_uninit(); purple_ciphers_uninit(); purple_notify_uninit(); purple_conversations_uninit(); purple_connections_uninit(); - purple_certificate_uninit(); purple_buddy_icons_uninit(); purple_accounts_uninit(); purple_savedstatuses_uninit(); purple_status_uninit(); - purple_prefs_uninit(); purple_sound_uninit(); purple_xfers_uninit(); purple_proxy_uninit(); @@ -221,19 +239,15 @@ purple_imgstore_uninit(); purple_network_uninit(); - purple_debug_info("main", "Unloading all plugins\n"); - purple_plugins_destroy_all(); - - ops = purple_core_get_ui_ops(); - if (ops != NULL && ops->quit != NULL) - ops->quit(); - + /* Everything after this must not try to read any prefs */ + purple_prefs_uninit(); purple_plugins_uninit(); #ifdef HAVE_DBUS purple_dbus_uninit(); #endif purple_cmds_uninit(); + /* Everything after this cannot try to write things to the confdir */ purple_util_uninit(); purple_signals_uninit();
--- a/libpurple/dbus-analyze-functions.py Fri Jan 30 08:52:27 2009 +0000 +++ b/libpurple/dbus-analyze-functions.py Fri Jan 30 08:58:07 2009 +0000 @@ -117,7 +117,7 @@ self.params.append(Parameter.fromtokens(paramtexts[i].split(), i)) self.call = "%s(%s)" % (self.function.name, - ", ".join([param.name for param in self.params])) + ", ".join(param.name for param in self.params)) def process(self): @@ -160,6 +160,10 @@ elif type[0].startswith("Purple") or type[0] == "xmlnode": return self.inputpurplestructure(type, name) + # special case for *_get_data functions, be careful here... + elif (type[0] == "size_t") and (name == "len"): + return self.inputgetdata(type, name) + # unknown pointers are always replaced with NULL else: return self.inputpointer(type, name) @@ -196,6 +200,10 @@ if type[0] in ["GList", "GSList"]: return self.outputlist(type, name) + # Special case for *_get_data functions + if type[0] == "gconstpointer": + return self.outputgetdata(type, name) + raise myexception @@ -309,7 +317,13 @@ self.returncode.append("return garray_int_to_%s(%s);" % (type[0].lower(), name)); - + # Special case for *_get_data functions, don't need client bindings, + # but do need the name so it doesn't crash + def inputgetdata(self, type, name): + raise myexception + def outputgetdata(self, type, name): + raise myexception + class ServerBinding (Binding): def __init__(self, functiontext, paramtexts): Binding.__init__(self, functiontext, paramtexts) @@ -475,6 +489,21 @@ % (name, name)) self.addouttype("ai", name) + # Special case for *_get_data functions + def inputgetdata(self, type, name): + self.cdecls.append("\tsize_t %s = 0;" % name) + return True + def outputgetdata(self, type, name): + # This is a total hack, but self.call is set up before the parameters + # are processed, so we can't tell it to pass a parameter by reference. + self.call = "%s(%s)" % (self.function.name, + ", ".join(param.name if param.name != "len" else "&len" for param in self.params)) + + self.cdecls.append("\tgconstpointer %s;" % name) + self.ccode.append("\t%s = %s;" % (name, self.call)) + self.cparamsout.append("DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &%s, %s" \ + % (name, "len")) + self.addouttype("ay", name) class BindingSet: regexp = r"^(\w[^()]*)\(([^()]*)\)\s*;\s*$";
--- a/libpurple/prefs.c Fri Jan 30 08:52:27 2009 +0000 +++ b/libpurple/prefs.c Fri Jan 30 08:58:07 2009 +0000 @@ -693,12 +693,15 @@ char *name; GSList *l; - if(!pref || pref == &prefs) + if(!pref) return; while(pref->first_child) remove_pref(pref->first_child); + if(pref == &prefs) + return; + if(pref->parent->first_child == pref) { pref->parent->first_child = pref->sibling; } else { @@ -711,7 +714,8 @@ name = pref_full_name(pref); - purple_debug_info("prefs", "removing pref %s\n", name); + if (prefs_loaded) + purple_debug_info("prefs", "removing pref %s\n", name); g_hash_table_remove(prefs_hash, name); g_free(name); @@ -1451,6 +1455,9 @@ sync_prefs(); } + prefs_loaded = FALSE; + purple_prefs_destroy(); + g_hash_table_destroy(prefs_hash); + prefs_hash = NULL; - prefs_loaded = FALSE; }
--- a/libpurple/protocols/jabber/auth.c Fri Jan 30 08:52:27 2009 +0000 +++ b/libpurple/protocols/jabber/auth.c Fri Jan 30 08:58:07 2009 +0000 @@ -749,8 +749,8 @@ val_end = cur; while (val_end != val_start && (*val_end == ' ' || *val_end == ',' || *val_end == '\t' - || *val_end == '\r' || *val_start == '\n' - || *val_end == '"')) + || *val_end == '\r' || *val_end == '\n' + || *val_end == '"' || *val_end == '\0')) val_end--; if (val_start != val_end)
--- a/libpurple/protocols/jabber/buddy.c Fri Jan 30 08:52:27 2009 +0000 +++ b/libpurple/protocols/jabber/buddy.c Fri Jan 30 08:58:07 2009 +0000 @@ -2518,7 +2518,7 @@ JabberBuddyResource *jbr = jabber_buddy_find_resource((JabberBuddy*)jb, NULL); if (!jbr) { - purple_debug_error("jabber", + purple_debug_info("jabber", "Unable to find caps: buddy might be offline\n"); return FALSE; }
--- a/libpurple/protocols/msn/cmdproc.c Fri Jan 30 08:52:27 2009 +0000 +++ b/libpurple/protocols/msn/cmdproc.c Fri Jan 30 08:58:07 2009 +0000 @@ -35,6 +35,9 @@ cmdproc->txqueue = g_queue_new(); cmdproc->history = msn_history_new(); + cmdproc->multiparts = g_hash_table_new_full(g_str_hash, g_str_equal, + NULL, (GDestroyNotify)msn_message_unref); + return cmdproc; } @@ -53,6 +56,8 @@ if (cmdproc->last_cmd != NULL) msn_command_destroy(cmdproc->last_cmd); + g_hash_table_destroy(cmdproc->multiparts); + g_free(cmdproc); } @@ -235,6 +240,61 @@ msn_cmdproc_process_msg(MsnCmdProc *cmdproc, MsnMessage *msg) { MsnMsgTypeCb cb; + const char *messageId = NULL; + + /* Multi-part messages */ + if ((messageId = msn_message_get_attr(msg, "Message-ID")) != NULL) { + const char *chunk_text = msn_message_get_attr(msg, "Chunks"); + guint chunk; + if (chunk_text != NULL) { + chunk = strtol(chunk_text, NULL, 10); + /* 1024 chunks of ~1300 bytes is ~1MB, which seems OK to prevent + some random client causing pidgin to hog a ton of memory. + Probably should figure out the maximum that the official client + actually supports, though. */ + if (chunk > 0 && chunk < 1024) { + msg->total_chunks = chunk; + msg->received_chunks = 1; + g_hash_table_insert(cmdproc->multiparts, (gpointer)messageId, msn_message_ref(msg)); + purple_debug_info("msn", "Received chunked message, messageId: '%s', total chunks: %d\n", + messageId, chunk); + } else { + purple_debug_error("msn", "MessageId '%s' has too many chunks: %d\n", messageId, chunk); + } + return; + } else { + chunk_text = msn_message_get_attr(msg, "Chunk"); + if (chunk_text != NULL) { + MsnMessage *first = g_hash_table_lookup(cmdproc->multiparts, messageId); + chunk = strtol(chunk_text, NULL, 10); + if (first == NULL) { + purple_debug_error("msn", + "Unable to find first chunk of messageId '%s' to correspond with chunk %d.\n", + messageId, chunk+1); + } else if (first->received_chunks == chunk) { + /* Chunk is from 1 to total-1 (doesn't count first one) */ + purple_debug_info("msn", "Received chunk %d of %d, messageId: '%s'\n", + chunk+1, first->total_chunks, messageId); + first->body = g_realloc(first->body, first->body_len + msg->body_len); + memcpy(first->body + first->body_len, msg->body, msg->body_len); + first->body_len += msg->body_len; + first->received_chunks++; + if (first->received_chunks != first->total_chunks) + return; + else + /* We're done! Send it along... The caller takes care of + freeing the old one. */ + msg = first; + } else { + /* TODO: Can you legitimately receive chunks out of order? */ + g_hash_table_remove(cmdproc->multiparts, messageId); + return; + } + } else { + purple_debug_error("msn", "Received MessageId '%s' with no chunk number!\n", messageId); + } + } + } if (msn_message_get_content_type(msg) == NULL) { @@ -245,15 +305,14 @@ cb = g_hash_table_lookup(cmdproc->cbs_table->msgs, msn_message_get_content_type(msg)); - if (cb == NULL) - { + if (cb != NULL) + cb(cmdproc, msg); + else purple_debug_warning("msn", "Unhandled content-type '%s'\n", msn_message_get_content_type(msg)); - return; - } - - cb(cmdproc, msg); + if (messageId != NULL) + g_hash_table_remove(cmdproc->multiparts, messageId); } void
--- a/libpurple/protocols/msn/cmdproc.h Fri Jan 30 08:52:27 2009 +0000 +++ b/libpurple/protocols/msn/cmdproc.h Fri Jan 30 08:58:07 2009 +0000 @@ -46,6 +46,8 @@ MsnHistory *history; + GHashTable *multiparts; /**< Multi-part message ID's */ + void *data; /**< Extra data, like the switchboard. */ };
--- a/libpurple/protocols/msn/contact.c Fri Jan 30 08:52:27 2009 +0000 +++ b/libpurple/protocols/msn/contact.c Fri Jan 30 08:58:07 2009 +0000 @@ -1362,7 +1362,8 @@ xmlnode *changes; purple_debug_info("msn", "Update contact information with new %s: %s\n", - type==MSN_UPDATE_DISPLAY ? "display name" : "alias", value); + type == MSN_UPDATE_DISPLAY ? "display name" : "alias", + value ? value : "(null)"); purple_debug_info("msn", "passport=%s\n", passport); g_return_if_fail(passport != NULL); contact_info = xmlnode_new("contactInfo");
--- a/libpurple/protocols/msn/msg.h Fri Jan 30 08:52:27 2009 +0000 +++ b/libpurple/protocols/msn/msg.h Fri Jan 30 08:58:07 2009 +0000 @@ -109,6 +109,8 @@ char *charset; char *body; gsize body_len; + guint total_chunks; /**< How many chunks in this multi-part message */ + guint received_chunks; /**< How many chunks we've received so far */ MsnSlpHeader msnslp_header; MsnSlpFooter msnslp_footer;
--- a/libpurple/protocols/msn/notification.c Fri Jan 30 08:52:27 2009 +0000 +++ b/libpurple/protocols/msn/notification.c Fri Jan 30 08:58:07 2009 +0000 @@ -1094,8 +1094,10 @@ return; } - serv_got_alias(gc, passport, friendly); - msn_user_set_friendly_name(user, friendly); + if (msn_user_set_friendly_name(user, friendly)) { + serv_got_alias(gc, passport, friendly); + msn_update_contact(session, passport, MSN_UPDATE_DISPLAY, friendly); + } g_free(friendly); msn_user_set_object(user, msnobj); @@ -1220,7 +1222,7 @@ MsnObject *msnobj; unsigned long clientid; int networkid; - const char *state, *passport, *friendly, *old_friendly; + const char *state, *passport, *friendly; session = cmdproc->session; account = session->account; @@ -1234,11 +1236,10 @@ user = msn_userlist_find_user(session->userlist, passport); if (user == NULL) return; - old_friendly = msn_user_get_friendly_name(user); - if (!old_friendly || (old_friendly && (!friendly || strcmp(old_friendly, friendly)))) + if (msn_user_set_friendly_name(user, friendly)) { serv_got_alias(gc, passport, friendly); - msn_user_set_friendly_name(user, friendly); + msn_update_contact(session, passport, MSN_UPDATE_DISPLAY, friendly); } if (cmd->param_count == 6)
--- a/libpurple/protocols/msn/slpcall.c Fri Jan 30 08:52:27 2009 +0000 +++ b/libpurple/protocols/msn/slpcall.c Fri Jan 30 08:58:07 2009 +0000 @@ -239,6 +239,10 @@ msn_slpcall_session_init(slpcall); } #endif + else if (slpmsg->flags == 0x2) + { + /* Acknowledgement of previous message. Don't do anything currently. */ + } else purple_debug_warning("msn", "Unprocessed SLP message with flags 0x%08lx\n", slpmsg->flags);
--- a/libpurple/protocols/msn/switchboard.c Fri Jan 30 08:52:27 2009 +0000 +++ b/libpurple/protocols/msn/switchboard.c Fri Jan 30 08:58:07 2009 +0000 @@ -799,7 +799,7 @@ msn_cmdproc_process_msg(cmdproc, msg); - msn_message_destroy(msg); + msn_message_unref(msg); } static void
--- a/libpurple/protocols/msn/user.c Fri Jan 30 08:52:27 2009 +0000 +++ b/libpurple/protocols/msn/user.c Fri Jan 30 08:58:07 2009 +0000 @@ -177,13 +177,18 @@ user->passport = g_strdup(passport); } -void +gboolean msn_user_set_friendly_name(MsnUser *user, const char *name) { g_return_if_fail(user != NULL); + if (user->friendly_name && name && !strcmp(user->friendly_name, name)) + return FALSE; + g_free(user->friendly_name); user->friendly_name = g_strdup(name); + + return TRUE; } void
--- a/libpurple/protocols/msn/user.h Fri Jan 30 08:52:27 2009 +0000 +++ b/libpurple/protocols/msn/user.h Fri Jan 30 08:58:07 2009 +0000 @@ -178,8 +178,10 @@ * * @param user The user. * @param name The friendly name. + * + * @returns TRUE is name actually changed, FALSE otherwise. */ -void msn_user_set_friendly_name(MsnUser *user, const char *name); +gboolean msn_user_set_friendly_name(MsnUser *user, const char *name); /** * Sets the buddy icon for a local user.
--- a/libpurple/protocols/oscar/family_chat.c Fri Jan 30 08:52:27 2009 +0000 +++ b/libpurple/protocols/oscar/family_chat.c Fri Jan 30 08:58:07 2009 +0000 @@ -79,13 +79,15 @@ if (conn->type != SNAC_FAMILY_CHAT) continue; - if (!conn->internal) { - purple_debug_misc("oscar", "faim: chat: chat connection with no name! (fd = %d)\n", conn->fd); + if (!conn->internal) + { + purple_debug_misc("oscar", "%sfaim: chat: chat connection with no name! (fd = %d)\n", + conn->gsc ? "(ssl) " : "", conn->gsc ? conn->gsc->fd : conn->fd); continue; } if (strcmp(ccp->name, name) == 0) - return conn;; + return conn; } return NULL;
--- a/libpurple/protocols/oscar/family_icq.c Fri Jan 30 08:52:27 2009 +0000 +++ b/libpurple/protocols/oscar/family_icq.c Fri Jan 30 08:58:07 2009 +0000 @@ -456,64 +456,6 @@ return 0; } -/* - * getstatusnote may be a misleading name because the response - * contains a lot of different information but currently it's only - * used to get that. - */ -int aim_icq_getstatusnote(OscarData *od, const char *uin, guint8 *note_hash, guint16 note_hash_len) -{ - FlapConnection *conn; - ByteStream bs; - aim_snacid_t snacid; - int bslen; - - purple_debug_misc("oscar", "aim_icq_getstatusnote: requesting status note for %s.\n", uin); - - if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICQ))) - { - purple_debug_misc("oscar", "aim_icq_getstatusnote: no connection.\n"); - return -EINVAL; - } - - bslen = 2 + 4 + 2 + 2 + 2 + 2 + 58 + strlen(uin); - byte_stream_new(&bs, 4 + bslen); - - snacid = aim_cachesnac(od, SNAC_FAMILY_ICQ, 0x0002, 0x0000, NULL, 0); - - byte_stream_put16(&bs, 0x0001); - byte_stream_put16(&bs, bslen); - - byte_stream_putle16(&bs, bslen - 2); - byte_stream_putuid(&bs, od); - byte_stream_putle16(&bs, 0x07d0); /* I command thee. */ - byte_stream_putle16(&bs, snacid); /* eh. */ - byte_stream_putle16(&bs, 0x0fa0); /* shrug. */ - byte_stream_putle16(&bs, 58 + strlen(uin)); - - byte_stream_put32(&bs, 0x05b90002); /* don't ask */ - byte_stream_put32(&bs, 0x80000000); - byte_stream_put32(&bs, 0x00000006); - byte_stream_put32(&bs, 0x00010002); - byte_stream_put32(&bs, 0x00020000); - byte_stream_put32(&bs, 0x04e30000); - byte_stream_put32(&bs, 0x00020002); - byte_stream_put32(&bs, 0x00000001); - - byte_stream_put16(&bs, 24 + strlen(uin)); - byte_stream_put32(&bs, 0x003c0010); - byte_stream_putraw(&bs, note_hash, 16); /* status note hash */ - byte_stream_put16(&bs, 0x0032); /* buddy uin */ - byte_stream_put16(&bs, strlen(uin)); - byte_stream_putstr(&bs, uin); - - flap_connection_send_snac_with_priority(od, conn, SNAC_FAMILY_ICQ, 0x0002, 0x000, snacid, &bs, FALSE); - - byte_stream_destroy(&bs); - - return 0; -} - static void aim_icq_freeinfo(struct aim_icq_info *info) { int i;
--- a/libpurple/protocols/oscar/family_oservice.c Fri Jan 30 08:52:27 2009 +0000 +++ b/libpurple/protocols/oscar/family_oservice.c Fri Jan 30 08:58:07 2009 +0000 @@ -103,12 +103,29 @@ aim_srv_requestnew(OscarData *od, guint16 serviceid) { FlapConnection *conn; + ByteStream bs; + aim_snacid_t snacid; + GSList *tlvlist = NULL; conn = flap_connection_findbygroup(od, SNAC_FAMILY_BOS); if(!conn) return; - aim_genericreq_s(od, conn, SNAC_FAMILY_OSERVICE, 0x0004, &serviceid); + byte_stream_new(&bs, 6); + + byte_stream_put16(&bs, serviceid); + + if (od->use_ssl) + /* Request SSL Connection */ + aim_tlvlist_add_noval(&tlvlist, 0x008c); + + aim_tlvlist_write(&bs, &tlvlist); + aim_tlvlist_free(tlvlist); + + snacid = aim_cachesnac(od, SNAC_FAMILY_OSERVICE, 0x0004, 0x0000, NULL, 0); + flap_connection_send_snac(od, conn, SNAC_FAMILY_OSERVICE, 0x0004, 0x0000, snacid, &bs); + + byte_stream_destroy(&bs); } /* @@ -127,10 +144,10 @@ struct chatsnacinfo csi; conn = flap_connection_findbygroup(od, SNAC_FAMILY_BOS); - if (!conn || !roomname || !strlen(roomname)) + if (!conn || !roomname || roomname[0] == '\0') return -EINVAL; - byte_stream_new(&bs, 502); + byte_stream_new(&bs, 506); memset(&csi, 0, sizeof(csi)); csi.exchange = exchange; @@ -143,6 +160,11 @@ byte_stream_put16(&bs, 0x000e); aim_tlvlist_add_chatroom(&tlvlist, 0x0001, exchange, roomname, instance); + + if (od->use_ssl) + /* Request SSL Connection */ + aim_tlvlist_add_noval(&tlvlist, 0x008c); + aim_tlvlist_write(&bs, &tlvlist); aim_tlvlist_free(tlvlist); @@ -179,6 +201,8 @@ redir.ip = aim_tlv_getstr(tlvlist, 0x0005, 1); redir.cookielen = aim_tlv_gettlv(tlvlist, 0x0006, 1)->length; redir.cookie = (guchar *)aim_tlv_getstr(tlvlist, 0x0006, 1); + redir.ssl_cert_cn = aim_tlv_getstr(tlvlist, 0x008d, 1); + redir.use_ssl = aim_tlv_get8(tlvlist, 0x008e, 1); /* Fetch original SNAC so we can get csi if needed */ origsnac = aim_remsnac(od, snac->id); @@ -196,6 +220,7 @@ g_free((void *)redir.ip); g_free((void *)redir.cookie); + g_free((void *)redir.ssl_cert_cn); if (origsnac) g_free(origsnac->data);
--- a/libpurple/protocols/oscar/flap_connection.c Fri Jan 30 08:52:27 2009 +0000 +++ b/libpurple/protocols/oscar/flap_connection.c Fri Jan 30 08:58:07 2009 +0000 @@ -364,6 +364,15 @@ conn->fd = -1; } + if (conn->gsc != NULL) + { + if (conn->type == SNAC_FAMILY_LOCATE) + flap_connection_send_close(od, conn); + + purple_ssl_close(conn->gsc); + conn->gsc = NULL; + } + if (conn->watcher_incoming != 0) { purple_input_remove(conn->watcher_incoming); @@ -467,6 +476,7 @@ g_free(conn->error_message); g_free(conn->cookie); + g_free(conn->ssl_cert_cn); /* * Free conn->internal, if necessary @@ -844,24 +854,31 @@ * All complete FLAPs handled immedate after they're received. * Incomplete FLAP data is stored locally and appended to the next * time this callback is triggered. + * + * This is called by flap_connection_recv_cb and + * flap_connection_recv_cb_ssl for unencrypted/encrypted connections. */ -void -flap_connection_recv_cb(gpointer data, gint source, PurpleInputCondition cond) +static void +flap_connection_recv(FlapConnection *conn) { - FlapConnection *conn; + gpointer buf; + gsize buflen; gssize read; - conn = data; - /* Read data until we run out of data and break out of the loop */ while (TRUE) { /* Start reading a new FLAP */ if (conn->buffer_incoming.data.data == NULL) { + buf = conn->header + conn->header_received; + buflen = 6 - conn->header_received; + /* Read the first 6 bytes (the FLAP header) */ - read = recv(conn->fd, conn->header + conn->header_received, - 6 - conn->header_received, 0); + if (conn->gsc) + read = purple_ssl_read(conn->gsc, buf, buflen); + else + read = recv(conn->fd, buf, buflen, 0); /* Check if the FLAP server closed the connection */ if (read == 0) @@ -918,13 +935,15 @@ conn->buffer_incoming.data.offset = 0; } - if (conn->buffer_incoming.data.len - conn->buffer_incoming.data.offset) + buflen = conn->buffer_incoming.data.len - conn->buffer_incoming.data.offset; + if (buflen) { + buf = &conn->buffer_incoming.data.data[conn->buffer_incoming.data.offset]; /* Read data into the temporary FlapFrame until it is complete */ - read = recv(conn->fd, - &conn->buffer_incoming.data.data[conn->buffer_incoming.data.offset], - conn->buffer_incoming.data.len - conn->buffer_incoming.data.offset, - 0); + if (conn->gsc) + read = purple_ssl_read(conn->gsc, buf, buflen); + else + read = recv(conn->fd, buf, buflen, 0); /* Check if the FLAP server closed the connection */ if (read == 0) @@ -964,6 +983,29 @@ } } +void +flap_connection_recv_cb(gpointer data, gint source, PurpleInputCondition cond) +{ + FlapConnection *conn = data; + + flap_connection_recv(conn); +} + +void +flap_connection_recv_cb_ssl(gpointer data, PurpleSslConnection *gsc, PurpleInputCondition cond) +{ + FlapConnection *conn = data; + + flap_connection_recv(conn); +} + +/** + * @param source When this function is called as a callback source is + * set to the fd that triggered the callback. But this function + * is also called directly from flap_connection_send_byte_stream(), + * in which case source will be -1. So don't use source--use + * conn->gsc or conn->fd instead. + */ static void send_cb(gpointer data, gint source, PurpleInputCondition cond) { @@ -980,7 +1022,11 @@ return; } - ret = send(conn->fd, conn->buffer_outgoing->outptr, writelen, 0); + if (conn->gsc) + ret = purple_ssl_write(conn->gsc, conn->buffer_outgoing->outptr, + writelen); + else + ret = send(conn->fd, conn->buffer_outgoing->outptr, writelen, 0); if (ret <= 0) { if (ret < 0 && ((errno == EAGAIN) || (errno == EWOULDBLOCK))) @@ -990,8 +1036,13 @@ /* Error! */ purple_input_remove(conn->watcher_outgoing); conn->watcher_outgoing = 0; - close(conn->fd); - conn->fd = -1; + if (conn->gsc) { + purple_ssl_close(conn->gsc); + conn->gsc = NULL; + } else { + close(conn->fd); + conn->fd = -1; + } flap_connection_schedule_destroy(conn, OSCAR_DISCONNECT_LOST_CONNECTION, g_strerror(errno)); return; @@ -1017,11 +1068,17 @@ purple_circ_buffer_append(conn->buffer_outgoing, bs->data, count); /* If we haven't already started writing stuff, then start the cycle */ - if ((conn->watcher_outgoing == 0) && (conn->fd >= 0)) + if (conn->watcher_outgoing == 0) { - conn->watcher_outgoing = purple_input_add(conn->fd, - PURPLE_INPUT_WRITE, send_cb, conn); - send_cb(conn, conn->fd, 0); + if (conn->gsc) { + conn->watcher_outgoing = purple_input_add(conn->gsc->fd, + PURPLE_INPUT_WRITE, send_cb, conn); + send_cb(conn, -1, 0); + } else if (conn->fd >= 0) { + conn->watcher_outgoing = purple_input_add(conn->fd, + PURPLE_INPUT_WRITE, send_cb, conn); + send_cb(conn, -1, 0); + } } }
--- a/libpurple/protocols/oscar/oscar.c Fri Jan 30 08:52:27 2009 +0000 +++ b/libpurple/protocols/oscar/oscar.c Fri Jan 30 08:58:07 2009 +0000 @@ -1088,59 +1088,64 @@ } /** - * This is the callback function anytime purple_proxy_connect() - * establishes a new TCP connection with an oscar host. Depending - * on the type of host, we do a few different things here. + * This is called from the callback functions for establishing + * a TCP connection with an oscar host if an error occurred. */ static void -connection_established_cb(gpointer data, gint source, const gchar *error_message) +connection_common_error_cb(FlapConnection *conn, const gchar *error_message) { - PurpleConnection *gc; OscarData *od; + PurpleConnection *gc; + + od = conn->od; + gc = od->gc; + + purple_debug_error("oscar", "unable to connect to FLAP " + "server of type 0x%04hx\n", conn->type); + + if (conn->type == SNAC_FAMILY_AUTH) + { + gchar *msg; + msg = g_strdup_printf(_("Could not connect to authentication server:\n%s"), + error_message); + purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg); + g_free(msg); + } + else if (conn->type == SNAC_FAMILY_LOCATE) + { + gchar *msg; + msg = g_strdup_printf(_("Could not connect to BOS server:\n%s"), + error_message); + purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg); + g_free(msg); + } + else + { + /* Maybe we should call this for BOS connections, too? */ + flap_connection_schedule_destroy(conn, + OSCAR_DISCONNECT_COULD_NOT_CONNECT, error_message); + } +} + +/** + * This is called from the callback functions for establishing + * a TCP connection with an oscar host. Depending on the type + * of host, we do a few different things here. + */ +static void +connection_common_established_cb(FlapConnection *conn) +{ + OscarData *od; + PurpleConnection *gc; PurpleAccount *account; - FlapConnection *conn; - - conn = data; + od = conn->od; gc = od->gc; account = purple_connection_get_account(gc); - conn->connect_data = NULL; - conn->fd = source; - - if (source < 0) - { - purple_debug_error("oscar", "unable to connect to FLAP " - "server of type 0x%04hx\n", conn->type); - if (conn->type == SNAC_FAMILY_AUTH) - { - gchar *msg; - msg = g_strdup_printf(_("Could not connect to authentication server:\n%s"), - error_message); - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg); - g_free(msg); - } - else if (conn->type == SNAC_FAMILY_LOCATE) - { - gchar *msg; - msg = g_strdup_printf(_("Could not connect to BOS server:\n%s"), - error_message); - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg); - g_free(msg); - } - else - { - /* Maybe we should call this for BOS connections, too? */ - flap_connection_schedule_destroy(conn, - OSCAR_DISCONNECT_COULD_NOT_CONNECT, error_message); - } - return; - } - purple_debug_info("oscar", "connected to FLAP server of type 0x%04hx\n", conn->type); - conn->watcher_incoming = purple_input_add(conn->fd, - PURPLE_INPUT_READ, flap_connection_recv_cb, conn); + if (conn->cookie == NULL) flap_connection_send_version(od, conn); else @@ -1171,6 +1176,85 @@ } static void +connection_established_cb(gpointer data, gint source, const gchar *error_message) +{ + FlapConnection *conn; + + conn = data; + + conn->connect_data = NULL; + conn->fd = source; + + if (source < 0) + { + connection_common_error_cb(conn, error_message); + return; + } + + conn->watcher_incoming = purple_input_add(conn->fd, + PURPLE_INPUT_READ, flap_connection_recv_cb, conn); + connection_common_established_cb(conn); +} + +static void +ssl_connection_established_cb(gpointer data, PurpleSslConnection *gsc, + PurpleInputCondition cond) +{ + FlapConnection *conn; + + conn = data; + + purple_ssl_input_add(gsc, flap_connection_recv_cb_ssl, conn); + connection_common_established_cb(conn); +} + +static void +ssl_connection_error_cb(PurpleSslConnection *gsc, PurpleSslErrorType error, + gpointer data) +{ + FlapConnection *conn; + + conn = data; + + if (conn->watcher_outgoing) + { + purple_input_remove(conn->watcher_outgoing); + conn->watcher_outgoing = 0; + } + + /* sslconn frees the connection on error */ + conn->gsc = NULL; + + connection_common_error_cb(conn, purple_ssl_strerror(error)); +} + +static void +ssl_proxy_conn_established_cb(gpointer data, gint source, const gchar *error_message) +{ + OscarData *od; + PurpleConnection *gc; + PurpleAccount *account; + FlapConnection *conn; + + conn = data; + od = conn->od; + gc = od->gc; + account = purple_connection_get_account(gc); + + conn->connect_data = NULL; + + if (source < 0) + { + connection_common_error_cb(conn, error_message); + return; + } + + conn->gsc = purple_ssl_connect_with_host_fd(account, source, + ssl_connection_established_cb, ssl_connection_error_cb, + conn->ssl_cert_cn, conn); +} + +static void flap_connection_established_bos(OscarData *od, FlapConnection *conn) { PurpleConnection *gc = od->gc; @@ -1430,17 +1514,56 @@ gc->flags |= PURPLE_CONNECTION_AUTO_RESP; } + od->use_ssl = purple_account_get_bool(account, "use_ssl", OSCAR_DEFAULT_USE_SSL); + /* Connect to core Purple signals */ purple_prefs_connect_callback(gc, "/purple/away/idle_reporting", idle_reporting_pref_cb, gc); purple_prefs_connect_callback(gc, "/plugins/prpl/oscar/recent_buddies", recent_buddies_pref_cb, gc); newconn = flap_connection_new(od, SNAC_FAMILY_AUTH); - newconn->connect_data = purple_proxy_connect(NULL, account, - purple_account_get_string(account, "server", OSCAR_DEFAULT_LOGIN_SERVER), - purple_account_get_int(account, "port", OSCAR_DEFAULT_LOGIN_PORT), - connection_established_cb, newconn); - if (newconn->connect_data == NULL) - { + if (od->use_ssl) { + if (purple_ssl_is_supported()) { + const char *server = purple_account_get_string(account, "server", OSCAR_DEFAULT_SSL_LOGIN_SERVER); + /* + * If the account's server is what the oscar prpl has offered as + * the default login server through the vast eons (all two of + * said default options, AFAIK) and the user wants SSL, we'll + * do what we know is best for them and change the setting out + * from under them to the SSL login server. + */ + if (!strcmp(server, OSCAR_DEFAULT_LOGIN_SERVER) || !strcmp(server, OSCAR_OLD_LOGIN_SERVER)) { + purple_debug_info("oscar", "Account uses SSL, so changing server to default SSL server\n"); + purple_account_set_string(account, "server", OSCAR_DEFAULT_SSL_LOGIN_SERVER); + server = OSCAR_DEFAULT_SSL_LOGIN_SERVER; + } + + newconn->gsc = purple_ssl_connect(account, server, + purple_account_get_int(account, "port", OSCAR_DEFAULT_LOGIN_PORT), + ssl_connection_established_cb, ssl_connection_error_cb, newconn); + } else { + purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT, + _("SSL support unavailable")); + } + } else { + const char *server = purple_account_get_string(account, "server", OSCAR_DEFAULT_LOGIN_SERVER); + + /* + * See the comment above. We do the reverse here. If they don't want + * SSL but their server is set to OSCAR_DEFAULT_SSL_LOGIN_SERVER, + * set it back to the default. + */ + if (!strcmp(server, OSCAR_DEFAULT_SSL_LOGIN_SERVER)) { + purple_debug_info("oscar", "Account does not use SSL, so changing server back to non-SSL\n"); + purple_account_set_string(account, "server", OSCAR_DEFAULT_LOGIN_SERVER); + server = OSCAR_DEFAULT_LOGIN_SERVER; + } + + newconn->connect_data = purple_proxy_connect(NULL, account, server, + purple_account_get_int(account, "port", OSCAR_DEFAULT_LOGIN_PORT), + connection_established_cb, newconn); + } + + if (newconn->gsc == NULL && newconn->connect_data == NULL) { purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Couldn't connect to host")); return; @@ -1565,8 +1688,23 @@ newconn = flap_connection_new(od, SNAC_FAMILY_LOCATE); newconn->cookielen = info->cookielen; newconn->cookie = g_memdup(info->cookie, info->cookielen); - newconn->connect_data = purple_proxy_connect(NULL, account, host, port, - connection_established_cb, newconn); + + if (od->use_ssl) + { + /* + * This shouldn't be hardcoded except that the server isn't sending + * us a name to use for comparing the certificate common name. + */ + newconn->ssl_cert_cn = g_strdup("bos.oscar.aol.com"); + newconn->connect_data = purple_proxy_connect(NULL, account, host, port, + ssl_proxy_conn_established_cb, newconn); + } + else + { + newconn->connect_data = purple_proxy_connect(NULL, account, host, port, + connection_established_cb, newconn); + } + g_free(host); if (newconn->connect_data == NULL) { @@ -1871,8 +2009,22 @@ else host = g_strdup(redir->ip); - purple_debug_info("oscar", "Connecting to FLAP server %s:%d of type 0x%04hx\n", - host, port, redir->group); + /* + * These FLAP servers advertise SSL (type "0x02"), but SSL connections to these hosts + * die a painful death. iChat and Miranda, when using SSL, still do these in plaintext. + */ + if (redir->use_ssl && (redir->group == SNAC_FAMILY_ADMIN || + redir->group == SNAC_FAMILY_BART)) + { + purple_debug_info("oscar", "Ignoring broken SSL for FLAP type 0x%04hx.\n", + redir->group); + redir->use_ssl = 0; + } + + purple_debug_info("oscar", "Connecting to FLAP server %s:%d of type 0x%04hx%s\n", + host, port, redir->group, + od->use_ssl && !redir->use_ssl ? " without SSL, despite main stream encryption" : ""); + newconn = flap_connection_new(od, redir->group); newconn->cookielen = redir->cookielen; newconn->cookie = g_memdup(redir->cookie, redir->cookielen); @@ -1890,9 +2042,26 @@ purple_debug_info("oscar", "Connecting to chat room %s exchange %hu\n", cc->name, cc->exchange); } - newconn->connect_data = purple_proxy_connect(NULL, account, host, port, - connection_established_cb, newconn); - if (newconn->connect_data == NULL) + + if (redir->use_ssl) + { + /* + * TODO: It should be possible to specify a certificate common name + * distinct from the host we're passing to purple_ssl_connect. The + * way to work around that is to use purple_proxy_connect + + * purple_ssl_connect_with_host_fd + */ + newconn->ssl_cert_cn = g_strdup(redir->ssl_cert_cn); + newconn->connect_data = purple_proxy_connect(NULL, account, host, port, + ssl_proxy_conn_established_cb, newconn); + } + else + { + newconn->connect_data = purple_proxy_connect(NULL, account, host, port, + connection_established_cb, newconn); + } + + if (newconn->gsc == NULL && newconn->connect_data == NULL) { flap_connection_schedule_destroy(newconn, OSCAR_DISCONNECT_COULD_NOT_CONNECT, @@ -1905,37 +2074,6 @@ return 1; } -static gboolean purple_requesticqstatusnote(gpointer data) -{ - PurpleConnection *gc = data; - OscarData *od = gc->proto_data; - - while (od->statusnotes_queue != NULL) - { - char *sn; - struct aim_ssi_item *ssi_item; - aim_tlv_t *note_hash; - - sn = od->statusnotes_queue->data; - - ssi_item = aim_ssi_itemlist_finditem(od->ssi.local, - NULL, sn, AIM_SSI_TYPE_BUDDY); - if (ssi_item != NULL) - { - note_hash = aim_tlv_gettlv(ssi_item->data, 0x015c, 1); - if (note_hash != NULL) { - aim_icq_getstatusnote(od, sn, note_hash->value, note_hash->length); - } - } - - od->statusnotes_queue = g_slist_remove(od->statusnotes_queue, sn); - g_free(sn); - } - - od->statusnotes_queue_timer = 0; - return FALSE; -} - static int purple_parse_oncoming(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { @@ -1948,6 +2086,10 @@ const char *status_id; va_list ap; aim_userinfo_t *info; + char *message = NULL; + char *itmsurl = NULL; + char *tmp; + const char *tmp2; gc = od->gc; account = purple_connection_get_account(gc); @@ -2002,49 +2144,36 @@ purple_prpl_got_user_status_deactive(account, info->sn, OSCAR_STATUS_ID_MOBILE); } - if (strcmp(status_id, OSCAR_STATUS_ID_AVAILABLE) == 0) - { - char *message = NULL; - char *itmsurl = NULL; - char *tmp; - const char *tmp2; - - if (info->status != NULL && info->status[0] != '\0') - /* Grab the available message */ - message = oscar_encoding_to_utf8(account, info->status_encoding, - info->status, info->status_len); - + if (info->status != NULL && info->status[0] != '\0') + /* Grab the available message */ + message = oscar_encoding_to_utf8(account, info->status_encoding, + info->status, info->status_len); + + tmp2 = tmp = (message ? g_markup_escape_text(message, -1) : NULL); + + if (strcmp(status_id, OSCAR_STATUS_ID_AVAILABLE) == 0) { if (info->itmsurl_encoding && info->itmsurl && info->itmsurl_len) /* Grab the iTunes Music Store URL */ itmsurl = oscar_encoding_to_utf8(account, info->itmsurl_encoding, - info->itmsurl, info->itmsurl_len); - - tmp2 = tmp = (message ? g_markup_escape_text(message, -1) : NULL); + info->itmsurl, info->itmsurl_len); if (tmp2 == NULL && itmsurl != NULL) + /* + * The message can't be NULL because NULL means it was the + * last attribute, so the itmsurl would get ignored below. + */ tmp2 = ""; purple_prpl_got_user_status(account, info->sn, status_id, - "message", tmp2, "itmsurl", itmsurl, NULL); - g_free(tmp); - - g_free(message); - g_free(itmsurl); + "message", tmp2, "itmsurl", itmsurl, NULL); } else - { - PurpleBuddy *b = purple_find_buddy(account, info->sn); - PurplePresence *presence = purple_buddy_get_presence(b); - PurpleStatus *old_status = purple_presence_get_active_status(presence); - PurpleStatus *new_status = purple_presence_get_status(presence, status_id); - - /* If our status_id would change with this update, pass it to the core. - * However, if our status_id would not change, do nothing, as we would clear out any existing - * attributes on the status prematurely. purple_got_infoblock() will update the message as needed. - */ - if (old_status != new_status) - purple_prpl_got_user_status(account, info->sn, status_id, NULL); - } + purple_prpl_got_user_status(account, info->sn, status_id, "message", tmp2, NULL); + + g_free(tmp); + + g_free(message); + g_free(itmsurl); /* Login time stuff */ if (info->present & AIM_USERINFO_PRESENT_ONLINESINCE) @@ -2099,51 +2228,6 @@ g_free(b16); } - /* - * If we didn't receive a status message with the status change, - * or if the message is empty, and we have a note hash, then - * query the ICQ6 status note. - * - * TODO: We should probably always query the status note regardless - * of whether they have a status message set, and we should - * figure out a way to display both the status note and the - * status message at the same time. - */ - if (info->status == NULL || info->status[0] == '\0') - { - struct aim_ssi_item *ssi_item; - aim_tlv_t *note_hash; - - ssi_item = aim_ssi_itemlist_finditem(od->ssi.local, - NULL, info->sn, AIM_SSI_TYPE_BUDDY); - if (ssi_item != NULL) - { - note_hash = aim_tlv_gettlv(ssi_item->data, 0x015c, 1); - if (note_hash != NULL) { - /* We do automatic rate limiting at the FLAP level, so - * a flood of requests won't disconnect us. However, - * it WOULD mean that we would have to wait a - * potentially long time to be able to message in real - * time again. Also, since we're requesting with every - * purple_parse_oncoming() call, which often come in - * groups, we should coalesce to do only one lookup per - * buddy. - */ - if (od->statusnotes_queue == NULL || - g_slist_find_custom(od->statusnotes_queue, info->sn, (GCompareFunc)strcmp) == NULL) - { - od->statusnotes_queue = g_slist_prepend(od->statusnotes_queue, - g_strdup(info->sn)); - - if (od->statusnotes_queue_timer > 0) - purple_timeout_remove(od->statusnotes_queue_timer); - od->statusnotes_queue_timer = purple_timeout_add_seconds(3, - purple_requesticqstatusnote, gc); - } - } - } - } - return 1; } @@ -5309,7 +5393,6 @@ PurpleBuddy *b; PurpleGroup *g; struct aim_ssi_item *ssi_item; - aim_tlv_t *note_hash; va_list ap; guint16 snac_subtype, type; const char *name; @@ -5379,13 +5462,7 @@ ssi_item = aim_ssi_itemlist_finditem(od->ssi.local, gname, name, AIM_SSI_TYPE_BUDDY); - if (ssi_item != NULL) - { - note_hash = aim_tlv_gettlv(ssi_item->data, 0x015c, 1); - if (note_hash != NULL) - aim_icq_getstatusnote(od, name, note_hash->value, note_hash->length); - } - else + if (ssi_item == NULL) { purple_debug_error("oscar", "purple_ssi_parseaddmod: " "Could not find ssi item for oncoming buddy %s, " @@ -5823,19 +5900,8 @@ else ret = g_strdup(_("Offline")); } - else if (purple_status_is_available(status) && !strcmp(id, OSCAR_STATUS_ID_AVAILABLE)) + else { - /* Available */ - message = purple_status_get_attr_string(status, "message"); - if (message != NULL) - { - ret = g_strdup(message); - purple_util_chrreplace(ret, '\n', ' '); - } - } - else if (!purple_status_is_available(status) && !strcmp(id, OSCAR_STATUS_ID_AWAY)) - { - /* Away */ message = purple_status_get_attr_string(status, "message"); if (message != NULL) { @@ -5847,13 +5913,15 @@ g_free(tmp1); g_free(tmp2); } + else if (purple_status_is_available(status)) + { + /* Don't show "Available" as status message in case buddy doesn't have a status message */ + } else { - ret = g_strdup(_("Away")); + ret = g_strdup(purple_status_get_name(status)); } } - else - ret = g_strdup(purple_status_get_name(status)); return ret; } @@ -6859,6 +6927,10 @@ option = purple_account_option_int_new(_("Port"), "port", OSCAR_DEFAULT_LOGIN_PORT); prpl_info->protocol_options = g_list_append(prpl_info->protocol_options, option); + option = purple_account_option_bool_new(_("Use SSL"), "use_ssl", + OSCAR_DEFAULT_USE_SSL); + prpl_info->protocol_options = g_list_append(prpl_info->protocol_options, option); + option = purple_account_option_bool_new( _("Always use AIM/ICQ proxy server for\nfile transfers and direct IM (slower,\nbut does not reveal your IP address)"), "always_use_rv_proxy", OSCAR_DEFAULT_ALWAYS_USE_RV_PROXY);
--- a/libpurple/protocols/oscar/oscar.h Fri Jan 30 08:52:27 2009 +0000 +++ b/libpurple/protocols/oscar/oscar.h Fri Jan 30 08:58:07 2009 +0000 @@ -34,6 +34,7 @@ #include "eventloop.h" #include "internal.h" #include "proxy.h" +#include "sslconn.h" #include <stdio.h> #include <string.h> @@ -417,8 +418,10 @@ guint16 cookielen; guint8 *cookie; gpointer new_conn_data; + gchar *ssl_cert_cn; int fd; + PurpleSslConnection *gsc; guint8 header[6]; gssize header_received; FlapFrame buffer_incoming; @@ -476,6 +479,7 @@ GHashTable *buddyinfo; GSList *requesticon; + gboolean use_ssl; gboolean icq; guint getblisttimer; @@ -537,10 +541,6 @@ /** A linked list containing PeerConnections. */ GSList *peer_connections; - - /** Queue of ICQ Status Notes to request. */ - GSList *statusnotes_queue; - guint statusnotes_queue_timer; }; /* Valid for calling aim_icq_setstatus() and for aim_userinfo_t->icqinfo.status */ @@ -593,6 +593,8 @@ const char *ip; guint16 cookielen; const guint8 *cookie; + const char *ssl_cert_cn; + guint8 use_ssl; struct { /* group == SNAC_FAMILY_CHAT */ guint16 exchange; const char *room; @@ -616,6 +618,8 @@ FlapConnection *flap_connection_getbytype(OscarData *, int type); FlapConnection *flap_connection_getbytype_all(OscarData *, int type); void flap_connection_recv_cb(gpointer data, gint source, PurpleInputCondition cond); +void flap_connection_recv_cb_ssl(gpointer data, PurpleSslConnection *gsc, PurpleInputCondition cond); + void flap_connection_send(FlapConnection *conn, FlapFrame *frame); void flap_connection_send_version(OscarData *od, FlapConnection *conn); void flap_connection_send_version_with_cookie(OscarData *od, FlapConnection *conn, guint16 length, const guint8 *chipsahoy); @@ -1352,7 +1356,6 @@ int aim_icq_getalias(OscarData *od, const char *uin); int aim_icq_getallinfo(OscarData *od, const char *uin); int aim_icq_sendsms(OscarData *od, const char *name, const char *msg, const char *alias); -int aim_icq_getstatusnote(OscarData *od, const char *uin, guint8 *note_hash, guint16 note_hash_len); /* 0x0017 - family_auth.c */
--- a/libpurple/protocols/oscar/oscar_data.c Fri Jan 30 08:52:27 2009 +0000 +++ b/libpurple/protocols/oscar/oscar_data.c Fri Jan 30 08:58:07 2009 +0000 @@ -91,14 +91,6 @@ g_free(od->requesticon->data); od->requesticon = g_slist_delete_link(od->requesticon, od->requesticon); } - while (od->statusnotes_queue) - { - g_free(od->statusnotes_queue->data); - od->statusnotes_queue = g_slist_delete_link(od->statusnotes_queue, - od->statusnotes_queue); - } - if (od->statusnotes_queue_timer > 0) - purple_timeout_remove(od->statusnotes_queue_timer); g_free(od->email); g_free(od->newp); g_free(od->oldp);
--- a/libpurple/protocols/oscar/oscarcommon.h Fri Jan 30 08:52:27 2009 +0000 +++ b/libpurple/protocols/oscar/oscarcommon.h Fri Jan 30 08:58:07 2009 +0000 @@ -32,6 +32,8 @@ #define OSCAR_DEFAULT_LOGIN_SERVER "login.messaging.aol.com" #define OSCAR_DEFAULT_LOGIN_PORT 5190 +#define OSCAR_DEFAULT_SSL_LOGIN_SERVER "slogin.oscar.aol.com" +#define OSCAR_OLD_LOGIN_SERVER "login.oscar.aol.com" #ifndef _WIN32 #define OSCAR_DEFAULT_CUSTOM_ENCODING "ISO-8859-1" #else @@ -42,6 +44,7 @@ #define OSCAR_DEFAULT_WEB_AWARE FALSE #define OSCAR_DEFAULT_ALWAYS_USE_RV_PROXY FALSE #define OSCAR_DEFAULT_ALLOW_MULTIPLE_LOGINS TRUE +#define OSCAR_DEFAULT_USE_SSL FALSE #ifdef _WIN32 const char *oscar_get_locale_charset(void);
--- a/libpurple/protocols/oscar/peer.c Fri Jan 30 08:52:27 2009 +0000 +++ b/libpurple/protocols/oscar/peer.c Fri Jan 30 08:58:07 2009 +0000 @@ -690,7 +690,10 @@ return; } - listener_ip = purple_network_get_my_ip(bos_conn->fd); + if (bos_conn->gsc) + listener_ip = purple_network_get_my_ip(bos_conn->gsc->fd); + else + listener_ip = purple_network_get_my_ip(bos_conn->fd); listener_port = purple_network_get_port_from_fd(conn->listenerfd); if (conn->type == OSCAR_CAPABILITY_DIRECTIM) {
--- a/libpurple/purple-url-handler Fri Jan 30 08:52:27 2009 +0000 +++ b/libpurple/purple-url-handler Fri Jan 30 08:58:07 2009 +0000 @@ -207,7 +207,11 @@ def correct_server(account): username = cpurple.PurpleAccountGetUsername(account) - return (server == (username.split("@"))[1]) + user_split = (username.split("@")) + # Not all accounts have a split, so append an empty string so the + # [1] doesn't throw an IndexError. + user_split.append("") + return (server == user_split[1]) account = findaccount(protocol, matcher=correct_server)
--- a/libpurple/status.c Fri Jan 30 08:52:27 2009 +0000 +++ b/libpurple/status.c Fri Jan 30 08:58:07 2009 +0000 @@ -250,7 +250,7 @@ { g_return_val_if_fail(primitive != PURPLE_STATUS_UNSET, NULL); - return purple_status_type_new_full(primitive, id, name, FALSE, + return purple_status_type_new_full(primitive, id, name, TRUE, user_settable, FALSE); } @@ -816,28 +816,42 @@ /* Reset any unspecified attributes to their default value */ status_type = purple_status_get_type(status); l = purple_status_type_get_attrs(status_type); - while (l != NULL) - { + while (l != NULL) { PurpleStatusAttr *attr; attr = l->data; - if (!g_list_find_custom(specified_attr_ids, attr->id, (GCompareFunc)strcmp)) - { + l = l->next; + + if (!g_list_find_custom(specified_attr_ids, attr->id, (GCompareFunc)strcmp)) { PurpleValue *default_value; default_value = purple_status_attr_get_value(attr); - if (default_value->type == PURPLE_TYPE_STRING) - purple_status_set_attr_string(status, attr->id, - purple_value_get_string(default_value)); - else if (default_value->type == PURPLE_TYPE_INT) - purple_status_set_attr_int(status, attr->id, - purple_value_get_int(default_value)); - else if (default_value->type == PURPLE_TYPE_BOOLEAN) - purple_status_set_attr_boolean(status, attr->id, - purple_value_get_boolean(default_value)); + if (default_value->type == PURPLE_TYPE_STRING) { + const char *cur = purple_status_get_attr_string(status, attr->id); + const char *def = purple_value_get_string(default_value); + if ((cur == NULL && def == NULL) + || (cur != NULL && def != NULL + && !strcmp(cur, def))) { + continue; + } + + purple_status_set_attr_string(status, attr->id, def); + } else if (default_value->type == PURPLE_TYPE_INT) { + int cur = purple_status_get_attr_int(status, attr->id); + int def = purple_value_get_int(default_value); + if (cur == def) + continue; + + purple_status_set_attr_int(status, attr->id, def); + } else if (default_value->type == PURPLE_TYPE_BOOLEAN) { + gboolean cur = purple_status_get_attr_boolean(status, attr->id); + gboolean def = purple_value_get_boolean(default_value); + if (cur == def) + continue; + + purple_status_set_attr_boolean(status, attr->id, def); + } changed = TRUE; } - - l = l->next; } g_list_free(specified_attr_ids);
--- a/libpurple/status.h Fri Jan 30 08:52:27 2009 +0000 +++ b/libpurple/status.h Fri Jan 30 08:58:07 2009 +0000 @@ -199,8 +199,8 @@ gboolean independent); /** - * Creates a new status type with some default values (not - * savable and not independent). + * Creates a new status type with some default values ( + * saveable and not independent). * * @param primitive The primitive status type. * @param id The ID of the status type, or @c NULL to use the id of
--- a/pidgin/gtkaccount.c Fri Jan 30 08:52:27 2009 +0000 +++ b/pidgin/gtkaccount.c Fri Jan 30 08:58:07 2009 +0000 @@ -84,6 +84,13 @@ typedef struct { + GtkWidget *widget; + gchar *setting; + PurplePrefType type; +} ProtocolOptEntry; + +typedef struct +{ PidginAccountDialogType type; PurpleAccount *account; @@ -548,8 +555,10 @@ /* Password */ dialog->password_entry = gtk_entry_new(); gtk_entry_set_visibility(GTK_ENTRY(dialog->password_entry), FALSE); +#if !GTK_CHECK_VERSION(2,16,0) if (gtk_entry_get_invisible_char(GTK_ENTRY(dialog->password_entry)) == '*') gtk_entry_set_invisible_char(GTK_ENTRY(dialog->password_entry), PIDGIN_INVISIBLE_CHAR); +#endif /* Less than GTK+ 2.16 */ dialog->password_box = add_pref_box(dialog, vbox, _("_Password:"), dialog->password_entry); @@ -740,21 +749,22 @@ char *title, *tmp; const char *str_value; gboolean bool_value; + ProtocolOptEntry *opt_entry; if (dialog->protocol_frame != NULL) { gtk_widget_destroy(dialog->protocol_frame); dialog->protocol_frame = NULL; } - if (dialog->protocol_opt_entries != NULL) { - g_list_free(dialog->protocol_opt_entries); - dialog->protocol_opt_entries = NULL; - } - if (dialog->prpl_info == NULL || - dialog->prpl_info->protocol_options == NULL) { - + dialog->prpl_info->protocol_options == NULL) return; + + while (dialog->protocol_opt_entries != NULL) { + ProtocolOptEntry *opt_entry = dialog->protocol_opt_entries->data; + g_free(opt_entry->setting); + g_free(opt_entry); + dialog->protocol_opt_entries = g_list_delete_link(dialog->protocol_opt_entries, dialog->protocol_opt_entries); } account = dialog->account; @@ -778,7 +788,11 @@ { option = (PurpleAccountOption *)l->data; - switch (purple_account_option_get_type(option)) + opt_entry = g_new0(ProtocolOptEntry, 1); + opt_entry->type = purple_account_option_get_type(option); + opt_entry->setting = g_strdup(purple_account_option_get_setting(option)); + + switch (opt_entry->type) { case PURPLE_PREF_BOOLEAN: if (account == NULL || @@ -795,7 +809,7 @@ } tmp = g_strconcat("_", purple_account_option_get_text(option), NULL); - check = gtk_check_button_new_with_mnemonic(tmp); + opt_entry->widget = check = gtk_check_button_new_with_mnemonic(tmp); g_free(tmp); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), @@ -803,10 +817,6 @@ gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0); gtk_widget_show(check); - - dialog->protocol_opt_entries = - g_list_append(dialog->protocol_opt_entries, check); - break; case PURPLE_PREF_INT: @@ -825,19 +835,13 @@ g_snprintf(buf, sizeof(buf), "%d", int_value); - entry = gtk_entry_new(); + opt_entry->widget = entry = gtk_entry_new(); gtk_entry_set_text(GTK_ENTRY(entry), buf); title = g_strdup_printf("_%s:", purple_account_option_get_text(option)); - add_pref_box(dialog, vbox, title, entry); - g_free(title); - - dialog->protocol_opt_entries = - g_list_append(dialog->protocol_opt_entries, entry); - break; case PURPLE_PREF_STRING: @@ -854,12 +858,14 @@ purple_account_option_get_default_string(option)); } - entry = gtk_entry_new(); + opt_entry->widget = entry = gtk_entry_new(); if (purple_account_option_get_masked(option)) { gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE); +#if !GTK_CHECK_VERSION(2,16,0) if (gtk_entry_get_invisible_char(GTK_ENTRY(entry)) == '*') gtk_entry_set_invisible_char(GTK_ENTRY(entry), PIDGIN_INVISIBLE_CHAR); +#endif /* Less than GTK+ 2.16 */ } if (str_value != NULL) @@ -867,14 +873,8 @@ title = g_strdup_printf("_%s:", purple_account_option_get_text(option)); - add_pref_box(dialog, vbox, title, entry); - g_free(title); - - dialog->protocol_opt_entries = - g_list_append(dialog->protocol_opt_entries, entry); - break; case PURPLE_PREF_STRING_LIST: @@ -896,7 +896,7 @@ list = purple_account_option_get_list(option); model = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_POINTER); - combo = gtk_combo_box_new_with_model(GTK_TREE_MODEL(model)); + opt_entry->widget = combo = gtk_combo_box_new_with_model(GTK_TREE_MODEL(model)); /* Loop through list of PurpleKeyValuePair items */ for (node = list; node != NULL; node = node->next) { @@ -928,20 +928,21 @@ title = g_strdup_printf("_%s:", purple_account_option_get_text(option)); - add_pref_box(dialog, vbox, title, combo); - g_free(title); - - dialog->protocol_opt_entries = - g_list_append(dialog->protocol_opt_entries, combo); - break; - default: - break; + purple_debug_error("gtkaccount", "Invalid Account Option pref type (%d)\n", + opt_entry->type); + g_free(opt_entry->setting); + g_free(opt_entry); + continue; } + + dialog->protocol_opt_entries = + g_list_append(dialog->protocol_opt_entries, opt_entry); + } } @@ -1092,8 +1093,10 @@ /* Password */ dialog->proxy_pass_entry = gtk_entry_new(); gtk_entry_set_visibility(GTK_ENTRY(dialog->proxy_pass_entry), FALSE); +#if !GTK_CHECK_VERSION(2,16,0) if (gtk_entry_get_invisible_char(GTK_ENTRY(dialog->proxy_pass_entry)) == '*') gtk_entry_set_invisible_char(GTK_ENTRY(dialog->proxy_pass_entry), PIDGIN_INVISIBLE_CHAR); +#endif /* Less than GTK+ 2.16 */ add_pref_box(dialog, vbox2, _("Pa_ssword:"), dialog->proxy_pass_entry); if (dialog->account != NULL && @@ -1152,7 +1155,12 @@ gtk_widget_destroy(dialog->window); g_list_free(dialog->user_split_entries); - g_list_free(dialog->protocol_opt_entries); + while (dialog->protocol_opt_entries != NULL) { + ProtocolOptEntry *opt_entry = dialog->protocol_opt_entries->data; + g_free(opt_entry->setting); + g_free(opt_entry); + dialog->protocol_opt_entries = g_list_delete_link(dialog->protocol_opt_entries, dialog->protocol_opt_entries); + } g_free(dialog->protocol_id); g_object_unref(dialog->sg); @@ -1317,46 +1325,38 @@ /* Add the protocol settings */ if (dialog->prpl_info) { - for (l = dialog->prpl_info->protocol_options, - l2 = dialog->protocol_opt_entries; - l != NULL && l2 != NULL; - l = l->next, l2 = l2->next) { - - PurplePrefType type; - PurpleAccountOption *option = l->data; - GtkWidget *widget = l2->data; - GtkTreeIter iter; - const char *setting; - char *value2; - int int_value; - gboolean bool_value; - - type = purple_account_option_get_type(option); - - setting = purple_account_option_get_setting(option); - - switch (type) { + ProtocolOptEntry *opt_entry; + GtkTreeIter iter; + char *value2; + int int_value; + gboolean bool_value; + + for (l2 = dialog->protocol_opt_entries; l2; l2 = l2->next) { + + opt_entry = l2->data; + + switch (opt_entry->type) { case PURPLE_PREF_STRING: - value = gtk_entry_get_text(GTK_ENTRY(widget)); - purple_account_set_string(account, setting, value); + value = gtk_entry_get_text(GTK_ENTRY(opt_entry->widget)); + purple_account_set_string(account, opt_entry->setting, value); break; case PURPLE_PREF_INT: - int_value = atoi(gtk_entry_get_text(GTK_ENTRY(widget))); - purple_account_set_int(account, setting, int_value); + int_value = atoi(gtk_entry_get_text(GTK_ENTRY(opt_entry->widget))); + purple_account_set_int(account, opt_entry->setting, int_value); break; case PURPLE_PREF_BOOLEAN: bool_value = - gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); - purple_account_set_bool(account, setting, bool_value); + gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(opt_entry->widget)); + purple_account_set_bool(account, opt_entry->setting, bool_value); break; case PURPLE_PREF_STRING_LIST: value2 = NULL; - if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(widget), &iter)) - gtk_tree_model_get(gtk_combo_box_get_model(GTK_COMBO_BOX(widget)), &iter, 1, &value2, -1); - purple_account_set_string(account, setting, value2); + if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(opt_entry->widget), &iter)) + gtk_tree_model_get(gtk_combo_box_get_model(GTK_COMBO_BOX(opt_entry->widget)), &iter, 1, &value2, -1); + purple_account_set_string(account, opt_entry->setting, value2); break; default: @@ -1990,9 +1990,13 @@ if (purple_account_get_bool(account, "use-global-buddyicon", TRUE)) { if (global_buddyicon != NULL) buddyicon = g_object_ref(G_OBJECT(global_buddyicon)); - /* This is for when set_account() is called for a single account */ - else - img = purple_buddy_icons_find_account_icon(account); + else { + /* This is for when set_account() is called for a single account */ + const char *path; + path = purple_prefs_get_path(PIDGIN_PREFS_ROOT "/accounts/buddyicon"); + if (path != NULL) + img = purple_imgstore_new_from_file(path); + } } else { img = purple_buddy_icons_find_account_icon(account); }
--- a/pidgin/gtkblist.c Fri Jan 30 08:52:27 2009 +0000 +++ b/pidgin/gtkblist.c Fri Jan 30 08:58:07 2009 +0000 @@ -978,8 +978,10 @@ if (pce->secret) { gtk_entry_set_visibility(GTK_ENTRY(input), FALSE); +#if !GTK_CHECK_VERSION(2,16,0) if (gtk_entry_get_invisible_char(GTK_ENTRY(input)) == '*') gtk_entry_set_invisible_char(GTK_ENTRY(input), PIDGIN_INVISIBLE_CHAR); +#endif /* Less than GTK+ 2.16 */ } pidgin_add_widget_to_vbox(GTK_BOX(data->entries_box), pce->label, data->sg, input, TRUE, NULL); g_signal_connect(G_OBJECT(input), "changed", @@ -6873,8 +6875,10 @@ if (pce->secret) { gtk_entry_set_visibility(GTK_ENTRY(input), FALSE); +#if !GTK_CHECK_VERSION(2,16,0) if (gtk_entry_get_invisible_char(GTK_ENTRY(input)) == '*') gtk_entry_set_invisible_char(GTK_ENTRY(input), PIDGIN_INVISIBLE_CHAR); +#endif /* Less than GTK+ 2.16 */ } pidgin_add_widget_to_vbox(GTK_BOX(data->entries_box), pce->label, data->sg, input, TRUE, NULL); g_signal_connect(G_OBJECT(input), "changed",
--- a/pidgin/gtkgaim-compat.h Fri Jan 30 08:52:27 2009 +0000 +++ b/pidgin/gtkgaim-compat.h Fri Jan 30 08:58:07 2009 +0000 @@ -297,7 +297,9 @@ #define GAIM_HIG_BORDER PIDGIN_HIG_BORDER #define GAIM_HIG_BOX_SPACE PIDGIN_HIG_BOX_SPACE #define GAIM_HIG_CAT_SPACE PIDGIN_HIG_CAT_SPACE +#if !GTK_CHECK_VERSION(2,16,0) #define GAIM_INVISIBLE_CHAR PIDGIN_INVISIBLE_CHAR +#endif /* Less than GTK+ 2.16 */ #define GAIM_IS_GTK_CONVERSATION PIDGIN_IS_PIDGIN_CONVERSATION #define GAIM_IS_GTK_PLUGIN PIDGIN_IS_PIDGIN_PLUGIN #define gaim_new_check_item pidgin_new_check_item
--- a/pidgin/gtkimhtml.c Fri Jan 30 08:52:27 2009 +0000 +++ b/pidgin/gtkimhtml.c Fri Jan 30 08:58:07 2009 +0000 @@ -5378,12 +5378,14 @@ text_tag_data_destroy(tmp); } - if (tmp == NULL) - purple_debug_warning("gtkimhtml", "empty queue, more closing tags than open tags!\n"); - else { + if (tmp != NULL) { g_string_append(str, tmp->end); text_tag_data_destroy(tmp); } +#if 0 /* This can't be allowed to happen because it causes the iters to be invalidated in the debug window imhtml during text copying */ + else + purple_debug_warning("gtkimhtml", "empty queue, more closing tags than open tags!\n"); +#endif while ((tmp = g_queue_pop_head(r))) { g_string_append(str, tmp->start);
--- a/pidgin/gtkmain.c Fri Jan 30 08:52:27 2009 +0000 +++ b/pidgin/gtkmain.c Fri Jan 30 08:58:07 2009 +0000 @@ -324,9 +324,6 @@ pidgin_session_end(); #endif - /* Save the plugins we have loaded for next time. */ - pidgin_plugins_save(); - /* Uninit */ pidgin_smileys_uninit(); pidgin_conversations_uninit(); @@ -789,8 +786,8 @@ dbus_connection_send_with_reply_and_block(conn, message, -1, NULL); dbus_message_unref(message); #endif - purple_debug_info("main", "exiting because another libpurple client is already running\n"); purple_core_quit(); + g_printerr(_("Exiting because another libpurple client is already running.\n")); #ifdef HAVE_SIGNAL_H g_free(segfault_message); #endif
--- a/pidgin/gtkpluginpref.c Fri Jan 30 08:52:27 2009 +0000 +++ b/pidgin/gtkpluginpref.c Fri Jan 30 08:58:07 2009 +0000 @@ -101,8 +101,10 @@ if (purple_plugin_pref_get_masked(pref)) { gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE); +#if !GTK_CHECK_VERSION(2,16,0) if (gtk_entry_get_invisible_char(GTK_ENTRY(entry)) == '*') gtk_entry_set_invisible_char(GTK_ENTRY(entry), PIDGIN_INVISIBLE_CHAR); +#endif /* Less than GTK+ 2.16 */ } g_signal_connect(G_OBJECT(entry), "changed", G_CALLBACK(entry_cb),
--- a/pidgin/gtkprefs.c Fri Jan 30 08:52:27 2009 +0000 +++ b/pidgin/gtkprefs.c Fri Jan 30 08:58:07 2009 +0000 @@ -1509,8 +1509,10 @@ gtk_label_set_mnemonic_widget(GTK_LABEL(label), entry); gtk_table_attach(GTK_TABLE(table), entry, 3, 4, 1, 2, GTK_FILL , 0, 0, 0); gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE); +#if !GTK_CHECK_VERSION(2,16,0) if (gtk_entry_get_invisible_char(GTK_ENTRY(entry)) == '*') gtk_entry_set_invisible_char(GTK_ENTRY(entry), PIDGIN_INVISIBLE_CHAR); +#endif /* Less than GTK+ 2.16 */ g_signal_connect(G_OBJECT(entry), "changed", G_CALLBACK(proxy_print_option), (void *)PROXYPASS);
--- a/pidgin/gtkrequest.c Fri Jan 30 08:52:27 2009 +0000 +++ b/pidgin/gtkrequest.c Fri Jan 30 08:58:07 2009 +0000 @@ -430,8 +430,10 @@ if (masked) { gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE); +#if !GTK_CHECK_VERSION(2,16,0) if (gtk_entry_get_invisible_char(GTK_ENTRY(entry)) == '*') gtk_entry_set_invisible_char(GTK_ENTRY(entry), PIDGIN_INVISIBLE_CHAR); +#endif /* Less than GTK+ 2.16 */ } } gtk_widget_show_all(vbox); @@ -791,8 +793,10 @@ if (purple_request_field_string_is_masked(field)) { gtk_entry_set_visibility(GTK_ENTRY(widget), FALSE); +#if !GTK_CHECK_VERSION(2,16,0) if (gtk_entry_get_invisible_char(GTK_ENTRY(widget)) == '*') gtk_entry_set_invisible_char(GTK_ENTRY(widget), PIDGIN_INVISIBLE_CHAR); +#endif /* Less than GTK+ 2.16 */ } gtk_editable_set_editable(GTK_EDITABLE(widget),
--- a/pidgin/pidgin.h Fri Jan 30 08:52:27 2009 +0000 +++ b/pidgin/pidgin.h Fri Jan 30 08:58:07 2009 +0000 @@ -91,11 +91,22 @@ #define PIDGIN_HIG_BORDER 12 #define PIDGIN_HIG_BOX_SPACE 6 +#if !GTK_CHECK_VERSION(2,16,0) || !defined(PIDGIN_DISABLE_DEPRECATED) /* - * See GNOME bug #307304 for some discussion about the invisible - * character. 0x25cf is a good choice, too. + * Older versions of GNOME defaulted to using an asterisk as the invisible + * character. But this is ugly and we want to use something nicer. + * + * The default invisible character was changed in GNOME revision 21446 + * (GTK+ 2.16) from an asterisk to the first available character out of + * 0x25cf, 0x2022, 0x2731, 0x273a. See GNOME bugs 83935 and 307304 for + * discussion leading up to the change. + * + * Here's the change: + * http://svn.gnome.org/viewvc/gtk%2B?view=revision&revision=21446 + * */ -#define PIDGIN_INVISIBLE_CHAR (gunichar)0x2022 +#define PIDGIN_INVISIBLE_CHAR (gunichar)0x25cf +#endif /* Less than GTK+ 2.16 */ #endif /* _PIDGIN_H_ */
--- a/pidgin/win32/nsis/pidgin-installer.nsi Fri Jan 30 08:52:27 2009 +0000 +++ b/pidgin/win32/nsis/pidgin-installer.nsi Fri Jan 30 08:58:07 2009 +0000 @@ -718,6 +718,7 @@ Delete "$INSTDIR\ca-certs\StartCom_Free_SSL_CA.pem" Delete "$INSTDIR\ca-certs\Verisign_Class3_Primary_CA.pem" Delete "$INSTDIR\ca-certs\VeriSign_Class_3_Public_Primary_Certification_Authority_-_G5.pem" + Delete "$INSTDIR\ca-certs\VeriSign_International_Server_Class_3_CA.pem" Delete "$INSTDIR\ca-certs\Verisign_RSA_Secure_Server_CA.pem" RMDir "$INSTDIR\ca-certs" RMDir /r "$INSTDIR\locale"
--- a/po/fi.po Fri Jan 30 08:52:27 2009 +0000 +++ b/po/fi.po Fri Jan 30 08:58:07 2009 +0000 @@ -11,7 +11,7 @@ "Project-Id-Version: Pidgin\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2009-01-07 13:30+0200\n" -"PO-Revision-Date: 2009-01-07 13:30+0200\n" +"PO-Revision-Date: 2009-01-23 19:58+0200\n" "Last-Translator: Timo Jyrinki <timo.jyrinki@iki.fi>\n" "Language-Team: \n" "MIME-Version: 1.0\n" @@ -1169,7 +1169,7 @@ msgstr "Keskustelut" msgid "Logging" -msgstr "Kirjataan lokiin" +msgstr "Lokiinkirjaus" msgid "You must fill all the required fields." msgstr "Täytä kaikki vaaditut kentät." @@ -15466,7 +15466,7 @@ #~ "keskustelun uuden keskustelun aluksi.\n" #~ "\n" #~ "Historia-liitännäinen vaatii lokiinkirjauksen käyttöä. Loki voidaan ottaa " -#~ "käyttöön menemällä Työkalut -> Asetukset -> Kirjataan lokiin. Lokien " +#~ "käyttöön menemällä Työkalut -> Asetukset -> Lokiinkirjaus. Lokien " #~ "käyttöönotto pikaviesteille ja/tai ryhmäkeskusteluille ottaa käyttöön " #~ "historiatoiminnon vastaaville keskustelutyypeille."
--- a/po/l10n.xsl Fri Jan 30 08:52:27 2009 +0000 +++ b/po/l10n.xsl Fri Jan 30 08:58:07 2009 +0000 @@ -1,22 +1,47 @@ <?xml version='1.0' ?> <xsl:stylesheet version='2.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'> + <xsl:output + method="html" + omit-xml-declaration="yes" + doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" + doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" + indent="yes" + /> <xsl:template match='/project'> - <html> + <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <title><xsl:value-of select='@name'/> translation statistics</title> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <!-- <link rel="Stylesheet" href="/gaim.css" type="text/css" media="screen" /> --> - <style> + <style type="text/css"> .bargraph { width: 200px; height: 20px; - background: black; + background-color: red; border-collapse: collapse; border-spacing: 0px; margin: 0px; border: 0px; padding: 0px; } - + .translated { + background-color: green; + padding: 0px; + } + .fuzzy { + background-color: blue; + padding: 0px; + } + .untranslated { + background-color: red; + padding: 0px; + } + td.sep { + padding-right: 10px; + } + th { + text-align: left; + } </style> </head> <body> @@ -28,21 +53,23 @@ <xsl:sort select='@code' /> <tr> <td><a><xsl:attribute name='href'><xsl:value-of select='@code'/>.po</xsl:attribute><xsl:value-of select='@name'/> (<xsl:value-of select='@code'/>)</a></td> - <td><xsl:value-of select='@translated'/></td><td><xsl:value-of select="format-number(@translated div ../@strings * 100,'#.##')"/> %</td> - <td><xsl:value-of select='@fuzzy'/></td><td><xsl:value-of select="format-number(@fuzzy div ../@strings * 100,'#.##')"/> %</td> - <td><xsl:value-of select='../@strings - (@translated + @fuzzy)'/></td><td><xsl:value-of select="format-number((../@strings - (@translated + @fuzzy)) div ../@strings * 100,'#.##')"/> %</td> + <td><xsl:value-of select='@translated'/></td> + <td class='sep'><xsl:value-of select="format-number(@translated div ../@strings * 100,'#.##')"/> %</td> + <td><xsl:value-of select='@fuzzy'/></td> + <td class='sep'><xsl:value-of select="format-number(@fuzzy div ../@strings * 100,'#.##')"/> %</td> + <td><xsl:value-of select='../@strings - (@translated + @fuzzy)'/></td> + <td><xsl:value-of select="format-number((../@strings - (@translated + @fuzzy)) div ../@strings * 100,'#.##')"/> %</td> <td> <table class='bargraph'><tr> - <td bgcolor='green'><xsl:attribute name='width'><xsl:value-of select='round(@translated div ../@strings * 200)'/>px;</xsl:attribute></td> - <td bgcolor='blue'><xsl:attribute name='width'><xsl:value-of select='round(@fuzzy div ../@strings * 200)'/>px;</xsl:attribute></td> - <!-- <td bgcolor='red'><xsl:attribute name='width'><xsl:value-of select='200 - round((@translated + @fuzzy) div ../@strings * 200)'/>px;</xsl:attribute></td> --> - <td bgcolor='red'></td> + <td class="translated"><xsl:attribute name='style'>width:<xsl:value-of select='round(@translated div ../@strings * 200)'/>px;</xsl:attribute></td> + <td class="fuzzy"><xsl:attribute name='style'>width:<xsl:value-of select='round(@fuzzy div ../@strings * 200)'/>px;</xsl:attribute></td> + <td class="untranslated"><xsl:attribute name='style'>width:<xsl:value-of select='round((../@strings - @translated - @fuzzy) div ../@strings * 200)'/>px;</xsl:attribute></td> </tr></table> </td> </tr> </xsl:for-each> </table> - <a><xsl:attribute name='href'><xsl:value-of select='@pofile'/></xsl:attribute><xsl:value-of select='@pofile'/></a> generated on <xsl:value-of select='@generated'/> + <p><a><xsl:attribute name='href'><xsl:value-of select='@pofile'/></xsl:attribute><xsl:value-of select='@pofile'/></a> generated on <xsl:value-of select='@generated'/></p> <!-- </div> --> </body> </html>
--- a/share/ca-certs/Makefile.am Fri Jan 30 08:52:27 2009 +0000 +++ b/share/ca-certs/Makefile.am Fri Jan 30 08:58:07 2009 +0000 @@ -10,7 +10,8 @@ EXTRA_CERTS = \ Microsoft_Internet_Authority.pem \ - Microsoft_Secure_Server_Authority.pem + Microsoft_Secure_Server_Authority.pem \ + VeriSign_International_Server_Class_3_CA.pem cacertsdir = $(datadir)/purple/ca-certs
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/ca-certs/VeriSign_International_Server_Class_3_CA.pem Fri Jan 30 08:58:07 2009 +0000 @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDgzCCAuygAwIBAgIQRvzrurTQLw+SYJgjP5MHjzANBgkqhkiG9w0BAQUFADBf +MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xNzA1BgNVBAsT +LkNsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkw +HhcNOTcwNDE3MDAwMDAwWhcNMTYxMDI0MjM1OTU5WjCBujEfMB0GA1UEChMWVmVy +aVNpZ24gVHJ1c3QgTmV0d29yazEXMBUGA1UECxMOVmVyaVNpZ24sIEluYy4xMzAx +BgNVBAsTKlZlcmlTaWduIEludGVybmF0aW9uYWwgU2VydmVyIENBIC0gQ2xhc3Mg +MzFJMEcGA1UECxNAd3d3LnZlcmlzaWduLmNvbS9DUFMgSW5jb3JwLmJ5IFJlZi4g +TElBQklMSVRZIExURC4oYyk5NyBWZXJpU2lnbjCBnzANBgkqhkiG9w0BAQEFAAOB +jQAwgYkCgYEA2IKA6NYZAn0fhRg5JaJlK+G/1AXTvOY2O6rwTGxbtueqPHNFVbLx +veqXQu2aNAoV1Klc9UAl3dkHwTKydWzEyruj/lYncUOqY/UwPpMo5frxCTvzt01O +OfdcSVq4wR3Tsor+cDCVQsv+K1GLWjw6+SJPkLICp1OcTzTnqwSye28CAwEAAaOB +4zCB4DAPBgNVHRMECDAGAQH/AgEAMEQGA1UdIAQ9MDswOQYLYIZIAYb4RQEHAQEw +KjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cudmVyaXNpZ24uY29tL0NQUzA0BgNV +HSUELTArBggrBgEFBQcDAQYIKwYBBQUHAwIGCWCGSAGG+EIEAQYKYIZIAYb4RQEI +ATALBgNVHQ8EBAMCAQYwEQYJYIZIAYb4QgEBBAQDAgEGMDEGA1UdHwQqMCgwJqAk +oCKGIGh0dHA6Ly9jcmwudmVyaXNpZ24uY29tL3BjYTMuY3JsMA0GCSqGSIb3DQEB +BQUAA4GBAECOSZeWinPdjk3vPmG3yqBirfQOCrt1PeJu2CzHv/S5jDabyqLQnHJG +OfamggNlEcS8vy2m9dk7CrWY+rN4uR7yK0xi1f2yeh3fM/1z+aXYLYwq6tH8sCi2 +6UlIE0uDihtIeyT3ON5vQVS4q1drBt/HotSp9vE2YoCI8ot11oBx +-----END CERTIFICATE-----