Mercurial > pidgin.yaz
changeset 30707:2f96590b7b40
merged from im.pidgin.pidgin
author | Yoshiki Yazawa <yaz@honeyplanet.jp> |
---|---|
date | Thu, 22 Jul 2010 15:37:35 +0900 |
parents | 810a6be1920f (current diff) 901a57549910 (diff) |
children | d0f40f5f2fb2 |
files | configure.ac libpurple/protocols/jabber/jabber.c libpurple/protocols/oscar/family_icbm.c libpurple/protocols/oscar/oscar.c libpurple/util.c |
diffstat | 33 files changed, 508 insertions(+), 235 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog Wed Jul 07 17:52:44 2010 +0900 +++ b/ChangeLog Thu Jul 22 15:37:35 2010 +0900 @@ -1,6 +1,6 @@ Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul -version 2.7.2 (??/??/????): +version 2.7.3 (??/??/????): General: * Use silent build rules for automake >1.11. You can enable verbose builds with the --disable-silent-rules configure option, or using @@ -11,6 +11,7 @@ Pidgin: * Re-focus the input area after clicking the attention toolbar button. + * Re-arrange media window to make it more netbook-friendly. Finch: * Rebindable 'suggest-next-page' and 'suggest-prev-page' actions for @@ -28,6 +29,8 @@ the specification. * When initiating a file transfer, don't show resources that are certain to not support file transfers in the resource selection dialog. + * Fix connecting to servers using BOSH and authenticating with + DIGEST-MD5 when libpurple was built with Cyrus SASL support. Yahoo/Yahoo JAPAN: * Renamed "Use account proxy for SSL connections" to "Use account proxy @@ -43,6 +46,18 @@ * Fix file transfers that get stuck with "Waiting for transfer to begin". +version 2.7.2 (07/21/2010): + AIM and ICQ: + * Fix a crash bug related to X-Status messages that can be triggered by + remove users. This is CVE-2010-2528. + * Fix a rare crash bug caused by certain incoming SMS messages + (discovered by Jan Kaluza--thanks Jan!). + * Change HTML sent from ICQ accounts so that official ICQ clients + hopefully display it correctly. + + MSN: + * Fix a crash related to fast buddy icon transfers. + version 2.7.1 (05/29/2010): General: * Build fixes on OpenSolaris. (Brian Lu)
--- a/ChangeLog.API Wed Jul 07 17:52:44 2010 +0900 +++ b/ChangeLog.API Thu Jul 22 15:37:35 2010 +0900 @@ -1,12 +1,16 @@ Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul -version 2.7.2 (??/??/????): +version 2.7.3 (??/??/????): libpurple: Fixed: * purple_account_[gs]et_public_alias no longer crash when called for a protocol that doesn't support the underlying calls and the caller does not specify a failure callback. + Perl: + Added: + * Exposed log-subsystem signals. + Pidgin: Changed: * Changing the visibility (gtk_widget_hide/show) of @@ -20,6 +24,9 @@ gnt_tree_row_get_prev, gnt_tree_row_get_child and gnt_tree_row_get_parent. +version 2.7.2 (07/21/2010): + * No changes + version 2.7.1 (05/29/2010): * No changes
--- a/ChangeLog.win32 Wed Jul 07 17:52:44 2010 +0900 +++ b/ChangeLog.win32 Thu Jul 22 15:37:35 2010 +0900 @@ -1,6 +1,9 @@ Starting with Pidgin version 2.7.1, this ChangeLog file will no longer be updated. It will be kept in the source tree for historical reasons only. +version 2.7.1 (05/29/2010): + * No changes + version 2.7.0 (05/12/2010): * Updated GTK+ to 2.16.6 * Private GTK+ Runtime now used (GTK+ Installer no longer supported)
--- a/NEWS Wed Jul 07 17:52:44 2010 +0900 +++ b/NEWS Thu Jul 22 15:37:35 2010 +0900 @@ -2,6 +2,11 @@ Our development blog is available at: http://planet.pidgin.im +2.7.2 (07/21/2010): + Mark: We discovered a security issue in Pidgin 2.7.0 and 2.7.1 and + decided to release a patched version quickly. This release contains + the fix for that crash, and a few other minor fixes. + 2.7.1 (05/29/2010): Elliott: Hey, I'm first! How did that happen?! Maybe because of the interesting changes in this release. Sure there were quite a few bug @@ -12,7 +17,7 @@ previous release! This fixes a number of bugs that you've all been reporting a ton of duplicate tickets about and even gives you the new direct connection file transfer support for MSN. Enjoy! - + Marcus: Quite a bit quicker to get this release out, compared with the previous one :). Fixes a number of bugs, and I'm sure the MSN direct connections will please many users. Enjoy!
--- a/configure.ac Wed Jul 07 17:52:44 2010 +0900 +++ b/configure.ac Thu Jul 22 15:37:35 2010 +0900 @@ -46,7 +46,7 @@ m4_define([purple_lt_current], [7]) m4_define([purple_major_version], [2]) m4_define([purple_minor_version], [7]) -m4_define([purple_micro_version], [2]) +m4_define([purple_micro_version], [3]) m4_define([purple_version_suffix], [devel]) m4_define([purple_version], [purple_major_version.purple_minor_version.purple_micro_version])
--- a/doc/finch.1.in Wed Jul 07 17:52:44 2010 +0900 +++ b/doc/finch.1.in Thu Jul 22 15:37:35 2010 +0900 @@ -59,7 +59,7 @@ Display the version information window. .SH GNT Shortcuts -You can use the following shortcuts (see the "\*QWidget Actions\*U" section for a more complete list): +You can use the following shortcuts (see the "Widget Actions" section for a more complete list): .TP .B Alt \+ a Bring up a list of available actions. You can use this list to access the @@ -507,6 +507,10 @@ .br a-/ = help-for-widget .br +a-c-j = window-scroll-down +.br +a-c-k = window-scroll-up +.br # The following action is still incomplete, and doesn't have a default binding .br # switch-window-n
--- a/libpurple/plugins/perl/common/Log.xs Wed Jul 07 17:52:44 2010 +0900 +++ b/libpurple/plugins/perl/common/Log.xs Thu Jul 22 15:37:35 2010 +0900 @@ -27,6 +27,9 @@ newCONSTSUB(flags_stash, (char *)civ->name, newSViv(civ->iv)); } +Purple::Handle +purple_log_get_handle() + int purple_log_common_sizer(log) Purple::Log log
--- a/libpurple/protocols/jabber/auth_cyrus.c Wed Jul 07 17:52:44 2010 +0900 +++ b/libpurple/protocols/jabber/auth_cyrus.c Thu Jul 22 15:37:35 2010 +0900 @@ -36,7 +36,7 @@ { purple_connection_error_reason(purple_account_get_connection(account), PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR, - _("Server requires plaintext authentication over an unencrypted stream")); + _("Server may require plaintext authentication over an unencrypted stream")); } static void start_cyrus_wrapper(JabberStream *js) @@ -240,8 +240,9 @@ * it in plaintext, see if we can turn on * plaintext auth */ + /* XXX Should we just check for PLAIN/LOGIN being offered mechanisms? */ } else if (!plaintext) { - char *msg = g_strdup_printf(_("%s requires plaintext authentication over an unencrypted connection. Allow this and continue authentication?"), + char *msg = g_strdup_printf(_("%s may require plaintext authentication over an unencrypted connection. Allow this and continue authentication?"), purple_account_get_username(account)); purple_request_yes_no(js->gc, _("Plaintext Authentication"), _("Plaintext Authentication"),
--- a/libpurple/protocols/jabber/bosh.c Wed Jul 07 17:52:44 2010 +0900 +++ b/libpurple/protocols/jabber/bosh.c Thu Jul 22 15:37:35 2010 +0900 @@ -195,6 +195,11 @@ g_free(path); conn->pipelining = TRUE; + if (purple_ip_address_is_valid(host)) + js->serverFQDN = g_strdup(js->user->domain); + else + js->serverFQDN = g_strdup(host); + if ((user && user[0] != '\0') || (passwd && passwd[0] != '\0')) { purple_debug_info("jabber", "Ignoring unexpected username and password " "in BOSH URL.\n");
--- a/libpurple/protocols/jabber/caps.c Wed Jul 07 17:52:44 2010 +0900 +++ b/libpurple/protocols/jabber/caps.c Thu Jul 22 15:37:35 2010 +0900 @@ -29,6 +29,7 @@ #include "iq.h" #include "presence.h" #include "util.h" +#include "xdata.h" #define JABBER_CAPS_FILENAME "xmpp-caps.xml" @@ -41,20 +42,14 @@ static GHashTable *nodetable = NULL; /* char *node -> JabberCapsNodeExts */ static guint save_timer = 0; -/** - * Processes a query-node and returns a JabberCapsClientInfo object with all relevant info. - * - * @param query A query object. - * @return A JabberCapsClientInfo object. - */ -static JabberCapsClientInfo *jabber_caps_parse_client_info(xmlnode *query); - /* Free a GList of allocated char* */ static void free_string_glist(GList *list) { - g_list_foreach(list, (GFunc)g_free, NULL); - g_list_free(list); + while (list) { + g_free(list->data); + list = g_list_delete_link(list, list); + } } static JabberCapsNodeExts* @@ -238,15 +233,15 @@ if(!capsdata) return; - if (strcmp(capsdata->name, "capabilities") != 0) { + if (!g_str_equal(capsdata->name, "capabilities")) { xmlnode_free(capsdata); return; } - for(client = capsdata->child; client; client = client->next) { - if(client->type != XMLNODE_TYPE_TAG) + for (client = capsdata->child; client; client = client->next) { + if (client->type != XMLNODE_TYPE_TAG) continue; - if(!strcmp(client->name, "client")) { + if (g_str_equal(client->name, "client")) { JabberCapsClientInfo *value = g_new0(JabberCapsClientInfo, 1); JabberCapsTuple *key = (JabberCapsTuple*)&value->tuple; xmlnode *child; @@ -259,15 +254,15 @@ if (key->hash == NULL) exts = jabber_caps_find_exts_by_node(key->node); - for(child = client->child; child; child = child->next) { - if(child->type != XMLNODE_TYPE_TAG) + for (child = client->child; child; child = child->next) { + if (child->type != XMLNODE_TYPE_TAG) continue; - if(!strcmp(child->name,"feature")) { + if (g_str_equal(child->name, "feature")) { const char *var = xmlnode_get_attrib(child, "var"); if(!var) continue; value->features = g_list_append(value->features,g_strdup(var)); - } else if(!strcmp(child->name,"identity")) { + } else if (g_str_equal(child->name, "identity")) { const char *category = xmlnode_get_attrib(child, "category"); const char *type = xmlnode_get_attrib(child, "type"); const char *name = xmlnode_get_attrib(child, "name"); @@ -284,15 +279,15 @@ id->lang = g_strdup(lang); value->identities = g_list_append(value->identities,id); - } else if(!strcmp(child->name,"x")) { + } else if (g_str_equal(child->name, "x")) { /* TODO: See #7814 -- this might cause problems if anyone * ever actually specifies forms. In fact, for this to * work properly, that bug needs to be fixed in * xmlnode_from_str, not the output version... */ value->forms = g_list_append(value->forms, xmlnode_copy(child)); - } else if (!strcmp(child->name, "ext") && key->hash != NULL) { + } else if (g_str_equal(child->name, "ext") && key->hash != NULL) { purple_debug_warning("jabber", "Ignoring exts when reading new-style caps\n"); - } else if (!strcmp(child->name, "ext")) { + } else if (g_str_equal(child->name, "ext")) { /* TODO: Do we care about reading in the identities listed here? */ const char *identifier = xmlnode_get_attrib(child, "identifier"); xmlnode *node; @@ -304,7 +299,7 @@ for (node = child->child; node; node = node->next) { if (node->type != XMLNODE_TYPE_TAG) continue; - if (!strcmp(node->name, "feature")) { + if (g_str_equal(node->name, "feature")) { const char *var = xmlnode_get_attrib(node, "var"); if (!var) continue; @@ -463,13 +458,13 @@ * size in jabber_caps_calculate_hash is large enough. The cipher API * doesn't seem to offer a "Get the hash size" function(?). */ - if (!strcmp(userdata->hash, "sha-1")) { + if (g_str_equal(userdata->hash, "sha-1")) { hash = jabber_caps_calculate_hash(info, "sha1"); - } else if (!strcmp(userdata->hash, "md5")) { + } else if (g_str_equal(userdata->hash, "md5")) { hash = jabber_caps_calculate_hash(info, "md5"); } - if (!hash || strcmp(hash, userdata->ver)) { + if (!hash || !g_str_equal(hash, userdata->ver)) { purple_debug_warning("jabber", "Could not validate caps info from " "%s. Expected %s, got %s\n", xmlnode_get_attrib(packet, "from"), @@ -709,44 +704,6 @@ } static gint -jabber_identity_compare(gconstpointer a, gconstpointer b) -{ - const JabberIdentity *ac; - const JabberIdentity *bc; - gint cat_cmp; - gint typ_cmp; - - ac = a; - bc = b; - - if ((cat_cmp = strcmp(ac->category, bc->category)) == 0) { - if ((typ_cmp = strcmp(ac->type, bc->type)) == 0) { - if (!ac->lang && !bc->lang) { - return 0; - } else if (ac->lang && !bc->lang) { - return 1; - } else if (!ac->lang && bc->lang) { - return -1; - } else { - return strcmp(ac->lang, bc->lang); - } - } else { - return typ_cmp; - } - } else { - return cat_cmp; - } -} - -static gchar *jabber_caps_get_formtype(const xmlnode *x) { - xmlnode *formtypefield; - formtypefield = xmlnode_get_child(x, "field"); - while (formtypefield && strcmp(xmlnode_get_attrib(formtypefield, "var"), "FORM_TYPE")) formtypefield = xmlnode_get_next_twin(formtypefield); - formtypefield = xmlnode_get_child(formtypefield, "value"); - return xmlnode_get_data(formtypefield);; -} - -static gint jabber_xdata_compare(gconstpointer a, gconstpointer b) { const xmlnode *aformtypefield = a; @@ -755,8 +712,8 @@ char *bformtype; int result; - aformtype = jabber_caps_get_formtype(aformtypefield); - bformtype = jabber_caps_get_formtype(bformtypefield); + aformtype = jabber_x_data_get_formtype(aformtypefield); + bformtype = jabber_x_data_get_formtype(bformtypefield); result = strcmp(aformtype, bformtype); g_free(aformtype); @@ -764,20 +721,21 @@ return result; } -static JabberCapsClientInfo *jabber_caps_parse_client_info(xmlnode *query) +JabberCapsClientInfo *jabber_caps_parse_client_info(xmlnode *query) { xmlnode *child; JabberCapsClientInfo *info; - if (!query || strcmp(query->xmlns, NS_DISCO_INFO)) - return 0; + if (!query || !g_str_equal(query->name, "query") || + !purple_strequal(query->xmlns, NS_DISCO_INFO)) + return NULL; info = g_new0(JabberCapsClientInfo, 1); for(child = query->child; child; child = child->next) { if (child->type != XMLNODE_TYPE_TAG) continue; - if (!strcmp(child->name,"identity")) { + if (g_str_equal(child->name, "identity")) { /* parse identity */ const char *category = xmlnode_get_attrib(child, "category"); const char *type = xmlnode_get_attrib(child, "type"); @@ -795,13 +753,13 @@ id->lang = g_strdup(lang); info->identities = g_list_append(info->identities, id); - } else if (!strcmp(child->name, "feature")) { + } else if (g_str_equal(child->name, "feature")) { /* parse feature */ const char *var = xmlnode_get_attrib(child, "var"); if (var) info->features = g_list_prepend(info->features, g_strdup(var)); - } else if (!strcmp(child->name, "x")) { - if (child->xmlns && !strcmp(child->xmlns, "jabber:x:data")) { + } else if (g_str_equal(child->name, "x")) { + if (purple_strequal(child->xmlns, "jabber:x:data")) { /* x-data form */ xmlnode *dataform = xmlnode_copy(child); info->forms = g_list_append(info->forms, dataform); @@ -848,9 +806,12 @@ static void append_escaped_string(PurpleCipherContext *context, const gchar *str) { - char *tmp = g_markup_escape_text(str, -1); - purple_cipher_context_append(context, (const guchar *)tmp, strlen(tmp)); - g_free(tmp); + if (str && *str) { + char *tmp = g_markup_escape_text(str, -1); + purple_cipher_context_append(context, (const guchar *)tmp, strlen(tmp)); + g_free(tmp); + } + purple_cipher_context_append(context, (const guchar *)"<", 1); } @@ -904,7 +865,7 @@ /* concat x-data forms to the verification string */ for(node = info->forms; node; node = node->next) { xmlnode *data = (xmlnode *)node->data; - gchar *formtype = jabber_caps_get_formtype(data); + gchar *formtype = jabber_x_data_get_formtype(data); GList *fields = jabber_caps_xdata_get_fields(data); /* append FORM_TYPE's field value to the verification string */ @@ -965,6 +926,10 @@ } info.features = features; + /* TODO: This copy can go away, I think, since jabber_identities + * is pre-sorted, so the sort in calculate_hash should be idempotent. + * However, I want to test that. --darkrain + */ info.identities = g_list_copy(jabber_identities); info.forms = NULL; @@ -989,7 +954,7 @@ for (node = accounts; node; node = node->next) { PurpleAccount *account = node->data; const char *prpl_id = purple_account_get_protocol_id(account); - if (!strcmp("prpl-jabber", prpl_id) && purple_account_is_connected(account)) { + if (g_str_equal("prpl-jabber", prpl_id) && purple_account_is_connected(account)) { PurpleConnection *gc = purple_account_get_connection(account); jabber_presence_send(gc->proto_data, TRUE); }
--- a/libpurple/protocols/jabber/caps.h Wed Jul 07 17:52:44 2010 +0900 +++ b/libpurple/protocols/jabber/caps.h Thu Jul 22 15:37:35 2010 +0900 @@ -115,4 +115,15 @@ */ void jabber_caps_broadcast_change(void); +/** + * Parse the <query/> element from an IQ stanza into a JabberCapsClientInfo + * struct. + * + * Exposed for tests + * + * @param query The 'query' element from an IQ reply stanza. + * @returns A JabberCapsClientInfo struct, or NULL on error + */ +JabberCapsClientInfo *jabber_caps_parse_client_info(xmlnode *query); + #endif /* PURPLE_JABBER_CAPS_H_ */
--- a/libpurple/protocols/jabber/jabber.c Wed Jul 07 17:52:44 2010 +0900 +++ b/libpurple/protocols/jabber/jabber.c Thu Jul 22 15:37:35 2010 +0900 @@ -1964,20 +1964,53 @@ } } -void jabber_add_identity(const gchar *category, const gchar *type, const gchar *lang, const gchar *name) { +gint +jabber_identity_compare(gconstpointer a, gconstpointer b) +{ + const JabberIdentity *ac; + const JabberIdentity *bc; + gint cat_cmp; + gint typ_cmp; + + ac = a; + bc = b; + + if ((cat_cmp = strcmp(ac->category, bc->category)) == 0) { + if ((typ_cmp = strcmp(ac->type, bc->type)) == 0) { + if (!ac->lang && !bc->lang) { + return 0; + } else if (ac->lang && !bc->lang) { + return 1; + } else if (!ac->lang && bc->lang) { + return -1; + } else { + return strcmp(ac->lang, bc->lang); + } + } else { + return typ_cmp; + } + } else { + return cat_cmp; + } +} + +void jabber_add_identity(const gchar *category, const gchar *type, + const gchar *lang, const gchar *name) +{ GList *identity; JabberIdentity *ident; + /* both required according to XEP-0030 */ g_return_if_fail(category != NULL); g_return_if_fail(type != NULL); - for(identity = jabber_identities; identity; identity = identity->next) { - JabberIdentity *ident = (JabberIdentity*)identity->data; - if (!strcmp(ident->category, category) && - !strcmp(ident->type, type) && - ((!ident->lang && !lang) || (ident->lang && lang && !strcmp(ident->lang, lang)))) { + /* Check if this identity is already there... */ + for (identity = jabber_identities; identity; identity = identity->next) { + JabberIdentity *id = identity->data; + if (g_str_equal(id->category, category) && + g_str_equal(id->type, type) && + purple_strequal(id->lang, lang)) return; - } } ident = g_new0(JabberIdentity, 1); @@ -1985,7 +2018,8 @@ ident->type = g_strdup(type); ident->lang = g_strdup(lang); ident->name = g_strdup(name); - jabber_identities = g_list_prepend(jabber_identities, ident); + jabber_identities = g_list_insert_sorted(jabber_identities, ident, + jabber_identity_compare); } static void jabber_identities_destroy(void)
--- a/libpurple/protocols/jabber/jabber.h Wed Jul 07 17:52:44 2010 +0900 +++ b/libpurple/protocols/jabber/jabber.h Thu Jul 22 15:37:35 2010 +0900 @@ -303,6 +303,9 @@ /* what kind of additional features as returned from disco#info are supported? */ extern GList *jabber_features; +/* A sorted list of identities advertised. Use jabber_add_identity to add + * so it remains sorted. + */ extern GList *jabber_identities; void jabber_stream_features_parse(JabberStream *js, xmlnode *packet); @@ -342,6 +345,11 @@ void jabber_add_identity(const gchar *category, const gchar *type, const gchar *lang, const gchar *name); /** + * GCompareFunc for JabberIdentity structs. + */ +gint jabber_identity_compare(gconstpointer a, gconstpointer b); + +/** * Returns true if this connection is over a secure (SSL) stream. Use this * instead of checking js->gsc because BOSH stores its PurpleSslConnection * members in its own data structure.
--- a/libpurple/protocols/jabber/xdata.c Wed Jul 07 17:52:44 2010 +0900 +++ b/libpurple/protocols/jabber/xdata.c Thu Jul 22 15:37:35 2010 +0900 @@ -411,4 +411,30 @@ return handle; } +gchar * +jabber_x_data_get_formtype(const xmlnode *form) +{ + xmlnode *field; + g_return_val_if_fail(form != NULL, NULL); + + for (field = xmlnode_get_child((xmlnode *)form, "field"); field; + field = xmlnode_get_next_twin(field)) { + const char *var = xmlnode_get_attrib(field, "var"); + if (purple_strequal(var, "FORM_TYPE")) { + xmlnode *value = xmlnode_get_child(field, "value"); + if (value) + return xmlnode_get_data(value); + else + /* An interesting corner case... Looking for a second + * FORM_TYPE would be more considerate, but I'm in favor + * of not helping broken clients. + */ + return NULL; + } + } + + /* Erm, none found :( */ + return NULL; +} +
--- a/libpurple/protocols/jabber/xdata.h Wed Jul 07 17:52:44 2010 +0900 +++ b/libpurple/protocols/jabber/xdata.h Thu Jul 22 15:37:35 2010 +0900 @@ -37,4 +37,19 @@ void *jabber_x_data_request(JabberStream *js, xmlnode *packet, jabber_x_data_cb cb, gpointer user_data); void *jabber_x_data_request_with_actions(JabberStream *js, xmlnode *packet, GList *actions, int defaultaction, jabber_x_data_action_cb cb, gpointer user_data); +/* + * Return the form type (the CDATA of the value child of the FORM_TYPE + * field entry. + * E.g., for the following, "http://jabber.org/protocol/muc#roominfo". + * <x xmlns='jabber:x:data' type='result'> + * <field var='FORM_TYPE' type='hidden'> + * <value>http://jabber.org/protocol/muc#roominfo</value> + * </field> + * </x> + * + * @param form The xmlnode for the form (the 'x' element) + * @returns The FORM_TYPE. Must be freed by caller. + */ +gchar *jabber_x_data_get_formtype(const xmlnode *form); + #endif /* PURPLE_JABBER_XDATA_H_ */
--- a/libpurple/protocols/msn/notification.c Wed Jul 07 17:52:44 2010 +0900 +++ b/libpurple/protocols/msn/notification.c Thu Jul 22 15:37:35 2010 +0900 @@ -409,7 +409,7 @@ /* add contact to xmlnode */ static void -msn_add_contact_xml(MsnSession *session, xmlnode *mlNode,const char *passport, MsnListOp list_op, MsnNetwork networkId) +msn_add_contact_xml(xmlnode *mlNode, const char *passport, MsnListOp list_op, MsnNetwork networkId) { xmlnode *d_node,*c_node; char **tokens; @@ -543,8 +543,8 @@ adl_node = xmlnode_new("ml"); xmlnode_set_attrib(adl_node, "l", "1"); - msn_add_contact_xml(session, adl_node, passport, - user->list_op & MSN_LIST_OP_MASK, network); + msn_add_contact_xml(adl_node, passport, + user->list_op & MSN_LIST_OP_MASK, network); payload = xmlnode_to_str(adl_node, &payload_len); msn_notification_post_adl(session->notification->cmdproc, payload, payload_len); g_free(payload); @@ -600,8 +600,9 @@ } if (user->networkid != MSN_NETWORK_UNKNOWN) { - msn_add_contact_xml(session, adl_node, user->passport, - user->list_op & MSN_LIST_OP_MASK, user->networkid); + msn_add_contact_xml(adl_node, user->passport, + user->list_op & MSN_LIST_OP_MASK, + user->networkid); /* each ADL command may contain up to 150 contacts */ if (++adl_count % 150 == 0) { @@ -630,8 +631,7 @@ purple_debug_info("msn", "Adding FQY address, count is %d\n", session->adl_fqy); - msn_add_contact_xml(session, fqy_node, user->passport, - 0, user->networkid); + msn_add_contact_xml(fqy_node, user->passport, 0, user->networkid); /* each FQY command may contain up to 150 contacts, probably */ if (++fqy_count % 150 == 0) { @@ -674,6 +674,8 @@ xmlnode_free(adl_node); xmlnode_free(fqy_node); + msn_session_activate_login_timeout(session); + pc = purple_account_get_connection(session->account); display_name = purple_connection_get_display_name(pc); if (display_name @@ -1956,8 +1958,7 @@ node = xmlnode_new("ml"); node->child = NULL; - msn_add_contact_xml(session, node, passport, - addrem->list_op, network); + msn_add_contact_xml(node, passport, addrem->list_op, network); payload = xmlnode_to_str(node, &payload_len); xmlnode_free(node); @@ -1987,8 +1988,7 @@ adl_node = xmlnode_new("ml"); adl_node->child = NULL; - msn_add_contact_xml(notification->session, adl_node, user->passport, - list_op, user->networkid); + msn_add_contact_xml(adl_node, user->passport, list_op, user->networkid); payload = xmlnode_to_str(adl_node, &payload_len); xmlnode_free(adl_node); @@ -2026,8 +2026,7 @@ rml_node = xmlnode_new("ml"); rml_node->child = NULL; - msn_add_contact_xml(notification->session, rml_node, user->passport, - list_op, user->networkid); + msn_add_contact_xml(rml_node, user->passport, list_op, user->networkid); payload = xmlnode_to_str(rml_node, &payload_len); xmlnode_free(rml_node);
--- a/libpurple/protocols/msn/session.c Wed Jul 07 17:52:44 2010 +0900 +++ b/libpurple/protocols/msn/session.c Thu Jul 22 15:37:35 2010 +0900 @@ -131,6 +131,11 @@ if (!session->connected) return; + if (session->login_timeout) { + purple_timeout_remove(session->login_timeout); + session->login_timeout = 0; + } + session->connected = FALSE; while (session->switches != NULL) @@ -258,6 +263,28 @@ return swboard; } +static gboolean +msn_login_timeout_cb(gpointer data) +{ + MsnSession *session = data; + /* This forces the login process to finish, even though we haven't heard + a response for our FQY requests yet. We'll at least end up online to the + people we've already added. The rest will follow later. */ + msn_session_finish_login(session); + session->login_timeout = 0; + return FALSE; +} + +void +msn_session_activate_login_timeout(MsnSession *session) +{ + if (!session->logged_in) { + session->login_timeout = + purple_timeout_add_seconds(MSN_LOGIN_FQY_TIMEOUT, + msn_login_timeout_cb, session); + } +} + static void msn_session_sync_users(MsnSession *session) { @@ -362,6 +389,9 @@ msg = g_strdup_printf(_("Unable to authenticate: %s"), (info == NULL ) ? _("Unknown error") : info); + /* Clear the password if it isn't being saved */ + if (!purple_account_get_remember_password(session->account)) + purple_account_set_password(session->account, NULL); break; case MSN_ERROR_BAD_BLIST: reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
--- a/libpurple/protocols/msn/session.h Wed Jul 07 17:52:44 2010 +0900 +++ b/libpurple/protocols/msn/session.h Thu Jul 22 15:37:35 2010 +0900 @@ -59,6 +59,8 @@ #define MSN_LOGIN_STEPS MSN_LOGIN_STEP_END +#define MSN_LOGIN_FQY_TIMEOUT 30 + #include "group.h" #include "httpconn.h" #include "nexus.h" @@ -83,6 +85,7 @@ gboolean connected; gboolean logged_in; /**< A temporal flag to ignore local buddy list adds. */ int adl_fqy; /**< A count of ADL/FQY so status is only changed once. */ + guint login_timeout; /**< Timeout to force status change if ADL/FQY fail. */ gboolean destroying; /**< A flag that states if the session is being destroyed. */ gboolean http_method; @@ -213,7 +216,16 @@ const char *info); /** - * Sets the current step in the login proccess. + * Starts a timeout to initiate finishing login. Sometimes the server ignores + * our FQY requests, so this forces ourselves online eventually. + * + * @param session The MSN session. + */ +void +msn_session_activate_login_timeout(MsnSession *session); + +/** + * Sets the current step in the login process. * * @param session The MSN session. * @param step The current step.
--- a/libpurple/protocols/msn/switchboard.c Wed Jul 07 17:52:44 2010 +0900 +++ b/libpurple/protocols/msn/switchboard.c Thu Jul 22 15:37:35 2010 +0900 @@ -740,8 +740,13 @@ else if ((swboard->current_users > 1) || (purple_conversation_get_type(swboard->conv) == PURPLE_CONV_TYPE_CHAT)) { + GList *passport; /* This is a switchboard used for a chat */ purple_conv_chat_remove_user(PURPLE_CONV_CHAT(swboard->conv), user, NULL); + + passport = g_list_find_custom(swboard->users, user, (GCompareFunc)strcmp); + g_free(passport->data); + swboard->users = g_list_delete_link(swboard->users, passport); swboard->current_users--; if (swboard->current_users == 0) msn_switchboard_destroy(swboard);
--- a/libpurple/protocols/oscar/family_icbm.c Wed Jul 07 17:52:44 2010 +0900 +++ b/libpurple/protocols/oscar/family_icbm.c Thu Jul 22 15:37:35 2010 +0900 @@ -250,9 +250,6 @@ } g_free(buf); - - - g_free(snac2->data); g_free(snac2); @@ -2727,7 +2724,6 @@ guint16 hdrlen; int curpos; guint16 num1, num2; - char *desc, *title, *temp; PurpleAccount *account; PurpleBuddy *buddy; PurplePresence *presence; @@ -2754,33 +2750,41 @@ xml = byte_stream_getstr(bs, bs->len - curpos); purple_debug_misc("oscar", "X-Status: Received XML reply\n"); if (xml) { - /* purple_debug_misc("oscar", "X-Status: XML reply: %s\n", xml); */ - desc = strstr(xml, "<desc>"); - if (desc != NULL) { - temp = strstr(xml, "</desc>"); - temp[0] = 0; - desc = desc + 12; + GString *xstatus; + char *tmp1, *tmp2; + + /* purple_debug_misc("oscar", "X-Status: XML reply: %s\n", xml); */ + + xstatus = g_string_new(NULL); + + tmp1 = strstr(xml, "<title>"); + if (tmp1 != NULL) { + tmp1 += 13; + tmp2 = strstr(tmp1, "</title>"); + if (tmp2 != NULL) + g_string_append_len(xstatus, tmp1, tmp2 - tmp1); } - title = strstr(xml, "<title>"); - if (title != NULL) { - temp = strstr(xml, "</title>"); - temp[0] = 0; - title = title + 13; - } else { - title = ""; + tmp1 = strstr(xml, "<desc>"); + if (tmp1 != NULL) { + tmp1 += 12; + tmp2 = strstr(tmp1, "</desc>"); + if (tmp2 != NULL) { + if (xstatus->len > 0) + g_string_append(xstatus, " - "); + g_string_append_len(xstatus, tmp1, tmp2 - tmp1); + } } - strcpy(xml,title); - if (desc) { - strcat(xml, " - "); - strcat(xml, desc); + if (xstatus->len > 0) { + purple_debug_misc("oscar", "X-Status reply: %s\n", xstatus->str); + account = purple_connection_get_account(od->gc); + buddy = purple_find_buddy(account, bn); + presence = purple_buddy_get_presence(buddy); + status = purple_presence_get_active_status(presence); + purple_prpl_got_user_status(account, bn, + purple_status_get_id(status), + "message", xstatus->str, NULL); } - purple_debug_misc("oscar", "X-Status reply: %s\n", xml); - account = purple_connection_get_account(od->gc); - buddy = purple_find_buddy(account, bn); - presence = purple_buddy_get_presence(buddy); - status = purple_presence_get_active_status(presence); - purple_prpl_got_user_status(account, bn, - purple_status_get_id(status), "message", xml, NULL); + g_string_free(xstatus, TRUE); } else { purple_debug_misc("oscar", "X-Status: Can't get XML reply string\n"); }
--- a/libpurple/protocols/oscar/oscar.c Wed Jul 07 17:52:44 2010 +0900 +++ b/libpurple/protocols/oscar/oscar.c Thu Jul 22 15:37:35 2010 +0900 @@ -3061,12 +3061,23 @@ if (smstype != 0) break; taglen = byte_stream_getle32(&qbs); + if (taglen > 2000) { + /* Avoid trying to allocate large amounts of memory, in + case we get something unexpected. */ + break; + } tagstr = byte_stream_getstr(&qbs, taglen); if (tagstr == NULL) break; byte_stream_advance(&qbs, 3); byte_stream_advance(&qbs, 4); smslen = byte_stream_getle32(&qbs); + if (smslen > 2000) { + /* Avoid trying to allocate large amounts of memory, in + case we get something unexpected. */ + g_free(tagstr); + break; + } smsmsg = byte_stream_getstr(&qbs, smslen); /* Check if this is an SMS being sent from server */
--- a/libpurple/purple-url-handler Wed Jul 07 17:52:44 2010 +0900 +++ b/libpurple/purple-url-handler Thu Jul 22 15:37:35 2010 +0900 @@ -73,7 +73,8 @@ def findaccount(protocolname, accountname="", matcher=None): if matcher: for account in cpurple.PurpleAccountsGetAll(): - if accountname != "" and accountname != cpurple.PurpleAccountGetUsername(a): + if (protocolname != cpurple.PurpleAccountGetProtocolID(account)) or \ + (accountname != "" and accountname != cpurple.PurpleAccountGetUsername(account)): continue if matcher(account): bring_account_online(account) @@ -182,7 +183,7 @@ def irc(uri): protocol = "prpl-irc" - match = re.match(r"^irc:(//([^/]*)/)?([^?]*)(\?(.*))?", uri) + match = re.match(r"^irc:(//([^/]*))?/?([^?]*)(\?(.*))?", uri) if not match: print "Invalid irc URI: %s" % uri return @@ -207,7 +208,7 @@ def correct_server(account): username = cpurple.PurpleAccountGetUsername(account) - return ("@" in username) and (server == (username.split("@"))[1]) + return ((server == "") or ("@" in username) and (server == (username.split("@"))[1])) account = findaccount(protocol, matcher=correct_server)
--- a/libpurple/tests/Makefile.am Wed Jul 07 17:52:44 2010 +0900 +++ b/libpurple/tests/Makefile.am Thu Jul 22 15:37:35 2010 +0900 @@ -10,6 +10,7 @@ check_libpurple.c \ tests.h \ test_cipher.c \ + test_jabber_caps.c \ test_jabber_jutil.c \ test_jabber_scram.c \ test_qq.c \
--- a/libpurple/tests/check_libpurple.c Wed Jul 07 17:52:44 2010 +0900 +++ b/libpurple/tests/check_libpurple.c Thu Jul 22 15:37:35 2010 +0900 @@ -84,6 +84,7 @@ sr = srunner_create (master_suite()); srunner_add_suite(sr, cipher_suite()); + srunner_add_suite(sr, jabber_caps_suite()); srunner_add_suite(sr, jabber_jutil_suite()); srunner_add_suite(sr, jabber_scram_suite()); srunner_add_suite(sr, qq_suite());
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/tests/test_jabber_caps.c Thu Jul 22 15:37:35 2010 +0900 @@ -0,0 +1,54 @@ +#include <string.h> + +#include "tests.h" +#include "../xmlnode.h" +#include "../protocols/jabber/caps.h" + +START_TEST(test_parse_invalid) +{ + xmlnode *query; + + fail_unless(NULL == jabber_caps_parse_client_info(NULL)); + + /* Something other than a disco#info query */ + query = xmlnode_new("foo"); + fail_unless(NULL == jabber_caps_parse_client_info(query)); + xmlnode_free(query); + + query = xmlnode_new("query"); + fail_unless(NULL == jabber_caps_parse_client_info(query)); + xmlnode_set_namespace(query, "jabber:iq:last"); + fail_unless(NULL == jabber_caps_parse_client_info(query)); + xmlnode_free(query); +} +END_TEST + +#define assert_caps_calculate_match(hash_func, hash, str) { \ + xmlnode *query = xmlnode_from_str((str), -1); \ + JabberCapsClientInfo *info = jabber_caps_parse_client_info(query); \ + gchar *got_hash = jabber_caps_calculate_hash(info, (hash_func)); \ + assert_string_equal_free((hash), got_hash); \ +} + +START_TEST(test_calculate_caps) +{ + assert_caps_calculate_match("sha1", "GNjxthSckUNvAIoCCJFttjl6VL8=", + "<query xmlns='http://jabber.org/protocol/disco#info' node='http://tkabber.jabber.ru/#GNjxthSckUNvAIoCCJFttjl6VL8='><identity category='client' type='pc' name='Tkabber'/><x xmlns='jabber:x:data' type='result'><field var='FORM_TYPE' type='hidden'><value>urn:xmpp:dataforms:softwareinfo</value></field><field var='software'><value>Tkabber</value></field><field var='software_version'><value> ( 8.5.5 )</value></field><field var='os'><value>ATmega640-16AU</value></field><field var='os_version'><value/></field></x><feature var='games:board'/><feature var='google:mail:notify'/><feature var='http://jabber.org/protocol/activity'/><feature var='http://jabber.org/protocol/bytestreams'/><feature var='http://jabber.org/protocol/chatstates'/><feature var='http://jabber.org/protocol/commands'/><feature var='http://jabber.org/protocol/commands'/><feature var='http://jabber.org/protocol/disco#info'/><feature var='http://jabber.org/protocol/disco#items'/><feature var='http://jabber.org/protocol/feature-neg'/><feature var='http://jabber.org/protocol/geoloc'/><feature var='http://jabber.org/protocol/ibb'/><feature var='http://jabber.org/protocol/iqibb'/><feature var='http://jabber.org/protocol/mood'/><feature var='http://jabber.org/protocol/muc'/><feature var='http://jabber.org/protocol/mute#ancestor'/><feature var='http://jabber.org/protocol/mute#editor'/><feature var='http://jabber.org/protocol/rosterx'/><feature var='http://jabber.org/protocol/si'/><feature var='http://jabber.org/protocol/si/profile/file-transfer'/><feature var='http://jabber.org/protocol/tune'/><feature var='jabber:iq:avatar'/><feature var='jabber:iq:browse'/><feature var='jabber:iq:dtcp'/><feature var='jabber:iq:filexfer'/><feature var='jabber:iq:ibb'/><feature var='jabber:iq:inband'/><feature var='jabber:iq:jidlink'/><feature var='jabber:iq:last'/><feature var='jabber:iq:oob'/><feature var='jabber:iq:privacy'/><feature var='jabber:iq:time'/><feature var='jabber:iq:version'/><feature var='jabber:x:data'/><feature var='jabber:x:event'/><feature var='jabber:x:oob'/><feature var='urn:xmpp:ping'/><feature var='urn:xmpp:receipts'/><feature var='urn:xmpp:time'/></query>"); +} +END_TEST + +Suite * +jabber_caps_suite(void) +{ + Suite *s = suite_create("Jabber Caps Functions"); + + TCase *tc = tcase_create("Parsing invalid ndoes"); + tcase_add_test(tc, test_parse_invalid); + suite_add_tcase(s, tc); + + tc = tcase_create("Calculating from XMLnode"); + tcase_add_test(tc, test_calculate_caps); + suite_add_tcase(s, tc); + + return s; +}
--- a/libpurple/tests/tests.h Wed Jul 07 17:52:44 2010 +0900 +++ b/libpurple/tests/tests.h Thu Jul 22 15:37:35 2010 +0900 @@ -9,6 +9,7 @@ /* remember to add the suite to the runner in check_libpurple.c */ Suite * master_suite(void); Suite * cipher_suite(void); +Suite * jabber_caps_suite(void); Suite * jabber_jutil_suite(void); Suite * jabber_scram_suite(void); Suite * qq_suite(void);
--- a/libpurple/upnp.c Wed Jul 07 17:52:44 2010 +0900 +++ b/libpurple/upnp.c Thu Jul 22 15:37:35 2010 +0900 @@ -403,6 +403,11 @@ lookup_internal_ip(); } + if (dd->inpa > 0) + purple_input_remove(dd->inpa); + if (dd->tima > 0) + purple_timeout_remove(dd->tima); + g_free(dd); } @@ -506,6 +511,8 @@ if (dd->inpa) purple_input_remove(dd->inpa); + if (dd->tima > 0) + purple_timeout_remove(dd->tima); dd->inpa = 0; dd->tima = 0; @@ -610,7 +617,7 @@ /* We have already done all our retries. Make sure that the callback * doesn't get called before the original function returns */ - purple_timeout_add(10, purple_upnp_discover_timeout, dd); + dd->tima = purple_timeout_add(10, purple_upnp_discover_timeout, dd); } void @@ -647,7 +654,7 @@ "purple_upnp_discover(): Failed In sock creation\n"); /* Short circuit the retry attempts */ dd->retry_count = NUM_UDP_ATTEMPTS; - purple_timeout_add(10, purple_upnp_discover_timeout, dd); + dd->tima = purple_timeout_add(10, purple_upnp_discover_timeout, dd); return; } @@ -659,7 +666,7 @@ "purple_upnp_discover(): Failed In gethostbyname\n"); /* Short circuit the retry attempts */ dd->retry_count = NUM_UDP_ATTEMPTS; - purple_timeout_add(10, purple_upnp_discover_timeout, dd); + dd->tima = purple_timeout_add(10, purple_upnp_discover_timeout, dd); return; }
--- a/libpurple/util.c Wed Jul 07 17:52:44 2010 +0900 +++ b/libpurple/util.c Thu Jul 22 15:37:35 2010 +0900 @@ -3451,7 +3451,7 @@ char **ret_path, char **ret_user, char **ret_passwd) { gboolean is_https = FALSE; - char scan_info[255]; + const char * scan_info; char port_str[6]; int f; const char *at, *slash; @@ -3459,11 +3459,12 @@ char host[256], path[256], user[256], passwd[256]; int port = 0; /* hyphen at end includes it in control set */ - static const char addr_ctrl[] = "A-Za-z0-9.-"; - static const char port_ctrl[] = "0-9"; - static const char page_ctrl[] = "A-Za-z0-9.~_/:*!@&%%?=+^-"; - static const char user_ctrl[] = "A-Za-z0-9.~_/*!&%%?=+^-"; - static const char passwd_ctrl[] = "A-Za-z0-9.~_/*!&%%?=+^-"; + +#define ADDR_CTRL "A-Za-z0-9.-" +#define PORT_CTRL "0-9" +#define PAGE_CTRL "A-Za-z0-9.~_/:*!@&%%?=+^-" +#define USER_CTRL "A-Za-z0-9.~_/*!&%%?=+^-" +#define PASSWD_CTRL "A-Za-z0-9.~_/*!&%%?=+^-" g_return_val_if_fail(url != NULL, FALSE); @@ -3483,37 +3484,32 @@ /* Only care about @ char BEFORE the first / */ at = strchr(url, '@'); slash = strchr(url, '/'); - if ((at != NULL) && - (((slash != NULL) && (strlen(at) > strlen(slash))) || - (slash == NULL))) { - g_snprintf(scan_info, sizeof(scan_info), - "%%255[%s]:%%255[%s]^@", user_ctrl, passwd_ctrl); + f = 0; + if (at && (!slash || at < slash)) { + scan_info = "%255[" USER_CTRL "]:%255[" PASSWD_CTRL "]^@"; f = sscanf(url, scan_info, user, passwd); - if (f ==1 ) { + if (f == 1) { /* No passwd, possibly just username supplied */ - g_snprintf(scan_info, sizeof(scan_info), - "%%255[%s]^@", user_ctrl); + scan_info = "%255[" USER_CTRL "]^@"; f = sscanf(url, scan_info, user); - *passwd = '\0'; } url = at+1; /* move pointer after the @ char */ - } else { + } + + if (f < 1) { *user = '\0'; *passwd = '\0'; - } - - g_snprintf(scan_info, sizeof(scan_info), - "%%255[%s]:%%5[%s]/%%255[%s]", addr_ctrl, port_ctrl, page_ctrl); - + } else if (f == 1) + *passwd = '\0'; + + scan_info = "%255[" ADDR_CTRL "]:%5[" PORT_CTRL "]/%255[" PAGE_CTRL "]"; f = sscanf(url, scan_info, host, port_str, path); if (f == 1) { - g_snprintf(scan_info, sizeof(scan_info), - "%%255[%s]/%%255[%s]", - addr_ctrl, page_ctrl); + scan_info = "%255[" ADDR_CTRL "]/%255[" PAGE_CTRL "]"; f = sscanf(url, scan_info, host, path); /* Use the default port */ if (is_https) @@ -3537,6 +3533,12 @@ if (ret_passwd != NULL) *ret_passwd = g_strdup(passwd); return ((*host != '\0') ? TRUE : FALSE); + +#undef ADDR_CTRL +#undef PORT_CTRL +#undef PAGE_CTRL +#undef USER_CTRL +#undef PASSWD_CTRL } /**
--- a/libpurple/xmlnode.c Wed Jul 07 17:52:44 2010 +0900 +++ b/libpurple/xmlnode.c Thu Jul 22 15:37:35 2010 +0900 @@ -223,7 +223,7 @@ const char * -xmlnode_get_attrib(xmlnode *node, const char *attr) +xmlnode_get_attrib(const xmlnode *node, const char *attr) { xmlnode *x; @@ -240,9 +240,9 @@ } const char * -xmlnode_get_attrib_with_namespace(xmlnode *node, const char *attr, const char *xmlns) +xmlnode_get_attrib_with_namespace(const xmlnode *node, const char *attr, const char *xmlns) { - xmlnode *x; + const xmlnode *x; g_return_val_if_fail(node != NULL, NULL); g_return_val_if_fail(attr != NULL, NULL);
--- a/libpurple/xmlnode.h Wed Jul 07 17:52:44 2010 +0900 +++ b/libpurple/xmlnode.h Thu Jul 22 15:37:35 2010 +0900 @@ -205,7 +205,7 @@ * * @return The value of the attribute. */ -const char *xmlnode_get_attrib(xmlnode *node, const char *attr); +const char *xmlnode_get_attrib(const xmlnode *node, const char *attr); /** * Gets a namespaced attribute from a node @@ -216,7 +216,7 @@ * * @return The value of the attribute/ */ -const char *xmlnode_get_attrib_with_namespace(xmlnode *node, const char *attr, const char *xmlns); +const char *xmlnode_get_attrib_with_namespace(const xmlnode *node, const char *attr, const char *xmlns); /** * Removes an attribute from a node.
--- a/pidgin/gtkmedia.c Wed Jul 07 17:52:44 2010 +0900 +++ b/pidgin/gtkmedia.c Thu Jul 22 15:37:35 2010 +0900 @@ -333,7 +333,7 @@ gtk_box_pack_start(GTK_BOX(vbox), media->priv->menubar, FALSE, TRUE, 0); - media->priv->display = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); + media->priv->display = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); gtk_container_set_border_width(GTK_CONTAINER(media->priv->display), PIDGIN_HIG_BOX_SPACE); gtk_box_pack_start(GTK_BOX(vbox), media->priv->display, @@ -629,29 +629,29 @@ gtk_box_pack_start(GTK_BOX(gtkmedia->priv->display), recv_widget, TRUE, TRUE, 0); gtk_widget_show(recv_widget); - } else + } else { recv_widget = gtkmedia->priv->recv_widget; + } if (gtkmedia->priv->send_widget == NULL && type & (PURPLE_MEDIA_SEND_VIDEO | PURPLE_MEDIA_SEND_AUDIO)) { send_widget = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); gtk_box_pack_start(GTK_BOX(gtkmedia->priv->display), - send_widget, TRUE, TRUE, 0); + send_widget, FALSE, TRUE, 0); button_widget = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); - gtk_box_pack_end(GTK_BOX(send_widget), button_widget, - FALSE, FALSE, 0); - gtk_widget_show(GTK_WIDGET(button_widget)); + gtk_box_pack_end(GTK_BOX(recv_widget), button_widget, + FALSE, TRUE, 0); gtk_widget_show(send_widget); /* Hold button */ gtkmedia->priv->hold = gtk_toggle_button_new_with_mnemonic("_Hold"); + gtk_box_pack_end(GTK_BOX(button_widget), gtkmedia->priv->hold, + FALSE, FALSE, 0); + gtk_widget_show(gtkmedia->priv->hold); g_signal_connect(gtkmedia->priv->hold, "toggled", G_CALLBACK(pidgin_media_hold_toggled), gtkmedia); - gtk_box_pack_end(GTK_BOX(button_widget), gtkmedia->priv->hold, - FALSE, FALSE, 0); - gtk_widget_show(gtkmedia->priv->hold); } else { send_widget = gtkmedia->priv->send_widget; button_widget = gtkmedia->priv->button_widget; @@ -663,7 +663,7 @@ GtkWidget *remote_video; GdkColor color = {0, 0, 0, 0}; - aspect = gtk_aspect_frame_new(NULL, 0.5, 0.5, 4.0/3.0, FALSE); + aspect = gtk_aspect_frame_new(NULL, 0, 0, 4.0/3.0, FALSE); gtk_frame_set_shadow_type(GTK_FRAME(aspect), GTK_SHADOW_IN); gtk_box_pack_start(GTK_BOX(recv_widget), aspect, TRUE, TRUE, 0); @@ -683,15 +683,16 @@ gtkmedia->priv->remote_video = remote_video; } + if (type & PURPLE_MEDIA_SEND_VIDEO) { PidginMediaRealizeData *data; GtkWidget *aspect; GtkWidget *local_video; GdkColor color = {0, 0, 0, 0}; - aspect = gtk_aspect_frame_new(NULL, 0.5, 0.5, 4.0/3.0, FALSE); + aspect = gtk_aspect_frame_new(NULL, 0, 0, 4.0/3.0, TRUE); gtk_frame_set_shadow_type(GTK_FRAME(aspect), GTK_SHADOW_IN); - gtk_box_pack_start(GTK_BOX(send_widget), aspect, TRUE, TRUE, 0); + gtk_box_pack_start(GTK_BOX(send_widget), aspect, FALSE, TRUE, 0); data = g_new0(PidginMediaRealizeData, 1); data->gtkmedia = gtkmedia; @@ -703,44 +704,43 @@ g_signal_connect(G_OBJECT(local_video), "realize", G_CALLBACK(realize_cb), data); gtk_container_add(GTK_CONTAINER(aspect), local_video); - gtk_widget_set_size_request (GTK_WIDGET(local_video), 160, 120); + gtk_widget_set_size_request (GTK_WIDGET(local_video), 80, 60); gtk_widget_show(local_video); gtk_widget_show(aspect); gtkmedia->priv->pause = gtk_toggle_button_new_with_mnemonic(_("_Pause")); + gtk_box_pack_end(GTK_BOX(button_widget), gtkmedia->priv->pause, + FALSE, FALSE, 0); + gtk_widget_show(gtkmedia->priv->pause); g_signal_connect(gtkmedia->priv->pause, "toggled", G_CALLBACK(pidgin_media_pause_toggled), gtkmedia); - gtk_box_pack_end(GTK_BOX(button_widget), gtkmedia->priv->pause, - FALSE, FALSE, 0); - gtk_widget_show(gtkmedia->priv->pause); gtkmedia->priv->local_video = local_video; } - if (type & PURPLE_MEDIA_RECV_AUDIO) { gtk_box_pack_end(GTK_BOX(recv_widget), pidgin_media_add_audio_widget(gtkmedia, PURPLE_MEDIA_RECV_AUDIO), FALSE, FALSE, 0); } + if (type & PURPLE_MEDIA_SEND_AUDIO) { gtkmedia->priv->mute = gtk_toggle_button_new_with_mnemonic("_Mute"); + gtk_box_pack_end(GTK_BOX(button_widget), gtkmedia->priv->mute, + FALSE, FALSE, 0); + gtk_widget_show(gtkmedia->priv->mute); g_signal_connect(gtkmedia->priv->mute, "toggled", G_CALLBACK(pidgin_media_mute_toggled), gtkmedia); - gtk_box_pack_end(GTK_BOX(button_widget), gtkmedia->priv->mute, - FALSE, FALSE, 0); - gtk_widget_show(gtkmedia->priv->mute); - gtk_box_pack_end(GTK_BOX(send_widget), + gtk_box_pack_end(GTK_BOX(recv_widget), pidgin_media_add_audio_widget(gtkmedia, PURPLE_MEDIA_SEND_AUDIO), FALSE, FALSE, 0); } - if (type & PURPLE_MEDIA_AUDIO && gtkmedia->priv->level_handler_id == 0) { gtkmedia->priv->level_handler_id = g_signal_connect( @@ -752,8 +752,10 @@ gtkmedia->priv->send_widget = send_widget; if (recv_widget != NULL) gtkmedia->priv->recv_widget = recv_widget; - if (button_widget != NULL) + if (button_widget != NULL) { gtkmedia->priv->button_widget = button_widget; + gtk_widget_show(GTK_WIDGET(button_widget)); + } if (purple_media_is_initiator(media, sid, NULL) == FALSE) { if (gtkmedia->priv->timeout_id != 0)
--- a/po/ChangeLog Wed Jul 07 17:52:44 2010 +0900 +++ b/po/ChangeLog Thu Jul 22 15:37:35 2010 +0900 @@ -1,5 +1,8 @@ Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul +version 2.7.2 + * No changes + version 2.7.1 * Chinese (Hong Kong) translation updated (Ambrose C. Li, Paladin R. Liu)
--- a/po/de.po Wed Jul 07 17:52:44 2010 +0900 +++ b/po/de.po Thu Jul 22 15:37:35 2010 +0900 @@ -11,14 +11,14 @@ msgstr "" "Project-Id-Version: de\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-05-30 23:15-0400\n" -"PO-Revision-Date: 2010-05-29 17:30+0200\n" +"POT-Creation-Date: 2010-07-20 19:00+0200\n" +"PO-Revision-Date: 2010-07-20 18:52+0200\n" "Last-Translator: Björn Voigt <bjoern@cs.tu-berlin.de>\n" "Language-Team: Deutsch <de@li.org>\n" -"Language: de\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Language: de\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #. Translators may want to transliterate the name. @@ -65,12 +65,27 @@ msgid "Error" msgstr "Fehler" +msgid "Account was not modified" +msgstr "Konto wurde nicht modifiziert" + msgid "Account was not added" msgstr "Konto wurde nicht hinzugefügt" msgid "Username of an account must be non-empty." msgstr "Benutzername eines Kontos darf nicht leer sein." +msgid "" +"The account's protocol cannot be changed while it is connected to the server." +msgstr "" +"Das Protokoll des Kontos kann nicht geändert werden solange das Konto mit " +"dem Server verbunden ist." + +msgid "" +"The account's username cannot be changed while it is connected to the server." +msgstr "" +"Der Benutzername des Kontos kann nicht geändert werden solange das Konto mit " +"dem Server verbunden ist." + msgid "New mail notifications" msgstr "Benachrichtigung über neue Mails" @@ -1269,6 +1284,9 @@ msgid "Someone says your username in chat" msgstr "Jemand nennt Ihren Benutzernamen im Chat" +msgid "Attention received" +msgstr "Aufmerksamkeitsgesuch erhalten" + msgid "GStreamer Failure" msgstr "GStreamer-Fehler" @@ -1685,8 +1703,12 @@ "Diesem Zertifikat wird nicht vertraut, da kein Zertifikat bestätigen kann, " "dass ihm aktuell vertraut wird." -msgid "The certificate is not valid yet." -msgstr "Das Zertifikat ist noch nicht gültig." +msgid "" +"The certificate is not valid yet. Check that your computer's date and time " +"are accurate." +msgstr "" +"Das Zertifikat ist nicht mehr gültig. Überprüfen Sie, ob Datum und Zeit " +"Ihres Computers stimmen." msgid "The certificate has expired and should not be considered valid." msgstr "" @@ -3857,6 +3879,19 @@ "Der Server ist der Meinung, dass die Authentifizierung vollständig ist, der " "Client aber nicht" +msgid "Server may require plaintext authentication over an unencrypted stream" +msgstr "" +"Der Server könnte eine Klartext-Authentifizierung über einen " +"unverschlüsselten Kanal anfordern" + +#, c-format +msgid "" +"%s may require plaintext authentication over an unencrypted connection. " +"Allow this and continue authentication?" +msgstr "" +"%s könnte eine Klartext-Authentifizierung über einen unverschlüsselten Kanal " +"anfordern. Wollen Sie dies erlauben und mit der Authentifikation fortfahren?" + msgid "SASL authentication failed" msgstr "SASL-Authentifizierung fehlgeschlagen" @@ -6175,17 +6210,14 @@ msgstr "Startbildschirm-Popup aktivieren" #. you were kicked -#, fuzzy msgid "You have been kicked from this MultiMX." -msgstr "Sie wurden hinausgeworfen: (%s)" - -#, fuzzy +msgstr "Sie wurden von MultiMX hinausgeworfen." + msgid "was kicked" -msgstr "Falsches Ticket" - -#, fuzzy +msgstr "wurde hinausgeworfen" + msgid "_Room Name:" -msgstr "_Raum:" +msgstr "_Raumname:" #. we must have lost the connection, so terminate it so that we can reconnect msgid "We have lost the connection to MXit. Please reconnect." @@ -6767,8 +6799,8 @@ #, c-format msgid "Unable to send message. Could not get details for user (%s)." msgstr "" -"Kann die Nachricht nicht senden. Kann die Details vom Benutzer nicht holen " -"(%s)." +"Kann die Nachricht nicht senden. Kann die Details vom Benutzer nicht holen (%" +"s)." #, c-format msgid "Unable to add %s to your buddy list (%s)." @@ -6786,8 +6818,8 @@ #, c-format msgid "Unable to send message to %s. Could not create the conference (%s)." msgstr "" -"Kann die Nachricht nicht an %s senden. Kann die Konferenz nicht erstellen " -"(%s)." +"Kann die Nachricht nicht an %s senden. Kann die Konferenz nicht erstellen (%" +"s)." #, c-format msgid "Unable to send message. Could not create the conference (%s)." @@ -7200,8 +7232,8 @@ "(There was an error receiving this message. Either you and %s have " "different encodings selected, or %s has a buggy client.)" msgstr "" -"(Es gab einen Fehler beim Empfang dieser Nachricht. Entweder haben Sie und " -"%s unterschiedliche Kodierungen gesetzt oder %s hat einen fehlerhaften " +"(Es gab einen Fehler beim Empfang dieser Nachricht. Entweder haben Sie und %" +"s unterschiedliche Kodierungen gesetzt oder %s hat einen fehlerhaften " "Client.)" #. Label @@ -7512,10 +7544,10 @@ msgid_plural "" "You missed %hu messages from %s because the rate limit has been exceeded." msgstr[0] "" -"Sie haben %hu Nachricht von %s nicht erhalten, da die Senderate " +"Sie haben %hu Nachricht von %s nicht erhalten, da die Datenrate " "überschritten wurde." msgstr[1] "" -"Sie haben %hu Nachrichten von %s nicht erhalten, da die Senderate " +"Sie haben %hu Nachrichten von %s nicht erhalten, da die Datenrate " "überschritten wurde." #, c-format @@ -7989,11 +8021,11 @@ msgid "Invalid SNAC" msgstr "Ungültiger SNAC" -msgid "Rate to host" -msgstr "Bewertung zum Host" - -msgid "Rate to client" -msgstr "Bewertung zum Client" +msgid "Server rate limit exceeded" +msgstr "Server-Datenrate überschritten" + +msgid "Client rate limit exceeded" +msgstr "Client-Datenrate überschritten" msgid "Service unavailable" msgstr "Dienst nicht verfügbar" @@ -8428,8 +8460,8 @@ #, c-format msgid "<b>Joining Qun %u is approved by admin %u for %s</b>" msgstr "" -"<b>Das Betreten des Qun %u wurde vom Admin bestätigt wegen by admin %u for " -"%s</b>" +"<b>Das Betreten des Qun %u wurde vom Admin bestätigt wegen by admin %u for %" +"s</b>" #, c-format msgid "<b>Removed buddy %u.</b>" @@ -10283,8 +10315,8 @@ msgid "Ignore conference and chatroom invitations" msgstr "Konferenz- und Chateinladungen ignorieren" -msgid "Use account proxy for SSL connections" -msgstr "Proxy-Zugang für SSL-Verbindungen benutzen" +msgid "Use account proxy for HTTP and HTTPS connections" +msgstr "Proxy-Zugang für HTTP- und HTTPS-Verbindungen benutzen" msgid "Chat room list URL" msgstr "Chatraumliste (URL)" @@ -12501,8 +12533,8 @@ "to multiple messaging services at once. %s is written in C using GTK+. %s " "is released, and may be modified and redistributed, under the terms of the " "GPL version 2 (or later). A copy of the GPL is distributed with %s. %s is " -"copyrighted by its contributors, a list of whom is also distributed with " -"%s. There is no warranty for %s.<BR><BR>" +"copyrighted by its contributors, a list of whom is also distributed with %" +"s. There is no warranty for %s.<BR><BR>" msgstr "" "%s ist ein Nachrichtendienst, basierend auf libpurple, der die Verbindung zu " "mehreren Nachrichtendiensten gleichzeitig unterstützt. %s wird in C " @@ -13074,16 +13106,16 @@ #, c-format msgid "" -"Are you sure you want to permanently delete the log of the conversation in " -"%s which started at %s?" +"Are you sure you want to permanently delete the log of the conversation in %" +"s which started at %s?" msgstr "" "Wollen Sie wirklich den Mitschnitt der Unterhaltung in %s, gestartet am %s, " "permanent löschen?" #, c-format msgid "" -"Are you sure you want to permanently delete the system log which started at " -"%s?" +"Are you sure you want to permanently delete the system log which started at %" +"s?" msgstr "" "Wollen Sie wirklich den Systemmitschnitt, gestartet am %s, permanent löschen?" @@ -14003,9 +14035,6 @@ msgid "Custom Smiley Manager" msgstr "Verwaltung für benutzerdefinierte Smileys" -msgid "Attention received" -msgstr "Aufmerksamkeitsgesuch erhalten" - msgid "Select Buddy Icon" msgstr "Buddy-Icon auswählen" @@ -15429,13 +15458,13 @@ #, no-c-format msgid "" "Error Installing Spellchecking ($R3).$\\rIf retrying fails, manual " -"installation instructions are at: http://developer.pidgin.im/wiki/Installing" -"%20Pidgin#manual_win32_spellcheck_installation" +"installation instructions are at: http://developer.pidgin.im/wiki/Installing%" +"20Pidgin#manual_win32_spellcheck_installation" msgstr "" "Fehler beim Installieren der Rechtschreibkontrolle ($R3).$\\rFalls ein " "erneuter Versuch fehlschlägt, finden Sie Anweisungen zur manuellen " -"Installation unter: http://developer.pidgin.im/wiki/Installing" -"%20Pidgin#manual_win32_spellcheck_installation" +"Installation unter: http://developer.pidgin.im/wiki/Installing%" +"20Pidgin#manual_win32_spellcheck_installation" #. Installer Subsection Text msgid "GTK+ Runtime (required if not present)" @@ -15515,6 +15544,15 @@ msgid "You do not have permission to uninstall this application." msgstr "Sie haben keine Berechtigung, diese Anwendung zu deinstallieren." +#~ msgid "The certificate is not valid yet." +#~ msgstr "Das Zertifikat ist noch nicht gültig." + +#~ msgid "Rate to host" +#~ msgstr "Bewertung zum Host" + +#~ msgid "Rate to client" +#~ msgstr "Bewertung zum Client" + #~ msgid "Unknown reason." #~ msgstr "Unbekannter Grund."