pidgin/ljfisher-ssl-client-auth

propagate from branch 'im.pidgin.pidgin' (head c7737916ec11f06833800adbd3ef6ae2990611e0)
to branch 'im.pidgin.cpw.qulogic.gtk3' (head 8c5d1edf9da2be491f35c621bde4165007c94c1b)
  • +4 -0
    COPYRIGHT
  • +22 -2
    ChangeLog
  • +1 -1
    configure.ac
  • +17 -15
    libpurple/certificate.c
  • +39 -1
    libpurple/media/backend-fs2.c
  • +0 -1
    libpurple/mediamanager.c
  • +4 -0
    libpurple/protocols/gg/gg.c
  • +1 -0
    libpurple/protocols/jabber/Makefile.am
  • +5 -2
    libpurple/protocols/jabber/auth_cyrus.c
  • +5 -4
    libpurple/protocols/jabber/auth_digest_md5.c
  • +39 -0
    libpurple/protocols/jabber/auth_digest_md5.h
  • +119 -31
    libpurple/protocols/jabber/bosh.c
  • +16 -24
    libpurple/protocols/msn/error.c
  • +2 -20
    libpurple/protocols/msn/msg.c
  • +0 -4
    libpurple/protocols/msn/msg.h
  • +187 -10
    libpurple/protocols/msn/p2p.c
  • +90 -6
    libpurple/protocols/msn/p2p.h
  • +0 -2
    libpurple/protocols/msn/sbconn.c
  • +12 -7
    libpurple/protocols/msn/slpcall.c
  • +69 -52
    libpurple/protocols/msn/slplink.c
  • +24 -37
    libpurple/protocols/msn/slpmsg.c
  • +2 -7
    libpurple/protocols/msn/slpmsg.h
  • +34 -27
    libpurple/protocols/msn/slpmsg_part.c
  • +6 -3
    libpurple/protocols/msn/slpmsg_part.h
  • +7 -8
    libpurple/protocols/novell/novell.c
  • +76 -1
    libpurple/protocols/oscar/family_feedbag.c
  • +0 -1
    libpurple/protocols/zephyr/Zinternal.c
  • +13 -13
    libpurple/protocols/zephyr/zephyr.c
  • +1 -0
    libpurple/tests/Makefile.am
  • +1 -0
    libpurple/tests/check_libpurple.c
  • +59 -0
    libpurple/tests/test_jabber_digest_md5.c
  • +1 -0
    libpurple/tests/tests.h
  • +135 -64
    pidgin/gtkutils.c
  • +6 -20
    pidgin/plugins/vvconfig.c
  • +1 -0
    pidgin/win32/nsis/pidgin-installer.nsi
  • +3 -3
    pidgin/win32/winpidgin.c
  • +2 -2
    po/POTFILES.in
  • +27 -29
    po/ar.po
  • +1 -1
    po/az.po
  • +115 -98
    po/ca.po
  • +55 -56
    po/de.po
  • +1 -1
    po/el.po
  • +1 -1
    po/en_AU.po
  • +1 -1
    po/en_GB.po
  • +1 -1
    po/eu.po
  • +132 -116
    po/fr.po
  • +1 -1
    po/gl.po
  • +44 -36
    po/hu.po
  • +1 -2
    po/hy.po
  • +1 -1
    po/mn.po
  • +1 -1
    po/ms_MY.po
  • +1 -1
    po/ta.po
  • +25 -0
    share/ca-certs/AddTrust_External_Root.pem
  • +1 -0
    share/ca-certs/Makefile.am
  • --- a/COPYRIGHT Sun Jan 09 23:32:10 2011 +0000
    +++ b/COPYRIGHT Wed Feb 02 23:26:42 2011 +0000
    @@ -81,6 +81,7 @@
    Norbert Buchmuller
    Johannes Buchner
    Sean Burke
    +Gabriel Burt
    Thomas Butter
    Trevor Caira
    Andrea Canciani
    @@ -131,6 +132,7 @@
    Florian Delizy
    Jiri Denemark
    Vinicius Depizzol
    +Marc Dequènes
    Philip Derrin
    Taso N. Devetzis
    Balwinder Singh Dheeman
    @@ -377,6 +379,7 @@
    Riley Patterson
    Havoc Pennington
    Ted Percival
    +Hugo Pereira Da Costa
    Eduardo Pérez
    Matt Perry
    Ani Peter
    @@ -580,6 +583,7 @@
    Timmy Yee
    Li Yuan
    Yuriy Yevgrafov
    +Jan Zachorowski
    Nickolai Zeldovich
    Tom Zickel
    Marco Ziech
    --- a/ChangeLog Sun Jan 09 23:32:10 2011 +0000
    +++ b/ChangeLog Wed Feb 02 23:26:42 2011 +0000
    @@ -6,9 +6,20 @@
    number of times video must be scaled down, saving CPU time. (Jakub Adam)
    (half of #13095)
    * Starting multiple video calls and ending one no longer causes the other
    - calls to stop sending audio and video. (Jakub Adam) (#12758)
    + calls to stop sending audio and video. (Jakub Adam) (#12758, #13237)
    * Perl bindings now respect LDFLAGS. (Peter Volkov, Markos Chandras)
    (#12638)
    + * Added AddTrust External Root CA. (#11554)
    + * Resolve some issues validating X.509 certificates signed off the CAcert
    + Class 3 intermediate cert when using the GnuTLS SSL/TLS plugin.
    +
    + Gadu-Gadu:
    + * Don't drop whole messages when text is colored. (Jan Zachorowski)
    + (#13259)
    +
    + Groupwise:
    + * Don't show two windows when using "Get Info" on a buddy. (Gabriel Burt;
    + Novell, Inc.) (#13108)
    IRC:
    * Don't send ISON messages longer than 512 bytes. (Jeffrey Honig) (#9692)
    @@ -27,10 +38,15 @@
    the conversation window. (Ryan Flegel) (#13127)
    * Fix a few memory leaks. (Nader Morshed) (#13162)
    * Support rendering strikethrough when received as in-line CSS. (#13168)
    + * Editable comboboxes are now more friendly to some GTK+ themes. (Hugo
    + Pereira Da Costa) (#13164).
    Plugins:
    * The Voice/Video Settings plugin no longer resets selected devices to
    defaults. (Jakub Adam) (#13044)
    + * The Voice/Video Settings plugin no longer crashes when a stored device
    + name is not found in the list of available devices. (Jakub Adam)
    + (#13238)
    * The Autoaccept plugin now allows disabling filename escaping. (Rok
    Mandeljc) (half of #11459)
    * The Autoaccept plugin now allows choosing Reject/Ask/Accept for
    @@ -42,6 +58,10 @@
    XMPP:
    * Don't crash when receiving an unexpected/invalid jingle transport type.
    (Nikita Kozlov) (#13136)
    + * Handle Connection: Close headers for BOSH, when the server does not
    + terminate the connection itself. (#13008)
    + * Improved parsing for DIGEST-MD5, which should resolve issues
    + connecting to some jabberd2 servers. (#a14514)
    Yahoo!/Yahoo! JAPAN:
    * Fix a crash when an account disconnects before a p2p session is
    @@ -927,7 +947,7 @@
    from you on MSN.
    * Support sending an invite message to buddies when requesting
    authorization from them on MSN.
    - * Timeout switchboard connections aggressively (60 seconds).
    + * Timeout switchboard connections after 60 seconds (msn-pecan devs).
    XMPP:
    * Voice & Video support with Jingle (XEP-0166, 0167, 0176, & 0177),
    --- a/configure.ac Sun Jan 09 23:32:10 2011 +0000
    +++ b/configure.ac Wed Feb 02 23:26:42 2011 +0000
    @@ -329,7 +329,7 @@
    dnl #######################################################################
    dnl # Check for GLib 2.12 (required)
    dnl #######################################################################
    -PKG_CHECK_MODULES(GLIB, [glib-2.0 >= 2.12.0 gio-2.0 gobject-2.0 gmodule-2.0 gthread-2.0], , [
    +PKG_CHECK_MODULES(GLIB, [glib-2.0 >= 2.12.0 gobject-2.0 gmodule-2.0 gthread-2.0], , [
    AC_MSG_RESULT(no)
    AC_MSG_ERROR([
    --- a/libpurple/certificate.c Sun Jan 09 23:32:10 2011 +0000
    +++ b/libpurple/certificate.c Wed Feb 02 23:26:42 2011 +0000
    @@ -1602,7 +1602,7 @@
    GSList *ca_crts, *cur;
    GByteArray *last_fpr, *ca_fpr;
    gboolean valid = FALSE;
    - gchar *ca_id;
    + gchar *ca_id, *ca2_id;
    peer_crt = (PurpleCertificate *) chain->data;
    @@ -1619,7 +1619,6 @@
    return;
    } /* if (self signed) */
    - /* Next, attempt to verify the last certificate against a CA */
    ca = purple_certificate_find_pool(x509_tls_cached.scheme_name, "ca");
    /* Next, check that the certificate chain is valid */
    @@ -1669,6 +1668,9 @@
    return;
    } /* if (signature chain not good) */
    + /* Next, attempt to verify the last certificate is signed by a trusted
    + * CA, or is a trusted CA (based on fingerprint).
    + */
    /* If, for whatever reason, there is no Certificate Authority pool
    loaded, we'll verify the subject name and then warn about thsi. */
    if ( !ca ) {
    @@ -1684,27 +1686,31 @@
    end_crt = g_list_last(chain)->data;
    - /* Attempt to look up the last certificate's issuer */
    - ca_id = purple_certificate_get_issuer_unique_id(end_crt);
    + /* Attempt to look up the last certificate, and the last certificate's
    + * issuer.
    + */
    + ca_id = purple_certificate_get_issuer_unique_id(end_crt);
    + ca2_id = purple_certificate_get_unique_id(end_crt);
    purple_debug_info("certificate/x509/tls_cached",
    "Checking for a CA with DN=%s\n",
    ca_id);
    - ca_crts = x509_ca_get_certs(ca_id);
    + purple_debug_info("certificate/x509/tls_cached",
    + "Also checking for a CA with DN=%s\n",
    + ca2_id);
    + ca_crts = g_slist_concat(x509_ca_get_certs(ca_id), x509_ca_get_certs(ca2_id));
    + g_free(ca_id);
    + g_free(ca2_id);
    if ( NULL == ca_crts ) {
    flags |= PURPLE_CERTIFICATE_CA_UNKNOWN;
    purple_debug_warning("certificate/x509/tls_cached",
    - "Certificate Authority with DN='%s' not "
    - "found. I'll prompt the user, I guess.\n",
    - ca_id);
    - g_free(ca_id);
    + "No Certificate Authorities with either DN found "
    + "found. I'll prompt the user, I guess.\n");
    x509_tls_cached_check_subject_name(vrq, flags);
    return;
    }
    - g_free(ca_id);
    -
    /*
    * Check the fingerprints; if they match, then this certificate *is* one
    * of the designated "trusted roots", and we don't need to verify the
    @@ -1714,10 +1720,6 @@
    *
    * If the fingerprints don't match, we'll fall back to checking the
    * signature.
    - *
    - * GnuTLS doesn't seem to include the final root in the verification
    - * list, so this check will never succeed. NSS *does* include it in
    - * the list, so here we are.
    */
    last_fpr = purple_certificate_get_fingerprint_sha1(end_crt);
    for (cur = ca_crts; cur; cur = cur->next) {
    --- a/libpurple/media/backend-fs2.c Sun Jan 09 23:32:10 2011 +0000
    +++ b/libpurple/media/backend-fs2.c Wed Feb 02 23:26:42 2011 +0000
    @@ -155,6 +155,44 @@
    {
    }
    +static gboolean
    +event_probe_cb(GstPad *srcpad, GstEvent *event, gboolean release_pad)
    +{
    + if (GST_EVENT_TYPE(event) == GST_EVENT_CUSTOM_DOWNSTREAM
    + && gst_event_has_name(event, "purple-unlink-tee")) {
    +
    + const GstStructure *s = gst_event_get_structure(event);
    +
    + gst_pad_unlink(srcpad, gst_pad_get_peer(srcpad));
    +
    + gst_pad_remove_event_probe(srcpad,
    + g_value_get_uint(gst_structure_get_value(s, "handler-id")));
    +
    + if (g_value_get_boolean(gst_structure_get_value(s, "release-pad")))
    + gst_element_release_request_pad(GST_ELEMENT_PARENT(srcpad), srcpad);
    +
    + return FALSE;
    + }
    +
    + return TRUE;
    +}
    +
    +static void
    +unlink_teepad_dynamic(GstPad *srcpad, gboolean release_pad)
    +{
    + guint id = gst_pad_add_event_probe(srcpad, G_CALLBACK(event_probe_cb), NULL);
    +
    + if (GST_IS_GHOST_PAD(srcpad))
    + srcpad = gst_ghost_pad_get_target(GST_GHOST_PAD(srcpad));
    +
    + gst_element_send_event(gst_pad_get_parent_element(srcpad),
    + gst_event_new_custom(GST_EVENT_CUSTOM_DOWNSTREAM,
    + gst_structure_new("purple-unlink-tee",
    + "release-pad", G_TYPE_BOOLEAN, release_pad,
    + "handler-id", G_TYPE_UINT, id,
    + NULL)));
    +}
    +
    static void
    purple_media_backend_fs2_dispose(GObject *obj)
    {
    @@ -179,7 +217,7 @@
    g_list_delete_link(sessions, sessions)) {
    PurpleMediaBackendFs2Session *session = sessions->data;
    if (session->srcpad) {
    - gst_pad_set_blocked(session->srcpad, TRUE);
    + unlink_teepad_dynamic(session->srcpad, FALSE);
    gst_object_unref(session->srcpad);
    session->srcpad = NULL;
    }
    --- a/libpurple/mediamanager.c Sun Jan 09 23:32:10 2011 +0000
    +++ b/libpurple/mediamanager.c Wed Feb 02 23:26:42 2011 +0000
    @@ -400,7 +400,6 @@
    GstIteratorResult result;
    gst_element_release_request_pad(GST_ELEMENT_PARENT(pad), pad);
    - gst_pad_set_blocked(pad, FALSE);
    iter = gst_element_iterate_src_pads(parent);
    --- a/libpurple/protocols/gg/gg.c Sun Jan 09 23:32:10 2011 +0000
    +++ b/libpurple/protocols/gg/gg.c Wed Feb 02 23:26:42 2011 +0000
    @@ -1464,6 +1464,10 @@
    increased_len += 4;
    under = FALSE;
    }
    +
    + if (actformat->font & GG_FONT_COLOR) {
    + cformats += sizeof(struct gg_msg_richtext_color);
    + }
    }
    msg = message->str;
    --- a/libpurple/protocols/jabber/Makefile.am Sun Jan 09 23:32:10 2011 +0000
    +++ b/libpurple/protocols/jabber/Makefile.am Wed Feb 02 23:26:42 2011 +0000
    @@ -11,6 +11,7 @@
    auth.c \
    auth.h \
    auth_digest_md5.c \
    + auth_digest_md5.h \
    auth_plain.c \
    auth_scram.c \
    auth_scram.h \
    --- a/libpurple/protocols/jabber/auth_cyrus.c Sun Jan 09 23:32:10 2011 +0000
    +++ b/libpurple/protocols/jabber/auth_cyrus.c Wed Feb 02 23:26:42 2011 +0000
    @@ -520,9 +520,12 @@
    g_free(dec_in);
    if (js->sasl_state != SASL_OK) {
    - /* This should never happen! */
    + /* This happens when the server sends back jibberish
    + * in the "additional data with success" case.
    + * Seen with Wildfire 3.0.1.
    + */
    *error = g_strdup(_("Invalid response from server"));
    - g_return_val_if_reached(JABBER_SASL_STATE_FAIL);
    + return JABBER_SASL_STATE_FAIL;
    }
    }
    --- a/libpurple/protocols/jabber/auth_digest_md5.c Sun Jan 09 23:32:10 2011 +0000
    +++ b/libpurple/protocols/jabber/auth_digest_md5.c Wed Feb 02 23:26:42 2011 +0000
    @@ -27,6 +27,7 @@
    #include "util.h"
    #include "xmlnode.h"
    +#include "auth_digest_md5.h"
    #include "auth.h"
    #include "jabber.h"
    @@ -43,7 +44,7 @@
    }
    /* Parts of this algorithm are inspired by stuff in libgsasl */
    -static GHashTable* parse_challenge(const char *challenge)
    +GHashTable* jabber_auth_digest_md5_parse(const char *challenge)
    {
    const char *token_start, *val_start, *val_end, *cur;
    GHashTable *ret = g_hash_table_new_full(g_str_hash, g_str_equal,
    @@ -77,12 +78,12 @@
    val_start++;
    val_end = cur;
    - while (val_end != val_start && (*val_end == ' ' || *val_end == ',' || *val_end == '\t'
    + while (val_end >= val_start && (*val_end == ' ' || *val_end == ',' || *val_end == '\t'
    || *val_end == '\r' || *val_end == '\n'
    || *val_end == '"' || *val_end == '\0'))
    val_end--;
    - if (val_start != val_end)
    + if (val_end - val_start + 1 >= 0)
    value = g_strndup(val_start, val_end - val_start + 1);
    }
    @@ -186,7 +187,7 @@
    dec_in != NULL ? strlen(dec_in) : 0,
    dec_in != NULL ? dec_in : "(null)");
    - parts = parse_challenge(dec_in);
    + parts = jabber_auth_digest_md5_parse(dec_in);
    if (g_hash_table_lookup(parts, "rspauth")) {
    char *rspauth = g_hash_table_lookup(parts, "rspauth");
    --- /dev/null Thu Jan 01 00:00:00 1970 +0000
    +++ b/libpurple/protocols/jabber/auth_digest_md5.h Wed Feb 02 23:26:42 2011 +0000
    @@ -0,0 +1,39 @@
    +/**
    + * @file auth_digest_md5.h Implementation of SASL DIGEST-MD5 authentication
    + *
    + * purple
    + *
    + * Purple is the legal property of its developers, whose names are too numerous
    + * to list here. Please refer to the COPYRIGHT file distributed with this
    + * source distribution.
    + *
    + * This program is free software; you can redistribute it and/or modify
    + * it under the terms of the GNU General Public License as published by
    + * the Free Software Foundation; either version 2 of the License, or
    + * (at your option) any later version.
    + *
    + * This program is distributed in the hope that it will be useful,
    + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    + * GNU General Public License for more details.
    + *
    + * You should have received a copy of the GNU General Public License
    + * along with this program; if not, write to the Free Software
    + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
    + */
    +#ifndef PURPLE_JABBER_AUTH_DIGEST_MD5_H_
    +#define PURPLE_JABBER_AUTH_DIGEST_MD5_H_
    +
    +#include "internal.h"
    +
    +/*
    + * Every function in this file is ONLY exposed for tests.
    + * DO NOT USE ANYTHING HERE OR YOU WILL BE SENT TO THE PIT OF DESPAIR.
    + */
    +
    +/*
    + * Parse a DIGEST-MD5 challenge.
    + */
    +GHashTable *jabber_auth_digest_md5_parse(const char *challenge);
    +
    +#endif /* PURPLE_JABBER_AUTH_DIGEST_MD5_H_ */
    --- a/libpurple/protocols/jabber/bosh.c Sun Jan 09 23:32:10 2011 +0000
    +++ b/libpurple/protocols/jabber/bosh.c Wed Feb 02 23:26:42 2011 +0000
    @@ -108,8 +108,27 @@
    int requests; /* number of outstanding HTTP requests */
    gboolean headers_done;
    + gboolean close;
    +};
    -};
    +static void
    +debug_dump_http_connections(PurpleBOSHConnection *conn)
    +{
    + int i;
    +
    + g_return_if_fail(conn != NULL);
    +
    + for (i = 0; i < NUM_HTTP_CONNECTIONS; ++i) {
    + PurpleHTTPConnection *httpconn = conn->connections[i];
    + if (httpconn == NULL)
    + purple_debug_misc("jabber", "BOSH %p->connections[%d] = (nil)\n",
    + conn, i);
    + else
    + purple_debug_misc("jabber", "BOSH %p->connections[%d] = %p, state = %d"
    + ", requests = %d\n", conn, i, httpconn,
    + httpconn->state, httpconn->requests);
    + }
    +}
    static void http_connection_connect(PurpleHTTPConnection *conn);
    static void http_connection_send_request(PurpleHTTPConnection *conn,
    @@ -263,18 +282,8 @@
    {
    int i;
    - if (purple_debug_is_verbose()) {
    - for (i = 0; i < NUM_HTTP_CONNECTIONS; ++i) {
    - PurpleHTTPConnection *httpconn = conn->connections[i];
    - if (httpconn == NULL)
    - purple_debug_misc("jabber", "BOSH %p->connections[%d] = (nil)\n",
    - conn, i);
    - else
    - purple_debug_misc("jabber", "BOSH %p->connections[%d] = %p, state = %d"
    - ", requests = %d\n", conn, i, httpconn,
    - httpconn->state, httpconn->requests);
    - }
    - }
    + if (purple_debug_is_verbose())
    + debug_dump_http_connections(conn);
    /* Easy solution: Does everyone involved support pipelining? Hooray! Just use
    * one TCP connection! */
    @@ -297,11 +306,23 @@
    return NULL;
    }
    - /* Third loop, look for one that's NULL and create a new connection */
    + /* Third loop, is something offline that we can connect? */
    + for (i = 0; i < NUM_HTTP_CONNECTIONS; ++i) {
    + if (conn->connections[i] &&
    + conn->connections[i]->state == HTTP_CONN_OFFLINE) {
    + purple_debug_info("jabber", "bosh: Reconnecting httpconn "
    + "(%i, %p)\n", i, conn->connections[i]);
    + http_connection_connect(conn->connections[i]);
    + return NULL;
    + }
    + }
    +
    + /* Fourth loop, look for one that's NULL and create a new connection */
    for (i = 0; i < NUM_HTTP_CONNECTIONS; ++i) {
    if (!conn->connections[i]) {
    - purple_debug_info("jabber", "bosh: Creating and connecting new httpconn\n");
    conn->connections[i] = jabber_bosh_http_connection_init(conn);
    + purple_debug_info("jabber", "bosh: Creating and connecting new httpconn "
    + "(%i, %p)\n", i, conn->connections[i]);
    http_connection_connect(conn->connections[i]);
    return NULL;
    @@ -344,6 +365,8 @@
    chosen = find_available_http_connection(conn);
    if (!chosen) {
    + if (type == PACKET_FLUSH)
    + return;
    /*
    * For non-ordinary traffic, we can't 'buffer' it, so use the
    * first connection.
    @@ -444,6 +467,27 @@
    send_timer_cb(bosh);
    }
    +static void
    +jabber_bosh_disable_pipelining(PurpleBOSHConnection *bosh)
    +{
    + /* Do nothing if it's already disabled */
    + if (!bosh->pipelining)
    + return;
    +
    + purple_debug_info("jabber", "BOSH: Disabling pipelining on conn %p\n",
    + bosh);
    + bosh->pipelining = FALSE;
    + if (bosh->connections[1] == NULL) {
    + bosh->connections[1] = jabber_bosh_http_connection_init(bosh);
    + http_connection_connect(bosh->connections[1]);
    + } else {
    + /* Shouldn't happen; this should be the only place pipelining
    + * is turned off.
    + */
    + g_warn_if_reached();
    + }
    +}
    +
    static void jabber_bosh_connection_received(PurpleBOSHConnection *conn, xmlnode *node) {
    xmlnode *child;
    JabberStream *js = conn->js;
    @@ -611,6 +655,8 @@
    static void
    connection_common_established_cb(PurpleHTTPConnection *conn)
    {
    + purple_debug_misc("jabber", "bosh: httpconn %p re-connected\n", conn);
    +
    /* Indicate we're ready and reset some variables */
    conn->state = HTTP_CONN_CONNECTED;
    if (conn->requests != 0)
    @@ -622,9 +668,13 @@
    g_string_free(conn->read_buf, TRUE);
    conn->read_buf = NULL;
    }
    + conn->close = FALSE;
    conn->headers_done = FALSE;
    conn->handled_len = conn->body_len = 0;
    + if (purple_debug_is_verbose())
    + debug_dump_http_connections(conn->bosh);
    +
    if (conn->bosh->js->reinit)
    jabber_bosh_connection_send(conn->bosh, PACKET_NORMAL, NULL);
    else if (conn->bosh->state == BOSH_CONN_ONLINE) {
    @@ -639,6 +689,7 @@
    static void http_connection_disconnected(PurpleHTTPConnection *conn)
    {
    + gboolean had_requests = FALSE;
    /*
    * Well, then. Fine! I never liked you anyway, server! I was cheating on you
    * with AIM!
    @@ -662,7 +713,8 @@
    conn->writeh = 0;
    }
    - if (conn->requests > 0 && conn->read_buf->len == 0) {
    + had_requests = (conn->requests > 0);
    + if (had_requests && conn->read_buf->len == 0) {
    purple_debug_error("jabber", "bosh: Adjusting BOSHconn requests (%d) to %d\n",
    conn->bosh->requests, conn->bosh->requests - conn->requests);
    conn->bosh->requests -= conn->requests;
    @@ -671,13 +723,15 @@
    if (conn->bosh->pipelining) {
    /* Hmmmm, fall back to multiple connections */
    - conn->bosh->pipelining = FALSE;
    - if (conn->bosh->connections[1] == NULL) {
    - conn->bosh->connections[1] = jabber_bosh_http_connection_init(conn->bosh);
    - http_connection_connect(conn->bosh->connections[1]);
    - }
    + jabber_bosh_disable_pipelining(conn->bosh);
    }
    + if (!had_requests)
    + /* If the server disconnected us without any requests, let's
    + * just wait until we have something to send before we reconnect
    + */
    + return;
    +
    if (++conn->bosh->failed_connections == MAX_FAILED_CONNECTIONS) {
    purple_connection_error_reason(conn->bosh->js->gc,
    PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
    @@ -704,30 +758,49 @@
    cursor = conn->read_buf->str + conn->handled_len;
    + if (purple_debug_is_verbose())
    + purple_debug_misc("jabber", "BOSH server sent: %s\n", cursor);
    +
    + /* TODO: Chunked encoding and check response version :/ */
    if (!conn->headers_done) {
    - const char *content_length = purple_strcasestr(cursor, "\r\nContent-Length");
    + const char *content_length = purple_strcasestr(cursor, "\r\nContent-Length:");
    + const char *connection = purple_strcasestr(cursor, "\r\nConnection:");
    const char *end_of_headers = strstr(cursor, "\r\n\r\n");
    /* Make sure Content-Length is in headers, not body */
    if (content_length && (!end_of_headers || content_length < end_of_headers)) {
    - const char *sep;
    int len;
    - if ((sep = strstr(content_length, ": ")) == NULL ||
    - strstr(sep, "\r\n") == NULL)
    + if (strstr(content_length, "\r\n") == NULL)
    /*
    * The packet ends in the middle of the Content-Length line.
    * We'll try again later when we have more.
    */
    return;
    - len = atoi(sep + 2);
    + len = atoi(content_length + strlen("\r\nContent-Length:"));
    if (len == 0)
    - purple_debug_warning("jabber", "Found mangled Content-Length header.\n");
    + purple_debug_warning("jabber", "Found mangled Content-Length header, or server returned 0-length response.\n");
    conn->body_len = len;
    }
    + if (connection && (!end_of_headers || content_length < end_of_headers)) {
    + const char *tmp;
    + if (strstr(connection, "\r\n") == NULL)
    + return;
    +
    +
    + tmp = connection + strlen("\r\nConnection:");
    + while (*tmp && (*tmp == ' ' || *tmp == '\t'))
    + ++tmp;
    +
    + if (!g_ascii_strncasecmp(tmp, "close", strlen("close"))) {
    + conn->close = TRUE;
    + jabber_bosh_disable_pipelining(conn->bosh);
    + }
    + }
    +
    if (end_of_headers) {
    conn->headers_done = TRUE;
    conn->handled_len = end_of_headers - conn->read_buf->str + 4;
    @@ -752,6 +825,14 @@
    http_received_cb(conn->read_buf->str + conn->handled_len, conn->body_len,
    conn->bosh);
    + /* Connection: Close? */
    + if (conn->close && conn->state == HTTP_CONN_CONNECTED) {
    + if (purple_debug_is_verbose())
    + purple_debug_misc("jabber", "bosh (%p), server sent Connection: "
    + "close\n", conn);
    + http_connection_disconnected(conn);
    + }
    +
    if (conn->bosh->state == BOSH_CONN_ONLINE &&
    (conn->bosh->requests == 0 || conn->bosh->pending->bufused > 0)) {
    purple_debug_misc("jabber", "BOSH: Sending an empty request\n");
    @@ -791,10 +872,11 @@
    if (cnt == 0 || (cnt < 0 && errno != EAGAIN)) {
    if (cnt < 0)
    - purple_debug_info("jabber", "bosh read=%d, errno=%d, error=%s\n",
    - cnt, errno, g_strerror(errno));
    + purple_debug_info("jabber", "BOSH (%p) read=%d, errno=%d, error=%s\n",
    + conn, cnt, errno, g_strerror(errno));
    else
    - purple_debug_info("jabber", "bosh server closed the connection\n");
    + purple_debug_info("jabber", "BOSH server closed the connection (%p)\n",
    + conn);
    /*
    * If the socket is closed, the processing really needs to know about
    @@ -911,6 +993,9 @@
    else
    ret = write(conn->fd, data, len);
    + if (purple_debug_is_verbose())
    + purple_debug_misc("jabber", "BOSH (%p): wrote %d bytes\n", conn, ret);
    +
    return ret;
    }
    @@ -975,7 +1060,10 @@
    if (purple_debug_is_unsafe() && purple_debug_is_verbose())
    /* Will contain passwords for SASL PLAIN and is verbose */
    - purple_debug_misc("jabber", "BOSH: Sending %s\n", data);
    + purple_debug_misc("jabber", "BOSH (%p): Sending %s\n", conn, data);
    + else if (purple_debug_is_verbose())
    + purple_debug_misc("jabber", "BOSH (%p): Sending request of "
    + "%" G_GSIZE_FORMAT " bytes.\n", conn, len);
    if (conn->writeh == 0)
    ret = http_connection_do_send(conn, data, len);
    --- a/libpurple/protocols/msn/error.c Sun Jan 09 23:32:10 2011 +0000
    +++ b/libpurple/protocols/msn/error.c Wed Feb 02 23:26:42 2011 +0000
    @@ -31,7 +31,7 @@
    typedef struct
    {
    - PurpleConnection *gc;
    + MsnSession *session;
    char *who;
    char *group;
    gboolean add;
    @@ -293,9 +293,9 @@
    group = purple_find_group(data->group);
    if (group != NULL)
    - buddy = purple_find_buddy_in_group(purple_connection_get_account(data->gc), data->who, group);
    + buddy = purple_find_buddy_in_group(data->session->account, data->who, group);
    else
    - buddy = purple_find_buddy(purple_connection_get_account(data->gc), data->who);
    + buddy = purple_find_buddy(data->session->account, data->who);
    if (buddy != NULL)
    purple_blist_remove_buddy(buddy);
    @@ -309,14 +309,9 @@
    /* this *should* be necessary !! */
    msn_complete_sync_issue(data);
    #endif
    + MsnUserList *userlist = data->session->userlist;
    - if (g_list_find(purple_connections_get_all(), data->gc) != NULL)
    - {
    - MsnSession *session = data->gc->proto_data;
    - MsnUserList *userlist = session->userlist;
    -
    - msn_userlist_add_buddy(userlist, data->who, data->group);
    - }
    + msn_userlist_add_buddy(userlist, data->who, data->group);
    g_free(data->group);
    g_free(data->who);
    @@ -326,18 +321,14 @@
    static void
    msn_rem_cb(MsnAddRemData *data)
    {
    + MsnUserList *userlist = data->session->userlist;
    msn_complete_sync_issue(data);
    - if (g_list_find(purple_connections_get_all(), data->gc) != NULL)
    - {
    - MsnSession *session = data->gc->proto_data;
    - MsnUserList *userlist = session->userlist;
    - if (data->group == NULL) {
    - msn_userlist_rem_buddy_from_list(userlist, data->who, MSN_LIST_FL);
    - } else {
    - g_free(data->group);
    - }
    + if (data->group == NULL) {
    + msn_userlist_rem_buddy_from_list(userlist, data->who, MSN_LIST_FL);
    + } else {
    + g_free(data->group);
    }
    g_free(data->who);
    @@ -356,10 +347,10 @@
    account = session->account;
    gc = purple_account_get_connection(account);
    - data = g_new0(MsnAddRemData, 1);
    - data->who = g_strdup(passport);
    - data->group = g_strdup(group_name);
    - data->gc = gc;
    + data = g_new0(MsnAddRemData, 1);
    + data->who = g_strdup(passport);
    + data->group = g_strdup(group_name);
    + data->session = session;
    msg = g_strdup_printf(_("Buddy list synchronization issue in %s (%s)"),
    purple_account_get_username(account),
    @@ -382,7 +373,7 @@
    }
    purple_request_action(gc, NULL, msg, reason, PURPLE_DEFAULT_ACTION_NONE,
    - purple_connection_get_account(gc), data->who, NULL,
    + account, data->who, NULL,
    data, 2,
    _("Yes"), G_CALLBACK(msn_add_cb),
    _("No"), G_CALLBACK(msn_rem_cb));
    @@ -390,3 +381,4 @@
    g_free(reason);
    g_free(msg);
    }
    +
    --- a/libpurple/protocols/msn/msg.c Sun Jan 09 23:32:10 2011 +0000
    +++ b/libpurple/protocols/msn/msg.c Wed Feb 02 23:26:42 2011 +0000
    @@ -613,15 +613,7 @@
    if (msg->msnslp_message)
    {
    - g_string_append_printf(str, "Session ID: %u\r\n", msg->part->header->session_id);
    - g_string_append_printf(str, "ID: %u\r\n", msg->part->header->id);
    - g_string_append_printf(str, "Offset: %" G_GUINT64_FORMAT "\r\n", msg->part->header->offset);
    - g_string_append_printf(str, "Total size: %" G_GUINT64_FORMAT "\r\n", msg->part->header->total_size);
    - g_string_append_printf(str, "Length: %u\r\n", msg->part->header->length);
    - g_string_append_printf(str, "Flags: 0x%x\r\n", msg->part->header->flags);
    - g_string_append_printf(str, "ACK ID: %u\r\n", msg->part->header->ack_id);
    - g_string_append_printf(str, "SUB ID: %u\r\n", msg->part->header->ack_sub_id);
    - g_string_append_printf(str, "ACK Size: %" G_GUINT64_FORMAT "\r\n", msg->part->header->ack_size);
    + msn_slpmsgpart_to_string(msg->part, str);
    if (purple_debug_is_verbose() && body != NULL)
    {
    @@ -638,27 +630,17 @@
    else
    {
    int i;
    - int bin_len;
    - if (msg->part->footer->value == P2P_APPID_SESSION)
    - bin_len = P2P_PACKET_HEADER_SIZE;
    - else
    - bin_len = body_len;
    -
    - for (i = 0; i < bin_len; i++)
    + for (i = 0; i < body_len; i++)
    {
    g_string_append_printf(str, "%.2hhX ", body[i]);
    if ((i % 16) == 15)
    g_string_append(str, "\r\n");
    }
    - if (bin_len == P2P_PACKET_HEADER_SIZE)
    - g_string_append_printf(str, "%s ", body + P2P_PACKET_HEADER_SIZE);
    g_string_append(str, "\r\n");
    }
    }
    -
    - g_string_append_printf(str, "Footer: 0x%08X\r\n", msg->part->footer->value);
    }
    else
    {
    --- a/libpurple/protocols/msn/msg.h Sun Jan 09 23:32:10 2011 +0000
    +++ b/libpurple/protocols/msn/msg.h Wed Feb 02 23:26:42 2011 +0000
    @@ -79,7 +79,6 @@
    MsnMsgType type;
    gboolean msnslp_message;
    - MsnSlpMessage *slpmsg;
    MsnSlpMessagePart *part;
    char *remote_user;
    @@ -99,7 +98,6 @@
    been ref'ed for using it in a callback. */
    MsnCommand *cmd;
    - MsnTransaction *trans;
    MsnMsgCb ack_cb; /**< The callback to call when we receive an ACK of this
    message. */
    @@ -107,8 +105,6 @@
    message. */
    void *ack_data; /**< The data used by callbacks. */
    - MsnMsgErrorType error; /**< The error of the message. */
    -
    guint32 retries;
    };
    --- a/libpurple/protocols/msn/p2p.c Sun Jan 09 23:32:10 2011 +0000
    +++ b/libpurple/protocols/msn/p2p.c Wed Feb 02 23:26:42 2011 +0000
    @@ -27,12 +27,32 @@
    #include "p2p.h"
    #include "msnutils.h"
    -MsnP2PHeader *
    -msn_p2p_header_from_wire(const char *wire)
    +MsnP2PInfo *
    +msn_p2p_info_new(void)
    +{
    + return g_new0(MsnP2PInfo, 1);
    +}
    +
    +MsnP2PInfo *
    +msn_p2p_info_dup(MsnP2PInfo *info)
    +{
    + MsnP2PInfo *new_info = g_new0(MsnP2PInfo, 1);
    + *new_info = *info;
    + return new_info;
    +}
    +
    +void
    +msn_p2p_info_free(MsnP2PInfo *info)
    +{
    + g_free(info);
    +}
    +
    +size_t
    +msn_p2p_header_from_wire(MsnP2PInfo *info, const char *wire)
    {
    MsnP2PHeader *header;
    - header = g_new(MsnP2PHeader, 1);
    + header = &info->header;
    header->session_id = msn_pop32le(wire);
    header->id = msn_pop32le(wire);
    @@ -44,15 +64,17 @@
    header->ack_sub_id = msn_pop32le(wire);
    header->ack_size = msn_pop64le(wire);
    - return header;
    + return P2P_PACKET_HEADER_SIZE;
    }
    char *
    -msn_p2p_header_to_wire(MsnP2PHeader *header)
    +msn_p2p_header_to_wire(MsnP2PInfo *info, size_t *len)
    {
    + MsnP2PHeader *header;
    char *wire;
    char *tmp;
    + header = &info->header;
    tmp = wire = g_new(char, P2P_PACKET_HEADER_SIZE);
    msn_push32le(tmp, header->session_id);
    @@ -65,35 +87,58 @@
    msn_push32le(tmp, header->ack_sub_id);
    msn_push64le(tmp, header->ack_size);
    + if (len)
    + *len = P2P_PACKET_HEADER_SIZE;
    +
    return wire;
    }
    -MsnP2PFooter *
    -msn_p2p_footer_from_wire(const char *wire)
    +size_t
    +msn_p2p_footer_from_wire(MsnP2PInfo *info, const char *wire)
    {
    MsnP2PFooter *footer;
    - footer = g_new(MsnP2PFooter, 1);
    + footer = &info->footer;
    footer->value = msn_pop32be(wire);
    - return footer;
    + return P2P_PACKET_FOOTER_SIZE;
    }
    char *
    -msn_p2p_footer_to_wire(MsnP2PFooter *footer)
    +msn_p2p_footer_to_wire(MsnP2PInfo *info, size_t *len)
    {
    + MsnP2PFooter *footer;
    char *wire;
    char *tmp;
    + footer = &info->footer;
    tmp = wire = g_new(char, P2P_PACKET_FOOTER_SIZE);
    msn_push32be(tmp, footer->value);
    + if (len)
    + *len = P2P_PACKET_FOOTER_SIZE;
    +
    return wire;
    }
    +void
    +msn_p2p_info_to_string(MsnP2PInfo *info, GString *str)
    +{
    + g_string_append_printf(str, "Session ID: %u\r\n", info->header.session_id);
    + g_string_append_printf(str, "ID: %u\r\n", info->header.id);
    + g_string_append_printf(str, "Offset: %" G_GUINT64_FORMAT "\r\n", info->header.offset);
    + g_string_append_printf(str, "Total size: %" G_GUINT64_FORMAT "\r\n", info->header.total_size);
    + g_string_append_printf(str, "Length: %u\r\n", info->header.length);
    + g_string_append_printf(str, "Flags: 0x%x\r\n", info->header.flags);
    + g_string_append_printf(str, "ACK ID: %u\r\n", info->header.ack_id);
    + g_string_append_printf(str, "SUB ID: %u\r\n", info->header.ack_sub_id);
    + g_string_append_printf(str, "ACK Size: %" G_GUINT64_FORMAT "\r\n", info->header.ack_size);
    + g_string_append_printf(str, "Footer: 0x%08X\r\n", info->footer.value);
    +}
    +
    gboolean
    msn_p2p_msg_is_data(const MsnP2PHeaderFlag flags)
    {
    @@ -102,3 +147,135 @@
    flags == P2P_FILE_DATA);
    }
    +gboolean
    +msn_p2p_info_is_valid(MsnP2PInfo *info)
    +{
    + return info->header.total_size >= info->header.length;
    +}
    +
    +gboolean
    +msn_p2p_info_is_final(MsnP2PInfo *info)
    +{
    + return info->header.offset + info->header.length >= info->header.total_size;
    +}
    +
    +guint32
    +msn_p2p_info_get_session_id(MsnP2PInfo *info)
    +{
    + return info->header.session_id;
    +}
    +
    +guint32
    +msn_p2p_info_get_id(MsnP2PInfo *info)
    +{
    + return info->header.id;
    +}
    +
    +guint64
    +msn_p2p_info_get_offset(MsnP2PInfo *info)
    +{
    + return info->header.offset;
    +}
    +
    +guint64
    +msn_p2p_info_get_total_size(MsnP2PInfo *info)
    +{
    + return info->header.total_size;
    +}
    +
    +guint32
    +msn_p2p_info_get_length(MsnP2PInfo *info)
    +{
    + return info->header.length;
    +}
    +
    +guint32
    +msn_p2p_info_get_flags(MsnP2PInfo *info)
    +{
    + return info->header.flags;
    +}
    +
    +guint32
    +msn_p2p_info_get_ack_id(MsnP2PInfo *info)
    +{
    + return info->header.ack_id;
    +}
    +
    +guint32
    +msn_p2p_info_get_ack_sub_id(MsnP2PInfo *info)
    +{
    + return info->header.ack_sub_id;
    +}
    +
    +guint64
    +msn_p2p_info_get_ack_size(MsnP2PInfo *info)
    +{
    + return info->header.ack_size;
    +}
    +
    +guint32
    +msn_p2p_info_get_app_id(MsnP2PInfo *info)
    +{
    + return info->footer.value;
    +}
    +
    +void
    +msn_p2p_info_set_session_id(MsnP2PInfo *info, guint32 session_id)
    +{
    + info->header.session_id = session_id;
    +}
    +
    +void
    +msn_p2p_info_set_id(MsnP2PInfo *info, guint32 id)
    +{
    + info->header.id = id;
    +}
    +
    +void
    +msn_p2p_info_set_offset(MsnP2PInfo *info, guint64 offset)
    +{
    + info->header.offset = offset;
    +}
    +
    +void
    +msn_p2p_info_set_total_size(MsnP2PInfo *info, guint64 total_size)
    +{
    + info->header.total_size = total_size;
    +}
    +
    +void
    +msn_p2p_info_set_length(MsnP2PInfo *info, guint32 length)
    +{
    + info->header.length = length;
    +}
    +
    +void
    +msn_p2p_info_set_flags(MsnP2PInfo *info, guint32 flags)
    +{
    + info->header.flags = flags;
    +}
    +
    +void
    +msn_p2p_info_set_ack_id(MsnP2PInfo *info, guint32 ack_id)
    +{
    + info->header.ack_id = ack_id;
    +}
    +
    +void
    +msn_p2p_info_set_ack_sub_id(MsnP2PInfo *info, guint32 ack_sub_id)
    +{
    + info->header.ack_sub_id = ack_sub_id;
    +}
    +
    +void
    +msn_p2p_info_set_ack_size(MsnP2PInfo *info, guint64 ack_size)
    +{
    + info->header.ack_size = ack_size;
    +}
    +
    +void
    +msn_p2p_info_set_app_id(MsnP2PInfo *info, guint32 app_id)
    +{
    + info->footer.value = app_id;
    +}
    +
    --- a/libpurple/protocols/msn/p2p.h Sun Jan 09 23:32:10 2011 +0000
    +++ b/libpurple/protocols/msn/p2p.h Wed Feb 02 23:26:42 2011 +0000
    @@ -58,6 +58,11 @@
    } MsnP2PFooter;
    #define P2P_PACKET_FOOTER_SIZE (1 * 4)
    +typedef struct {
    + MsnP2PHeader header;
    + MsnP2PFooter footer;
    +} MsnP2PInfo;
    +
    typedef enum
    {
    P2P_NO_FLAG = 0x0, /**< No flags specified */
    @@ -88,19 +93,98 @@
    P2P_APPID_DISPLAY = 0xC /**< Display Image */
    } MsnP2PAppId;
    -MsnP2PHeader *
    -msn_p2p_header_from_wire(const char *wire);
    +MsnP2PInfo *
    +msn_p2p_info_new(void);
    +
    +MsnP2PInfo *
    +msn_p2p_info_dup(MsnP2PInfo *info);
    +
    +void
    +msn_p2p_info_free(MsnP2PInfo *info);
    +
    +size_t
    +msn_p2p_header_from_wire(MsnP2PInfo *info, const char *wire);
    char *
    -msn_p2p_header_to_wire(MsnP2PHeader *header);
    +msn_p2p_header_to_wire(MsnP2PInfo *info, size_t *len);
    -MsnP2PFooter *
    -msn_p2p_footer_from_wire(const char *wire);
    +size_t
    +msn_p2p_footer_from_wire(MsnP2PInfo *info, const char *wire);
    char *
    -msn_p2p_footer_to_wire(MsnP2PFooter *footer);
    +msn_p2p_footer_to_wire(MsnP2PInfo *info, size_t *len);
    +
    +void
    +msn_p2p_info_to_string(MsnP2PInfo *info, GString *str);
    gboolean
    msn_p2p_msg_is_data(const MsnP2PHeaderFlag flags);
    +gboolean
    +msn_p2p_info_is_valid(MsnP2PInfo *info);
    +
    +gboolean
    +msn_p2p_info_is_final(MsnP2PInfo *info);
    +
    +guint32
    +msn_p2p_info_get_session_id(MsnP2PInfo *info);
    +
    +guint32
    +msn_p2p_info_get_id(MsnP2PInfo *info);
    +
    +guint64
    +msn_p2p_info_get_offset(MsnP2PInfo *info);
    +
    +guint64
    +msn_p2p_info_get_total_size(MsnP2PInfo *info);
    +
    +guint32
    +msn_p2p_info_get_length(MsnP2PInfo *info);
    +
    +guint32
    +msn_p2p_info_get_flags(MsnP2PInfo *info);
    +
    +guint32
    +msn_p2p_info_get_ack_id(MsnP2PInfo *info);
    +
    +guint32
    +msn_p2p_info_get_ack_sub_id(MsnP2PInfo *info);
    +
    +guint64
    +msn_p2p_info_get_ack_size(MsnP2PInfo *info);
    +
    +guint32
    +msn_p2p_info_get_app_id(MsnP2PInfo *info);
    +
    +void
    +msn_p2p_info_set_session_id(MsnP2PInfo *info, guint32 session_id);
    +
    +void
    +msn_p2p_info_set_id(MsnP2PInfo *info, guint32 id);
    +
    +void
    +msn_p2p_info_set_offset(MsnP2PInfo *info, guint64 offset);
    +
    +void
    +msn_p2p_info_set_total_size(MsnP2PInfo *info, guint64 total_size);
    +
    +void
    +msn_p2p_info_set_length(MsnP2PInfo *info, guint32 length);
    +
    +void
    +msn_p2p_info_set_flags(MsnP2PInfo *info, guint32 flags);
    +
    +void
    +msn_p2p_info_set_ack_id(MsnP2PInfo *info, guint32 ack_id);
    +
    +void
    +msn_p2p_info_set_ack_sub_id(MsnP2PInfo *info, guint32 ack_sub_id);
    +
    +void
    +msn_p2p_info_set_ack_size(MsnP2PInfo *info, guint64 ack_size);
    +
    +void
    +msn_p2p_info_set_app_id(MsnP2PInfo *info, guint32 app_id);
    +
    #endif /* MSN_P2P_H */
    +
    --- a/libpurple/protocols/msn/sbconn.c Sun Jan 09 23:32:10 2011 +0000
    +++ b/libpurple/protocols/msn/sbconn.c Wed Feb 02 23:26:42 2011 +0000
    @@ -126,8 +126,6 @@
    trans->payload = payload;
    trans->payload_len = payload_len;
    - msg->trans = trans;
    -
    msn_cmdproc_send_trans(cmdproc, trans);
    }
    --- a/libpurple/protocols/msn/slpcall.c Sun Jan 09 23:32:10 2011 +0000
    +++ b/libpurple/protocols/msn/slpcall.c Wed Feb 02 23:26:42 2011 +0000
    @@ -1059,16 +1059,21 @@
    MsnSlpCall *slpcall;
    const guchar *body;
    gsize body_len;
    + guint32 session_id;
    + guint32 flags;
    slpcall = NULL;
    body = slpmsg->buffer;
    - body_len = slpmsg->header->offset;
    + body_len = msn_p2p_info_get_offset(slpmsg->p2p_info);
    - if (slpmsg->header->flags == P2P_NO_FLAG || slpmsg->header->flags == P2P_WLM2009_COMP)
    + session_id = msn_p2p_info_get_session_id(slpmsg->p2p_info);
    + flags = msn_p2p_info_get_flags(slpmsg->p2p_info);
    +
    + if (flags == P2P_NO_FLAG || flags == P2P_WLM2009_COMP)
    {
    char *body_str;
    - if (slpmsg->header->session_id == 64)
    + if (session_id == 64)
    {
    /* This is for handwritten messages (Ink) */
    GError *error = NULL;
    @@ -1125,9 +1130,9 @@
    }
    g_free(body_str);
    }
    - else if (msn_p2p_msg_is_data(slpmsg->header->flags))
    + else if (msn_p2p_msg_is_data(flags))
    {
    - slpcall = msn_slplink_find_slp_call_with_session_id(slplink, slpmsg->header->session_id);
    + slpcall = msn_slplink_find_slp_call_with_session_id(slplink, session_id);
    if (slpcall != NULL)
    {
    @@ -1142,13 +1147,13 @@
    slpcall->wasted = TRUE;
    }
    }
    - else if (slpmsg->header->flags == P2P_ACK)
    + else if (flags == P2P_ACK)
    {
    /* Acknowledgement of previous message. Don't do anything currently. */
    }
    else
    purple_debug_warning("msn", "Unprocessed SLP message with flags 0x%04x\n",
    - slpmsg->header->flags);
    + flags);
    return slpcall;
    }
    --- a/libpurple/protocols/msn/slplink.c Sun Jan 09 23:32:10 2011 +0000
    +++ b/libpurple/protocols/msn/slplink.c Wed Feb 02 23:26:42 2011 +0000
    @@ -281,17 +281,21 @@
    msn_slplink_send_msgpart(MsnSlpLink *slplink, MsnSlpMessage *slpmsg)
    {
    MsnSlpMessagePart *part;
    + MsnP2PInfo *info;
    long long real_size;
    size_t len = 0;
    + guint64 offset;
    /* Maybe we will want to create a new msg for this slpmsg instead of
    * reusing the same one all the time. */
    - part = msn_slpmsgpart_new(slpmsg->header, slpmsg->footer);
    + info = slpmsg->p2p_info;
    + part = msn_slpmsgpart_new(info);
    part->ack_data = slpmsg;
    - real_size = (slpmsg->header->flags == P2P_ACK) ? 0 : slpmsg->size;
    + real_size = (msn_p2p_info_get_flags(info) == P2P_ACK) ? 0 : slpmsg->size;
    - if (slpmsg->header->offset < real_size)
    + offset = msn_p2p_info_get_offset(info);
    + if (offset < real_size)
    {
    if (slpmsg->slpcall && slpmsg->slpcall->xfer && purple_xfer_get_type(slpmsg->slpcall->xfer) == PURPLE_XFER_SEND &&
    purple_xfer_get_status(slpmsg->slpcall->xfer) == PURPLE_XFER_STATUS_STARTED)
    @@ -301,15 +305,15 @@
    }
    else
    {
    - len = slpmsg->size - slpmsg->header->offset;
    + len = slpmsg->size - offset;
    if (len > MSN_SBCONN_MAX_SIZE)
    len = MSN_SBCONN_MAX_SIZE;
    - msn_slpmsgpart_set_bin_data(part, slpmsg->buffer + slpmsg->header->offset, len);
    + msn_slpmsgpart_set_bin_data(part, slpmsg->buffer + offset, len);
    }
    - slpmsg->header->length = len;
    + msn_p2p_info_set_length(slpmsg->p2p_info, len);
    }
    #if 0
    @@ -326,7 +330,7 @@
    msn_slplink_send_part(slplink, part);
    - if (msn_p2p_msg_is_data(slpmsg->header->flags) &&
    + if (msn_p2p_msg_is_data(msn_p2p_info_get_flags(info)) &&
    (slpmsg->slpcall != NULL))
    {
    slpmsg->slpcall->progress = TRUE;
    @@ -334,7 +338,7 @@
    if (slpmsg->slpcall->progress_cb != NULL)
    {
    slpmsg->slpcall->progress_cb(slpmsg->slpcall, slpmsg->size,
    - len, slpmsg->header->offset);
    + len, offset);
    }
    }
    @@ -344,27 +348,30 @@
    static void
    msn_slplink_release_slpmsg(MsnSlpLink *slplink, MsnSlpMessage *slpmsg)
    {
    - slpmsg = slpmsg;
    - slpmsg->footer = g_new0(MsnP2PFooter, 1);
    + MsnP2PInfo *info;
    + guint32 flags;
    +
    + info = slpmsg->p2p_info;
    - if (slpmsg->header->flags == P2P_NO_FLAG)
    + flags = msn_p2p_info_get_flags(info);
    + if (flags == P2P_NO_FLAG)
    {
    - slpmsg->header->ack_id = rand() % 0xFFFFFF00;
    + msn_p2p_info_set_ack_id(info, rand() % 0xFFFFFF00);
    }
    - else if (msn_p2p_msg_is_data(slpmsg->header->flags))
    + else if (msn_p2p_msg_is_data(flags))
    {
    MsnSlpCall *slpcall;
    slpcall = slpmsg->slpcall;
    g_return_if_fail(slpcall != NULL);
    - slpmsg->header->session_id = slpcall->session_id;
    - slpmsg->footer->value = slpcall->app_id;
    - slpmsg->header->ack_id = rand() % 0xFFFFFF00;
    + msn_p2p_info_set_session_id(info, slpcall->session_id);
    + msn_p2p_info_set_app_id(info, slpcall->app_id);
    + msn_p2p_info_set_ack_id(info, rand() % 0xFFFFFF00);
    }
    - slpmsg->header->id = slpmsg->id;
    + msn_p2p_info_set_id(info, slpmsg->id);
    - slpmsg->header->total_size = slpmsg->size;
    + msn_p2p_info_set_total_size(info, slpmsg->size);
    msn_slplink_send_msgpart(slplink, slpmsg);
    }
    @@ -400,20 +407,20 @@
    }
    static MsnSlpMessage *
    -msn_slplink_create_ack(MsnSlpLink *slplink, MsnP2PHeader *header)
    +msn_slplink_create_ack(MsnSlpLink *slplink, MsnP2PInfo *info)
    {
    MsnSlpMessage *slpmsg;
    - slpmsg = msn_slpmsg_ack_new(header);
    + slpmsg = msn_slpmsg_ack_new(info);
    msn_slpmsg_set_slplink(slpmsg, slplink);
    return slpmsg;
    }
    static void
    -msn_slplink_send_ack(MsnSlpLink *slplink, MsnP2PHeader *header)
    +msn_slplink_send_ack(MsnSlpLink *slplink, MsnP2PInfo *info)
    {
    - MsnSlpMessage *slpmsg = msn_slplink_create_ack(slplink, header);
    + MsnSlpMessage *slpmsg = msn_slplink_create_ack(slplink, info);
    msn_slplink_send_slpmsg(slplink, slpmsg);
    msn_slpmsg_destroy(slpmsg);
    @@ -428,7 +435,7 @@
    {
    MsnSlpMessage *slpmsg = e->data;
    - if ((slpmsg->header->session_id == session_id) && (slpmsg->id == id))
    + if ((msn_p2p_info_get_session_id(slpmsg->p2p_info) == session_id) && (slpmsg->id == id))
    return slpmsg;
    }
    @@ -436,22 +443,26 @@
    }
    static MsnSlpMessage *
    -init_first_msg(MsnSlpLink *slplink, MsnP2PHeader *header)
    +init_first_msg(MsnSlpLink *slplink, MsnP2PInfo *info)
    {
    MsnSlpMessage *slpmsg;
    + guint32 session_id;
    + guint32 flags;
    slpmsg = msn_slpmsg_new(slplink);
    - slpmsg->id = header->id;
    - slpmsg->header->session_id = header->session_id;
    - slpmsg->size = header->total_size;
    - slpmsg->header->flags = header->flags;
    + slpmsg->id = msn_p2p_info_get_id(info);
    + session_id = msn_p2p_info_get_session_id(info);
    + msn_p2p_info_set_session_id(slpmsg->p2p_info, session_id);
    + slpmsg->size = msn_p2p_info_get_total_size(info);
    + flags = msn_p2p_info_get_flags(info);
    + msn_p2p_info_set_flags(slpmsg->p2p_info, flags);
    - if (slpmsg->header->session_id)
    + if (session_id)
    {
    - slpmsg->slpcall = msn_slplink_find_slp_call_with_session_id(slplink, slpmsg->header->session_id);
    + slpmsg->slpcall = msn_slplink_find_slp_call_with_session_id(slplink, session_id);
    if (slpmsg->slpcall != NULL)
    {
    - if (msn_p2p_msg_is_data(header->flags))
    + if (msn_p2p_msg_is_data(flags))
    {
    PurpleXfer *xfer = slpmsg->slpcall->xfer;
    if (xfer != NULL)
    @@ -488,9 +499,10 @@
    }
    static void
    -process_complete_msg(MsnSlpLink *slplink, MsnSlpMessage *slpmsg, MsnP2PHeader *header)
    +process_complete_msg(MsnSlpLink *slplink, MsnSlpMessage *slpmsg, MsnP2PInfo *info)
    {
    MsnSlpCall *slpcall;
    + guint32 flags;
    slpcall = msn_slp_process_msg(slplink, slpmsg);
    @@ -501,8 +513,10 @@
    purple_debug_info("msn", "msn_slplink_process_msg: slpmsg complete\n");
    - if (slpmsg->header->flags == P2P_NO_FLAG || slpmsg->header->flags == P2P_WLM2009_COMP ||
    - msn_p2p_msg_is_data(slpmsg->header->flags))
    + flags = msn_p2p_info_get_flags(slpmsg->p2p_info);
    +
    + if (flags == P2P_NO_FLAG || flags == P2P_WLM2009_COMP ||
    + msn_p2p_msg_is_data(flags))
    {
    /* Release all the messages and send the ACK */
    @@ -515,11 +529,11 @@
    */
    purple_debug_info("msn", "msn_slplink_process_msg: save ACK\n");
    - slpcall->slplink->dc->prev_ack = msn_slplink_create_ack(slplink, header);
    + slpcall->slplink->dc->prev_ack = msn_slplink_create_ack(slplink, info);
    } else if (!slpcall->wasted) {
    purple_debug_info("msn", "msn_slplink_process_msg: send ACK\n");
    - msn_slplink_send_ack(slplink, header);
    + msn_slplink_send_ack(slplink, info);
    msn_slplink_send_queued_slpmsgs(slplink);
    }
    }
    @@ -539,16 +553,17 @@
    purple_xfer_prpl_ready(slpmsg->slpcall->xfer);
    }
    else if (slpmsg->size && slpmsg->buffer) {
    - if (G_MAXSIZE - part->size < part->header->offset
    - || (part->header->offset + part->size) > slpmsg->size
    - || slpmsg->header->offset != part->header->offset) {
    + guint64 offset = msn_p2p_info_get_offset(part->info);
    + if (G_MAXSIZE - part->size < offset
    + || (offset + part->size) > slpmsg->size
    + || msn_p2p_info_get_offset(slpmsg->p2p_info) != offset) {
    purple_debug_error("msn",
    "Oversized slpmsg - msgsize=%lld offset=%" G_GUINT64_FORMAT " len=%" G_GSIZE_FORMAT "\n",
    - slpmsg->size, part->header->offset, part->size);
    + slpmsg->size, offset, part->size);
    g_return_if_reached();
    } else {
    - memcpy(slpmsg->buffer + part->header->offset, part->buffer, part->size);
    - slpmsg->header->offset += part->size;
    + memcpy(slpmsg->buffer + offset, part->buffer, part->size);
    + msn_p2p_info_set_offset(slpmsg->p2p_info, offset + part->size);
    }
    }
    }
    @@ -557,12 +572,12 @@
    msn_slplink_process_msg(MsnSlpLink *slplink, MsnSlpMessagePart *part)
    {
    MsnSlpMessage *slpmsg;
    - MsnP2PHeader *header;
    + MsnP2PInfo *info;
    guint64 offset;
    - header = part->header;
    + info = part->info;
    - if (header->total_size < header->length)
    + if (!msn_p2p_info_is_valid(info))
    {
    /* We seem to have received a bad header */
    purple_debug_warning("msn", "Total size listed in SLP binary header "
    @@ -571,12 +586,15 @@
    return;
    }
    - offset = header->offset;
    + offset = msn_p2p_info_get_offset(info);
    if (offset == 0)
    - slpmsg = init_first_msg(slplink, header);
    + slpmsg = init_first_msg(slplink, info);
    else {
    - slpmsg = msn_slplink_message_find(slplink, header->session_id, header->id);
    + guint32 session_id, id;
    + session_id = msn_p2p_info_get_session_id(info);
    + id = msn_p2p_info_get_id(info);
    + slpmsg = msn_slplink_message_find(slplink, session_id, id);
    if (slpmsg == NULL)
    {
    /* Probably the transfer was cancelled */
    @@ -587,8 +605,7 @@
    slpmsg_add_part(slpmsg, part);
    -
    - if (msn_p2p_msg_is_data(slpmsg->header->flags) &&
    + if (msn_p2p_msg_is_data(msn_p2p_info_get_flags(slpmsg->p2p_info)) &&
    (slpmsg->slpcall != NULL))
    {
    slpmsg->slpcall->progress = TRUE;
    @@ -606,8 +623,8 @@
    #endif
    /* All the pieces of the slpmsg have been received */
    - if (header->offset + header->length >= header->total_size)
    - process_complete_msg(slplink, slpmsg, header);
    + if (msn_p2p_info_is_final(info))
    + process_complete_msg(slplink, slpmsg, info);
    /* NOTE: The slpmsg will be destroyed in process_complete_msg or left in
    the slplink until fully received. Don't free it here!
    --- a/libpurple/protocols/msn/slpmsg.c Sun Jan 09 23:32:10 2011 +0000
    +++ b/libpurple/protocols/msn/slpmsg.c Wed Feb 02 23:26:42 2011 +0000
    @@ -48,8 +48,7 @@
    else
    slpmsg->slplink = NULL;
    - slpmsg->header = g_new0(MsnP2PHeader, 1);
    - slpmsg->footer = NULL;
    + slpmsg->p2p_info = msn_p2p_info_new();
    return slpmsg;
    }
    @@ -90,8 +89,7 @@
    slplink->slp_msgs = g_list_remove(slplink->slp_msgs, slpmsg);
    - g_free(slpmsg->header);
    - g_free(slpmsg->footer);
    + msn_p2p_info_free(slpmsg->p2p_info);
    g_free(slpmsg);
    }
    @@ -193,7 +191,6 @@
    slpmsg = msn_slpmsg_new(slplink);
    msn_slpmsg_set_body(slpmsg, body, body_len);
    - slpmsg->sip = TRUE;
    slpmsg->slpcall = slpcall;
    g_free(body);
    @@ -201,18 +198,20 @@
    return slpmsg;
    }
    -MsnSlpMessage *msn_slpmsg_ack_new(MsnP2PHeader *header)
    +MsnSlpMessage *msn_slpmsg_ack_new(MsnP2PInfo *ack_info)
    {
    MsnSlpMessage *slpmsg;
    + MsnP2PInfo *new_info;
    slpmsg = msn_slpmsg_new(NULL);
    - slpmsg->header->session_id = header->session_id;
    - slpmsg->size = header->total_size;
    - slpmsg->header->flags = P2P_ACK;
    - slpmsg->header->ack_id = header->id;
    - slpmsg->header->ack_sub_id = header->ack_id;
    - slpmsg->header->ack_size = header->total_size;
    + new_info = slpmsg->p2p_info;
    + msn_p2p_info_set_session_id(new_info, msn_p2p_info_get_session_id(ack_info));
    + slpmsg->size = msn_p2p_info_get_total_size(ack_info);
    + msn_p2p_info_set_flags(new_info, P2P_ACK);
    + msn_p2p_info_set_ack_id(new_info, msn_p2p_info_get_id(ack_info));
    + msn_p2p_info_set_ack_sub_id(new_info, msn_p2p_info_get_ack_id(ack_info));
    + msn_p2p_info_set_ack_size(new_info, msn_p2p_info_get_total_size(ack_info));
    slpmsg->info = "SLP ACK";
    return slpmsg;
    @@ -224,7 +223,7 @@
    slpmsg = msn_slpmsg_new(NULL);
    slpmsg->slpcall = slpcall;
    - slpmsg->header->flags = P2P_MSN_OBJ_DATA;
    + msn_p2p_info_set_flags(slpmsg->p2p_info, P2P_MSN_OBJ_DATA);
    slpmsg->info = "SLP DATA";
    msn_slpmsg_set_image(slpmsg, img);
    @@ -239,7 +238,7 @@
    slpmsg = msn_slpmsg_new(NULL);
    slpmsg->slpcall = slpcall;
    - slpmsg->header->session_id = slpcall->session_id;
    + msn_p2p_info_set_session_id(slpmsg->p2p_info, slpcall->session_id);
    msn_slpmsg_set_body(slpmsg, NULL, 4);
    slpmsg->info = "SLP DATA PREP";
    @@ -254,7 +253,7 @@
    slpmsg = msn_slpmsg_new(NULL);
    slpmsg->slpcall = slpcall;
    - slpmsg->header->flags = P2P_FILE_DATA;
    + msn_p2p_info_set_flags(slpmsg->p2p_info, P2P_FILE_DATA);
    slpmsg->info = "SLP FILE";
    slpmsg->size = size;
    @@ -267,27 +266,25 @@
    char *footer;
    char *base;
    char *tmp;
    - size_t siz;
    + size_t header_size, footer_size;
    - base = g_malloc(P2P_PACKET_HEADER_SIZE + slpmsg->size + P2P_PACKET_FOOTER_SIZE);
    + header = msn_p2p_header_to_wire(slpmsg->p2p_info, &header_size);
    + footer = msn_p2p_footer_to_wire(slpmsg->p2p_info, &footer_size);
    +
    + base = g_malloc(header_size + slpmsg->size + footer_size);
    tmp = base;
    - header = msn_p2p_header_to_wire(slpmsg->header);
    - footer = msn_p2p_footer_to_wire(slpmsg->footer);
    -
    - siz = P2P_PACKET_HEADER_SIZE;
    /* Copy header */
    - memcpy(tmp, header, siz);
    - tmp += siz;
    + memcpy(tmp, header, header_size);
    + tmp += header_size;
    /* Copy body */
    memcpy(tmp, slpmsg->buffer, slpmsg->size);
    tmp += slpmsg->size;
    /* Copy footer */
    - siz = P2P_PACKET_FOOTER_SIZE;
    - memcpy(tmp, footer, siz);
    - tmp += siz;
    + memcpy(tmp, footer, footer_size);
    + tmp += footer_size;
    *ret_size = tmp - base;
    @@ -303,15 +300,7 @@
    str = g_string_new(NULL);
    - g_string_append_printf(str, "Session ID: %u\r\n", slpmsg->header->session_id);
    - g_string_append_printf(str, "ID: %u\r\n", slpmsg->header->id);
    - g_string_append_printf(str, "Offset: %" G_GUINT64_FORMAT "\r\n", slpmsg->header->offset);
    - g_string_append_printf(str, "Total size: %" G_GUINT64_FORMAT "\r\n", slpmsg->header->total_size);
    - g_string_append_printf(str, "Length: %u\r\n", slpmsg->header->length);
    - g_string_append_printf(str, "Flags: 0x%x\r\n", slpmsg->header->flags);
    - g_string_append_printf(str, "ACK ID: %u\r\n", slpmsg->header->ack_id);
    - g_string_append_printf(str, "SUB ID: %u\r\n", slpmsg->header->ack_sub_id);
    - g_string_append_printf(str, "ACK Size: %" G_GUINT64_FORMAT "\r\n", slpmsg->header->ack_size);
    + msn_p2p_info_to_string(slpmsg->p2p_info, str);
    if (purple_debug_is_verbose() && slpmsg->buffer != NULL) {
    g_string_append_len(str, (gchar*)slpmsg->buffer, slpmsg->size);
    @@ -324,7 +313,5 @@
    }
    - g_string_append_printf(str, "Footer: %u\r\n", slpmsg->footer->value);
    -
    purple_debug_info("msn", "SlpMessage %s:\n{%s}\n", slpmsg->info, str->str);
    }
    --- a/libpurple/protocols/msn/slpmsg.h Sun Jan 09 23:32:10 2011 +0000
    +++ b/libpurple/protocols/msn/slpmsg.h Wed Feb 02 23:26:42 2011 +0000
    @@ -45,13 +45,10 @@
    MsnSlpLink *slplink; /**< The slplink through which this slp message is being sent. */
    MsnSession *session;
    - MsnP2PHeader *header;
    - MsnP2PFooter *footer;
    + MsnP2PInfo *p2p_info;
    long id;
    - gboolean sip; /**< A flag that states if this is a SIP slp message. */
    -
    gboolean ft;
    PurpleStoredImage *img;
    guchar *buffer;
    @@ -94,8 +91,6 @@
    void msn_slpmsg_set_body(MsnSlpMessage *slpmsg, const char *body,
    long long size);
    void msn_slpmsg_set_image(MsnSlpMessage *slpmsg, PurpleStoredImage *img);
    -void msn_slpmsg_open_file(MsnSlpMessage *slpmsg,
    - const char *file_name);
    MsnSlpMessage * msn_slpmsg_sip_new(MsnSlpCall *slpcall, int cseq,
    const char *header,
    const char *branch,
    @@ -109,7 +104,7 @@
    *
    * @return A new SlpMessage with ACK headers
    */
    -MsnSlpMessage *msn_slpmsg_ack_new(MsnP2PHeader *header);
    +MsnSlpMessage *msn_slpmsg_ack_new(MsnP2PInfo *info);
    /**
    * Create a new SLP message for MsnObject data.
    --- a/libpurple/protocols/msn/slpmsg_part.c Sun Jan 09 23:32:10 2011 +0000
    +++ b/libpurple/protocols/msn/slpmsg_part.c Wed Feb 02 23:26:42 2011 +0000
    @@ -28,16 +28,14 @@
    #include "slpmsg.h"
    #include "slpmsg_part.h"
    -MsnSlpMessagePart *msn_slpmsgpart_new(MsnP2PHeader *header, MsnP2PFooter *footer)
    +MsnSlpMessagePart *msn_slpmsgpart_new(MsnP2PInfo *info)
    {
    MsnSlpMessagePart *part;
    part = g_new0(MsnSlpMessagePart, 1);
    - if (header)
    - part->header = g_memdup(header, P2P_PACKET_HEADER_SIZE);
    - if (footer)
    - part->footer = g_memdup(footer, P2P_PACKET_FOOTER_SIZE);
    + if (info)
    + part->info = msn_p2p_info_dup(info);
    part->ack_cb = msn_slpmsgpart_ack;
    part->nak_cb = msn_slpmsgpart_nak;
    @@ -48,20 +46,22 @@
    MsnSlpMessagePart *msn_slpmsgpart_new_from_data(const char *data, size_t data_len)
    {
    MsnSlpMessagePart *part;
    + size_t len;
    int body_len;
    if (data_len < P2P_PACKET_HEADER_SIZE) {
    return NULL;
    }
    - part = msn_slpmsgpart_new(NULL, NULL);
    + part = msn_slpmsgpart_new(NULL);
    + part->info = msn_p2p_info_new();
    /* Extract the binary SLP header */
    - part->header = msn_p2p_header_from_wire(data);
    - data += P2P_PACKET_HEADER_SIZE;
    + len = msn_p2p_header_from_wire(part->info, data);
    + data += len;
    /* Extract the body */
    - body_len = data_len - P2P_PACKET_HEADER_SIZE - P2P_PACKET_FOOTER_SIZE;
    + body_len = data_len - len - P2P_PACKET_FOOTER_SIZE;
    /* msg->body_len = msg->msnslp_header.length; */
    if (body_len > 0) {
    @@ -73,15 +73,14 @@
    /* Extract the footer */
    if (body_len >= 0)
    - part->footer = msn_p2p_footer_from_wire(data);
    + msn_p2p_footer_from_wire(part->info, data);
    return part;
    }
    static void msn_slpmsgpart_destroy(MsnSlpMessagePart *part)
    {
    - g_free(part->header);
    - g_free(part->footer);
    + g_free(part->info);
    g_free(part->buffer);
    g_free(part);
    @@ -138,27 +137,25 @@
    char *footer;
    char *base;
    char *tmp;
    - size_t siz;
    + size_t header_size, footer_size;
    - base = g_malloc(P2P_PACKET_HEADER_SIZE + part->size + P2P_PACKET_FOOTER_SIZE);
    + header = msn_p2p_header_to_wire(part->info, &header_size);
    + footer = msn_p2p_footer_to_wire(part->info, &footer_size);
    +
    + base = g_malloc(header_size + part->size + footer_size);
    tmp = base;
    - header = msn_p2p_header_to_wire(part->header);
    - footer = msn_p2p_footer_to_wire(part->footer);
    -
    - siz = P2P_PACKET_HEADER_SIZE;
    /* Copy header */
    - memcpy(tmp, header, siz);
    - tmp += siz;
    + memcpy(tmp, header, header_size);
    + tmp += header_size;
    /* Copy body */
    memcpy(tmp, part->buffer, part->size);
    tmp += part->size;
    /* Copy footer */
    - siz = P2P_PACKET_FOOTER_SIZE;
    - memcpy(tmp, footer, siz);
    - tmp += siz;
    + memcpy(tmp, footer, footer_size);
    + tmp += footer_size;
    *ret_size = tmp - base;
    @@ -167,23 +164,27 @@
    return base;
    }
    +
    /* We have received the message ack */
    void
    msn_slpmsgpart_ack(MsnSlpMessagePart *part, void *data)
    {
    MsnSlpMessage *slpmsg;
    + guint64 offset;
    long long real_size;
    slpmsg = data;
    - real_size = (slpmsg->header->flags == P2P_ACK) ? 0 : slpmsg->size;
    + real_size = (msn_p2p_info_get_flags(slpmsg->p2p_info) == P2P_ACK) ? 0 : slpmsg->size;
    - slpmsg->header->offset += part->header->length;
    + offset = msn_p2p_info_get_offset(slpmsg->p2p_info);
    + offset += msn_p2p_info_get_length(part->info);
    + msn_p2p_info_set_offset(slpmsg->p2p_info, offset);
    slpmsg->parts = g_list_remove(slpmsg->parts, part);
    msn_slpmsgpart_unref(part);
    - if (slpmsg->header->offset < real_size)
    + if (offset < real_size)
    {
    if (slpmsg->slpcall->xfer && purple_xfer_get_status(slpmsg->slpcall->xfer) == PURPLE_XFER_STATUS_STARTED)
    {
    @@ -196,7 +197,7 @@
    else
    {
    /* The whole message has been sent */
    - if (msn_p2p_msg_is_data(slpmsg->header->flags))
    + if (msn_p2p_msg_is_data(msn_p2p_info_get_flags(slpmsg->p2p_info)))
    {
    if (slpmsg->slpcall != NULL)
    {
    @@ -222,3 +223,9 @@
    msn_slpmsgpart_unref(part);
    }
    +void
    +msn_slpmsgpart_to_string(MsnSlpMessagePart *part, GString *str)
    +{
    + msn_p2p_info_to_string(part->info, str);
    +}
    +
    --- a/libpurple/protocols/msn/slpmsg_part.h Sun Jan 09 23:32:10 2011 +0000
    +++ b/libpurple/protocols/msn/slpmsg_part.h Wed Feb 02 23:26:42 2011 +0000
    @@ -34,8 +34,7 @@
    {
    guint ref_count;
    - MsnP2PHeader *header;
    - MsnP2PFooter *footer;
    + MsnP2PInfo *info;
    MsnSlpPartCb ack_cb;
    MsnSlpPartCb nak_cb;
    @@ -45,7 +44,7 @@
    size_t size;
    };
    -MsnSlpMessagePart *msn_slpmsgpart_new(MsnP2PHeader *header, MsnP2PFooter *footer);
    +MsnSlpMessagePart *msn_slpmsgpart_new(MsnP2PInfo *info);
    MsnSlpMessagePart *msn_slpmsgpart_new_from_data(const char *data, size_t data_len);
    @@ -60,4 +59,8 @@
    void msn_slpmsgpart_ack(MsnSlpMessagePart *part, void *data);
    void msn_slpmsgpart_nak(MsnSlpMessagePart *part, void *data);
    +
    +void msn_slpmsgpart_to_string(MsnSlpMessagePart *part, GString *str);
    +
    #endif /* MSN_SLPMSG_PART_H */
    +
    --- a/libpurple/protocols/novell/novell.c Sun Jan 09 23:32:10 2011 +0000
    +++ b/libpurple/protocols/novell/novell.c Wed Feb 02 23:26:42 2011 +0000
    @@ -74,7 +74,7 @@
    _sync_privacy_lists(NMUser *user);
    static void
    -_show_info(PurpleConnection * gc, NMUserRecord * user_record);
    +_show_info(PurpleConnection * gc, NMUserRecord * user_record, char * name);
    const char *
    _get_conference_name(int id);
    @@ -705,7 +705,7 @@
    user_record = (NMUserRecord *) resp_data;
    if (user_record) {
    _show_info(purple_account_get_connection(user->client_data),
    - user_record);
    + user_record, g_strdup(name));
    }
    } else {
    gc = purple_account_get_connection(user->client_data);
    @@ -1505,7 +1505,7 @@
    /* Display a dialog box showing the properties for the given user record */
    static void
    -_show_info(PurpleConnection * gc, NMUserRecord * user_record)
    +_show_info(PurpleConnection * gc, NMUserRecord * user_record, char * name)
    {
    PurpleNotifyUserInfo *user_info = purple_notify_user_info_new();
    int count, i;
    @@ -1544,9 +1544,10 @@
    }
    }
    - purple_notify_userinfo(gc, nm_user_record_get_userid(user_record),
    - user_info, NULL, NULL);
    + purple_notify_userinfo(gc, name, user_info, NULL, NULL);
    purple_notify_user_info_destroy(user_info);
    +
    + g_free(name);
    }
    /* Send a join conference, the first item in the parms list is the
    @@ -2912,11 +2913,9 @@
    user_record = nm_find_user_record(user, name);
    if (user_record) {
    -
    - _show_info(gc, user_record);
    + _show_info(gc, user_record, g_strdup(name));
    } else {
    -
    rc = nm_send_get_details(user, name,
    _get_details_resp_show_info, g_strdup(name));
    --- a/libpurple/protocols/oscar/family_feedbag.c Sun Jan 09 23:32:10 2011 +0000
    +++ b/libpurple/protocols/oscar/family_feedbag.c Wed Feb 02 23:26:42 2011 +0000
    @@ -44,10 +44,66 @@
    */
    #include "oscar.h"
    +#include "debug.h"
    static int aim_ssi_addmoddel(OscarData *od);
    /**
    + * List types based on http://dev.aol.com/aim/oscar/#FEEDBAG (archive.org)
    + * and http://iserverd.khstu.ru/oscar/ssi_item.html
    + *
    + * @param type The type of a list item as integer number, as provided by an aim_ssi_item struct.
    + * @return Returns the name of the item type as a character string.
    + */
    +static const gchar*
    +aim_ssi_type_to_string(guint16 type)
    +{
    + struct TypeStringPair
    + {
    + guint16 type;
    + const gchar *string;
    + };
    + static const struct TypeStringPair type_strings[] = {
    + { 0x0000, "Buddy" },
    + { 0x0001, "Group" },
    + { 0x0002, "Permit/Visible" },
    + { 0x0003, "Deny/Invisible" },
    + { 0x0004, "PDInfo" },
    + { 0x0005, "PresencePrefs" },
    + { 0x0006, "Non-Buddy Info" },
    + { 0x0009, "ClientPrefs" },
    + { 0x000e, "ICQDeny/Ignore" },
    + { 0x0014, "Buddy Icon" },
    + { 0x0015, "Recent Buddies" },
    + { 0x0019, "Non-Buddy" },
    + { 0x001d, "Vanity Info" },
    + { 0x0020, "ICQ-MDir" },
    + { 0x0029, "Facebook" },
    + };
    + int i;
    + for (i = 0; i < G_N_ELEMENTS(type_strings); i++) {
    + if (type_strings[i].type == type) {
    + return type_strings[i].string;
    + }
    + }
    + return "unknown";
    +}
    +
    +/** For debug log output: Appends a line containing information about a given list item to a string.
    + *
    + * @param str String to which the line will be appended.
    + * @param prefix A string which will be prepended to the line.
    + * @param item List item from which information is extracted.
    + */
    +static void
    +aim_ssi_item_debug_append(GString *str, char *prefix, struct aim_ssi_item *item)
    +{
    + g_string_append_printf(str,
    + "%s gid=0x%04hx, bid=0x%04hx, list_type=0x%04hx [%s], name=%s.\n",
    + prefix, item->gid, item->bid, item->type, aim_ssi_type_to_string(item->type), item->name);
    +}
    +
    +/**
    * Locally rebuild the 0x00c8 TLV in the additional data of the given group.
    *
    * @param list A pointer to a pointer to the current list of items.
    @@ -478,6 +534,7 @@
    struct aim_ssi_item *cur1, *cur2;
    struct aim_ssi_tmp *cur, *new;
    int n = 0;
    + GString *debugstr = g_string_new("");
    /*
    * The variable "n" is used to limit the number of addmoddel's that
    @@ -517,6 +574,7 @@
    cur->next = new;
    } else
    od->ssi.pending = new;
    + aim_ssi_item_debug_append(debugstr, "Deleting item ", cur1);
    }
    }
    }
    @@ -537,6 +595,7 @@
    cur->next = new;
    } else
    od->ssi.pending = new;
    + aim_ssi_item_debug_append(debugstr, "Adding item ", cur1);
    }
    }
    }
    @@ -558,9 +617,21 @@
    cur->next = new;
    } else
    od->ssi.pending = new;
    + aim_ssi_item_debug_append(debugstr, "Modifying item ", cur1);
    }
    }
    }
    + if (debugstr->len > 0) {
    + purple_debug_info("oscar", "%s", debugstr->str);
    + if (purple_debug_is_verbose()) {
    + g_string_truncate(debugstr, 0);
    + for (cur1 = od->ssi.local; cur1; cur1 = cur1->next)
    + aim_ssi_item_debug_append(debugstr, "\t", cur1);
    + purple_debug_misc("oscar", "Dumping item list of account %s:\n%s",
    + purple_connection_get_account(od->gc)->username, debugstr->str);
    + }
    + }
    + g_string_free(debugstr, TRUE);
    /* We're out of stuff to do, so tell the AIM servers we're done and exit */
    if (!od->ssi.pending) {
    @@ -1165,6 +1236,7 @@
    guint16 namelen, gid, bid, type;
    char *name;
    GSList *data;
    + GString *debugstr = g_string_new("");
    fmtver = byte_stream_get8(bs); /* Version of ssi data. Should be 0x00 */
    od->ssi.numitems += byte_stream_get16(bs); /* # of items in this SSI SNAC */
    @@ -1179,10 +1251,13 @@
    bid = byte_stream_get16(bs);
    type = byte_stream_get16(bs);
    data = aim_tlvlist_readlen(bs, byte_stream_get16(bs));
    - aim_ssi_itemlist_add(&od->ssi.official, name, gid, bid, type, data);
    + aim_ssi_item_debug_append(debugstr, "\t", aim_ssi_itemlist_add(&od->ssi.official, name, gid, bid, type, data));
    g_free(name);
    aim_tlvlist_free(data);
    }
    + purple_debug_misc("oscar", "Reading items from tlvlist for account %s:\n%s",
    + purple_connection_get_account(od->gc)->username, debugstr->str);
    + g_string_free(debugstr, TRUE);
    /* Read in the timestamp */
    od->ssi.timestamp = byte_stream_get32(bs);
    --- a/libpurple/protocols/zephyr/Zinternal.c Sun Jan 09 23:32:10 2011 +0000
    +++ b/libpurple/protocols/zephyr/Zinternal.c Wed Feb 02 23:26:42 2011 +0000
    @@ -30,7 +30,6 @@
    #else
    #include <arpa/inet.h>
    #include <sys/socket.h>
    -#include <utmp.h>
    #endif
    int __Zephyr_fd = -1;
    --- a/libpurple/protocols/zephyr/zephyr.c Sun Jan 09 23:32:10 2011 +0000
    +++ b/libpurple/protocols/zephyr/zephyr.c Wed Feb 02 23:26:42 2011 +0000
    @@ -870,12 +870,12 @@
    zephyr_triple *zt1, *zt2;
    gchar *send_inst_utf8;
    zephyr_account *zephyr = gc->proto_data;
    - zt1 = new_triple(gc->proto_data,notice.z_class, notice.z_class_inst, notice.z_recipient);
    - zt2 = find_sub_by_triple(gc->proto_data,zt1);
    + zt1 = new_triple(zephyr,notice.z_class, notice.z_class_inst, notice.z_recipient);
    + zt2 = find_sub_by_triple(zephyr,zt1);
    if (!zt2) {
    /* This is a server supplied subscription */
    zephyr->subscrips = g_slist_append(zephyr->subscrips, new_triple(zephyr,zt1->class,zt1->instance,zt1->recipient));
    - zt2 = find_sub_by_triple(gc->proto_data,zt1);
    + zt2 = find_sub_by_triple(zephyr,zt1);
    }
    if (!zt2->open) {
    @@ -1499,6 +1499,7 @@
    static void process_anyone(PurpleConnection *gc)
    {
    + zephyr_account *zephyr = purple_connection_get_protocol_data(gc);
    FILE *fd;
    gchar buff[BUFSIZ], *filename;
    PurpleGroup *g;
    @@ -1515,7 +1516,7 @@
    strip_comments(buff);
    if (buff[0]) {
    if (!(b = purple_find_buddy(gc->account, buff))) {
    - char *stripped_user = zephyr_strip_local_realm(gc->proto_data,buff);
    + char *stripped_user = zephyr_strip_local_realm(zephyr,buff);
    purple_debug_info("zephyr","stripped_user %s\n",stripped_user);
    if (!(b = purple_find_buddy(gc->account,stripped_user))){
    b = purple_buddy_new(gc->account, stripped_user, NULL);
    @@ -1924,13 +1925,12 @@
    fclose(fd);
    }
    -static void write_anyone(PurpleConnection *gc)
    +static void write_anyone(zephyr_account *zephyr)
    {
    GSList *buddies;
    char *fname;
    FILE *fd;
    PurpleAccount *account;
    - zephyr_account* zephyr = gc->proto_data;
    fname = g_strdup_printf("%s/.anyone", purple_home_dir());
    fd = g_fopen(fname, "w");
    if (!fd) {
    @@ -1938,7 +1938,7 @@
    return;
    }
    - account = purple_connection_get_account(gc);
    + account = zephyr->account;
    for (buddies = purple_find_buddies(account, NULL); buddies;
    buddies = g_slist_delete_link(buddies, buddies)) {
    PurpleBuddy *b = buddies->data;
    @@ -1966,10 +1966,10 @@
    g_list_free(zephyr->pending_zloc_names);
    if (purple_account_get_bool(gc->account, "write_anyone", FALSE))
    - write_anyone(gc);
    + write_anyone(zephyr);
    if (purple_account_get_bool(gc->account, "write_zsubs", FALSE))
    - write_zsubs(gc->proto_data);
    + write_zsubs(zephyr);
    s = zephyr->subscrips;
    while (s) {
    @@ -2032,7 +2032,7 @@
    char *recipient;
    zephyr_account *zephyr = gc->proto_data;
    - zt = find_sub_by_id(gc->proto_data,id);
    + zt = find_sub_by_id(zephyr,id);
    if (!zt)
    /* this should never happen. */
    return -EINVAL;
    @@ -2432,8 +2432,8 @@
    if (!g_ascii_strcasecmp(recip, "%me%"))
    recip = zephyr->username;
    - zt1 = new_triple(gc->proto_data,classname, instname, recip);
    - zt2 = find_sub_by_triple(gc->proto_data,zt1);
    + zt1 = new_triple(zephyr,classname, instname, recip);
    + zt2 = find_sub_by_triple(zephyr,zt1);
    if (zt2) {
    free_triple(zt1);
    if (!zt2->open) {
    @@ -2563,7 +2563,7 @@
    zephyr_account* zephyr = gc->proto_data;
    char *sender = (char *)zephyr->username;
    - zt = find_sub_by_id(gc->proto_data,id);
    + zt = find_sub_by_id(zephyr,id);
    /* find_sub_by_id can return NULL */
    if (!zt)
    return;
    --- a/libpurple/tests/Makefile.am Sun Jan 09 23:32:10 2011 +0000
    +++ b/libpurple/tests/Makefile.am Wed Feb 02 23:26:42 2011 +0000
    @@ -11,6 +11,7 @@
    tests.h \
    test_cipher.c \
    test_jabber_caps.c \
    + test_jabber_digest_md5.c \
    test_jabber_jutil.c \
    test_jabber_scram.c \
    test_qq.c \
    --- a/libpurple/tests/check_libpurple.c Sun Jan 09 23:32:10 2011 +0000
    +++ b/libpurple/tests/check_libpurple.c Wed Feb 02 23:26:42 2011 +0000
    @@ -85,6 +85,7 @@
    srunner_add_suite(sr, cipher_suite());
    srunner_add_suite(sr, jabber_caps_suite());
    + srunner_add_suite(sr, jabber_digest_md5_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_digest_md5.c Wed Feb 02 23:26:42 2011 +0000
    @@ -0,0 +1,59 @@
    +#include <string.h>
    +
    +#include "tests.h"
    +#include "../util.h"
    +#include "../protocols/jabber/auth_digest_md5.h"
    +#include "../protocols/jabber/jutil.h"
    +
    +START_TEST(test_parsing)
    +{
    + GHashTable *table;
    +
    + table = jabber_auth_digest_md5_parse("r=\"realm\",token= \" asdf\"");
    + fail_if(g_hash_table_lookup(table, "r") == NULL);
    + assert_string_equal("realm", g_hash_table_lookup(table, "r"));
    + fail_if(g_hash_table_lookup(table, "token") == NULL);
    + assert_string_equal("asdf", g_hash_table_lookup(table, "token"));
    + g_hash_table_destroy(table);
    +
    + table = jabber_auth_digest_md5_parse("r=\"a\", token= \" asdf\"");
    + fail_if(g_hash_table_lookup(table, "r") == NULL);
    + assert_string_equal("a", g_hash_table_lookup(table, "r"));
    + fail_if(g_hash_table_lookup(table, "token") == NULL);
    + assert_string_equal("asdf", g_hash_table_lookup(table, "token"));
    + g_hash_table_destroy(table);
    +
    + table = jabber_auth_digest_md5_parse("r=\"\", token= \" asdf\"");
    + fail_if(g_hash_table_lookup(table, "r") == NULL);
    + assert_string_equal("", g_hash_table_lookup(table, "r"));
    + fail_if(g_hash_table_lookup(table, "token") == NULL);
    + assert_string_equal("asdf", g_hash_table_lookup(table, "token"));
    + g_hash_table_destroy(table);
    +
    + table = jabber_auth_digest_md5_parse("realm=\"somerealm\",nonce=\"OA6MG9tEQGm2hh\",qop=\"auth\",charset=utf-8,algorithm=md5-sess");
    + fail_if(g_hash_table_lookup(table, "realm") == NULL);
    + assert_string_equal("somerealm", g_hash_table_lookup(table, "realm"));
    + fail_if(g_hash_table_lookup(table, "nonce") == NULL);
    + assert_string_equal("OA6MG9tEQGm2hh", g_hash_table_lookup(table, "nonce"));
    + fail_if(g_hash_table_lookup(table, "qop") == NULL);
    + assert_string_equal("auth", g_hash_table_lookup(table, "qop"));
    + fail_if(g_hash_table_lookup(table, "charset") == NULL);
    + assert_string_equal("utf-8", g_hash_table_lookup(table, "charset"));
    + fail_if(g_hash_table_lookup(table, "algorithm") == NULL);
    + assert_string_equal("md5-sess", g_hash_table_lookup(table, "algorithm"));
    +
    + g_hash_table_destroy(table);
    +
    +}
    +END_TEST
    +
    +Suite *
    +jabber_digest_md5_suite(void)
    +{
    + Suite *s = suite_create("Jabber SASL DIGEST-MD5 functions");
    +
    + TCase *tc = tcase_create("Parsing Functionality");
    + tcase_add_test(tc, test_parsing);
    + suite_add_tcase(s, tc);
    + return s;
    +}
    --- a/libpurple/tests/tests.h Sun Jan 09 23:32:10 2011 +0000
    +++ b/libpurple/tests/tests.h Wed Feb 02 23:26:42 2011 +0000
    @@ -10,6 +10,7 @@
    Suite * master_suite(void);
    Suite * cipher_suite(void);
    Suite * jabber_caps_suite(void);
    +Suite * jabber_digest_md5_suite(void);
    Suite * jabber_jutil_suite(void);
    Suite * jabber_scram_suite(void);
    Suite * qq_suite(void);
    --- a/pidgin/gtkutils.c Sun Jan 09 23:32:10 2011 +0000
    +++ b/pidgin/gtkutils.c Wed Feb 02 23:26:42 2011 +0000
    @@ -526,35 +526,68 @@
    }
    static gpointer
    -aop_option_menu_get_selected(GtkWidget *optmenu)
    +aop_option_menu_get_selected(GtkWidget *optmenu, GtkWidget **p_item)
    {
    - gpointer data = NULL;
    - GtkTreeIter iter;
    -
    - g_return_val_if_fail(optmenu != NULL, NULL);
    -
    - if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(optmenu), &iter))
    - gtk_tree_model_get(gtk_combo_box_get_model(GTK_COMBO_BOX(optmenu)), &iter, 2, &data, -1);
    -
    - return data;
    + GtkWidget *menu = gtk_option_menu_get_menu(GTK_OPTION_MENU(optmenu));
    + GtkWidget *item = gtk_menu_get_active(GTK_MENU(menu));
    + if (p_item)
    + (*p_item) = item;
    + return item ? g_object_get_data(G_OBJECT(item), "aop_per_item_data") : NULL;
    }
    static void
    aop_menu_cb(GtkWidget *optmenu, GCallback cb)
    {
    + GtkWidget *item;
    + gpointer per_item_data;
    +
    + per_item_data = aop_option_menu_get_selected(optmenu, &item);
    +
    if (cb != NULL) {
    - ((void (*)(GtkWidget *, gpointer, gpointer))cb)(optmenu,
    - aop_option_menu_get_selected(optmenu),
    - g_object_get_data(G_OBJECT(optmenu), "user_data"));
    + ((void (*)(GtkWidget *, gpointer, gpointer))cb)(item, per_item_data, g_object_get_data(G_OBJECT(optmenu), "user_data"));
    }
    }
    -static void
    -aop_option_menu_replace_menu(GtkWidget *optmenu, AopMenu *new_aop_menu)
    +static GtkWidget *
    +aop_menu_item_new(GtkSizeGroup *sg, GdkPixbuf *pixbuf, const char *lbl, gpointer per_item_data, const char *data)
    {
    - gtk_combo_box_set_model(GTK_COMBO_BOX(optmenu), new_aop_menu->model);
    - gtk_combo_box_set_active(GTK_COMBO_BOX(optmenu), new_aop_menu->default_item);
    - g_object_set_data_full(G_OBJECT(optmenu), "aop_menu", new_aop_menu, (GDestroyNotify)g_free);
    + GtkWidget *item;
    + GtkWidget *hbox;
    + GtkWidget *image;
    + GtkWidget *label;
    +
    + item = gtk_menu_item_new();
    + gtk_widget_show(item);
    +
    + hbox = gtk_hbox_new(FALSE, 4);
    + gtk_widget_show(hbox);
    +
    + /* Create the image */
    + if (pixbuf == NULL)
    + image = gtk_image_new();
    + else
    + image = gtk_image_new_from_pixbuf(pixbuf);
    + gtk_widget_show(image);
    +
    + if (sg)
    + gtk_size_group_add_widget(sg, image);
    +
    + /* Create the label */
    + label = gtk_label_new (lbl);
    + gtk_widget_show (label);
    + gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
    + gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
    +
    + gtk_container_add(GTK_CONTAINER(item), hbox);
    + gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 0);
    + gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
    +
    + g_object_set_data(G_OBJECT (item), data, per_item_data);
    + g_object_set_data(G_OBJECT (item), "aop_per_item_data", per_item_data);
    +
    + pidgin_set_accessible_label(item, label);
    +
    + return item;
    }
    static GdkPixbuf *
    @@ -595,19 +628,16 @@
    static GtkWidget *
    aop_option_menu_new(AopMenu *aop_menu, GCallback cb, gpointer user_data)
    {
    - GtkWidget *optmenu = NULL;
    - GtkCellRenderer *cr = NULL;
    -
    - optmenu = gtk_combo_box_new();
    + GtkWidget *optmenu;
    +
    + optmenu = gtk_option_menu_new();
    gtk_widget_show(optmenu);
    - gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(optmenu), cr = gtk_cell_renderer_pixbuf_new(), FALSE);
    - gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(optmenu), cr, "pixbuf", 0);
    - gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(optmenu), cr = gtk_cell_renderer_text_new(), TRUE);
    - gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(optmenu), cr, "text", 1);
    -
    - aop_option_menu_replace_menu(optmenu, aop_menu);
    - if (aop_menu->default_item == -1)
    - gtk_combo_box_set_active(GTK_COMBO_BOX(optmenu), 0);
    + gtk_option_menu_set_menu(GTK_OPTION_MENU(optmenu), aop_menu->menu);
    +
    + if (aop_menu->default_item != -1)
    + gtk_option_menu_set_history(GTK_OPTION_MENU(optmenu), aop_menu->default_item);
    +
    + g_object_set_data_full(G_OBJECT(optmenu), "aop_menu", aop_menu, (GDestroyNotify)g_free);
    g_object_set_data(G_OBJECT(optmenu), "user_data", user_data);
    g_signal_connect(G_OBJECT(optmenu), "changed", G_CALLBACK(aop_menu_cb), cb);
    @@ -616,20 +646,32 @@
    }
    static void
    +aop_option_menu_replace_menu(GtkWidget *optmenu, AopMenu *new_aop_menu)
    +{
    + if (gtk_option_menu_get_menu(GTK_OPTION_MENU(optmenu)))
    + gtk_option_menu_remove_menu(GTK_OPTION_MENU(optmenu));
    +
    + gtk_option_menu_set_menu(GTK_OPTION_MENU(optmenu), new_aop_menu->menu);
    +
    + if (new_aop_menu->default_item != -1)
    + gtk_option_menu_set_history(GTK_OPTION_MENU(optmenu), new_aop_menu->default_item);
    +
    + g_object_set_data_full(G_OBJECT(optmenu), "aop_menu", new_aop_menu, (GDestroyNotify)g_free);
    +}
    +
    +static void
    aop_option_menu_select_by_data(GtkWidget *optmenu, gpointer data)
    {
    - GtkTreeModel *model;
    - GtkTreeIter iter;
    - gpointer iter_data;
    - model = gtk_combo_box_get_model(GTK_COMBO_BOX(optmenu));
    - if (gtk_tree_model_get_iter_first(model, &iter)) {
    - do {
    - gtk_tree_model_get(model, &iter, 2, &iter_data, -1);
    - if (iter_data == data) {
    - gtk_combo_box_set_active_iter(GTK_COMBO_BOX(optmenu), &iter);
    - return;
    - }
    - } while (gtk_tree_model_iter_next(model, &iter));
    + guint idx;
    + GList *llItr = NULL;
    +
    + for (idx = 0, llItr = GTK_MENU_SHELL(gtk_option_menu_get_menu(GTK_OPTION_MENU(optmenu)))->children;
    + llItr != NULL;
    + llItr = llItr->next, idx++) {
    + if (data == g_object_get_data(G_OBJECT(llItr->data), "aop_per_item_data")) {
    + gtk_option_menu_set_history(GTK_OPTION_MENU(optmenu), idx);
    + break;
    + }
    }
    }
    @@ -639,17 +681,16 @@
    AopMenu *aop_menu = NULL;
    PurplePlugin *plugin;
    GdkPixbuf *pixbuf = NULL;
    - GtkTreeIter iter;
    - GtkListStore *ls;
    + GtkSizeGroup *sg;
    GList *p;
    const char *gtalk_name = NULL, *facebook_name = NULL;
    int i;
    - ls = gtk_list_store_new(3, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_POINTER);
    -
    aop_menu = g_malloc0(sizeof(AopMenu));
    aop_menu->default_item = -1;
    - aop_menu->model = GTK_TREE_MODEL(ls);
    + aop_menu->menu = gtk_menu_new();
    + gtk_widget_show(aop_menu->menu);
    + sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
    if (purple_find_prpl("prpl-jabber")) {
    gtalk_name = _("Google Talk");
    @@ -665,11 +706,14 @@
    if (gtalk_name && strcmp(gtalk_name, plugin->info->name) < 0) {
    char *filename = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols",
    "16", "google-talk.png", NULL);
    + GtkWidget *item;
    +
    pixbuf = gdk_pixbuf_new_from_file(filename, NULL);
    g_free(filename);
    - gtk_list_store_append(ls, &iter);
    - gtk_list_store_set(ls, &iter, 0, pixbuf, 1, gtalk_name, 2, "prpl-jabber", -1);
    + gtk_menu_shell_append(GTK_MENU_SHELL(aop_menu->menu),
    + item = aop_menu_item_new(sg, pixbuf, gtalk_name, "prpl-jabber", "protocol"));
    + g_object_set_data(G_OBJECT(item), "fakegoogle", GINT_TO_POINTER(1));
    if (pixbuf)
    g_object_unref(pixbuf);
    @@ -686,8 +730,9 @@
    pixbuf = gdk_pixbuf_new_from_file(filename, NULL);
    g_free(filename);
    - gtk_list_store_append(ls, &iter);
    - gtk_list_store_set(ls, &iter, 0, pixbuf, 1, facebook_name, 2, "prpl-jabber", -1);
    + gtk_menu_shell_append(GTK_MENU_SHELL(aop_menu->menu),
    + item = aop_menu_item_new(sg, pixbuf, facebook_name, "prpl-jabber", "protocol"));
    + g_object_set_data(G_OBJECT(item), "fakefacebook", GINT_TO_POINTER(1));
    if (pixbuf)
    g_object_unref(pixbuf);
    @@ -698,8 +743,8 @@
    pixbuf = pidgin_create_prpl_icon_from_prpl(plugin, PIDGIN_PRPL_ICON_SMALL, NULL);
    - gtk_list_store_append(ls, &iter);
    - gtk_list_store_set(ls, &iter, 0, pixbuf, 1, plugin->info->name, 2, plugin->info->id, -1);
    + gtk_menu_shell_append(GTK_MENU_SHELL(aop_menu->menu),
    + aop_menu_item_new(sg, pixbuf, plugin->info->name, plugin->info->id, "protocol"));
    if (pixbuf)
    g_object_unref(pixbuf);
    @@ -707,6 +752,9 @@
    if (default_proto_id != NULL && !strcmp(plugin->info->id, default_proto_id))
    aop_menu->default_item = i;
    }
    +
    + g_object_unref(sg);
    +
    return aop_menu;
    }
    @@ -720,13 +768,13 @@
    const char *
    pidgin_protocol_option_menu_get_selected(GtkWidget *optmenu)
    {
    - return (const char *)aop_option_menu_get_selected(optmenu);
    + return (const char *)aop_option_menu_get_selected(optmenu, NULL);
    }
    PurpleAccount *
    pidgin_account_option_menu_get_selected(GtkWidget *optmenu)
    {
    - return (PurpleAccount *)aop_option_menu_get_selected(optmenu);
    + return (PurpleAccount *)aop_option_menu_get_selected(optmenu, NULL);
    }
    static AopMenu *
    @@ -738,8 +786,7 @@
    GdkPixbuf *pixbuf = NULL;
    GList *list;
    GList *p;
    - GtkListStore *ls;
    - GtkTreeIter iter;
    + GtkSizeGroup *sg;
    int i;
    char buf[256];
    @@ -748,11 +795,11 @@
    else
    list = purple_connections_get_all();
    - ls = gtk_list_store_new(3, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_POINTER);
    -
    aop_menu = g_malloc0(sizeof(AopMenu));
    aop_menu->default_item = -1;
    - aop_menu->model = GTK_TREE_MODEL(ls);
    + aop_menu->menu = gtk_menu_new();
    + gtk_widget_show(aop_menu->menu);
    + sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
    for (p = list, i = 0; p != NULL; p = p->next, i++) {
    if (show_all)
    @@ -787,8 +834,8 @@
    purple_account_get_protocol_name(account));
    }
    - gtk_list_store_append(ls, &iter);
    - gtk_list_store_set(ls, &iter, 0, pixbuf, 1, buf, 2, account, -1);
    + gtk_menu_shell_append(GTK_MENU_SHELL(aop_menu->menu),
    + aop_menu_item_new(sg, pixbuf, buf, account, "account"));
    if (pixbuf)
    g_object_unref(pixbuf);
    @@ -796,6 +843,9 @@
    if (default_account && account == default_account)
    aop_menu->default_item = i;
    }
    +
    + g_object_unref(sg);
    +
    return aop_menu;
    }
    @@ -806,7 +856,7 @@
    PurpleAccount *account;
    PurpleFilterAccountFunc filter_func;
    - account = (PurpleAccount *)aop_option_menu_get_selected(optmenu);
    + account = (PurpleAccount *)aop_option_menu_get_selected(optmenu, NULL);
    show_all = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(optmenu), "show_all"));
    filter_func = g_object_get_data(G_OBJECT(optmenu), "filter_func");
    @@ -876,6 +926,24 @@
    return optmenu;
    }
    +gboolean
    +pidgin_check_if_dir(const char *path, GtkFileSelection *filesel)
    +{
    + char *dirname = NULL;
    +
    + if (g_file_test(path, G_FILE_TEST_IS_DIR)) {
    + /* append a / if needed */
    + if (path[strlen(path) - 1] != G_DIR_SEPARATOR) {
    + dirname = g_strconcat(path, G_DIR_SEPARATOR_S, NULL);
    + }
    + gtk_file_selection_set_filename(filesel, (dirname != NULL) ? dirname : path);
    + g_free(dirname);
    + return TRUE;
    + }
    +
    + return FALSE;
    +}
    +
    void
    pidgin_setup_gtkspell(GtkTextView *textview)
    {
    @@ -1394,6 +1462,7 @@
    static void dnd_image_ok_callback(_DndData *data, int choice)
    {
    + const gchar *shortname;
    gchar *filedata;
    size_t size;
    struct stat st;
    @@ -1448,7 +1517,9 @@
    break;
    }
    - id = purple_imgstore_add_with_id(filedata, size, data->filename);
    + shortname = strrchr(data->filename, G_DIR_SEPARATOR);
    + shortname = shortname ? shortname + 1 : data->filename;
    + id = purple_imgstore_add_with_id(filedata, size, shortname);
    gtk_text_buffer_get_iter_at_mark(GTK_IMHTML(gtkconv->entry)->text_buffer, &iter,
    gtk_text_buffer_get_insert(GTK_IMHTML(gtkconv->entry)->text_buffer));
    --- a/pidgin/plugins/vvconfig.c Sun Jan 09 23:32:10 2011 +0000
    +++ b/pidgin/plugins/vvconfig.c Wed Feb 02 23:26:42 2011 +0000
    @@ -82,20 +82,11 @@
    GstPropertyProbe *probe;
    const GParamSpec *pspec;
    - if (!strcmp(element_name, "<custom>")) {
    - ret = g_list_prepend(ret, NULL);
    - ret = g_list_prepend(ret, (gpointer)_("Default"));
    - ret = g_list_prepend(ret, "");
    - return ret;
    - }
    -
    ret = g_list_prepend(ret, (gpointer)_("Default"));
    ret = g_list_prepend(ret, "");
    - if (*element_name == '\0') {
    - ret = g_list_prepend(ret, NULL);
    - ret = g_list_reverse(ret);
    - return ret;
    + if (!strcmp(element_name, "<custom>") || (*element_name == '\0')) {
    + return g_list_reverse(ret);
    }
    element = gst_element_factory_make(element_name, "test");
    @@ -120,9 +111,7 @@
    array = gst_property_probe_probe_and_get_values (probe, pspec);
    if (array == NULL) {
    purple_debug_info("vvconfig", "'%s' has no devices\n", element_name);
    - ret = g_list_prepend(ret, NULL);
    - ret = g_list_reverse(ret);
    - return ret;
    + return g_list_reverse(ret);
    }
    for (n=0; n < array->n_values; ++n) {
    @@ -153,10 +142,7 @@
    }
    gst_object_unref(element);
    - ret = g_list_prepend(ret, NULL);
    - ret = g_list_reverse(ret);
    -
    - return ret;
    + return g_list_reverse(ret);
    }
    static GList *
    @@ -173,7 +159,6 @@
    ret = g_list_prepend(ret, (gpointer)plugins[0]);
    }
    }
    - ret = g_list_prepend(ret, NULL);
    ret = g_list_reverse(ret);
    return ret;
    }
    @@ -236,7 +221,8 @@
    pref = g_strdup(name);
    strcpy(pref + strlen(pref) - strlen("plugin"), "device");
    devices = get_element_devices(value);
    - if (g_list_find(devices, purple_prefs_get_string(pref)) == NULL)
    + if (g_list_find_custom(devices, purple_prefs_get_string(pref),
    + (GCompareFunc)strcmp) == NULL)
    purple_prefs_set_string(pref, g_list_next(devices)->data);
    widget = pidgin_prefs_dropdown_from_list(parent,
    label, PURPLE_PREF_STRING,
    --- a/pidgin/win32/nsis/pidgin-installer.nsi Sun Jan 09 23:32:10 2011 +0000
    +++ b/pidgin/win32/nsis/pidgin-installer.nsi Wed Feb 02 23:26:42 2011 +0000
    @@ -530,6 +530,7 @@
    Push "xmpp"
    Call un.UnregisterURIHandler
    + Delete "$INSTDIR\ca-certs\AddTrust_External_Root.pem"
    Delete "$INSTDIR\ca-certs\America_Online_Root_Certification_Authority_1.pem"
    Delete "$INSTDIR\ca-certs\AOL_Member_CA.pem"
    Delete "$INSTDIR\ca-certs\CAcert_Class3.pem"
    --- a/pidgin/win32/winpidgin.c Sun Jan 09 23:32:10 2011 +0000
    +++ b/pidgin/win32/winpidgin.c Wed Feb 02 23:26:42 2011 +0000
    @@ -632,11 +632,11 @@
    } else {
    if (strchr(__argv[i], 'd'))
    debug = TRUE;
    - else if (strchr(__argv[i], 'h'))
    + if (strchr(__argv[i], 'h'))
    help = TRUE;
    - else if (strchr(__argv[i], 'v'))
    + if (strchr(__argv[i], 'v'))
    version = TRUE;
    - else if (strchr(__argv[i], 'm'))
    + if (strchr(__argv[i], 'm'))
    multiple = TRUE;
    }
    }
    --- a/po/POTFILES.in Sun Jan 09 23:32:10 2011 +0000
    +++ b/po/POTFILES.in Wed Feb 02 23:26:42 2011 +0000
    @@ -124,8 +124,8 @@
    libpurple/protocols/mxit/filexfer.c
    libpurple/protocols/mxit/http.c
    libpurple/protocols/mxit/login.c
    +libpurple/protocols/mxit/multimx.c
    libpurple/protocols/mxit/mxit.c
    -libpurple/protocols/mxit/multimx.c
    libpurple/protocols/mxit/profile.c
    libpurple/protocols/mxit/protocol.c
    libpurple/protocols/mxit/roster.c
    @@ -148,8 +148,8 @@
    libpurple/protocols/oscar/oft.c
    libpurple/protocols/oscar/oscar.c
    libpurple/protocols/oscar/peer.c
    +libpurple/protocols/oscar/userinfo.c
    libpurple/protocols/oscar/util.c
    -libpurple/protocols/oscar/userinfo.c
    libpurple/protocols/oscar/visibility.c
    libpurple/protocols/qq/buddy_info.c
    libpurple/protocols/qq/buddy_list.c
    --- a/po/ar.po Sun Jan 09 23:32:10 2011 +0000
    +++ b/po/ar.po Wed Feb 02 23:26:42 2011 +0000
    @@ -747,9 +747,9 @@
    #, c-format
    msgid "File Transfers - %d%% of %d file"
    msgid_plural "File Transfers - %d%% of %d files"
    -msgstr[0] "نقل الملفات - %d%% من %0.sصفر ملفات"
    -msgstr[1] "نقل الملفات - %d%% من %0.sملف واحد"
    -msgstr[2] "نقل الملفات - %d%% من %0.sملفين"
    +msgstr[0] "نقل الملفات - %d%% من صفر ملفات"
    +msgstr[1] "نقل الملفات - %d%% من ملف واحد"
    +msgstr[2] "نقل الملفات - %d%% من ملفين"
    msgstr[3] "نقل الملفات - %d%% من %d ملفات"
    msgstr[4] "نقل الملفات - %d%% من %d ملفا"
    msgstr[5] "نقل الملفات - %d%% من %d ملف"
    @@ -921,9 +921,9 @@
    #, c-format
    msgid "%s (%s) has %d new message."
    msgid_plural "%s (%s) has %d new messages."
    -msgstr[0] "لا رسائل%0.s جديدة لـ ‏%s (%s)."
    -msgstr[1] "‏%s (%s) لديه %0.sرسالة واحدة جديدة"
    -msgstr[2] "‏%s (%s) لديه %0.sرسالتان جديدتان."
    +msgstr[0] "لا رسائل جديدة لـ ‏%s ‏(%s)."
    +msgstr[1] "‏%s (%s) لديه رسالة واحدة جديدة"
    +msgstr[2] "‏%s (%s) لديه رسالتان جديدتان."
    msgstr[3] "‏%s (%s) لديه %d رسائل جديدة."
    msgstr[4] "‏%s (%s) لديه %d رسالة جديدة."
    msgstr[5] "‏%s (%s) لديه %d رسالة جديدة."
    @@ -11231,9 +11231,9 @@
    #, c-format
    msgid "%s, %d hour"
    msgid_plural "%s, %d hours"
    -msgstr[0] "%s، %0.sلا ساعات"
    -msgstr[1] "‏%s، %0.sساعة واحدة"
    -msgstr[2] "‏%s، %0.sساعتين"
    +msgstr[0] "%s، لا ساعات"
    +msgstr[1] "‏%s، ساعة واحدة"
    +msgstr[2] "‏%s، ساعتين"
    msgstr[3] "‏%s، %d ساعات"
    msgstr[4] "‏%s، %d ساعة"
    msgstr[5] "‏%s، %d ساعة"
    @@ -11251,9 +11251,9 @@
    #, c-format
    msgid "%s, %d minute"
    msgid_plural "%s, %d minutes"
    -msgstr[0] "‏%s، %0.sلا دقائق"
    -msgstr[1] "‏%s، %0.sدقيقة واحدة"
    -msgstr[2] "‏%s، %0.sدقيقتين"
    +msgstr[0] "‏%s، لا دقائق"
    +msgstr[1] "‏%s، دقيقة واحدة"
    +msgstr[2] "‏%s، دقيقتين"
    msgstr[3] "%s، %d دقائق"
    msgstr[4] "%s، %d دقيقة"
    msgstr[5] "%s، %d دقيقة"
    @@ -11604,13 +11604,12 @@
    msgid "The text information for a buddy's status"
    msgstr "غيّر معلومات المستخدم لأجل %s"
    -#, c-format
    msgid "You have %d contact named %s. Would you like to merge them?"
    msgid_plural ""
    "You currently have %d contacts named %s. Would you like to merge them?"
    -msgstr[0] "لا مراسلين%0.s لديك باسم %s. أتريد دمجهم؟"
    -msgstr[1] "لديك مراسل واحد%0.s باسم %s. أتريد دمجه؟"
    -msgstr[2] "لديك مراسليْن%0.s باسم %s. أتريد دمجهما؟"
    +msgstr[0] "%0.sلا مراسلين لديك باسم %s. أتريد دمجهم؟"
    +msgstr[1] "%0.sلديك مراسل واحد باسم %s. أتريد دمجه؟"
    +msgstr[2] "%0.sلديك مراسليْن باسم %s. أتريد دمجهما؟"
    msgstr[3] "لديك %d مراسلين باسم %s. أتريد دمجهم؟"
    msgstr[4] "لديك %d مراسلا باسم %s. أتريد دمجهم؟"
    msgstr[5] "لديك %d مراسل باسم %s. أتريد دمجهم؟"
    @@ -11948,12 +11947,11 @@
    msgid "/Tools/Room List"
    msgstr "/الأدوات/قائمة الغرف"
    -#, c-format
    msgid "%d unread message from %s\n"
    msgid_plural "%d unread messages from %s\n"
    -msgstr[0] "لا رسائل%0.s غير مقروءة من %s\n"
    -msgstr[1] "رسالة واحدة%0.s غير مقروءة من %s\n"
    -msgstr[2] "رسالتان%0.s غير مقروءتان من %s\n"
    +msgstr[0] "%0.sلا رسائل غير مقروءة من %s\n"
    +msgstr[1] "%0.sرسالة واحدة غير مقروءة من %s\n"
    +msgstr[2] "%0.sرسالتان غير مقروءتان من %s\n"
    msgstr[3] "%d رسائل غير مقروءة من %s\n"
    msgstr[4] "%d رسالة غير مقروءة من %s\n"
    msgstr[5] "%d رسالة غير مقروءة من %s\n"
    @@ -12932,13 +12930,13 @@
    "You are about to remove the contact containing %s and %d other buddies from "
    "your buddy list. Do you want to continue?"
    msgstr[0] ""
    -"أنت بصدد إزالة مراسل يحتوي %s و %0.sلا أصدقاء من قائمة أصدقائك. هل تريد "
    +"أنت بصدد إزالة مراسل يحتوي %s ولا أصدقاء من قائمة أصدقائك. هل تريد "
    "الاستمرار؟"
    msgstr[1] ""
    -"أنت بصدد إزالة مراسل يحتوي %s و %0.sصديق آخر من قائمة أصدقائك. هل تريد "
    +"أنت بصدد إزالة مراسل يحتوي %s وصديق آخر من قائمة أصدقائك. هل تريد "
    "الاستمرار؟"
    msgstr[2] ""
    -"أنت بصدد إزالة مراسل يحتوي %s و %0.sصديقين آخرين من قائمة أصدقائك. هل تريد "
    +"أنت بصدد إزالة مراسل يحتوي %s وصديقين آخرين من قائمة أصدقائك. هل تريد "
    "الاستمرار؟"
    msgstr[3] ""
    "أنت بصدد إزالة مراسل يحتوي %s و %d أصدقاء آخرين من قائمة أصدقائك. هل تريد "
    @@ -13504,12 +13502,12 @@
    #, c-format
    msgid "%s has %d new message."
    msgid_plural "%s has %d new messages."
    -msgstr[0] "لا رسائل%0.s جديدة ل %s."
    -msgstr[1] "رسالة%0.s جديدة ل %s."
    -msgstr[2] "رسالتان%0.s جديدتان ل %s."
    -msgstr[3] "%Id رسائل جديدة ل %s."
    -msgstr[4] "%Id رسالة جديدة ل %s."
    -msgstr[5] "%Id رسالة جديدة ل %s."
    +msgstr[0] "لا رسائل جديدة ل‍ %s."
    +msgstr[1] "رسالة جديدة ل‍ %s."
    +msgstr[2] "رسالتان جديدتان ل‍ %s."
    +msgstr[3] "%2$d رسائل جديدة ل‍ %1$s."
    +msgstr[4] "%2$d رسالة جديدة ل‍ %1$s."
    +msgstr[5] "%2$d رسالة جديدة ل‍ %1$s."
    #, c-format
    msgid "<b>%d new email.</b>"
    --- a/po/az.po Sun Jan 09 23:32:10 2011 +0000
    +++ b/po/az.po Wed Feb 02 23:26:42 2011 +0000
    @@ -15,7 +15,7 @@
    "MIME-Version: 1.0\n"
    "Content-Type: text/plain; charset=UTF-8\n"
    "Content-Transfer-Encoding: 8bit\n"
    -"Plural-Forms: Plural-Forms: nplurals=2; plural=(n != 1);\n"
    +"Plural-Forms: nplurals=2; plural=(n != 1);\n"
    "X-Generator: KBabel 1.3\n"
    #. Translators may want to transliterate the name.
    --- a/po/ca.po Sun Jan 09 23:32:10 2011 +0000
    +++ b/po/ca.po Wed Feb 02 23:26:42 2011 +0000
    @@ -3,7 +3,7 @@
    # Copyright (C) unknown, Robert Millan <zeratul2@wanadoo.es>
    # Copyright (C) December 2003 (from 2003-12-12 until 2003-12-18),
    # January (2004-01-07,12), Xan <dxpublica@telefonica.net>
    -# Copyright (c) 2004, 2005, 2006, 2007, 2008, 2009, 2010
    +# Copyright (c) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
    # Josep Puigdemont i Casamajó <josep.puigdemont@gmail.com>
    #
    # This file is distributed under the same license as the Pidgin package.
    @@ -33,8 +33,8 @@
    msgstr ""
    "Project-Id-Version: Pidgin\n"
    "Report-Msgid-Bugs-To: \n"
    -"POT-Creation-Date: 2010-12-23 07:57+0100\n"
    -"PO-Revision-Date: 2010-12-23 08:04+0100\n"
    +"POT-Creation-Date: 2011-01-30 11:04+0100\n"
    +"PO-Revision-Date: 2011-01-30 11:11+0100\n"
    "Last-Translator: Josep Puigdemont i Casamajó <josep.puigdemont@gmail.com>\n"
    "Language-Team: Catalan <tradgnome@softcatala.net>\n"
    "Language: ca\n"
    @@ -2387,9 +2387,12 @@
    "Camí on desar els fitxers\n"
    "(introduïu tot el camí)"
    -msgid "Automatically reject from users not in buddy list"
    -msgstr ""
    -"Rebutja automàticament dels usuaris que no estiguin a la llista d'amics"
    +msgid ""
    +"When a file-transfer request arrives from a user who is\n"
    +"*not* on your buddy list:"
    +msgstr ""
    +"Quan arribi una sol·licitud de transferència d'un fitxer d'un\n"
    +"usuari que *no* és a la vostra llista d'amics:"
    msgid ""
    "Notify with a popup when an autoaccepted file transfer is complete\n"
    @@ -2402,6 +2405,10 @@
    msgid "Create a new directory for each user"
    msgstr "Crea un directori nou per a cada usuari"
    +#, fuzzy
    +msgid "Escape the filenames"
    +msgstr "%s ha cancel·lat la transferència del fitxer"
    +
    msgid "Notes"
    msgstr "Notes"
    @@ -3859,7 +3866,10 @@
    msgid "Server requires plaintext authentication over an unencrypted stream"
    msgstr "El servidor requereix autenticació de text sobre un flux no xifrat"
    -#. This should never happen!
    +#. This happens when the server sends back jibberish
    +#. * in the "additional data with success" case.
    +#. * Seen with Wildfire 3.0.1.
    +#.
    msgid "Invalid response from server"
    msgstr "La resposta del servidor no és vàlida"
    @@ -6201,6 +6211,20 @@
    msgid "Retrieving User Information..."
    msgstr "S'està obtenint informació de l'usuari..."
    +#. you were kicked
    +msgid "You have been kicked from this MultiMX."
    +msgstr "Us han fet fora d'aquest MultiMX."
    +
    +msgid "was kicked"
    +msgstr "ha estat fet fora"
    +
    +msgid "_Room Name:"
    +msgstr "Nom de la _Sala:"
    +
    +#. Display system message in chat window
    +msgid "You have invited"
    +msgstr "Heu convidat"
    +
    msgid "Loading menu..."
    msgstr "S'està carregant el menú..."
    @@ -6229,20 +6253,6 @@
    msgid "Enable splash-screen popup"
    msgstr "Habilita la pantalla de presentació emergent"
    -#. you were kicked
    -msgid "You have been kicked from this MultiMX."
    -msgstr "Us han fet fora d'aquest MultiMX."
    -
    -msgid "was kicked"
    -msgstr "ha estat fet fora"
    -
    -msgid "_Room Name:"
    -msgstr "Nom de la _Sala:"
    -
    -#. Display system message in chat window
    -msgid "You have invited"
    -msgstr "Heu convidat"
    -
    msgid "Last Online"
    msgstr "Darrer cop en línia"
    @@ -7917,75 +7927,6 @@
    "necessari per poder enviar imatges instantànies. Atès que es revelarà la "
    "vostra adreça IP, això es pot considerar un risc de privadesa."
    -msgid "Invalid SNAC"
    -msgstr "SNAC invàlid"
    -
    -msgid "Server rate limit exceeded"
    -msgstr "S'ha excedit el límit de velocitat del servidor"
    -
    -msgid "Client rate limit exceeded"
    -msgstr "S'ha excedit el límit de velocitat del client"
    -
    -msgid "Service unavailable"
    -msgstr "Servei no disponible"
    -
    -msgid "Service not defined"
    -msgstr "Servei no definit"
    -
    -msgid "Obsolete SNAC"
    -msgstr "SNAC obsolet"
    -
    -msgid "Not supported by host"
    -msgstr "El servidor no ho permet"
    -
    -msgid "Not supported by client"
    -msgstr "El client no ho permet"
    -
    -msgid "Refused by client"
    -msgstr "Rebutjat pel client"
    -
    -msgid "Reply too big"
    -msgstr "Resposta massa gran"
    -
    -msgid "Responses lost"
    -msgstr "S'han perdut respostes"
    -
    -msgid "Request denied"
    -msgstr "Petició denegada"
    -
    -msgid "Busted SNAC payload"
    -msgstr "Càrrega SNAC malmesa"
    -
    -msgid "Insufficient rights"
    -msgstr "Drets insuficients"
    -
    -msgid "In local permit/deny"
    -msgstr "En la llista de permès/denegat local"
    -
    -msgid "Warning level too high (sender)"
    -msgstr "Nivell d'avís massa alt (remitent)"
    -
    -msgid "Warning level too high (receiver)"
    -msgstr "Nivell d'avís massa alt (receptor)"
    -
    -msgid "User temporarily unavailable"
    -msgstr "Usuari no disponible temporalment"
    -
    -msgid "No match"
    -msgstr "Cap coincidència"
    -
    -msgid "List overflow"
    -msgstr "Sobreeiximent de la llista"
    -
    -msgid "Request ambiguous"
    -msgstr "Petició ambigua"
    -
    -msgid "Queue full"
    -msgstr "Cua plena"
    -
    -msgid "Not while on AOL"
    -msgstr "No es pot fer mentre estigui a AOL"
    -
    #. Label
    msgid "Buddy Icon"
    msgstr "Icona de l'amic"
    @@ -8104,6 +8045,75 @@
    msgid "Capabilities"
    msgstr "Capacitats"
    +msgid "Invalid SNAC"
    +msgstr "SNAC invàlid"
    +
    +msgid "Server rate limit exceeded"
    +msgstr "S'ha excedit el límit de velocitat del servidor"
    +
    +msgid "Client rate limit exceeded"
    +msgstr "S'ha excedit el límit de velocitat del client"
    +
    +msgid "Service unavailable"
    +msgstr "Servei no disponible"
    +
    +msgid "Service not defined"
    +msgstr "Servei no definit"
    +
    +msgid "Obsolete SNAC"
    +msgstr "SNAC obsolet"
    +
    +msgid "Not supported by host"
    +msgstr "El servidor no ho permet"
    +
    +msgid "Not supported by client"
    +msgstr "El client no ho permet"
    +
    +msgid "Refused by client"
    +msgstr "Rebutjat pel client"
    +
    +msgid "Reply too big"
    +msgstr "Resposta massa gran"
    +
    +msgid "Responses lost"
    +msgstr "S'han perdut respostes"
    +
    +msgid "Request denied"
    +msgstr "Petició denegada"
    +
    +msgid "Busted SNAC payload"
    +msgstr "Càrrega SNAC malmesa"
    +
    +msgid "Insufficient rights"
    +msgstr "Drets insuficients"
    +
    +msgid "In local permit/deny"
    +msgstr "En la llista de permès/denegat local"
    +
    +msgid "Warning level too high (sender)"
    +msgstr "Nivell d'avís massa alt (remitent)"
    +
    +msgid "Warning level too high (receiver)"
    +msgstr "Nivell d'avís massa alt (receptor)"
    +
    +msgid "User temporarily unavailable"
    +msgstr "Usuari no disponible temporalment"
    +
    +msgid "No match"
    +msgstr "Cap coincidència"
    +
    +msgid "List overflow"
    +msgstr "Sobreeiximent de la llista"
    +
    +msgid "Request ambiguous"
    +msgstr "Petició ambigua"
    +
    +msgid "Queue full"
    +msgstr "Cua plena"
    +
    +msgid "Not while on AOL"
    +msgstr "No es pot fer mentre estigui a AOL"
    +
    #. Translators: This string is a menu option that, if selected, will cause
    #. you to appear online to the chosen user even when your status is set to
    #. Invisible.
    @@ -8703,14 +8713,14 @@
    msgid "Select Server"
    msgstr "Seleccioneu un servidor"
    -msgid "QQ2005"
    -msgstr "QQ2005"
    +msgid "QQ2008"
    +msgstr "QQ2008"
    msgid "QQ2007"
    msgstr "QQ2007"
    -msgid "QQ2008"
    -msgstr "QQ2008"
    +msgid "QQ2005"
    +msgstr "QQ2005"
    msgid "Connect by TCP"
    msgstr "Connecta amb TCP"
    @@ -12284,10 +12294,6 @@
    msgid "Fatal Error"
    msgstr "Error fatal"
    -# Fixme
    -msgid "bug master"
    -msgstr "bug master"
    -
    msgid "artist"
    msgstr "artista"
    @@ -12469,6 +12475,9 @@
    msgid "Maithili"
    msgstr "Maithili"
    +msgid "Meadow Mari"
    +msgstr "Txeremís oriental"
    +
    msgid "Macedonian"
    msgstr "Macedoni"
    @@ -15626,6 +15635,14 @@
    msgid "You do not have permission to uninstall this application."
    msgstr "No tens permís per desinstal.lar aquesta aplicació."
    +#~ msgid "Automatically reject from users not in buddy list"
    +#~ msgstr ""
    +#~ "Rebutja automàticament dels usuaris que no estiguin a la llista d'amics"
    +
    +# Fixme
    +#~ msgid "bug master"
    +#~ msgstr "bug master"
    +
    #~ msgid "Error requesting %s"
    #~ msgstr "S'ha produït un error en sol·licitar %s"
    --- a/po/de.po Sun Jan 09 23:32:10 2011 +0000
    +++ b/po/de.po Wed Feb 02 23:26:42 2011 +0000
    @@ -2,7 +2,7 @@
    # Pidgin German translation
    # Copyright (C) 2001, Daniel Seifert <Pidgin-translation@dseifert.de>
    # Copyright (C) 2002, Karsten Weiss <knweiss@gmx.de>
    -# Copyright (C) 2002-2010, Björn Voigt <bjoern@cs.tu-berlin.de>,
    +# Copyright (C) 2002-2011, Björn Voigt <bjoern@cs.tu-berlin.de>,
    # Jochen Kemnade <jochenkemnade@web.de>
    #
    # This file is distributed under the same license as the Pidgin package.
    @@ -11,9 +11,9 @@
    msgstr ""
    "Project-Id-Version: de\n"
    "Report-Msgid-Bugs-To: \n"
    -"POT-Creation-Date: 2010-12-22 10:12+0100\n"
    -"PO-Revision-Date: 2010-12-22 10:21+0100\n"
    -"Last-Translator: Björn Voigt <bjoern@cs.tu-berlin.de>\n"
    +"POT-Creation-Date: 2011-01-25 20:46+0100\n"
    +"PO-Revision-Date: 2011-01-25 20:46+0100\n"
    +"Last-Translator: Jochen Kemnade <jochenkemnade@web.de>\n"
    "Language-Team: German <de@li.org>\n"
    "Language: de\n"
    "MIME-Version: 1.0\n"
    @@ -401,7 +401,7 @@
    msgstr "Chat betreten"
    msgid "Please enter the name of the chat you want to join."
    -msgstr "Bitte geben Sie die den Namen des Chats an, den Sie betreten möchten."
    +msgstr "Bitte geben Sie den Namen des Chats an, den Sie betreten möchten."
    msgid "Join"
    msgstr "Betreten"
    @@ -568,7 +568,7 @@
    msgstr "Konten reaktivieren"
    msgid "No such command."
    -msgstr "Es gibt kein solches Kommando."
    +msgstr "Unbekanntes Kommando."
    msgid "Syntax Error: You typed the wrong number of arguments to that command."
    msgstr ""
    @@ -581,7 +581,8 @@
    msgstr "Dieses Kommando funktioniert nur in Chats, nicht bei IMs."
    msgid "That command only works in IMs, not chats."
    -msgstr "Dieses Kommando funktioniert nur bei IMs, nicht bei Chats."
    +msgstr ""
    +"Dieses Kommando funktioniert nur bei Sofortnachrichten, nicht bei Chats."
    msgid "That command doesn't work on this protocol."
    msgstr "Dieses Kommando funktioniert nicht in diesem Protokoll."
    @@ -646,7 +647,7 @@
    msgstr "Einladen..."
    msgid "Enable Logging"
    -msgstr "Mitschnitt einschalten"
    +msgstr "Mitschnitt aktivieren"
    msgid "Enable Sounds"
    msgstr "Klänge aktivieren"
    @@ -801,7 +802,7 @@
    msgstr "Status"
    msgid "Close this window when all transfers finish"
    -msgstr "Schließe dieses Fenster, wenn alle Übertragungen abgeschlossen sind"
    +msgstr "Fenster schließen, wenn alle Übertragungen abgeschlossen sind"
    msgid "Clear finished transfers"
    msgstr "Entferne komplette Übertragungen"
    @@ -816,7 +817,7 @@
    msgstr "Abgebrochen"
    msgid "Failed"
    -msgstr "Gescheitert"
    +msgstr "Fehlgeschlagen"
    #, c-format
    msgid "%.2f KiB/s"
    @@ -884,11 +885,11 @@
    #, c-format
    msgid "Conversations in %s"
    -msgstr "Unterhaltung in %s"
    +msgstr "Unterhaltungen in %s"
    #, c-format
    msgid "Conversations with %s"
    -msgstr "Unterhaltung mit %s"
    +msgstr "Unterhaltungen mit %s"
    msgid "All Conversations"
    msgstr "Alle Unterhaltungen"
    @@ -910,7 +911,7 @@
    msgstr "Ablehnen"
    msgid "Call in progress."
    -msgstr "Anruf läuft."
    +msgstr "Verbindungsaufbau."
    msgid "The call has been terminated."
    msgstr "Der Anruf wurde beendet."
    @@ -926,7 +927,7 @@
    "starten."
    msgid "You have rejected the call."
    -msgstr "Sie haben den Anruf abgelehnt."
    +msgstr "Sie haben den Anruf abgewiesen."
    msgid "call: Make an audio call."
    msgstr "call: Einen Audio-Anruf tätigen."
    @@ -1009,7 +1010,7 @@
    msgstr "Keine Einstellungsoptionen für dieses Plugin."
    msgid "Error loading plugin"
    -msgstr "Beim Laden des Plugins traten Fehler auf"
    +msgstr "Beim Laden des Plugins ist ein Fehler aufgetreten"
    msgid "The selected file is not a valid plugin."
    msgstr "Die gewählte Datei ist kein gültiges Plugin."
    @@ -1021,7 +1022,7 @@
    "genaue Fehlermeldung zu sehen."
    msgid "Select plugin to install"
    -msgstr "Wählen Sie ein Plugin zum Installieren"
    +msgstr "Zu installierendes Plugin auswählen"
    msgid "You can (un)load plugins from the following list."
    msgstr "Die können Plugins von der folgenden Liste laden bzw. entladen."
    @@ -1064,10 +1065,10 @@
    msgstr "Alarm, wenn Buddy..."
    msgid "Signs on"
    -msgstr "sich angemeldet"
    +msgstr "sich anmeldet"
    msgid "Signs off"
    -msgstr "sich abgemeldet"
    +msgstr "sich abmeldet"
    msgid "Goes away"
    msgstr "hinausgeht"
    @@ -1085,7 +1086,7 @@
    msgstr "zu tippen beginnt"
    msgid "Pauses while typing"
    -msgstr "beim Tippen anhält"
    +msgstr "das Tippen unterbricht"
    msgid "Stops typing"
    msgstr "aufhört zu tippen"
    @@ -1119,13 +1120,13 @@
    msgstr "Wiederkehrend"
    msgid "Cannot create pounce"
    -msgstr "Kann Alarm nicht erzeugen"
    +msgstr "Alarm konnte nicht erstellt werden"
    msgid "You do not have any accounts."
    msgstr "Sie haben keine Kontos."
    msgid "You must create an account first before you can create a pounce."
    -msgstr "Sie müssen ein Konto anlegen, bevor Sie einen Alarm erzeugen können."
    +msgstr "Sie müssen ein Konto anlegen, bevor Sie einen Alarm einrichten können."
    #, c-format
    msgid "Are you sure you want to delete the pounce on %s for %s?"
    @@ -1164,7 +1165,7 @@
    #, c-format
    msgid "%s has become idle (%s)"
    -msgstr "%s wurde untätig (%s)"
    +msgstr "%s ist nun untätig (%s)"
    #, c-format
    msgid "%s has gone away. (%s)"
    @@ -1178,7 +1179,7 @@
    msgstr "Unbekanntes Alarm-Ereignis. Bitte berichten Sie dieses Problem!"
    msgid "Based on keyboard use"
    -msgstr "Abhängig von Tastaturbenutzung"
    +msgstr "Abhängig von der Tastaturbenutzung"
    msgid "From last sent message"
    msgstr "Von letzter gesendeter Nachricht"
    @@ -1199,7 +1200,7 @@
    msgstr "Mitschnitt-Format"
    msgid "Log IMs"
    -msgstr "IMs mitschneiden"
    +msgstr "Sofortnachrichten mitschneiden"
    msgid "Log chats"
    msgstr "Chats mitschneiden"
    @@ -1247,7 +1248,7 @@
    msgstr "Drücken Sie 'Enter', um mehr Räume dieser Kategorie zu finden."
    msgid "Get"
    -msgstr "Holen"
    +msgstr "Abrufen"
    #. Create the window.
    msgid "Room List"
    @@ -1441,7 +1442,7 @@
    msgstr "Statusmeldungen"
    msgid "Error loading the plugin."
    -msgstr "Beim Laden des Plugins traten Fehler auf."
    +msgstr "Beim Laden des Plugins ist ein Fehler aufgetreten."
    msgid "Couldn't find X display"
    msgstr "Konnte X-Display nicht finden"
    @@ -1519,7 +1520,7 @@
    msgstr "<b>Unterhaltung mit %s am %s:</b><br>"
    msgid "History Plugin Requires Logging"
    -msgstr "Das Verlaufs-Plugin erfordert das Mitschneiden"
    +msgstr "Für das Verlaufs-Plugin muss das Mitschneiden aktiviert sein"
    msgid ""
    "Logging can be enabled from Tools -> Preferences -> Logging.\n"
    @@ -1543,7 +1544,7 @@
    "When a new conversation is opened this plugin will insert the last "
    "conversation into the current conversation."
    msgstr ""
    -"Wenn eine neue Unterhaltung eröffnet wird, fügt dieses Plugin die letzte "
    +"Wenn eine neue Unterhaltung begonnen wird, fügt dieses Plugin die letzte "
    "Unterhaltung in die aktuelle Unterhaltung ein."
    #, c-format
    @@ -1607,7 +1608,7 @@
    msgstr "Verschachtelte Gruppen (experimentell)"
    msgid "Provides alternate buddylist grouping options."
    -msgstr "Bietet alternative Einstellungen für die Kontaktlisten-Gruppierung."
    +msgstr "Bietet alternative Einstellungen für die Gruppierung der Kontaktliste."
    msgid "Lastlog"
    msgstr "Verlauf"
    @@ -1900,11 +1901,11 @@
    #, c-format
    msgid "Failed to get name: %s"
    -msgstr "Kann den Namen nicht bekommen: %s"
    +msgstr "Name konnte nicht abgerufen werden: %s"
    #, c-format
    msgid "Failed to get serv name: %s"
    -msgstr "Kann den Serv-Namen nicht bekommen: %s"
    +msgstr "Serv-Name konnte nicht abgerufen werden: %s"
    msgid "Purple's D-BUS server is not running for the reason listed below"
    msgstr "Purple's D-Bus-Server läuft aus dem folgenden Grund nicht"
    @@ -2041,7 +2042,7 @@
    msgstr "Übertragung der Datei %s ist komplett"
    msgid "File transfer complete"
    -msgstr "Dateiübertragung ist komplett"
    +msgstr "Dateiübertragung abgeschlossen"
    #, c-format
    msgid "You cancelled the transfer of %s"
    @@ -2368,8 +2369,12 @@
    "Pfad in denen die Dateien gespeichert werden sollen\n"
    "(Bitte geben Sie den vollständigen Pfad an)"
    -msgid "Automatically reject from users not in buddy list"
    -msgstr "Automatisch von Benutzern ablehnen, die nicht in der Buddy-Liste sind"
    +msgid ""
    +"When a file-transfer request arrives from a user who is\n"
    +"*not* on your buddy list:"
    +msgstr ""
    +"Wenn eine Dateitransferanfrage von einem Benutzer ankommt, \n"
    +"der *nicht* in Ihrer Buddy-Liste ist:"
    msgid ""
    "Notify with a popup when an autoaccepted file transfer is complete\n"
    @@ -2382,6 +2387,9 @@
    msgid "Create a new directory for each user"
    msgstr "Für jeden Benutzer ein neues Verzeichnis anlegen"
    +msgid "Escape the filenames"
    +msgstr "Sonderzeichen in Dateinamen ersetzen"
    +
    msgid "Notes"
    msgstr "Notizen"
    @@ -3850,7 +3858,10 @@
    "Der Server erfordert eine Klartext-Authentifizierung über einen "
    "unverschlüsselten Kanal"
    -#. This should never happen!
    +#. This happens when the server sends back jibberish
    +#. * in the "additional data with success" case.
    +#. * Seen with Wildfire 3.0.1.
    +#.
    msgid "Invalid response from server"
    msgstr "Ungültige Serverantwort"
    @@ -8730,14 +8741,14 @@
    msgid "Select Server"
    msgstr "Server wählen"
    -msgid "QQ2005"
    -msgstr "QQ2005"
    +msgid "QQ2008"
    +msgstr "QQ2008"
    msgid "QQ2007"
    msgstr "QQ2007"
    -msgid "QQ2008"
    -msgstr "QQ2008"
    +msgid "QQ2005"
    +msgstr "QQ2005"
    msgid "Connect by TCP"
    msgstr "Über TCP verbinden"
    @@ -12328,9 +12339,6 @@
    msgid "Fatal Error"
    msgstr "Schwerer Fehler"
    -msgid "bug master"
    -msgstr "Bug-Master"
    -
    msgid "artist"
    msgstr "Künstler"
    @@ -12510,6 +12518,9 @@
    msgid "Maithili"
    msgstr "Maithili"
    +msgid "Meadow Mari"
    +msgstr "Wiesen-Mari"
    +
    msgid "Macedonian"
    msgstr "Makedonisch"
    @@ -13448,10 +13459,10 @@
    msgstr "Budd_y-Name:"
    msgid "Si_gns on"
    -msgstr "si_ch angemeldet"
    +msgstr "si_ch anmeldet"
    msgid "Signs o_ff"
    -msgstr "sich abgemel_det"
    +msgstr "sich abmel_det"
    msgid "Goes a_way"
    msgstr "hinausgeh_t"
    @@ -15662,15 +15673,3 @@
    msgid "You do not have permission to uninstall this application."
    msgstr "Sie haben keine Berechtigung, diese Anwendung zu deinstallieren."
    -
    -#~ msgid "Error requesting %s"
    -#~ msgstr "Fehler beim Anfordern von %s"
    -
    -#~ msgid "An error occurred on the in-band bytestream transfer\n"
    -#~ msgstr "Bei der In-Band-Bytestrom-Übertragung trat ein Fehler auf\n"
    -
    -#~ msgid "Transfer was closed."
    -#~ msgstr "Übertragung wurde geschlossen."
    -
    -#~ msgid "Failed to open in-band bytestream"
    -#~ msgstr "Öffnen des In-Band-Bytestroms fehlgeschlagen"
    --- a/po/el.po Sun Jan 09 23:32:10 2011 +0000
    +++ b/po/el.po Wed Feb 02 23:26:42 2011 +0000
    @@ -18,7 +18,7 @@
    "MIME-Version: 1.0\n"
    "Content-Type: text/plain; charset=UTF-8\n"
    "Content-Transfer-Encoding: 8bit\n"
    -"Plural-Forms: Plural-Forms: nplurals=2; plural=(n != 1)\n"
    +"Plural-Forms: nplurals=2; plural=(n != 1)\n"
    "X-Generator: Lokalize 0.3\n"
    #. Translators may want to transliterate the name.
    --- a/po/en_AU.po Sun Jan 09 23:32:10 2011 +0000
    +++ b/po/en_AU.po Wed Feb 02 23:26:42 2011 +0000
    @@ -16,7 +16,7 @@
    "MIME-Version: 1.0\n"
    "Content-Type: text/plain; charset=UTF-8\n"
    "Content-Transfer-Encoding: 8bit\n"
    -"Plural-Forms: nplurals=2; plural=n>1;\n"
    +"Plural-Forms: nplurals=2; plural=(n != 1);\n"
    #. Translators may want to transliterate the name.
    #. It is not to be translated.
    --- a/po/en_GB.po Sun Jan 09 23:32:10 2011 +0000
    +++ b/po/en_GB.po Wed Feb 02 23:26:42 2011 +0000
    @@ -15,7 +15,7 @@
    "MIME-Version: 1.0\n"
    "Content-Type: text/plain; charset=UTF-8\n"
    "Content-Transfer-Encoding: 8bit\n"
    -"Plural-Forms: nplurals=2; plural=n>1;\n"
    +"Plural-Forms: nplurals=2; plural=(n != 1);\n"
    #. Translators may want to transliterate the name.
    #. It is not to be translated.
    --- a/po/eu.po Sun Jan 09 23:32:10 2011 +0000
    +++ b/po/eu.po Wed Feb 02 23:26:42 2011 +0000
    @@ -16,7 +16,7 @@
    "Content-Type: text/plain; charset=UTF-8\n"
    "Content-Transfer-Encoding: 8bit\n"
    "X-Generator: KBabel 1.9.1\n"
    -"Plural-Forms: Plural-Forms: Plural-Forms: nplurals=2; plural=(n != 1);\n"
    +"Plural-Forms: nplurals=2; plural=(n != 1);\n"
    #. Translators may want to transliterate the name.
    #. It is not to be translated.
    --- a/po/fr.po Sun Jan 09 23:32:10 2011 +0000
    +++ b/po/fr.po Wed Feb 02 23:26:42 2011 +0000
    @@ -4,7 +4,7 @@
    # Copyright (C) 2002, Stéphane Pontier <stephane.pontier@free.fr>
    # Copyright (C) 2002, Stéphane Wirtel <stephane.wirtel@belgacom.net>
    # Copyright (C) 2002, Loïc Jeannin <loic.jeannin@free.fr>
    -# Copyright (C) 2002-2010, Éric Boumaour <zongo_fr@users.sourceforge.net>
    +# Copyright (C) 2002-2011, Éric Boumaour <zongo_fr@users.sourceforge.net>
    #
    # This file is distributed under the same license as the Pidgin package.
    #
    @@ -21,14 +21,14 @@
    msgstr ""
    "Project-Id-Version: Pidgin\n"
    "Report-Msgid-Bugs-To: \n"
    -"POT-Creation-Date: 2010-12-19 13:33-0500\n"
    -"PO-Revision-Date: 2010-12-16 23:25+0100\n"
    +"POT-Creation-Date: 2011-01-30 21:28+0100\n"
    +"PO-Revision-Date: 2011-01-30 21:14+0100\n"
    "Last-Translator: Éric Boumaour <zongo_fr@users.sourceforge.net>\n"
    "Language-Team: fr <fr@li.org>\n"
    -"Language: \n"
    "MIME-Version: 1.0\n"
    "Content-Type: text/plain; charset=UTF-8\n"
    "Content-Transfer-Encoding: 8bit\n"
    +"Language: \n"
    "Plural-Forms: nplurals=2; plural=n>1;\n"
    #. Translators may want to transliterate the name.
    @@ -864,8 +864,8 @@
    "System events will only be logged if the \"Log all status changes to system "
    "log\" preference is enabled."
    msgstr ""
    -"Les événements système ne seront archivés que si l'option « Archiver tous "
    -"les changements d'état dans les archives système » est activée."
    +"Les événements système ne seront archivés que si l'option « Archiver tous les "
    +"changements d'état dans les archives système » est activée."
    msgid ""
    "Instant messages will only be logged if the \"Log all instant messages\" "
    @@ -2372,9 +2372,12 @@
    "Dossier où placer les fichiers\n"
    "(Veuillez fournir le chemin complet)"
    -msgid "Automatically reject from users not in buddy list"
    -msgstr ""
    -"Refuser automatiquement si l'utilisateur n'est pas dans ma liste de contacts"
    +msgid ""
    +"When a file-transfer request arrives from a user who is\n"
    +"*not* on your buddy list:"
    +msgstr ""
    +"Quand une demande de transfert arrive de quelqu'un qui\n"
    +"n'est *pas* dans la liste de contacts :"
    msgid ""
    "Notify with a popup when an autoaccepted file transfer is complete\n"
    @@ -2387,6 +2390,9 @@
    msgid "Create a new directory for each user"
    msgstr "Créer un nouveau dossier pour chaque contact"
    +msgid "Escape the filenames"
    +msgstr "Encoder les noms des fichiers"
    +
    msgid "Notes"
    msgstr "Notes"
    @@ -2767,8 +2773,7 @@
    msgstr "Message déconnecté"
    msgid "You can edit/delete the pounce from the `Buddy Pounces' dialog"
    -msgstr ""
    -"Vous pouvez modifier ou supprimer l'alerte dans la fenêtre « Alertes »."
    +msgstr "Vous pouvez modifier ou supprimer l'alerte dans la fenêtre « Alertes »."
    msgid "Yes"
    msgstr "Oui"
    @@ -3859,7 +3864,10 @@
    "Le serveur demande une authentification en texte non chiffré au travers d'un "
    "flux crypté."
    -#. This should never happen!
    +#. This happens when the server sends back jibberish
    +#. * in the "additional data with success" case.
    +#. * Seen with Wildfire 3.0.1.
    +#.
    msgid "Invalid response from server"
    msgstr "Réponse non valide du serveur"
    @@ -6197,6 +6205,20 @@
    msgid "Retrieving User Information..."
    msgstr "Récupération des informations de l'utilisateur..."
    +#. you were kicked
    +msgid "You have been kicked from this MultiMX."
    +msgstr "Vous avez été expulsé de ce MultiMX."
    +
    +msgid "was kicked"
    +msgstr "a été expulsé"
    +
    +msgid "_Room Name:"
    +msgstr "_Salon :"
    +
    +#. Display system message in chat window
    +msgid "You have invited"
    +msgstr "Vous avez été invité"
    +
    msgid "Loading menu..."
    msgstr "Chargement du menu..."
    @@ -6224,20 +6246,6 @@
    msgid "Enable splash-screen popup"
    msgstr "Activer l'affichage de la bannière"
    -#. you were kicked
    -msgid "You have been kicked from this MultiMX."
    -msgstr "Vous avez été expulsé de ce MultiMX."
    -
    -msgid "was kicked"
    -msgstr "a été expulsé"
    -
    -msgid "_Room Name:"
    -msgstr "_Salon :"
    -
    -#. Display system message in chat window
    -msgid "You have invited"
    -msgstr "Vous avez été invité"
    -
    msgid "Last Online"
    msgstr "En ligne dernièrement"
    @@ -7908,75 +7916,6 @@
    "d'images. Votre adresse IP sera révélée et ceci peut être considéré comme "
    "une faille de sécurité."
    -msgid "Invalid SNAC"
    -msgstr "SNAC non valide"
    -
    -msgid "Server rate limit exceeded"
    -msgstr "Vitesse du serveur dépassée"
    -
    -msgid "Client rate limit exceeded"
    -msgstr "Vitesse du client dépassée"
    -
    -msgid "Service unavailable"
    -msgstr "Service non disponible"
    -
    -msgid "Service not defined"
    -msgstr "Service non défini"
    -
    -msgid "Obsolete SNAC"
    -msgstr "SNAC obsolète"
    -
    -msgid "Not supported by host"
    -msgstr "Non supporté par l'hôte"
    -
    -msgid "Not supported by client"
    -msgstr "Non supporté par le client"
    -
    -msgid "Refused by client"
    -msgstr "Refusé par le client"
    -
    -msgid "Reply too big"
    -msgstr "Réponse trop grosse"
    -
    -msgid "Responses lost"
    -msgstr "Réponses perdues"
    -
    -msgid "Request denied"
    -msgstr "Requête refusée"
    -
    -msgid "Busted SNAC payload"
    -msgstr "Charge SNAC incorrecte"
    -
    -msgid "Insufficient rights"
    -msgstr "Droits insuffisants"
    -
    -msgid "In local permit/deny"
    -msgstr "Dans l'autorisation/interdiction locale"
    -
    -msgid "Warning level too high (sender)"
    -msgstr "Niveau d'avertissement trop élevé (émission)"
    -
    -msgid "Warning level too high (receiver)"
    -msgstr "Niveau d'avertissement trop élevé (réception)"
    -
    -msgid "User temporarily unavailable"
    -msgstr "L'utilisateur est temporairement indisponible."
    -
    -msgid "No match"
    -msgstr "Aucun résultat"
    -
    -msgid "List overflow"
    -msgstr "Dépassement de liste"
    -
    -msgid "Request ambiguous"
    -msgstr "Requête ambiguë"
    -
    -msgid "Queue full"
    -msgstr "File d'attente pleine"
    -
    -msgid "Not while on AOL"
    -msgstr "Impossible sur AOL"
    -
    #. Label
    msgid "Buddy Icon"
    msgstr "Icône du contact"
    @@ -8095,6 +8034,75 @@
    msgid "Capabilities"
    msgstr "Possibilités"
    +msgid "Invalid SNAC"
    +msgstr "SNAC non valide"
    +
    +msgid "Server rate limit exceeded"
    +msgstr "Vitesse du serveur dépassée"
    +
    +msgid "Client rate limit exceeded"
    +msgstr "Vitesse du client dépassée"
    +
    +msgid "Service unavailable"
    +msgstr "Service non disponible"
    +
    +msgid "Service not defined"
    +msgstr "Service non défini"
    +
    +msgid "Obsolete SNAC"
    +msgstr "SNAC obsolète"
    +
    +msgid "Not supported by host"
    +msgstr "Non supporté par l'hôte"
    +
    +msgid "Not supported by client"
    +msgstr "Non supporté par le client"
    +
    +msgid "Refused by client"
    +msgstr "Refusé par le client"
    +
    +msgid "Reply too big"
    +msgstr "Réponse trop grosse"
    +
    +msgid "Responses lost"
    +msgstr "Réponses perdues"
    +
    +msgid "Request denied"
    +msgstr "Requête refusée"
    +
    +msgid "Busted SNAC payload"
    +msgstr "Charge SNAC incorrecte"
    +
    +msgid "Insufficient rights"
    +msgstr "Droits insuffisants"
    +
    +msgid "In local permit/deny"
    +msgstr "Dans l'autorisation/interdiction locale"
    +
    +msgid "Warning level too high (sender)"
    +msgstr "Niveau d'avertissement trop élevé (émission)"
    +
    +msgid "Warning level too high (receiver)"
    +msgstr "Niveau d'avertissement trop élevé (réception)"
    +
    +msgid "User temporarily unavailable"
    +msgstr "L'utilisateur est temporairement indisponible."
    +
    +msgid "No match"
    +msgstr "Aucun résultat"
    +
    +msgid "List overflow"
    +msgstr "Dépassement de liste"
    +
    +msgid "Request ambiguous"
    +msgstr "Requête ambiguë"
    +
    +msgid "Queue full"
    +msgstr "File d'attente pleine"
    +
    +msgid "Not while on AOL"
    +msgstr "Impossible sur AOL"
    +
    #. Translators: This string is a menu option that, if selected, will cause
    #. you to appear online to the chosen user even when your status is set to
    #. Invisible.
    @@ -8686,14 +8694,14 @@
    msgid "Select Server"
    msgstr "Choisir le serveur"
    -msgid "QQ2005"
    -msgstr "QQ2005"
    +msgid "QQ2008"
    +msgstr "QQ2008"
    msgid "QQ2007"
    msgstr "QQ2007"
    -msgid "QQ2008"
    -msgstr "QQ2008"
    +msgid "QQ2005"
    +msgstr "QQ2005"
    msgid "Connect by TCP"
    msgstr "Connexion par TCP"
    @@ -10445,8 +10453,8 @@
    msgstr ""
    "Le serveur Yahoo! a demandé une méthode d'authentification non reconnue. "
    "Cette version de l'application n'arrivera probablement pas à se connecter au "
    -"service Yahoo!. Vous pouvez vérifier qu'une mise à jour est disponible sur "
    -"%s."
    +"service Yahoo!. Vous pouvez vérifier qu'une mise à jour est disponible sur %"
    +"s."
    msgid "Failed Yahoo! Authentication"
    msgstr "Échec de l'authentification Yahoo!"
    @@ -12257,9 +12265,6 @@
    msgid "Fatal Error"
    msgstr "Erreur critique"
    -msgid "bug master"
    -msgstr "maitre des bogues"
    -
    msgid "artist"
    msgstr "artiste"
    @@ -12439,6 +12444,9 @@
    msgid "Maithili"
    msgstr "Maïhili"
    +msgid "Meadow Mari"
    +msgstr "Mari des prairies"
    +
    msgid "Macedonian"
    msgstr "Macédonien"
    @@ -12559,8 +12567,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 est un client de messagerie basé sur libpurple capable de se connecter à "
    "de multiples services de messageries instantanées. %s est écrit en C et "
    @@ -13115,16 +13123,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 ""
    "Êtes-vous sûr de vouloir supprimer les archives de la conversation dans %s "
    "datée du %s ?"
    #, 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 "Êtes-vous sûr de vouloir supprimer les archives système datées du %s ?"
    msgid "Delete Log?"
    @@ -14956,8 +14964,8 @@
    "'Enter' in the entry box to send. Watch the debug window."
    msgstr ""
    "Permet d'envoyer des données brutes aux protocoles en mode texte (XMPP, MSN, "
    -"IRC, TOC). Tapez « Entrée » dans la boîte de saisie pour envoyer. Observez "
    -"le résultat dans la fenêtre de debug."
    +"IRC, TOC). Tapez « Entrée » dans la boîte de saisie pour envoyer. Observez le "
    +"résultat dans la fenêtre de debug."
    #, c-format
    msgid "You can upgrade to %s %s today."
    @@ -15485,13 +15493,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 ""
    "Erreur lors de l'installation du correcteur orthographique ($R3).$\\rSi une "
    "nouvelle tentative échoue, veuillez suivre les instructions sur http://"
    -"developer.pidgin.im/wiki/Installing"
    -"%20Pidgin#manual_win32_spellcheck_installation"
    +"developer.pidgin.im/wiki/Installing%"
    +"20Pidgin#manual_win32_spellcheck_installation"
    #. Installer Subsection Text
    msgid "GTK+ Runtime (required if not present)"
    @@ -15570,6 +15578,14 @@
    msgid "You do not have permission to uninstall this application."
    msgstr "Vous n'avez pas les permissions pour supprimer cette application."
    +#~ msgid "Automatically reject from users not in buddy list"
    +#~ msgstr ""
    +#~ "Refuser automatiquement si l'utilisateur n'est pas dans ma liste de "
    +#~ "contacts"
    +
    +#~ msgid "bug master"
    +#~ msgstr "maitre des bogues"
    +
    #~ msgid "An error occurred on the in-band bytestream transfer\n"
    #~ msgstr "Erreur lors du transfert dans le flux de données in-band.\n"
    --- a/po/gl.po Sun Jan 09 23:32:10 2011 +0000
    +++ b/po/gl.po Wed Feb 02 23:26:42 2011 +0000
    @@ -18,7 +18,7 @@
    "MIME-Version: 1.0\n"
    "Content-Type: text/plain; charset=UTF-8\n"
    "Content-Transfer-Encoding: 8bit\n"
    -"Plural-Forms: Plural-Forms: nplurals=2; plural=(n != 1);\n"
    +"Plural-Forms: nplurals=2; plural=(n != 1);\n"
    "X-Generator: KBabel 1.11.4\n"
    #. Translators may want to transliterate the name.
    --- a/po/hu.po Sun Jan 09 23:32:10 2011 +0000
    +++ b/po/hu.po Wed Feb 02 23:26:42 2011 +0000
    @@ -1,22 +1,22 @@
    # Hungarian translation of pidgin.
    -# Copyright (C) 2003, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
    +# Copyright (C) 2003, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
    # This file is distributed under the same license as the Pidgin package.
    # The Hungarian translation of Pidgin was sponsored by Novell Hungary, many thanks for it!
    #
    # Zoltan Sutto <suttozoltan@chello.hu>, 2003.
    -# Gabor Kelemen <kelemeng at gnome dot hu>, 2005, 2006, 2007, 2008, 2009, 2010.
    -msgid ""
    -msgstr ""
    -"Project-Id-Version: pidgin 2.7\n"
    +# Gabor Kelemen <kelemeng at gnome dot hu>, 2005, 2006, 2007, 2008, 2009, 2010, 2011.
    +msgid ""
    +msgstr ""
    +"Project-Id-Version: pidgin 2.7.10\n"
    "Report-Msgid-Bugs-To: \n"
    -"POT-Creation-Date: 2010-12-21 15:20+0100\n"
    -"PO-Revision-Date: 2010-12-21 15:19+0100\n"
    +"POT-Creation-Date: 2011-01-25 15:12+0100\n"
    +"PO-Revision-Date: 2011-01-25 15:12+0100\n"
    "Last-Translator: Gabor Kelemen <kelemeng at gnome dot hu>\n"
    "Language-Team: Hungarian <gnome at fsf dot hu>\n"
    -"Language: \n"
    "MIME-Version: 1.0\n"
    "Content-Type: text/plain; charset=UTF-8\n"
    "Content-Transfer-Encoding: 8bit\n"
    +"Language: \n"
    "Plural-Forms: nplurals=2; plural=(n != 1);\n"
    "X-Generator: KBabel 1.11.4\n"
    @@ -2350,9 +2350,12 @@
    "A fájlok mentési útvonala\n"
    "(Teljes elérési utat adjon meg)"
    -msgid "Automatically reject from users not in buddy list"
    -msgstr ""
    -"Automatikus visszautasítás a partnerlistán nem szereplő felhasználóktól"
    +msgid ""
    +"When a file-transfer request arrives from a user who is\n"
    +"*not* on your buddy list:"
    +msgstr ""
    +"Ha fájlküldési kérés érkezik egy a partnerlistán NEM szereplő\n"
    +"felhasználótól:"
    msgid ""
    "Notify with a popup when an autoaccepted file transfer is complete\n"
    @@ -2365,6 +2368,9 @@
    msgid "Create a new directory for each user"
    msgstr "Új könyvtár létrehozása minden felhasználóhoz"
    +msgid "Escape the filenames"
    +msgstr "Fájlnevek escape-elése."
    +
    msgid "Notes"
    msgstr "Megjegyzések"
    @@ -3828,7 +3834,10 @@
    msgstr ""
    "A kiszolgáló szöveges hitelesítést követel meg egy nem titkosított csatornán"
    -#. This should never happen!
    +#. This happens when the server sends back jibberish
    +#. * in the "additional data with success" case.
    +#. * Seen with Wildfire 3.0.1.
    +#.
    msgid "Invalid response from server"
    msgstr "Érvénytelen válasz a kiszolgálótól"
    @@ -6757,8 +6766,8 @@
    #, c-format
    msgid "Unable to send message. Could not get details for user (%s)."
    msgstr ""
    -"Az üzenetet nem lehet elküldeni. A felhasználó részletei nem kérhetőek le "
    -"(%s)."
    +"Az üzenetet nem lehet elküldeni. A felhasználó részletei nem kérhetőek le (%"
    +"s)."
    #, c-format
    msgid "Unable to add %s to your buddy list (%s)."
    @@ -7191,8 +7200,8 @@
    "%s tried to send you a %s file, but we only allow files up to %s over Direct "
    "IM. Try using file transfer instead.\n"
    msgstr ""
    -"%s egy %s fájlt próbált küldeni, de közvetlen kapcsolatban legfeljebb csak "
    -"%s méretű fájl küldhető. Próbálkozzon inkább a fájlátvitellel.\n"
    +"%s egy %s fájlt próbált küldeni, de közvetlen kapcsolatban legfeljebb csak %"
    +"s méretű fájl küldhető. Próbálkozzon inkább a fájlátvitellel.\n"
    #, c-format
    msgid "File %s is %s, which is larger than the maximum size of %s."
    @@ -8628,14 +8637,14 @@
    msgid "Select Server"
    msgstr "Válassza ki a kiszolgálót"
    -msgid "QQ2005"
    -msgstr "QQ2005"
    +msgid "QQ2008"
    +msgstr "QQ2008"
    msgid "QQ2007"
    msgstr "QQ2007"
    -msgid "QQ2008"
    -msgstr "QQ2008"
    +msgid "QQ2005"
    +msgstr "QQ2005"
    msgid "Connect by TCP"
    msgstr "Kapcsolódás TCP segítségével"
    @@ -10831,8 +10840,8 @@
    #, c-format
    msgid "Access denied: HTTP proxy server forbids port %d tunneling"
    msgstr ""
    -"Hozzáférés megtagadva: a HTTP proxy kiszolgáló tiltja az alagutazást a(z) "
    -"%d. porton"
    +"Hozzáférés megtagadva: a HTTP proxy kiszolgáló tiltja az alagutazást a(z) %"
    +"d. porton"
    #, c-format
    msgid "Error resolving %s"
    @@ -11080,8 +11089,8 @@
    "An error was encountered reading your %s. The file has not been loaded, and "
    "the old file has been renamed to %s~."
    msgstr ""
    -"Hiba történt a(z) %s olvasásakor. Ez a fájl nem lett betöltve, a régi fájl "
    -"%s~ néven lett elmentve."
    +"Hiba történt a(z) %s olvasásakor. Ez a fájl nem lett betöltve, a régi fájl %"
    +"s~ néven lett elmentve."
    msgid ""
    "Chat over IM. Supports AIM, Google Talk, Jabber/XMPP, MSN, Yahoo and more"
    @@ -12207,10 +12216,6 @@
    msgid "Fatal Error"
    msgstr "Végzetes hiba"
    -# fixme: jobb ötlet?
    -msgid "bug master"
    -msgstr "hibaritkító"
    -
    msgid "artist"
    msgstr "grafikus"
    @@ -12390,6 +12395,9 @@
    msgid "Maithili"
    msgstr "Maithili"
    +msgid "Meadow Mari"
    +msgstr "Mari"
    +
    msgid "Macedonian"
    msgstr "macedón"
    @@ -12510,8 +12518,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 ""
    "A %s egy libpurple alapú moduláris üzenetküldő kliens, amely egyszerre több "
    "üzenetküldő szolgáltatáshoz is képes csatlakozni. A %s GTK+ használatával, C "
    @@ -13061,16 +13069,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 ""
    "Biztos, hogy törölni akarja a(z) %s csatornán folytatott, %s időpontban "
    "kezdődött beszélgetés naplóját?"
    #, 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 ""
    "Biztos, hogy törölni akarja a(z) %s időpontban kezdődött rendszernaplót?"
    @@ -15421,8 +15429,8 @@
    #, 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 ""
    "Hiba a helyesírás-ellenőrző telepítésekor. ($R3).$\\rHa az újrapróbálkozás "
    "meghiúsul, akkor saját kezűleg is telepítheti a http://developer.pidgin.im/"
    --- a/po/hy.po Sun Jan 09 23:32:10 2011 +0000
    +++ b/po/hy.po Wed Feb 02 23:26:42 2011 +0000
    @@ -3,7 +3,6 @@
    # This file is distributed under the same license as the PACKAGE package.
    # David Avsharyan <avsharyan@gmail.com>, 2009.
    #
    -#, fuzzy
    msgid ""
    msgstr ""
    "Project-Id-Version: am\n"
    @@ -16,7 +15,7 @@
    "MIME-Version: 1.0\n"
    "Content-Type: text/plain; charset=UTF-8\n"
    "Content-Transfer-Encoding: 8bit\n"
    -"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
    +"Plural-Forms: nplurals=1; plural=0;\n"
    #. Translators may want to transliterate the name.
    #. It is not to be translated.
    --- a/po/mn.po Sun Jan 09 23:32:10 2011 +0000
    +++ b/po/mn.po Wed Feb 02 23:26:42 2011 +0000
    @@ -15,7 +15,7 @@
    "MIME-Version: 1.0\n"
    "Content-Type: text/plain; charset=UTF-8\n"
    "Content-Transfer-Encoding: 8bit\n"
    -"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
    +"Plural-Forms: nplurals=1; plural=0;\n"
    #. Translators may want to transliterate the name.
    #. It is not to be translated.
    --- a/po/ms_MY.po Sun Jan 09 23:32:10 2011 +0000
    +++ b/po/ms_MY.po Wed Feb 02 23:26:42 2011 +0000
    @@ -15,7 +15,7 @@
    "MIME-Version: 1.0\n"
    "Content-Type: text/plain; charset=UTF-8\n"
    "Content-Transfer-Encoding: 8bit\n"
    -"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
    +"Plural-Forms: nplurals=2; plural=(n != 1);\n"
    "X-Generator: KBabel 1.11.4\n"
    #. Translators may want to transliterate the name.
    --- a/po/ta.po Sun Jan 09 23:32:10 2011 +0000
    +++ b/po/ta.po Wed Feb 02 23:26:42 2011 +0000
    @@ -19,7 +19,7 @@
    "MIME-Version: 1.0\n"
    "Content-Type: text/plain; charset=UTF-8\n"
    "Content-Transfer-Encoding: 8bit\n"
    -"Plural-Forms: Plural-Forms: nplurals=2; plural=(n != 1);\n"
    +"Plural-Forms: nplurals=2; plural=(n != 1);\n"
    "X-Poedit-Country: INDIA\n"
    "X-Generator: Lokalize 1.0\n"
    "X-Poedit-Bookmarks: -1,470,-1,-1,-1,-1,-1,-1,-1,1715\n"
    --- /dev/null Thu Jan 01 00:00:00 1970 +0000
    +++ b/share/ca-certs/AddTrust_External_Root.pem Wed Feb 02 23:26:42 2011 +0000
    @@ -0,0 +1,25 @@
    +-----BEGIN CERTIFICATE-----
    +MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEU
    +MBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFs
    +IFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290
    +MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFowbzELMAkGA1UEBhMCU0Ux
    +FDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5h
    +bCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9v
    +dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvt
    +H7xsD821+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9
    +uMq/NzgtHj6RQa1wVsfwTz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzX
    +mk6vBbOmcZSccbNQYArHE504B4YCqOmoaSYYkKtMsE8jqzpPhNjfzp/haW+710LX
    +a0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy2xSoRcRdKn23tNbE7qzN
    +E0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv77+ldU9U0
    +WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYD
    +VR0PBAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0
    +Jvf6xCZU7wO94CTLVBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRU
    +cnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsx
    +IjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3SCAQEwDQYJKoZIhvcN
    +AQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZlj7DYd7usQWxH
    +YINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5
    +6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvC
    +Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX
    +c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a
    +mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ=
    +-----END CERTIFICATE-----
    --- a/share/ca-certs/Makefile.am Sun Jan 09 23:32:10 2011 +0000
    +++ b/share/ca-certs/Makefile.am Wed Feb 02 23:26:42 2011 +0000
    @@ -1,4 +1,5 @@
    CERTIFICATES = \
    + AddTrust_External_Root.pem \
    America_Online_Root_Certification_Authority_1.pem \
    CAcert_Root.pem \
    CAcert_Class3.pem \