Mercurial > pidgin.yaz
changeset 28140:5ac0a83f0b21
merged with im.pidgin.pidgin
author | Yoshiki Yazawa <yaz@honeyplanet.jp> |
---|---|
date | Sun, 02 Aug 2009 16:43:49 +0900 |
parents | 784013acc2f3 (current diff) 5b21007cf503 (diff) |
children | 2222357e5f45 |
files | libpurple/certificate.c libpurple/protocols/jabber/google.c libpurple/protocols/jabber/jabber.c libpurple/protocols/jabber/si.c libpurple/protocols/yahoo/libymsg.c libpurple/protocols/yahoo/util.c libpurple/protocols/yahoo/yahoo_filexfer.c libpurple/protocols/yahoo/yahoo_packet.c pidgin/gtkblist.c pidgin/gtkimhtml.c pidgin/gtkprefs.c |
diffstat | 31 files changed, 328 insertions(+), 245 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog Sat Aug 01 14:55:12 2009 +0900 +++ b/ChangeLog Sun Aug 02 16:43:49 2009 +0900 @@ -43,6 +43,8 @@ against the GNU IDN library. * Install scalable versions of the main Pidgin icon, the protocol icons, the dialog icons, and the Buddy List emblems. + * Build properly on Hurd. (Marc Dequènes) + * Various memory leaks fixed as reported by Josh Mueller. AIM and ICQ: * Preliminary support for a new authentication scheme called
--- a/libpurple/certificate.c Sat Aug 01 14:55:12 2009 +0900 +++ b/libpurple/certificate.c Sun Aug 02 16:43:49 2009 +0900 @@ -1375,7 +1375,7 @@ return; } /* if (name mismatch) */ - if (had_ca_pool) { + if (!had_ca_pool) { /* The subject name is correct, but we weren't able to verify the * chain because there was no pool of root CAs found. Prompt the user * to validate it.
--- a/libpurple/cipher.c Sat Aug 01 14:55:12 2009 +0900 +++ b/libpurple/cipher.c Sun Aug 02 16:43:49 2009 +0900 @@ -2727,8 +2727,6 @@ cipher = PURPLE_CIPHER(l->data); purple_ciphers_unregister_cipher(cipher); - - ciphers = g_list_remove(ciphers, cipher); } g_list_free(ciphers);
--- a/libpurple/desktopitem.c Sat Aug 01 14:55:12 2009 +0900 +++ b/libpurple/desktopitem.c Sun Aug 02 16:43:49 2009 +0900 @@ -831,11 +831,10 @@ static char * try_english_key (PurpleDesktopItem *item, const char *key) { - char *str; + char *str = NULL; char *locales[] = { "en_US", "en_GB", "en_AU", "en", NULL }; int i; - str = NULL; for (i = 0; locales[i] != NULL && str == NULL; i++) { str = g_strdup (lookup_locale (item, key, locales[i])); }
--- a/libpurple/ft.c Sat Aug 01 14:55:12 2009 +0900 +++ b/libpurple/ft.c Sun Aug 02 16:43:49 2009 +0900 @@ -953,15 +953,15 @@ if (wc != r) { purple_debug_error("filetransfer", "Unable to write whole buffer.\n"); purple_xfer_cancel_local(xfer); + g_free(buffer); return; } } else if(r < 0) { purple_xfer_cancel_remote(xfer); + g_free(buffer); return; } - } - - if (condition & PURPLE_INPUT_WRITE) { + } else if (condition & PURPLE_INPUT_WRITE) { size_t result; size_t s = MIN(purple_xfer_get_bytes_remaining(xfer), xfer->current_buffer_size);
--- a/libpurple/protocols/bonjour/mdns_avahi.c Sat Aug 01 14:55:12 2009 +0900 +++ b/libpurple/protocols/bonjour/mdns_avahi.c Sun Aug 02 16:43:49 2009 +0900 @@ -200,8 +200,8 @@ } if (!bonjour_buddy_check(bb)) { + b_impl->resolvers = g_slist_remove(b_impl->resolvers, rd); _cleanup_resolver_data(rd); - b_impl->resolvers = g_slist_remove(b_impl->resolvers, rd); /* If this was the last resolver, remove the buddy */ if (b_impl->resolvers == NULL) { if (pb != NULL)
--- a/libpurple/protocols/gg/lib/libgadu.c Sat Aug 01 14:55:12 2009 +0900 +++ b/libpurple/protocols/gg/lib/libgadu.c Sun Aug 02 16:43:49 2009 +0900 @@ -790,6 +790,7 @@ gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() body recv(%d,%p,%d) = %d\n", sess->fd, buf + sizeof(h) + offset, size, ret); if (!ret) { gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() body recv() failed: connection broken\n"); + free(buf); errno = ECONNRESET; return NULL; }
--- a/libpurple/protocols/jabber/bosh.c Sat Aug 01 14:55:12 2009 +0900 +++ b/libpurple/protocols/jabber/bosh.c Sun Aug 02 16:43:49 2009 +0900 @@ -31,6 +31,7 @@ #define MAX_HTTP_CONNECTIONS 2 #define MAX_FAILED_CONNECTIONS 3 +#define BUFFER_SEND_IN_SECS 1 typedef struct _PurpleHTTPConnection PurpleHTTPConnection; @@ -40,55 +41,63 @@ static char *bosh_useragent = NULL; typedef enum { + PACKET_NORMAL, PACKET_TERMINATE, - PACKET_STREAM_RESTART, - PACKET_NORMAL, + PACKET_FLUSH, } PurpleBOSHPacketType; struct _PurpleBOSHConnection { JabberStream *js; + PurpleHTTPConnection *connections[MAX_HTTP_CONNECTIONS]; + + PurpleCircBuffer *pending; + PurpleBOSHConnectionConnectFunction connect_cb; + PurpleBOSHConnectionReceiveFunction receive_cb; + + /* Must be big enough to hold 2^53 - 1 */ + char *sid; + guint64 rid; + + /* decoded URL */ + char *host; + char *path; + guint16 port; + gboolean pipelining; - PurpleHTTPConnection *connections[MAX_HTTP_CONNECTIONS]; - unsigned short failed_connections; + gboolean ssl; + gboolean needs_restart; enum { BOSH_CONN_OFFLINE, BOSH_CONN_BOOTING, BOSH_CONN_ONLINE } state; - gboolean ssl; - gboolean needs_restart; + guint8 failed_connections; - /* decoded URL */ - char *host; - int port; - char *path; - - /* Must be big enough to hold 2^53 - 1 */ - guint64 rid; - char *sid; - - unsigned int inactivity_timer; int max_inactivity; int wait; - PurpleCircBuffer *pending; int max_requests; int requests; - PurpleBOSHConnectionConnectFunction connect_cb; - PurpleBOSHConnectionReceiveFunction receive_cb; + guint inactivity_timer; + guint send_timer; }; struct _PurpleHTTPConnection { PurpleBOSHConnection *bosh; PurpleSslConnection *psc; + + PurpleCircBuffer *write_buf; + GString *read_buf; + + gsize handled_len; + gsize body_len; + int fd; guint readh; guint writeh; - PurpleCircBuffer *write_buffer; - enum { HTTP_CONN_OFFLINE, HTTP_CONN_CONNECTING, @@ -96,16 +105,14 @@ } state; int requests; /* number of outstanding HTTP requests */ - GString *buf; gboolean headers_done; - gsize handled_len; - gsize body_len; }; static void http_connection_connect(PurpleHTTPConnection *conn); static void http_connection_send_request(PurpleHTTPConnection *conn, const GString *req); +static gboolean send_timer_cb(gpointer data); void jabber_bosh_init(void) { @@ -140,7 +147,7 @@ conn->fd = -1; conn->state = HTTP_CONN_OFFLINE; - conn->write_buffer = purple_circ_buffer_new(0 /* default grow size */); + conn->write_buf = purple_circ_buffer_new(0 /* default grow size */); return conn; } @@ -148,11 +155,11 @@ static void jabber_bosh_http_connection_destroy(PurpleHTTPConnection *conn) { - if (conn->buf) - g_string_free(conn->buf, TRUE); + if (conn->read_buf) + g_string_free(conn->read_buf, TRUE); - if (conn->write_buffer) - purple_circ_buffer_destroy(conn->write_buffer); + if (conn->write_buf) + purple_circ_buffer_destroy(conn->write_buf); if (conn->readh) purple_input_remove(conn->readh); if (conn->writeh) @@ -227,6 +234,8 @@ g_free(conn->host); g_free(conn->path); + if (conn->send_timer) + purple_timeout_remove(conn->send_timer); if (conn->inactivity_timer) purple_timeout_remove(conn->inactivity_timer); @@ -250,6 +259,19 @@ { int i; + if (purple_debug_is_verbose()) { + for (i = 0; i < MAX_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); + } + } + /* Easy solution: Does everyone involved support pipelining? Hooray! Just use * one TCP connection! */ if (conn->pipelining) @@ -282,6 +304,8 @@ } } + purple_debug_warning("jabber", "Could not find a HTTP connection!\n"); + /* None available. */ return NULL; } @@ -293,9 +317,29 @@ PurpleHTTPConnection *chosen; GString *packet = NULL; + if (type != PACKET_FLUSH && type != PACKET_TERMINATE) { + /* + * Unless this is a flush (or session terminate, which needs to be + * sent immediately), queue up the data and start a timer to flush + * the buffer. + */ + if (data) { + int len = data ? strlen(data) : 0; + purple_circ_buffer_append(conn->pending, data, len); + } + + if (purple_debug_is_verbose()) + purple_debug_misc("jabber", "bosh: %p has %" G_GSIZE_FORMAT " bytes in " + "the buffer.\n", conn, conn->pending->bufused); + if (conn->send_timer == 0) + conn->send_timer = purple_timeout_add_seconds(BUFFER_SEND_IN_SECS, + send_timer_cb, conn); + return; + } + chosen = find_available_http_connection(conn); - if (type != PACKET_NORMAL && !chosen) { + if (!chosen) { /* * For non-ordinary traffic, we can't 'buffer' it, so use the * first connection. @@ -303,25 +347,16 @@ chosen = conn->connections[0]; if (chosen->state != HTTP_CONN_CONNECTED) { - purple_debug_info("jabber", "Unable to find a ready BOSH " + purple_debug_warning("jabber", "Unable to find a ready BOSH " "connection. Ignoring send of type 0x%02x.\n", type); return; } } - if (type == PACKET_NORMAL && (!chosen || - (conn->max_requests > 0 && conn->requests == conn->max_requests))) { - /* - * For normal data, send up to max_requests requests at a time or there is no - * connection ready (likely, we're currently opening a second connection and - * will send these packets when connected). - */ - if (data) { - int len = data ? strlen(data) : 0; - purple_circ_buffer_append(conn->pending, data, len); - } - - return; + /* We're flushing the send buffer, so remove the send timer */ + if (conn->send_timer != 0) { + purple_timeout_remove(conn->send_timer); + conn->send_timer = 0; } packet = g_string_new(NULL); @@ -337,7 +372,7 @@ conn->sid, conn->js->user->domain); - if (type == PACKET_STREAM_RESTART) { + if (conn->needs_restart) { packet = g_string_append(packet, " xmpp:restart='true'/>"); /* TODO: Do we need to wait for a response? */ conn->needs_restart = FALSE; @@ -369,7 +404,7 @@ static void jabber_bosh_connection_stream_restart(PurpleBOSHConnection *conn) { conn->needs_restart = TRUE; - jabber_bosh_connection_send(conn, PACKET_STREAM_RESTART, NULL); + jabber_bosh_connection_send(conn, PACKET_NORMAL, NULL); } static gboolean jabber_bosh_connection_error_check(PurpleBOSHConnection *conn, xmlnode *node) { @@ -388,12 +423,46 @@ } static gboolean +send_timer_cb(gpointer data) +{ + PurpleBOSHConnection *bosh; + + bosh = data; + bosh->send_timer = 0; + + jabber_bosh_connection_send(bosh, PACKET_FLUSH, NULL); + + return FALSE; +} + +static gboolean bosh_inactivity_cb(gpointer data) { PurpleBOSHConnection *bosh = data; + bosh->inactivity_timer = 0; - jabber_bosh_connection_send(bosh, PACKET_NORMAL, NULL); - return TRUE; + if (bosh->send_timer != 0) + purple_timeout_remove(bosh->send_timer); + + /* clears bosh->send_timer */ + send_timer_cb(bosh); + + return FALSE; +} + +static void +restart_inactivity_timer(PurpleBOSHConnection *conn) +{ + if (conn->inactivity_timer != 0) { + purple_timeout_remove(conn->inactivity_timer); + conn->inactivity_timer = 0; + } + + if (conn->max_inactivity != 0) { + conn->inactivity_timer = + purple_timeout_add_seconds(conn->max_inactivity - 5 /* rounding */, + bosh_inactivity_cb, conn); + } } static void jabber_bosh_connection_received(PurpleBOSHConnection *conn, xmlnode *node) { @@ -490,18 +559,18 @@ if (inactivity) { conn->max_inactivity = atoi(inactivity); - if (conn->max_inactivity <= 2) { + if (conn->max_inactivity <= 5) { purple_debug_warning("jabber", "Ignoring bogusly small inactivity: %s\n", inactivity); conn->max_inactivity = 0; } else { /* TODO: Integrate this with jabber.c keepalive checks... */ + /* TODO: Can this check fail? It shouldn't */ if (conn->inactivity_timer == 0) { - purple_debug_misc("jabber", "Starting BOSH inactivity timer for %d secs (compensating for rounding)\n", + purple_debug_misc("jabber", "Starting BOSH inactivity timer " + "for %d secs (compensating for rounding)\n", conn->max_inactivity - 5); - conn->inactivity_timer = purple_timeout_add_seconds( - conn->max_inactivity - 5 /* rounding */, - bosh_inactivity_cb, conn); + restart_inactivity_timer(conn); } } } @@ -512,7 +581,6 @@ /* FIXME: Depending on receiving features might break with some hosts */ packet = xmlnode_get_child(node, "features"); conn->state = BOSH_CONN_ONLINE; - conn->js->use_bosh = TRUE; conn->receive_cb = auth_response_cb; jabber_stream_features_parse(conn->js, packet); } @@ -578,10 +646,14 @@ { /* Indicate we're ready and reset some variables */ conn->state = HTTP_CONN_CONNECTED; + if (conn->requests != 0) + purple_debug_error("jabber", "bosh: httpconn %p has %d requests, != 0\n", + conn, conn->requests); + conn->requests = 0; - if (conn->buf) { - g_string_free(conn->buf, TRUE); - conn->buf = NULL; + if (conn->read_buf) { + g_string_free(conn->read_buf, TRUE); + conn->read_buf = NULL; } conn->headers_done = FALSE; conn->handled_len = conn->body_len = 0; @@ -592,22 +664,12 @@ purple_debug_info("jabber", "BOSH session already exists. Trying to reuse it.\n"); if (conn->bosh->requests == 0 || conn->bosh->pending->bufused > 0) { /* Send the pending data */ - jabber_bosh_connection_send(conn->bosh, PACKET_NORMAL, NULL); + jabber_bosh_connection_send(conn->bosh, PACKET_FLUSH, NULL); } -#if 0 - conn->bosh->receive_cb = jabber_bosh_connection_received; - if (conn->bosh->connect_cb) - conn->bosh->connect_cb(conn->bosh); -#endif } else jabber_bosh_connection_boot(conn->bosh); } -void jabber_bosh_connection_refresh(PurpleBOSHConnection *conn) -{ - jabber_bosh_connection_send(conn, PACKET_NORMAL, NULL); -} - static void http_connection_disconnected(PurpleHTTPConnection *conn) { /* @@ -633,6 +695,12 @@ conn->writeh = 0; } + if (conn->requests > 0 && 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; + conn->requests = 0; + } if (conn->bosh->pipelining) /* Hmmmm, fall back to multiple connections */ conn->bosh->pipelining = FALSE; @@ -661,7 +729,7 @@ { const char *cursor; - cursor = conn->buf->str + conn->handled_len; + cursor = conn->read_buf->str + conn->handled_len; if (!conn->headers_done) { const char *content_length = purple_strcasestr(cursor, "\r\nContent-Length"); @@ -690,26 +758,26 @@ if (end_of_headers) { conn->headers_done = TRUE; - conn->handled_len = end_of_headers - conn->buf->str + 4; + conn->handled_len = end_of_headers - conn->read_buf->str + 4; cursor = end_of_headers + 4; } else { - conn->handled_len = conn->buf->len; + conn->handled_len = conn->read_buf->len; return; } } /* Have we handled everything in the buffer? */ - if (conn->handled_len >= conn->buf->len) + if (conn->handled_len >= conn->read_buf->len) return; /* Have we read all that the Content-Length promised us? */ - if (conn->buf->len - conn->handled_len < conn->body_len) + if (conn->read_buf->len - conn->handled_len < conn->body_len) return; --conn->requests; --conn->bosh->requests; - http_received_cb(conn->buf->str + conn->handled_len, conn->body_len, + http_received_cb(conn->read_buf->str + conn->handled_len, conn->body_len, conn->bosh); if (conn->bosh->state == BOSH_CONN_ONLINE && @@ -718,8 +786,8 @@ jabber_bosh_connection_send(conn->bosh, PACKET_NORMAL, NULL); } - g_string_free(conn->buf, TRUE); - conn->buf = NULL; + g_string_free(conn->read_buf, TRUE); + conn->read_buf = NULL; conn->headers_done = FALSE; conn->handled_len = conn->body_len = 0; } @@ -734,8 +802,8 @@ char buffer[1025]; int cnt, count = 0; - if (!conn->buf) - conn->buf = g_string_new(NULL); + if (!conn->read_buf) + conn->read_buf = g_string_new(NULL); do { if (conn->psc) @@ -745,7 +813,7 @@ if (cnt > 0) { count += cnt; - g_string_append_len(conn->buf, buffer, cnt); + g_string_append_len(conn->read_buf, buffer, cnt); } } while (cnt > 0); @@ -765,7 +833,7 @@ /* Process what we do have */ } - if (conn->buf->len > 0) + if (conn->read_buf->len > 0) jabber_bosh_http_connection_process(conn); } @@ -879,7 +947,7 @@ { PurpleHTTPConnection *conn = data; int ret; - int writelen = purple_circ_buffer_get_max_read(conn->write_buffer); + int writelen = purple_circ_buffer_get_max_read(conn->write_buf); if (writelen == 0) { purple_input_remove(conn->writeh); @@ -887,7 +955,7 @@ return; } - ret = http_connection_do_send(conn, conn->write_buffer->outptr, writelen); + ret = http_connection_do_send(conn, conn->write_buf->outptr, writelen); if (ret < 0 && errno == EAGAIN) return; @@ -906,7 +974,7 @@ return; } - purple_circ_buffer_mark_read(conn->write_buffer, ret); + purple_circ_buffer_mark_read(conn->write_buf, ret); } static void @@ -916,6 +984,9 @@ int ret; size_t len; + /* Sending something to the server, restart the inactivity timer */ + restart_inactivity_timer(conn->bosh); + data = g_strdup_printf("POST %s HTTP/1.1\r\n" "Host: %s\r\n" "User-Agent: %s\r\n" @@ -930,6 +1001,10 @@ ++conn->requests; ++conn->bosh->requests; + 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); + if (conn->writeh == 0) ret = http_connection_do_send(conn, data, len); else { @@ -956,7 +1031,7 @@ if (conn->writeh == 0) conn->writeh = purple_input_add(conn->psc ? conn->psc->fd : conn->fd, PURPLE_INPUT_WRITE, http_connection_send_cb, conn); - purple_circ_buffer_append(conn->write_buffer, data + ret, len - ret); + purple_circ_buffer_append(conn->write_buf, data + ret, len - ret); } }
--- a/libpurple/protocols/jabber/bosh.h Sat Aug 01 14:55:12 2009 +0900 +++ b/libpurple/protocols/jabber/bosh.h Sun Aug 02 16:43:49 2009 +0900 @@ -37,5 +37,4 @@ void jabber_bosh_connection_connect(PurpleBOSHConnection *conn); void jabber_bosh_connection_close(PurpleBOSHConnection *conn); void jabber_bosh_connection_send_raw(PurpleBOSHConnection *conn, const char *data); -void jabber_bosh_connection_refresh(PurpleBOSHConnection *conn); #endif /* PURPLE_JABBER_BOSH_H_ */
--- a/libpurple/protocols/jabber/buddy.c Sat Aug 01 14:55:12 2009 +0900 +++ b/libpurple/protocols/jabber/buddy.c Sun Aug 02 16:43:49 2009 +0900 @@ -1765,9 +1765,7 @@ if(!jb) return m; - /* XXX: fix the NOT ME below */ - - if(js->protocol_version == JABBER_PROTO_0_9 /* && NOT ME */) { + if (js->protocol_version == JABBER_PROTO_0_9 && jb != js->user_jb) { if(jb->invisible & JABBER_INVIS_BUDDY) { act = purple_menu_action_new(_("Un-hide From"), PURPLE_CALLBACK(jabber_buddy_make_visible), @@ -1780,7 +1778,7 @@ m = g_list_append(m, act); } - if(jb->subscription & JABBER_SUB_FROM /* && NOT ME */) { + if(jb->subscription & JABBER_SUB_FROM && jb != js->user_jb) { act = purple_menu_action_new(_("Cancel Presence Notification"), PURPLE_CALLBACK(jabber_buddy_cancel_presence_notification), NULL, NULL); @@ -1793,7 +1791,7 @@ NULL, NULL); m = g_list_append(m, act); - } else /* if(NOT ME) */{ + } else if (jb != js->user_jb) { /* shouldn't this just happen automatically when the buddy is removed? */
--- a/libpurple/protocols/jabber/buddy.h Sat Aug 01 14:55:12 2009 +0900 +++ b/libpurple/protocols/jabber/buddy.h Sun Aug 02 16:43:49 2009 +0900 @@ -33,10 +33,12 @@ JABBER_BUDDY_STATE_DND } JabberBuddyState; +typedef struct _JabberBuddy JabberBuddy; + #include "jabber.h" #include "caps.h" -typedef struct _JabberBuddy { +struct _JabberBuddy { GList *resources; char *error_msg; enum { @@ -52,7 +54,7 @@ JABBER_SUB_BOTH = (JABBER_SUB_TO | JABBER_SUB_FROM), JABBER_SUB_REMOVE = 1 << 4 } subscription; -} JabberBuddy; +}; typedef struct _JabberAdHocCommands { char *jid;
--- a/libpurple/protocols/jabber/disco.c Sat Aug 01 14:55:12 2009 +0900 +++ b/libpurple/protocols/jabber/disco.c Sun Aug 02 16:43:49 2009 +0900 @@ -85,11 +85,11 @@ /* TODO: When we support zeroconf proxies, fix this to handle them */ if (!(sh->jid && sh->host && sh->port > 0)) { + js->bs_proxies = g_list_remove(js->bs_proxies, sh); g_free(sh->jid); g_free(sh->host); g_free(sh->zeroconf); g_free(sh); - js->bs_proxies = g_list_remove(js->bs_proxies, sh); } }
--- a/libpurple/protocols/jabber/google.c Sat Aug 01 14:55:12 2009 +0900 +++ b/libpurple/protocols/jabber/google.c Sun Aug 02 16:43:49 2009 +0900 @@ -431,7 +431,7 @@ return (session->media != NULL) ? TRUE : FALSE; } -static void +static gboolean google_session_handle_initiate(JabberStream *js, GoogleSession *session, xmlnode *sess, const char *iq_id) { JabberIq *result; @@ -444,7 +444,7 @@ if (session->state != UNINIT) { purple_debug_error("jabber", "Received initiate for active session.\n"); - return; + return FALSE; } desc_element = xmlnode_get_child(sess, "description"); @@ -457,7 +457,7 @@ else { purple_debug_error("jabber", "Received initiate with " "invalid namespace %s.\n", xmlns); - return; + return FALSE; } session->media = purple_media_manager_create_media( @@ -481,7 +481,7 @@ PURPLE_MEDIA_INFO_HANGUP, NULL, NULL, TRUE); google_session_send_terminate(session); g_free(params); - return; + return FALSE; } g_free(params); @@ -552,6 +552,8 @@ jabber_iq_set_id(result, iq_id); xmlnode_set_attrib(result->node, "to", session->remote_jid); jabber_iq_send(result); + + return TRUE; } static void @@ -777,7 +779,8 @@ session->js = js; session->remote_jid = g_strdup(session->id.initiator); - google_session_parse_iq(js, session, session_node, iq_id); + if (!google_session_handle_initiate(js, session, session_node, iq_id)) + google_session_destroy(session); } #endif /* USE_VV */
--- a/libpurple/protocols/jabber/jabber.c Sat Aug 01 14:55:12 2009 +0900 +++ b/libpurple/protocols/jabber/jabber.c Sun Aug 02 16:43:49 2009 +0900 @@ -132,15 +132,19 @@ xmlnode *jid; char *full_jid; if((jid = xmlnode_get_child(bind, "jid")) && (full_jid = xmlnode_get_data(jid))) { - JabberBuddy *my_jb = NULL; jabber_id_free(js->user); - if(!(js->user = jabber_id_new(full_jid))) { + + js->user = jabber_id_new(full_jid); + if (js->user == NULL) { purple_connection_error_reason(js->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Invalid response from server")); + g_free(full_jid); + return; } - if((my_jb = jabber_buddy_find(js, full_jid, TRUE))) - my_jb->subscription |= JABBER_SUB_BOTH; + + js->user_jb = jabber_buddy_find(js, full_jid, TRUE); + js->user_jb->subscription |= JABBER_SUB_BOTH; purple_connection_set_display_name(js->gc, full_jid); @@ -441,7 +445,7 @@ if (len == -1) len = strlen(data); - if (js->use_bosh) + if (js->bosh) jabber_bosh_connection_send_raw(js->bosh, data); else do_jabber_send_raw(js, data, len); @@ -466,7 +470,7 @@ return; js = purple_connection_get_protocol_data(pc); - if (js->use_bosh) + if (js->bosh) if (g_str_equal((*packet)->name, "message") || g_str_equal((*packet)->name, "iq") || g_str_equal((*packet)->name, "presence")) @@ -634,7 +638,6 @@ if (!strcmp(token[0], "_xmpp-client-xbosh")) { purple_debug_info("jabber","Found alternative connection method using %s at %s.\n", token[0], token[1]); js->bosh = jabber_bosh_connection_init(js, token[1]); - js->use_bosh = TRUE; g_strfreev(token); break; } @@ -778,7 +781,6 @@ { PurpleConnection *gc = purple_account_get_connection(account); JabberStream *js; - JabberBuddy *my_jb; PurplePresence *presence; gchar *user; gchar *slash; @@ -813,9 +815,9 @@ js->buddies = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify)jabber_buddy_free); - my_jb = jabber_buddy_find(js, user, TRUE); + js->user_jb = jabber_buddy_find(js, user, TRUE); g_free(user); - if (!my_jb) { + if (!js->user_jb) { /* This basically *can't* fail, but for good measure... */ purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_INVALID_SETTINGS, @@ -824,7 +826,7 @@ g_return_val_if_reached(NULL); } - my_jb->subscription |= JABBER_SUB_BOTH; + js->user_jb->subscription |= JABBER_SUB_BOTH; js->iq_callbacks = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); @@ -867,7 +869,6 @@ * attached to that choice, though. */ if (*bosh_url) { - js->use_bosh = TRUE; js->bosh = jabber_bosh_connection_init(js, bosh_url); if (js->bosh) jabber_bosh_connection_connect(js->bosh); @@ -1447,7 +1448,7 @@ * on some SSL backends. */ if (!gc->disconnect_timeout) { - if (js->use_bosh) + if (js->bosh) jabber_bosh_connection_close(js->bosh); else if ((js->gsc && js->gsc->fd > 0) || js->fd > 0) jabber_send_raw(js, "</stream:stream>", -1);
--- a/libpurple/protocols/jabber/jabber.h Sat Aug 01 14:55:12 2009 +0900 +++ b/libpurple/protocols/jabber/jabber.h Sun Aug 02 16:43:49 2009 +0900 @@ -164,6 +164,8 @@ time_t old_idle; JabberID *user; + JabberBuddy *user_jb; + PurpleConnection *gc; PurpleSslConnection *gsc; @@ -253,7 +255,6 @@ guint max_srv_rec_idx; /* BOSH stuff */ - gboolean use_bosh; PurpleBOSHConnection *bosh; /**
--- a/libpurple/protocols/jabber/roster.c Sat Aug 01 14:55:12 2009 +0900 +++ b/libpurple/protocols/jabber/roster.c Sun Aug 02 16:43:49 2009 +0900 @@ -66,7 +66,7 @@ } static void add_purple_buddy_to_groups(JabberStream *js, const char *jid, - const char *alias, GSList *groups, const char *own_jid) + const char *alias, GSList *groups) { GSList *buddies, *l; GSList *pool = NULL; @@ -162,12 +162,6 @@ purple_blist_add_buddy(b, NULL, g, NULL); purple_blist_alias_buddy(b, alias); - /* If we just learned about ourself, then fake our status, - * because we won't be receiving a normal presence message - * about ourself. */ - if(!strcmp(purple_buddy_get_name(b), own_jid)) - jabber_presence_fake_to_self(js, NULL); - g_free(groups->data); groups = g_slist_delete_link(groups, groups); } @@ -187,7 +181,6 @@ JabberIqType type, const char *id, xmlnode *query) { xmlnode *item, *group; - gchar *own_jid; if (!jabber_is_own_account(js, from)) { purple_debug_warning("jabber", "Received bogon roster push from %s\n", @@ -197,8 +190,6 @@ js->currently_parsing_roster_push = TRUE; - own_jid = g_strdup_printf("%s@%s", js->user->node, js->user->domain); - for(item = xmlnode_get_child(query, "item"); item; item = xmlnode_get_next_twin(item)) { const char *jid, *name, *subscription, *ask; @@ -216,11 +207,7 @@ continue; if(subscription) { - gboolean me = FALSE; - - me = g_str_equal(own_jid, jabber_normalize(js->gc->account, jid)); - - if(me) + if (jb == js->user_jb) jb->subscription = JABBER_SUB_BOTH; else if(!strcmp(subscription, "none")) jb->subscription = JABBER_SUB_NONE; @@ -260,11 +247,12 @@ groups = g_slist_prepend(groups, group_name); } - add_purple_buddy_to_groups(js, jid, name, groups, own_jid); + add_purple_buddy_to_groups(js, jid, name, groups); + if (jb == js->user_jb) + jabber_presence_fake_to_self(js, NULL); } } - g_free(own_jid); js->currently_parsing_roster_push = FALSE; /* if we're just now parsing the roster for the first time, @@ -348,7 +336,6 @@ char *who; JabberBuddy *jb; JabberBuddyResource *jbr; - char *own_jid; const char *name; /* If we haven't received the roster yet, ignore any adds */ @@ -366,8 +353,7 @@ jabber_roster_update(js, who, NULL); - own_jid = g_strdup_printf("%s@%s", js->user->node, js->user->domain); - if (g_str_equal(who, own_jid)) { + if (jb == js->user_jb) { jabber_presence_fake_to_self(js, NULL); } else if(!jb || !(jb->subscription & JABBER_SUB_TO)) { jabber_presence_subscription_set(js, who, "subscribe"); @@ -377,7 +363,6 @@ "priority", jbr->priority, jbr->status ? "message" : NULL, jbr->status, NULL); } - g_free(own_jid); g_free(who); }
--- a/libpurple/protocols/jabber/si.c Sat Aug 01 14:55:12 2009 +0900 +++ b/libpurple/protocols/jabber/si.c Sun Aug 02 16:43:49 2009 +0900 @@ -1359,6 +1359,8 @@ fclose(jsx->fp); } + purple_debug_info("jabber", "jabber_si_xfer_free(): freeing jsx %p\n", jsx); + g_free(jsx->stream_id); g_free(jsx->iq_id); /* XXX: free other stuff */ @@ -1366,7 +1368,6 @@ g_free(jsx); xfer->data = NULL; - purple_debug_info("jabber", "jabber_si_xfer_free(): freeing jsx %p\n", jsx); } }
--- a/libpurple/protocols/msn/directconn.c Sat Aug 01 14:55:12 2009 +0900 +++ b/libpurple/protocols/msn/directconn.c Sun Aug 02 16:43:49 2009 +0900 @@ -351,6 +351,8 @@ msn_directconn_destroy(directconn); } + + g_free(body); } static void
--- a/libpurple/protocols/msnp9/directconn.c Sat Aug 01 14:55:12 2009 +0900 +++ b/libpurple/protocols/msnp9/directconn.c Sun Aug 02 16:43:49 2009 +0900 @@ -355,6 +355,8 @@ msn_directconn_destroy(directconn); } + + g_free(body); } static void
--- a/libpurple/protocols/oscar/family_icq.c Sat Aug 01 14:55:12 2009 +0900 +++ b/libpurple/protocols/oscar/family_icq.c Sun Aug 02 16:43:49 2009 +0900 @@ -735,14 +735,6 @@ info = g_new0(struct aim_icq_info, 1); - if (info == NULL) - { - g_free(uin); - g_free(status_note_title); - - break; - } - bslen = 13 + strlen(uin) + 30 + 6 + 4 + 55 + 85 + 4; byte_stream_new(&bs, 4 + bslen);
--- a/libpurple/protocols/yahoo/libymsg.c Sat Aug 01 14:55:12 2009 +0900 +++ b/libpurple/protocols/yahoo/libymsg.c Sun Aug 02 16:43:49 2009 +0900 @@ -1836,6 +1836,7 @@ g_free(error_reason); g_free(auth_data->seed); g_free(auth_data); + g_free(token); } else { /* OK to login, correct information provided */ @@ -2088,6 +2089,12 @@ msg = g_strdup(_("Your account is locked, please log in to the Yahoo! website.")); reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED; break; + case 52: + /* See #9660. As much as we know, reconnecting shouldn't hurt */ + purple_debug_info("yahoo", "Got error 52, Set to autoreconnect\n"); + msg = g_strdup_printf(_("Unknown error")); + reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR; + break; case 1013: msg = g_strdup(_("Invalid username")); reason = PURPLE_CONNECTION_ERROR_INVALID_USERNAME;
--- a/libpurple/protocols/yahoo/util.c Sat Aug 01 14:55:12 2009 +0900 +++ b/libpurple/protocols/yahoo/util.c Sun Aug 02 16:43:49 2009 +0900 @@ -763,6 +763,8 @@ } else if (!g_ascii_strncasecmp(&src[i+1], "A HREF=\"", j - i - 1)) { j += 7; g_string_append(dest, "\033[lm"); + if (purple_str_has_prefix(src + j, "mailto:")) + j += sizeof("mailto:") - 1; while (1) { g_string_append_c(dest, src[j]); if (++j >= src_len) {
--- a/libpurple/protocols/yahoo/yahoo_filexfer.c Sat Aug 01 14:55:12 2009 +0900 +++ b/libpurple/protocols/yahoo/yahoo_filexfer.c Sun Aug 02 16:43:49 2009 +0900 @@ -889,46 +889,48 @@ /* Build the file transfer handle. */ xfer = purple_xfer_new(gc->account, PURPLE_XFER_RECEIVE, from); - if (xfer) - { - xfer->data = xfer_data; + if (xfer == NULL) { + g_free(xfer_data); + g_return_if_reached(); + } + + xfer->data = xfer_data; - /* Set the info about the incoming file. */ - if (filename) { - char *utf8_filename = yahoo_string_decode(gc, filename, TRUE); + /* Set the info about the incoming file. */ + if (filename) { + char *utf8_filename = yahoo_string_decode(gc, filename, TRUE); + purple_xfer_set_filename(xfer, utf8_filename); + g_free(utf8_filename); + } else { + gchar *start, *end; + start = g_strrstr(xfer_data->path, "/"); + if (start) + start++; + end = g_strrstr(xfer_data->path, "?"); + if (start && *start && end) { + char *utf8_filename; + filename = g_strndup(start, end - start); + utf8_filename = yahoo_string_decode(gc, filename, TRUE); + g_free(filename); purple_xfer_set_filename(xfer, utf8_filename); g_free(utf8_filename); - } else { - gchar *start, *end; - start = g_strrstr(xfer_data->path, "/"); - if (start) - start++; - end = g_strrstr(xfer_data->path, "?"); - if (start && *start && end) { - char *utf8_filename; - filename = g_strndup(start, end - start); - utf8_filename = yahoo_string_decode(gc, filename, TRUE); - g_free(filename); - purple_xfer_set_filename(xfer, utf8_filename); - g_free(utf8_filename); - filename = NULL; - } + filename = NULL; } + } - purple_xfer_set_size(xfer, filesize); + purple_xfer_set_size(xfer, filesize); - /* Setup our I/O op functions */ - purple_xfer_set_init_fnc(xfer, yahoo_xfer_init); - purple_xfer_set_start_fnc(xfer, yahoo_xfer_start); - purple_xfer_set_end_fnc(xfer, yahoo_xfer_end); - purple_xfer_set_cancel_send_fnc(xfer, yahoo_xfer_cancel_send); - purple_xfer_set_cancel_recv_fnc(xfer, yahoo_xfer_cancel_recv); - purple_xfer_set_read_fnc(xfer, yahoo_xfer_read); - purple_xfer_set_write_fnc(xfer, yahoo_xfer_write); + /* Setup our I/O op functions */ + purple_xfer_set_init_fnc(xfer, yahoo_xfer_init); + purple_xfer_set_start_fnc(xfer, yahoo_xfer_start); + purple_xfer_set_end_fnc(xfer, yahoo_xfer_end); + purple_xfer_set_cancel_send_fnc(xfer, yahoo_xfer_cancel_send); + purple_xfer_set_cancel_recv_fnc(xfer, yahoo_xfer_cancel_recv); + purple_xfer_set_read_fnc(xfer, yahoo_xfer_read); + purple_xfer_set_write_fnc(xfer, yahoo_xfer_write); - /* Now perform the request */ - purple_xfer_request(xfer); - } + /* Now perform the request */ + purple_xfer_request(xfer); } PurpleXfer *yahoo_new_xfer(PurpleConnection *gc, const char *who) @@ -943,19 +945,22 @@ /* Build the file transfer handle. */ xfer = purple_xfer_new(gc->account, PURPLE_XFER_SEND, who); - if (xfer) + if (xfer == NULL) { - xfer->data = xfer_data; + g_free(xfer_data); + g_return_val_if_reached(NULL); + } + + xfer->data = xfer_data; - /* Setup our I/O op functions */ - purple_xfer_set_init_fnc(xfer, yahoo_xfer_init); - purple_xfer_set_start_fnc(xfer, yahoo_xfer_start); - purple_xfer_set_end_fnc(xfer, yahoo_xfer_end); - purple_xfer_set_cancel_send_fnc(xfer, yahoo_xfer_cancel_send); - purple_xfer_set_cancel_recv_fnc(xfer, yahoo_xfer_cancel_recv); - purple_xfer_set_read_fnc(xfer, yahoo_xfer_read); - purple_xfer_set_write_fnc(xfer, yahoo_xfer_write); - } + /* Setup our I/O op functions */ + purple_xfer_set_init_fnc(xfer, yahoo_xfer_init); + purple_xfer_set_start_fnc(xfer, yahoo_xfer_start); + purple_xfer_set_end_fnc(xfer, yahoo_xfer_end); + purple_xfer_set_cancel_send_fnc(xfer, yahoo_xfer_cancel_send); + purple_xfer_set_cancel_recv_fnc(xfer, yahoo_xfer_cancel_recv); + purple_xfer_set_read_fnc(xfer, yahoo_xfer_read); + purple_xfer_set_write_fnc(xfer, yahoo_xfer_write); return xfer; } @@ -1593,6 +1598,7 @@ char *service = NULL; char *filename = NULL; char *xfer_peer_idstring = NULL; + char *utf8_filename; unsigned long filesize = 0L; GSList *l; GSList *filename_list = NULL; @@ -1719,42 +1725,44 @@ /* Build the file transfer handle. */ xfer = purple_xfer_new(gc->account, PURPLE_XFER_RECEIVE, from); + if (xfer == NULL) + { + g_free(xfer_data); + g_return_if_reached(); + } + xfer->message = NULL; - if (xfer) - { - /* Set the info about the incoming file. */ - char *utf8_filename = yahoo_string_decode(gc, filename, TRUE); - purple_xfer_set_filename(xfer, utf8_filename); - g_free(utf8_filename); - purple_xfer_set_size(xfer, filesize); + /* Set the info about the incoming file. */ + utf8_filename = yahoo_string_decode(gc, filename, TRUE); + purple_xfer_set_filename(xfer, utf8_filename); + g_free(utf8_filename); + purple_xfer_set_size(xfer, filesize); - xfer->data = xfer_data; - + xfer->data = xfer_data; - /* Setup our I/O op functions */ - purple_xfer_set_init_fnc(xfer, yahoo_xfer_init_15); - purple_xfer_set_start_fnc(xfer, yahoo_xfer_start); - purple_xfer_set_end_fnc(xfer, yahoo_xfer_end); - purple_xfer_set_cancel_send_fnc(xfer, yahoo_xfer_cancel_send); - purple_xfer_set_cancel_recv_fnc(xfer, yahoo_xfer_cancel_recv); - purple_xfer_set_read_fnc(xfer, yahoo_xfer_read); - purple_xfer_set_write_fnc(xfer, yahoo_xfer_write); - purple_xfer_set_request_denied_fnc(xfer,yahoo_xfer_cancel_recv); + /* Setup our I/O op functions */ + purple_xfer_set_init_fnc(xfer, yahoo_xfer_init_15); + purple_xfer_set_start_fnc(xfer, yahoo_xfer_start); + purple_xfer_set_end_fnc(xfer, yahoo_xfer_end); + purple_xfer_set_cancel_send_fnc(xfer, yahoo_xfer_cancel_send); + purple_xfer_set_cancel_recv_fnc(xfer, yahoo_xfer_cancel_recv); + purple_xfer_set_read_fnc(xfer, yahoo_xfer_read); + purple_xfer_set_write_fnc(xfer, yahoo_xfer_write); + purple_xfer_set_request_denied_fnc(xfer,yahoo_xfer_cancel_recv); - g_hash_table_insert(yd->xfer_peer_idstring_map, - xfer_data->xfer_peer_idstring, - xfer); + g_hash_table_insert(yd->xfer_peer_idstring_map, + xfer_data->xfer_peer_idstring, + xfer); - if(nooffiles > 1) { - gchar* message; - message = g_strdup_printf(_("%s is trying to send you a group of %d files.\n"), xfer->who, nooffiles); - purple_xfer_conversation_write(xfer, message, FALSE); - g_free(message); - } - /* Now perform the request */ - purple_xfer_request(xfer); + if(nooffiles > 1) { + gchar* message; + message = g_strdup_printf(_("%s is trying to send you a group of %d files.\n"), xfer->who, nooffiles); + purple_xfer_conversation_write(xfer, message, FALSE); + g_free(message); } + /* Now perform the request */ + purple_xfer_request(xfer); } void yahoo_process_filetrans_info_15(PurpleConnection *gc, struct yahoo_packet *pkt)
--- a/libpurple/protocols/yahoo/yahoo_packet.c Sat Aug 01 14:55:12 2009 +0900 +++ b/libpurple/protocols/yahoo/yahoo_packet.c Sun Aug 02 16:43:49 2009 +0900 @@ -403,7 +403,7 @@ struct yahoo_pair *pair = pkt->hash->data; g_free(pair->value); g_free(pair); - pkt->hash = g_slist_remove(pkt->hash, pair); + pkt->hash = g_slist_delete_link(pkt->hash, pkt->hash); } g_free(pkt); }
--- a/libpurple/protocols/zephyr/internal.h Sat Aug 01 14:55:12 2009 +0900 +++ b/libpurple/protocols/zephyr/internal.h Sun Aug 02 16:43:49 2009 +0900 @@ -23,6 +23,12 @@ #define ETIMEDOUT WSAETIMEDOUT #define EADDRINUSE WSAEADDRINUSE +#else /* !WIN32 */ + +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 4096 +#endif + #endif #ifdef ZEPHYR_USES_HESIOD
--- a/libpurple/signals.c Sat Aug 01 14:55:12 2009 +0900 +++ b/libpurple/signals.c Sun Aug 02 16:43:49 2009 +0900 @@ -363,8 +363,8 @@ { g_free(handler_data); - signal_data->handlers = g_list_remove(signal_data->handlers, - handler_data); + signal_data->handlers = g_list_delete_link(signal_data->handlers, + l); signal_data->handler_count--; found = TRUE; @@ -398,8 +398,8 @@ g_free(handler_data); signal_data->handler_count--; - signal_data->handlers = g_list_remove(signal_data->handlers, - handler_data); + signal_data->handlers = g_list_delete_link(signal_data->handlers, + l); } } }
--- a/pidgin/gtkblist.c Sat Aug 01 14:55:12 2009 +0900 +++ b/pidgin/gtkblist.c Sun Aug 02 16:43:49 2009 +0900 @@ -3566,7 +3566,7 @@ } g_free(pce); - cur = g_list_remove(cur, pce); + cur = g_list_delete_link(cur, cur); } } else if (PURPLE_BLIST_NODE_IS_CONTACT(node) || PURPLE_BLIST_NODE_IS_BUDDY(node))
--- a/pidgin/gtkimhtml.c Sat Aug 01 14:55:12 2009 +0900 +++ b/pidgin/gtkimhtml.c Sun Aug 02 16:43:49 2009 +0900 @@ -5853,9 +5853,9 @@ if (activate) { return FALSE; } + klass->protocols = g_list_remove(klass->protocols, proto); g_free(proto->name); g_free(proto); - klass->protocols = g_list_remove(klass->protocols, proto); return TRUE; } else if (!activate) { return FALSE;
--- a/pidgin/gtkprefs.c Sat Aug 01 14:55:12 2009 +0900 +++ b/pidgin/gtkprefs.c Sun Aug 02 16:43:49 2009 +0900 @@ -698,7 +698,8 @@ g_free(original_name); g_free(info); return; - } else g_free(info); + } else + g_free(info); is_archive = !g_ascii_strcasecmp(tail, ".gz") || !g_ascii_strcasecmp(tail, ".tgz"); @@ -1032,8 +1033,6 @@ info->original_name = NULL; theme_install_theme(theme_file_name, info); - - g_free(info); } static void
--- a/pidgin/gtkthemes.c Sat Aug 01 14:55:12 2009 +0900 +++ b/pidgin/gtkthemes.c Sun Aug 02 16:43:49 2009 +0900 @@ -183,7 +183,7 @@ } g_free(uio->smile); g_free(uio); - wer->smileys = g_slist_remove(wer->smileys, uio); + wer->smileys = g_slist_delete_link(wer->smileys, wer->smileys); } theme->list = wer->next; g_free(wer->sml); @@ -229,7 +229,6 @@ struct smiley_list *list = NULL; GSList *lst = smiley_themes; char *dirname; - gboolean new_theme = FALSE; if (!f) return; @@ -243,16 +242,18 @@ lst = lst->next; } - if (!theme) { - new_theme = TRUE; - theme = g_new0(struct smiley_theme, 1); - theme->path = g_strdup(file); - } else if (theme == current_smiley_theme) { + if (theme != NULL && theme == current_smiley_theme) { /* Don't reload the theme if it is already loaded */ fclose(f); return; } + if (theme == NULL) { + theme = g_new0(struct smiley_theme, 1); + theme->path = g_strdup(file); + smiley_themes = g_slist_prepend(smiley_themes, theme); + } + dirname = g_path_get_dirname(file); while (!feof(f)) { @@ -341,14 +342,11 @@ if (!theme->name || !theme->desc || !theme->author) { purple_debug_error("gtkthemes", "Invalid file format, not loading smiley theme from '%s'\n", file); + smiley_themes = g_slist_remove(smiley_themes, theme); pidgin_themes_destroy_smiley_theme(theme); return; } - if (new_theme) { - smiley_themes = g_slist_prepend(smiley_themes, theme); - } - if (load) { GList *cnv;