# HG changeset patch # User Paul Aurich # Date 1242596960 0 # Node ID 47d963966c9aea942d80a5c221296826e7f5fb09 # Parent 0bce1b58e1fe1a942dd317bf567051f650981d0c# Parent 34e4e2ca7db9ffc78d76038fd073d156c3a77c1d propagate from branch 'im.pidgin.cpw.sulabh.yahoo_16' (head 86a698e26bedb5017a143cb8cfeefd9c5bda7beb) to branch 'im.pidgin.pidgin' (head dcd01209d8af5268ac18d8f55577aadc4b1c1179) Whoops diff -r 0bce1b58e1fe -r 47d963966c9a .mtn-ignore --- a/.mtn-ignore Fri May 15 16:21:27 2009 +0000 +++ b/.mtn-ignore Sun May 17 21:49:20 2009 +0000 @@ -52,6 +52,7 @@ libpurple/dbus-types.h libpurple/example/nullclient libpurple/gconf/purple.schemas$ +libpurple/marshallers.[ch] libpurple/plugins/dbus-example-bindings.c libpurple/plugins/perl/common/Makefile.PL$ libpurple/plugins/perl/common/Makefile.old diff -r 0bce1b58e1fe -r 47d963966c9a ChangeLog --- a/ChangeLog Fri May 15 16:21:27 2009 +0000 +++ b/ChangeLog Sun May 17 21:49:20 2009 +0000 @@ -38,6 +38,9 @@ contains formatting. * Show when the user was last logged in when doing "Get Info" on an offline buddy, provided the server supports it. + * Support custom smileys in MUCs (only when all participants supports the + "Bits of Binary" extension, and a maximum of 10 participants are in the + chat (to avoid getting too many fetch requests). Yahoo: * P2P file transfers. (Sulabh Mahajan) diff -r 0bce1b58e1fe -r 47d963966c9a libpurple/account.c --- a/libpurple/account.c Fri May 15 16:21:27 2009 +0000 +++ b/libpurple/account.c Sun May 17 21:49:20 2009 +0000 @@ -99,7 +99,7 @@ const char *name; PurpleAccountSetting *setting; xmlnode *node, *child; - char buf[20]; + char buf[21]; name = (const char *)key; setting = (PurpleAccountSetting *)value; @@ -110,7 +110,7 @@ if (setting->type == PURPLE_PREF_INT) { xmlnode_set_attrib(child, "type", "int"); - snprintf(buf, sizeof(buf), "%d", setting->value.integer); + g_snprintf(buf, sizeof(buf), "%d", setting->value.integer); xmlnode_insert_data(child, buf, -1); } else if (setting->type == PURPLE_PREF_STRING && setting->value.string != NULL) { @@ -119,7 +119,7 @@ } else if (setting->type == PURPLE_PREF_BOOLEAN) { xmlnode_set_attrib(child, "type", "bool"); - snprintf(buf, sizeof(buf), "%d", setting->value.boolean); + g_snprintf(buf, sizeof(buf), "%d", setting->value.boolean); xmlnode_insert_data(child, buf, -1); } } @@ -281,7 +281,7 @@ PurpleProxyType proxy_type; const char *value; int int_value; - char buf[20]; + char buf[21]; proxy_type = purple_proxy_info_get_type(proxy_info); @@ -304,7 +304,7 @@ if ((int_value = purple_proxy_info_get_port(proxy_info)) != 0) { - snprintf(buf, sizeof(buf), "%d", int_value); + g_snprintf(buf, sizeof(buf), "%d", int_value); child = xmlnode_new_child(node, "port"); xmlnode_insert_data(child, buf, -1); } @@ -342,7 +342,7 @@ return node; child = xmlnode_new_child(node, "type"); - snprintf(type_str, sizeof(type_str), "%u", err->type); + g_snprintf(type_str, sizeof(type_str), "%u", err->type); xmlnode_insert_data(child, type_str, -1); child = xmlnode_new_child(node, "description"); diff -r 0bce1b58e1fe -r 47d963966c9a libpurple/blist.c --- a/libpurple/blist.c Fri May 15 16:21:27 2009 +0000 +++ b/libpurple/blist.c Sun May 17 21:49:20 2009 +0000 @@ -125,7 +125,7 @@ const char *name; PurpleValue *value; xmlnode *node, *child; - char buf[20]; + char buf[21]; name = (const char *)key; value = (PurpleValue *)hvalue; @@ -138,7 +138,7 @@ if (purple_value_get_type(value) == PURPLE_TYPE_INT) { xmlnode_set_attrib(child, "type", "int"); - snprintf(buf, sizeof(buf), "%d", purple_value_get_int(value)); + g_snprintf(buf, sizeof(buf), "%d", purple_value_get_int(value)); xmlnode_insert_data(child, buf, -1); } else if (purple_value_get_type(value) == PURPLE_TYPE_STRING) { @@ -147,7 +147,7 @@ } else if (purple_value_get_type(value) == PURPLE_TYPE_BOOLEAN) { xmlnode_set_attrib(child, "type", "bool"); - snprintf(buf, sizeof(buf), "%d", purple_value_get_boolean(value)); + g_snprintf(buf, sizeof(buf), "%d", purple_value_get_boolean(value)); xmlnode_insert_data(child, buf, -1); } } @@ -303,7 +303,7 @@ node = xmlnode_new("account"); xmlnode_set_attrib(node, "proto", purple_account_get_protocol_id(account)); xmlnode_set_attrib(node, "name", purple_account_get_username(account)); - snprintf(buf, sizeof(buf), "%d", account->perm_deny); + g_snprintf(buf, sizeof(buf), "%d", account->perm_deny); xmlnode_set_attrib(node, "mode", buf); for (cur = account->permit; cur; cur = cur->next) diff -r 0bce1b58e1fe -r 47d963966c9a libpurple/dnsquery.c --- a/libpurple/dnsquery.c Fri May 15 16:21:27 2009 +0000 +++ b/libpurple/dnsquery.c Sun May 17 21:49:20 2009 +0000 @@ -325,7 +325,7 @@ return; already_done = TRUE; ppid = getppid(); - snprintf(s, sizeof(s), "/proc/%d/exe", ppid); + g_snprintf(s, sizeof(s), "/proc/%d/exe", ppid); n = readlink(s, e, sizeof(e)); if(n < 0) return; diff -r 0bce1b58e1fe -r 47d963966c9a libpurple/network.c --- a/libpurple/network.c Fri May 15 16:21:27 2009 +0000 +++ b/libpurple/network.c Sun May 17 21:49:20 2009 +0000 @@ -303,7 +303,7 @@ /* * Get a list of addresses on this machine. */ - snprintf(serv, sizeof(serv), "%hu", port); + g_snprintf(serv, sizeof(serv), "%hu", port); memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_flags = AI_PASSIVE; hints.ai_family = AF_UNSPEC; diff -r 0bce1b58e1fe -r 47d963966c9a libpurple/plugins/perl/perl-handlers.c --- a/libpurple/plugins/perl/perl-handlers.c Fri May 15 16:21:27 2009 +0000 +++ b/libpurple/plugins/perl/perl-handlers.c Sun May 17 21:49:20 2009 +0000 @@ -284,6 +284,8 @@ DATATYPE **copy_args; dSP; + PERL_SET_CONTEXT(my_perl); + SPAGAIN; ENTER; SAVETMPS; PUSHMARK(sp); @@ -364,7 +366,8 @@ break; case PURPLE_TYPE_STRING: - if (strcmp(*((char **)copy_args[i]), SvPVX(sv_args[i]))) { + if (!*((char **)copy_args[i]) || !SvPVX(sv_args[i]) || + strcmp(*((char **)copy_args[i]), SvPVX(sv_args[i]))) { g_free(*((char **)copy_args[i])); *((char **)copy_args[i]) = g_strdup(SvPVutf8_nolen(sv_args[i])); diff -r 0bce1b58e1fe -r 47d963966c9a libpurple/prefs.c --- a/libpurple/prefs.c Fri May 15 16:21:27 2009 +0000 +++ b/libpurple/prefs.c Sun May 17 21:49:20 2009 +0000 @@ -118,7 +118,7 @@ { xmlnode *node, *childnode; struct purple_pref *child; - char buf[20]; + char buf[21]; GList *cur; /* Create a new node */ @@ -128,7 +128,7 @@ /* Set the type of this node (if type == PURPLE_PREF_NONE then do nothing) */ if (pref->type == PURPLE_PREF_INT) { xmlnode_set_attrib(node, "type", "int"); - snprintf(buf, sizeof(buf), "%d", pref->value.integer); + g_snprintf(buf, sizeof(buf), "%d", pref->value.integer); xmlnode_set_attrib(node, "value", buf); } else if (pref->type == PURPLE_PREF_STRING) { @@ -161,7 +161,7 @@ } else if (pref->type == PURPLE_PREF_BOOLEAN) { xmlnode_set_attrib(node, "type", "bool"); - snprintf(buf, sizeof(buf), "%d", pref->value.boolean); + g_snprintf(buf, sizeof(buf), "%d", pref->value.boolean); xmlnode_set_attrib(node, "value", buf); } diff -r 0bce1b58e1fe -r 47d963966c9a libpurple/protocols/jabber/buddy.c --- a/libpurple/protocols/jabber/buddy.c Fri May 15 16:21:27 2009 +0000 +++ b/libpurple/protocols/jabber/buddy.c Sun May 17 21:49:20 2009 +0000 @@ -74,7 +74,7 @@ if (js->buddies == NULL) return NULL; - if(!(realname = jabber_normalize(js->gc->account, name))) + if(!(realname = jabber_get_bare_jid(name))) return NULL; jb = g_hash_table_lookup(js->buddies, realname); diff -r 0bce1b58e1fe -r 47d963966c9a libpurple/protocols/jabber/chat.c --- a/libpurple/protocols/jabber/chat.c Fri May 15 16:21:27 2009 +0000 +++ b/libpurple/protocols/jabber/chat.c Sun May 17 21:49:20 2009 +0000 @@ -1162,5 +1162,59 @@ g_free(room_jid); } +typedef struct { + const gchar *cap; + gboolean *all_support; + JabberBuddy *jb; +} JabberChatCapsData; +static void +jabber_chat_all_participants_have_capability_foreach(gpointer key, + gpointer value, + gpointer user_data) +{ + const gchar *cap = ((JabberChatCapsData *) user_data)->cap; + gboolean *all_support = ((JabberChatCapsData *) user_data)->all_support; + JabberBuddy *jb = ((JabberChatCapsData *) user_data)->jb; + JabberChatMember *member = (JabberChatMember *) value; + const gchar *resource = member->handle; + JabberBuddyResource *jbr = jabber_buddy_find_resource(jb, resource); + if (jbr) { + *all_support &= jabber_resource_has_capability(jbr, cap); + } else { + *all_support = FALSE; + } +} + +gboolean +jabber_chat_all_participants_have_capability(const JabberChat *chat, + const gchar *cap) +{ + gchar *chat_jid = NULL; + JabberBuddy *jb = NULL; + gboolean all_support = TRUE; + JabberChatCapsData data; + + chat_jid = g_strdup_printf("%s@%s", chat->room, chat->server); + jb = jabber_buddy_find(chat->js, chat_jid, FALSE); + + if (jb) { + data.cap = cap; + data.all_support = &all_support; + data.jb = jb; + + g_hash_table_foreach(chat->members, + jabber_chat_all_participants_have_capability_foreach, &data); + } else { + all_support = FALSE; + } + g_free(chat_jid); + return all_support; +} + +guint +jabber_chat_get_num_participants(const JabberChat *chat) +{ + return g_hash_table_size(chat->members); +} diff -r 0bce1b58e1fe -r 47d963966c9a libpurple/protocols/jabber/chat.h --- a/libpurple/protocols/jabber/chat.h Fri May 15 16:21:27 2009 +0000 +++ b/libpurple/protocols/jabber/chat.h Sun May 17 21:49:20 2009 +0000 @@ -95,5 +95,8 @@ char *jabber_roomlist_room_serialize(PurpleRoomlistRoom *room); +gboolean jabber_chat_all_participants_have_capability(const JabberChat *chat, + const gchar *cap); +guint jabber_chat_get_num_participants(const JabberChat *chat); #endif /* PURPLE_JABBER_CHAT_H_ */ diff -r 0bce1b58e1fe -r 47d963966c9a libpurple/protocols/jabber/jabber.c --- a/libpurple/protocols/jabber/jabber.c Fri May 15 16:21:27 2009 +0000 +++ b/libpurple/protocols/jabber/jabber.c Sun May 17 21:49:20 2009 +0000 @@ -3359,7 +3359,7 @@ jabber_add_feature(XEP_0224_NAMESPACE, jabber_buzz_isenabled); /* Bits Of Binary */ - jabber_add_feature(XEP_0231_NAMESPACE, jabber_custom_smileys_isenabled); + jabber_add_feature(XEP_0231_NAMESPACE, 0); /* Jingle features! */ jabber_add_feature(JINGLE, 0); diff -r 0bce1b58e1fe -r 47d963966c9a libpurple/protocols/jabber/jutil.c --- a/libpurple/protocols/jabber/jutil.c Fri May 15 16:21:27 2009 +0000 +++ b/libpurple/protocols/jabber/jutil.c Sun May 17 21:49:20 2009 +0000 @@ -105,6 +105,8 @@ { char *at; char *slash; + char *node = NULL; + char *domain; JabberID *jid; if(!str || !g_utf8_validate(str, -1, NULL)) @@ -116,22 +118,31 @@ slash = g_utf8_strchr(str, -1, '/'); if(at) { - jid->node = g_utf8_normalize(str, at-str, G_NORMALIZE_NFKC); + node = g_utf8_normalize(str, at-str, G_NORMALIZE_NFKC); if(slash) { - jid->domain = g_utf8_normalize(at+1, slash-(at+1), G_NORMALIZE_NFKC); + domain = g_utf8_normalize(at+1, slash-(at+1), G_NORMALIZE_NFKC); jid->resource = g_utf8_normalize(slash+1, -1, G_NORMALIZE_NFKC); } else { - jid->domain = g_utf8_normalize(at+1, -1, G_NORMALIZE_NFKC); + domain = g_utf8_normalize(at+1, -1, G_NORMALIZE_NFKC); } } else { if(slash) { - jid->domain = g_utf8_normalize(str, slash-str, G_NORMALIZE_NFKC); + domain = g_utf8_normalize(str, slash-str, G_NORMALIZE_NFKC); jid->resource = g_utf8_normalize(slash+1, -1, G_NORMALIZE_NFKC); } else { - jid->domain = g_utf8_normalize(str, -1, G_NORMALIZE_NFKC); + domain = g_utf8_normalize(str, -1, G_NORMALIZE_NFKC); } } + if (node) { + jid->node = g_utf8_strdown(node, -1); + g_free(node); + } + + if (domain) { + jid->domain = g_utf8_strdown(domain, -1); + g_free(domain); + } if(!jabber_nodeprep_validate(jid->node) || !jabber_nameprep_validate(jid->domain) || @@ -193,28 +204,21 @@ JabberStream *js = gc ? gc->proto_data : NULL; static char buf[3072]; /* maximum legal length of a jabber jid */ JabberID *jid; - char *node, *domain; jid = jabber_id_new(in); if(!jid) return NULL; - node = jid->node ? g_utf8_strdown(jid->node, -1) : NULL; - domain = g_utf8_strdown(jid->domain, -1); - - - if(js && node && jid->resource && - jabber_chat_find(js, node, domain)) - g_snprintf(buf, sizeof(buf), "%s@%s/%s", node, domain, + if(js && jid->node && jid->resource && + jabber_chat_find(js, jid->node, jid->domain)) + g_snprintf(buf, sizeof(buf), "%s@%s/%s", jid->node, jid->domain, jid->resource); else - g_snprintf(buf, sizeof(buf), "%s%s%s", node ? node : "", - node ? "@" : "", domain); + g_snprintf(buf, sizeof(buf), "%s%s%s", jid->node ? jid->node : "", + jid->node ? "@" : "", jid->domain); jabber_id_free(jid); - g_free(node); - g_free(domain); return buf; } diff -r 0bce1b58e1fe -r 47d963966c9a libpurple/protocols/jabber/message.c --- a/libpurple/protocols/jabber/message.c Fri May 15 16:21:27 2009 +0000 +++ b/libpurple/protocols/jabber/message.c Sun May 17 21:49:20 2009 +0000 @@ -921,11 +921,12 @@ static gboolean jabber_conv_support_custom_smileys(const PurpleConnection *gc, - const PurpleConversation *conv, + PurpleConversation *conv, const gchar *who) { JabberStream *js = (JabberStream *) gc->proto_data; JabberBuddy *jb; + JabberChat *chat; if (!js) { purple_debug_error("jabber", @@ -934,7 +935,6 @@ } switch (purple_conversation_get_type(conv)) { - /* for the time being, we will not support custom smileys in MUCs */ case PURPLE_CONV_TYPE_IM: jb = jabber_buddy_find(js, who, FALSE); if (jb) { @@ -943,6 +943,18 @@ return FALSE; } break; + case PURPLE_CONV_TYPE_CHAT: + chat = jabber_chat_find_by_conv(conv); + if (chat) { + /* do not attempt to send custom smileys in a MUC with more than + 10 people, to avoid getting too many BoB requests */ + return jabber_chat_get_num_participants(chat) <= 10 && + jabber_chat_all_participants_have_capability(chat, + XEP_0231_NAMESPACE); + } else { + return FALSE; + } + break; default: return FALSE; break; @@ -1202,6 +1214,7 @@ JabberMessage *jm; JabberStream *js; char *xhtml; + char *tmp; if(!msg || !gc) return 0; @@ -1219,6 +1232,11 @@ jm->id = jabber_get_next_id(jm->js); purple_markup_html_to_xhtml(msg, &xhtml, &jm->body); + tmp = jabber_message_smileyfy_xhtml(jm, xhtml); + if (tmp) { + g_free(xhtml); + xhtml = tmp; + } if (chat->xhtml && !jabber_xhtml_plain_equal(xhtml, jm->body)) jm->xhtml = g_strdup_printf("%s", xhtml); diff -r 0bce1b58e1fe -r 47d963966c9a libpurple/protocols/jabber/si.c --- a/libpurple/protocols/jabber/si.c Fri May 15 16:21:27 2009 +0000 +++ b/libpurple/protocols/jabber/si.c Sun May 17 21:49:20 2009 +0000 @@ -407,7 +407,7 @@ { PurpleXfer *xfer = data; JabberSIXfer *jsx = xfer->data; - char buffer[256]; + char buffer[42]; /* 40 for DST.ADDR + 2 bytes for port number*/ int len; char *dstaddr, *hash; const char *host; @@ -431,16 +431,19 @@ jsx->rxlen += len; return; } else if(jsx->rxqueue[0] != 0x05 || jsx->rxqueue[1] != 0x01 || - jsx->rxqueue[3] != 0x03) { - purple_debug_info("jabber", "invalid socks5 stuff\n"); + jsx->rxqueue[3] != 0x03 || jsx->rxqueue[4] != 40) { + purple_debug_info("jabber", "Invalid socks5 conn req. header[0x%x,0x%x,0x%x,0x%x,0x%x]\n", + jsx->rxqueue[0], jsx->rxqueue[1], jsx->rxqueue[2], + jsx->rxqueue[3], jsx->rxqueue[4]); purple_input_remove(xfer->watcher); xfer->watcher = 0; close(source); purple_xfer_cancel_remote(xfer); return; } else if(jsx->rxlen - 5 < jsx->rxqueue[4] + 2) { - purple_debug_info("jabber", "reading umpteen more bytes\n"); - len = read(source, buffer, jsx->rxqueue[4] + 5 + 2 - jsx->rxlen); + purple_debug_info("jabber", "reading %u bytes for DST.ADDR + port num (trying to read %u now)\n", + jsx->rxqueue[4] + 2, jsx->rxqueue[4] + 2 - (jsx->rxlen - 5)); + len = read(source, buffer, jsx->rxqueue[4] + 2 - (jsx->rxlen - 5)); if(len < 0 && errno == EAGAIN) return; else if(len <= 0) { @@ -455,6 +458,7 @@ jsx->rxlen += len; } + /* Have we not read all of DST.ADDR and the following 2-byte port number? */ if(jsx->rxlen - 5 < jsx->rxqueue[4] + 2) return; @@ -468,9 +472,16 @@ /* Per XEP-0065, the 'host' must be SHA1(SID + from JID + to JID) */ hash = jabber_calculate_data_sha1sum(dstaddr, strlen(dstaddr)); - if(jsx->rxqueue[4] != 40 || strncmp(hash, jsx->rxqueue+5, 40) || + if(strncmp(hash, jsx->rxqueue + 5, 40) || jsx->rxqueue[45] != 0x00 || jsx->rxqueue[46] != 0x00) { - purple_debug_error("jabber", "someone connected with the wrong info!\n"); + if (jsx->rxqueue[45] != 0x00 || jsx->rxqueue[46] != 0x00) + purple_debug_error("jabber", "Got SOCKS5 BS conn with the wrong DST.PORT" + " (must be 0 - got[0x%x,0x%x]).\n", + jsx->rxqueue[45], jsx->rxqueue[46]); + else + purple_debug_error("jabber", "Got SOCKS5 BS conn with the wrong DST.ADDR" + " (expected '%s' - got '%.40s').\n", + hash, jsx->rxqueue + 5); close(source); purple_xfer_cancel_remote(xfer); g_free(hash); @@ -531,11 +542,13 @@ purple_input_remove(xfer->watcher); xfer->watcher = 0; + /* If we sent a "Success", wait for a response, otherwise give up and cancel */ if (jsx->rxqueue[1] == 0x00) { xfer->watcher = purple_input_add(source, PURPLE_INPUT_READ, jabber_si_xfer_bytestreams_send_read_again_cb, xfer); g_free(jsx->rxqueue); jsx->rxqueue = NULL; + jsx->rxlen = 0; } else { close(source); purple_xfer_cancel_remote(xfer); @@ -556,6 +569,7 @@ xfer->fd = source; + /** Try to read the SOCKS5 header */ if(jsx->rxlen < 2) { purple_debug_info("jabber", "reading those first two bytes\n"); len = read(source, buffer, 2 - jsx->rxlen); @@ -573,8 +587,9 @@ jsx->rxlen += len; return; } else if(jsx->rxlen - 2 < jsx->rxqueue[1]) { - purple_debug_info("jabber", "reading the next umpteen bytes\n"); - len = read(source, buffer, jsx->rxqueue[1] + 2 - jsx->rxlen); + purple_debug_info("jabber", "reading %u bytes for auth methods (trying to read %u now)\n", + jsx->rxqueue[1], jsx->rxqueue[1] - (jsx->rxlen - 2)); + len = read(source, buffer, jsx->rxqueue[1] - (jsx->rxlen - 2)); if(len < 0 && errno == EAGAIN) return; else if(len <= 0) { @@ -589,6 +604,7 @@ jsx->rxlen += len; } + /* Have we not read all the auth. method bytes? */ if(jsx->rxlen -2 < jsx->rxqueue[1]) return; diff -r 0bce1b58e1fe -r 47d963966c9a libpurple/protocols/msn/httpconn.c --- a/libpurple/protocols/msn/httpconn.c Fri May 15 16:21:27 2009 +0000 +++ b/libpurple/protocols/msn/httpconn.c Sun May 17 21:49:20 2009 +0000 @@ -219,7 +219,13 @@ g_free(tmp); t = strchr(full_session_id, '.'); - session_id = g_strndup(full_session_id, t - full_session_id); + if (t != NULL) + session_id = g_strndup(full_session_id, t - full_session_id); + else { + purple_debug_error("msn", "Malformed full_session_id[%s]\n", + full_session_id ? full_session_id : NULL); + session_id = g_strdup(full_session_id); + } if (session_action == NULL || strcmp(session_action, "close") != 0) { diff -r 0bce1b58e1fe -r 47d963966c9a libpurple/protocols/msn/oim.c --- a/libpurple/protocols/msn/oim.c Fri May 15 16:21:27 2009 +0000 +++ b/libpurple/protocols/msn/oim.c Sun May 17 21:49:20 2009 +0000 @@ -668,9 +668,15 @@ if (tokens[1] != NULL) from = (const char *)tokens[1]; - start = strchr(from, '<') + 1; - end = strchr(from, '>'); - passport = g_strndup(start, end - start); + start = strchr(from, '<'); + if (start != NULL) { + start++; + end = strchr(from, '>'); + if (end != NULL) + passport = g_strndup(start, end - start); + } + if (passport == NULL) + passport = g_strdup(_("Unknown")); g_strfreev(tokens); } diff -r 0bce1b58e1fe -r 47d963966c9a libpurple/protocols/msn/soap.c --- a/libpurple/protocols/msn/soap.c Fri May 15 16:21:27 2009 +0000 +++ b/libpurple/protocols/msn/soap.c Sun May 17 21:49:20 2009 +0000 @@ -434,7 +434,7 @@ g_free(line); return; } else if (strcmp(key, "Content-Length") == 0) { - conn->body_len = atoi(value); + sscanf(value, "%" G_GSIZE_FORMAT, &(conn->body_len)); } else if (strcmp(key, "Connection") == 0) { if (strcmp(value, "close") == 0) { conn->close_when_done = TRUE; @@ -667,7 +667,8 @@ conn->handled_len = 0; conn->current_request = req; - purple_input_remove(conn->event_handle); + if (conn->event_handle) + purple_input_remove(conn->event_handle); conn->event_handle = purple_input_add(conn->ssl->fd, PURPLE_INPUT_WRITE, msn_soap_write_cb, conn); if (!msn_soap_write_cb_internal(conn, conn->ssl->fd, PURPLE_INPUT_WRITE, TRUE)) { diff -r 0bce1b58e1fe -r 47d963966c9a libpurple/protocols/oscar/family_locate.c --- a/libpurple/protocols/oscar/family_locate.c Fri May 15 16:21:27 2009 +0000 +++ b/libpurple/protocols/oscar/family_locate.c Sun May 17 21:49:20 2009 +0000 @@ -68,12 +68,8 @@ {0x09, 0x46, 0x00, 0x02, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, + /* "Live Video" (SIP/RTC Video) support in Windows AIM 5.5.3501 and newer */ {OSCAR_CAPABILITY_VIDEO, - {0x09, 0x46, 0x01, 0x00, 0x4c, 0x7f, 0x11, 0xd1, - 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, - - /* "Live Video" (SIP/RTC Video) support in Windows AIM 5.5.3501 and newer */ - {OSCAR_CAPABILITY_LIVEVIDEO, {0x09, 0x46, 0x01, 0x01, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, diff -r 0bce1b58e1fe -r 47d963966c9a libpurple/protocols/oscar/family_oservice.c --- a/libpurple/protocols/oscar/family_oservice.c Fri May 15 16:21:27 2009 +0000 +++ b/libpurple/protocols/oscar/family_oservice.c Sun May 17 21:49:20 2009 +0000 @@ -151,7 +151,7 @@ memset(&csi, 0, sizeof(csi)); csi.exchange = exchange; - strncpy(csi.name, roomname, sizeof(csi.name)); + g_strlcpy(csi.name, roomname, sizeof(csi.name)); csi.instance = instance; /* diff -r 0bce1b58e1fe -r 47d963966c9a libpurple/protocols/oscar/oscar.c --- a/libpurple/protocols/oscar/oscar.c Fri May 15 16:21:27 2009 +0000 +++ b/libpurple/protocols/oscar/oscar.c Sun May 17 21:49:20 2009 +0000 @@ -714,9 +714,6 @@ case OSCAR_CAPABILITY_ICHATAV: tmp = _("iChat AV"); break; - case OSCAR_CAPABILITY_LIVEVIDEO: - tmp = _("Live Video"); - break; case OSCAR_CAPABILITY_CAMERA: tmp = _("Camera"); break; diff -r 0bce1b58e1fe -r 47d963966c9a libpurple/protocols/oscar/oscar.h --- a/libpurple/protocols/oscar/oscar.h Fri May 15 16:21:27 2009 +0000 +++ b/libpurple/protocols/oscar/oscar.h Sun May 17 21:49:20 2009 +0000 @@ -369,12 +369,11 @@ OSCAR_CAPABILITY_SMS = 0x00400000, OSCAR_CAPABILITY_VIDEO = 0x00800000, OSCAR_CAPABILITY_ICHATAV = 0x01000000, - OSCAR_CAPABILITY_LIVEVIDEO = 0x02000000, - OSCAR_CAPABILITY_CAMERA = 0x04000000, - OSCAR_CAPABILITY_ICHAT_SCREENSHARE = 0x08000000, - OSCAR_CAPABILITY_TYPING = 0x10000000, - OSCAR_CAPABILITY_GENERICUNKNOWN = 0x20000000, - OSCAR_CAPABILITY_LAST = 0x40000000 + OSCAR_CAPABILITY_CAMERA = 0x02000000, + OSCAR_CAPABILITY_ICHAT_SCREENSHARE = 0x04000000, + OSCAR_CAPABILITY_TYPING = 0x08000000, + OSCAR_CAPABILITY_GENERICUNKNOWN = 0x10000000, + OSCAR_CAPABILITY_LAST = 0x20000000 } OscarCapability; /* diff -r 0bce1b58e1fe -r 47d963966c9a libpurple/protocols/qq/utils.c --- a/libpurple/protocols/qq/utils.c Fri May 15 16:21:27 2009 +0000 +++ b/libpurple/protocols/qq/utils.c Sun May 17 21:49:20 2009 +0000 @@ -222,7 +222,8 @@ * The return should be freed later. */ guint8 *hex_str_to_bytes(const gchar *const buffer, gint *out_len) { - gchar *hex_str, *hex_buffer, *cursor, tmp; + gchar *hex_str, *hex_buffer, *cursor; + gchar tmp[2]; guint8 *bytes, nibble1, nibble2; gint index; @@ -242,7 +243,9 @@ index = 0; for (cursor = hex_str; cursor < hex_str + sizeof(gchar) * (strlen(hex_str)) - 1; cursor++) { if (g_ascii_isdigit(*cursor)) { - tmp = *cursor; nibble1 = atoi(&tmp); + tmp[0] = *cursor; + tmp[1] = '\0'; + nibble1 = atoi(tmp); } else if (g_ascii_isalpha(*cursor) && (gint) *cursor - 87 < 16) { nibble1 = (gint) *cursor - 87; } else { @@ -254,7 +257,9 @@ nibble1 = nibble1 << 4; cursor++; if (g_ascii_isdigit(*cursor)) { - tmp = *cursor; nibble2 = atoi(&tmp); + tmp[0] = *cursor; + tmp[1] = '\0'; + nibble2 = atoi(tmp); } else if (g_ascii_isalpha(*cursor) && (gint) (*cursor - 87) < 16) { nibble2 = (gint) *cursor - 87; } else { diff -r 0bce1b58e1fe -r 47d963966c9a libpurple/protocols/yahoo/yahoo.h --- a/libpurple/protocols/yahoo/yahoo.h Fri May 15 16:21:27 2009 +0000 +++ b/libpurple/protocols/yahoo/yahoo.h Sun May 17 21:49:20 2009 +0000 @@ -36,7 +36,7 @@ #define YAHOO_P2P_KEEPALIVE_SECS 300 #define YAHOO_P2P_SERVER_TIMEOUT 10 #define YAHOO_PROFILE_URL "http://profiles.yahoo.com/" -#define YAHOO_MAIL_URL "https://login.yahoo.com/config/login?.src=ym" +#define YAHOO_MAIL_URL "http://rd.yahoo.com/messenger/client/?http://mail.yahoo.com/" #define YAHOO_XFER_HOST "filetransfer.msg.yahoo.com" #define YAHOO_XFER_PORT 80 #define YAHOO_XFER_RELAY_HOST "relay.msg.yahoo.com" diff -r 0bce1b58e1fe -r 47d963966c9a libpurple/savedstatuses.c --- a/libpurple/savedstatuses.c Fri May 15 16:21:27 2009 +0000 +++ b/libpurple/savedstatuses.c Sun May 17 21:49:20 2009 +0000 @@ -285,13 +285,13 @@ xmlnode_set_attrib(node, "transient", "true"); } - snprintf(buf, sizeof(buf), "%lu", status->creation_time); + g_snprintf(buf, sizeof(buf), "%lu", status->creation_time); xmlnode_set_attrib(node, "created", buf); - snprintf(buf, sizeof(buf), "%lu", status->lastused); + g_snprintf(buf, sizeof(buf), "%lu", status->lastused); xmlnode_set_attrib(node, "lastused", buf); - snprintf(buf, sizeof(buf), "%u", status->usage_count); + g_snprintf(buf, sizeof(buf), "%u", status->usage_count); xmlnode_set_attrib(node, "usage_count", buf); child = xmlnode_new_child(node, "state"); diff -r 0bce1b58e1fe -r 47d963966c9a libpurple/util.c --- a/libpurple/util.c Fri May 15 16:21:27 2009 +0000 +++ b/libpurple/util.c Sun May 17 21:49:20 2009 +0000 @@ -129,7 +129,7 @@ ascii = g_malloc(len * 2 + 1); for (i = 0; i < len; i++) - snprintf(&ascii[i * 2], 3, "%02hhx", data[i]); + g_snprintf(&ascii[i * 2], 3, "%02hhx", data[i]); return ascii; } @@ -1623,7 +1623,7 @@ pt->dest_tag = "a"; tags = g_list_prepend(tags, pt); if(xhtml) - g_string_append_printf(xhtml, "", url ? g_strstrip(url->str) : ""); + g_string_append_printf(xhtml, "", url ? g_strstrip(url->str) : ""); continue; } if(!g_ascii_strncasecmp(c, "' || *(c+5) == ' ')) { @@ -2017,7 +2017,6 @@ case '<': case '>': case '"': - case '\'': return TRUE; default: return FALSE; diff -r 0bce1b58e1fe -r 47d963966c9a pidgin/gtkblist.c --- a/pidgin/gtkblist.c Fri May 15 16:21:27 2009 +0000 +++ b/pidgin/gtkblist.c Sun May 17 21:49:20 2009 +0000 @@ -75,47 +75,40 @@ typedef struct { PurpleAccount *account; - GtkWidget *window; + GtkBox *vbox; + GtkWidget *account_menu; + GtkSizeGroup *sg; +} PidginBlistRequestData; + +typedef struct +{ + PidginBlistRequestData rq_data; GtkWidget *combo; GtkWidget *entry; GtkWidget *entry_for_alias; - GtkWidget *account_box; } PidginAddBuddyData; typedef struct { - PurpleAccount *account; + PidginBlistRequestData rq_data; gchar *default_chat_name; - - GtkWidget *window; - GtkWidget *account_menu; + GList *entries; +} PidginChatData; + +typedef struct +{ + PidginChatData chat_data; + GtkWidget *alias_entry; GtkWidget *group_combo; - GtkWidget *entries_box; - GtkSizeGroup *sg; GtkWidget *autojoin; GtkWidget *persistent; - - GList *entries; - } PidginAddChatData; typedef struct { - PurpleAccount *account; - - GtkWidget *window; - GtkWidget *account_menu; - GtkWidget *entries_box; - GtkSizeGroup *sg; - - GList *entries; -} PidginJoinChatData; - -typedef struct -{ /** Used to hold error minidialogs. Gets packed * inside PidginBuddyList.error_buttons */ @@ -868,7 +861,7 @@ } static void -do_join_chat(PidginJoinChatData *data) +do_join_chat(PidginChatData *data) { if (data) { @@ -894,14 +887,14 @@ } } - chat = purple_chat_new(data->account, NULL, components); + chat = purple_chat_new(data->rq_data.account, NULL, components); gtk_blist_join_chat(chat); purple_blist_remove_chat(chat); } } static void -do_joinchat(GtkWidget *dialog, int id, PidginJoinChatData *info) +do_joinchat(GtkWidget *dialog, int id, PidginChatData *info) { switch(id) { @@ -910,7 +903,7 @@ break; case 1: - pidgin_roomlist_dialog_show_with_account(info->account); + pidgin_roomlist_dialog_show_with_account(info->rq_data.account); return; break; @@ -926,11 +919,11 @@ * strings are empty then don't allow the user to click on "OK." */ static void -joinchat_set_sensitive_if_input_cb(GtkWidget *entry, gpointer user_data) +set_sensitive_if_input_cb(GtkWidget *entry, gpointer user_data) { PurplePluginProtocolInfo *prpl_info; PurpleConnection *gc; - PidginJoinChatData *data; + PidginChatData *data; GList *tmp; const char *text; gboolean required; @@ -949,13 +942,13 @@ } } - gtk_dialog_set_response_sensitive(GTK_DIALOG(data->window), GTK_RESPONSE_OK, sensitive); - - gc = purple_account_get_connection(data->account); + gtk_dialog_set_response_sensitive(GTK_DIALOG(data->rq_data.window), GTK_RESPONSE_OK, sensitive); + + gc = purple_account_get_connection(data->rq_data.account); prpl_info = (gc != NULL) ? PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl) : NULL; sensitive = (prpl_info != NULL && prpl_info->roomlist_get_list != NULL); - gtk_dialog_set_response_sensitive(GTK_DIALOG(data->window), 1, sensitive); + gtk_dialog_set_response_sensitive(GTK_DIALOG(data->rq_data.window), 1, sensitive); } static void @@ -967,97 +960,6 @@ pidgin_blist_update_buddy(purple_get_blist(), PURPLE_BLIST_NODE(buddy), TRUE); } -static void -rebuild_joinchat_entries(PidginJoinChatData *data) -{ - PurpleConnection *gc; - GList *list = NULL, *tmp; - GHashTable *defaults = NULL; - struct proto_chat_entry *pce; - gboolean focus = TRUE; - - g_return_if_fail(data->account != NULL); - - gc = purple_account_get_connection(data->account); - - gtk_container_foreach(GTK_CONTAINER(data->entries_box), (GtkCallback)gtk_widget_destroy, NULL); - - g_list_free(data->entries); - data->entries = NULL; - - if (PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info != NULL) - list = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info(gc); - - if (PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info_defaults != NULL) - defaults = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info_defaults(gc, NULL); - - for (tmp = list; tmp; tmp = tmp->next) - { - GtkWidget *input; - - pce = tmp->data; - - if (pce->is_int) - { - GtkObject *adjust; - adjust = gtk_adjustment_new(pce->min, pce->min, pce->max, - 1, 10, 10); - input = gtk_spin_button_new(GTK_ADJUSTMENT(adjust), 1, 0); - gtk_widget_set_size_request(input, 50, -1); - pidgin_add_widget_to_vbox(GTK_BOX(data->entries_box), pce->label, data->sg, input, FALSE, NULL); - } - else - { - char *value; - input = gtk_entry_new(); - gtk_entry_set_activates_default(GTK_ENTRY(input), TRUE); - value = g_hash_table_lookup(defaults, pce->identifier); - if (value != NULL) - gtk_entry_set_text(GTK_ENTRY(input), value); - if (pce->secret) - { - gtk_entry_set_visibility(GTK_ENTRY(input), FALSE); -#if !GTK_CHECK_VERSION(2,16,0) - if (gtk_entry_get_invisible_char(GTK_ENTRY(input)) == '*') - gtk_entry_set_invisible_char(GTK_ENTRY(input), PIDGIN_INVISIBLE_CHAR); -#endif /* Less than GTK+ 2.16 */ - } - pidgin_add_widget_to_vbox(GTK_BOX(data->entries_box), pce->label, data->sg, input, TRUE, NULL); - g_signal_connect(G_OBJECT(input), "changed", - G_CALLBACK(joinchat_set_sensitive_if_input_cb), data); - } - - /* Do the following for any type of input widget */ - if (focus) - { - gtk_widget_grab_focus(input); - focus = FALSE; - } - g_object_set_data(G_OBJECT(input), "identifier", (gpointer)pce->identifier); - g_object_set_data(G_OBJECT(input), "is_spin", GINT_TO_POINTER(pce->is_int)); - g_object_set_data(G_OBJECT(input), "required", GINT_TO_POINTER(pce->required)); - data->entries = g_list_append(data->entries, input); - - g_free(pce); - } - - g_list_free(list); - g_hash_table_destroy(defaults); - - /* Set whether the "OK" button should be clickable initially */ - joinchat_set_sensitive_if_input_cb(NULL, data); - - gtk_widget_show_all(data->entries_box); -} - -static void -joinchat_select_account_cb(GObject *w, PurpleAccount *account, - PidginJoinChatData *data) -{ - data->account = account; - rebuild_joinchat_entries(data); -} - static gboolean chat_account_filter_func(PurpleAccount *account) { @@ -1085,32 +987,38 @@ return FALSE; } -void -pidgin_blist_joinchat_show(void) -{ - GtkWidget *hbox, *vbox; +static GtkWidget * +make_blist_request_dialog(PidginBlistRequestData *data, PurpleAccount *account, + const char *title, const char *window_role, const char *label_text, + GCallback callback_func, PurpleFilterAccountFunc filter_func, + GCallback response_cb) +{ GtkWidget *label; + GtkWidget *img; + GtkWidget *hbox; + GtkWidget *vbox; + GtkWindow *blist_window; PidginBuddyList *gtkblist; - GtkWidget *img = NULL; - PidginJoinChatData *data = NULL; - - gtkblist = purple_blist_get_ui_data(); + + data->account = account; + img = gtk_image_new_from_stock(PIDGIN_STOCK_DIALOG_QUESTION, - gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_HUGE)); - data = g_new0(PidginJoinChatData, 1); - - data->window = gtk_dialog_new_with_buttons(_("Join a Chat"), - NULL, GTK_DIALOG_NO_SEPARATOR, - _("Room _List"), 1, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - PIDGIN_STOCK_CHAT, GTK_RESPONSE_OK, NULL); + gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_HUGE)); + + gtkblist = PIDGIN_BLIST(purple_get_blist()); + blist_window = gtkblist ? GTK_WINDOW(gtkblist->window) : NULL; + + data->window = gtk_dialog_new_with_buttons(title, + blist_window, GTK_DIALOG_NO_SEPARATOR, + NULL); + + gtk_window_set_transient_for(GTK_WINDOW(data->window), blist_window); gtk_dialog_set_default_response(GTK_DIALOG(data->window), GTK_RESPONSE_OK); gtk_container_set_border_width(GTK_CONTAINER(data->window), PIDGIN_HIG_BOX_SPACE); gtk_window_set_resizable(GTK_WINDOW(data->window), FALSE); gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(data->window)->vbox), PIDGIN_HIG_BORDER); - gtk_container_set_border_width( - GTK_CONTAINER(GTK_DIALOG(data->window)->vbox), PIDGIN_HIG_BOX_SPACE); - gtk_window_set_role(GTK_WINDOW(data->window), "join_chat"); + gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(data->window)->vbox), PIDGIN_HIG_BOX_SPACE); + gtk_window_set_role(GTK_WINDOW(data->window), window_role); hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BORDER); gtk_container_add(GTK_CONTAINER(GTK_DIALOG(data->window)->vbox), hbox); @@ -1118,37 +1026,154 @@ gtk_misc_set_alignment(GTK_MISC(img), 0, 0); vbox = gtk_vbox_new(FALSE, 5); - gtk_container_set_border_width(GTK_CONTAINER(vbox), 0); gtk_container_add(GTK_CONTAINER(hbox), vbox); - label = gtk_label_new(_("Please enter the appropriate information " - "about the chat you would like to join.\n")); + label = gtk_label_new(label_text); + + gtk_widget_set_size_request(label, 400, -1); gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); gtk_misc_set_alignment(GTK_MISC(label), 0, 0); gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0); data->sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); - data->account_menu = pidgin_account_option_menu_new(NULL, FALSE, - G_CALLBACK(joinchat_select_account_cb), - chat_account_filter_func, data); - - pidgin_add_widget_to_vbox(GTK_BOX(vbox), _("_Account:"), data->sg, data->account_menu, TRUE, NULL); - - data->entries_box = gtk_vbox_new(FALSE, 5); - gtk_container_add(GTK_CONTAINER(vbox), data->entries_box); - gtk_container_set_border_width(GTK_CONTAINER(data->entries_box), 0); - - data->account = pidgin_account_option_menu_get_selected(data->account_menu); - - rebuild_joinchat_entries(data); - - g_signal_connect(G_OBJECT(data->window), "response", - G_CALLBACK(do_joinchat), data); + data->account_menu = pidgin_account_option_menu_new(account, FALSE, + callback_func, filter_func, data); + pidgin_add_widget_to_vbox(GTK_BOX(vbox), _("A_ccount"), data->sg, data->account_menu, TRUE, NULL); + + data->vbox = GTK_BOX(gtk_vbox_new(FALSE, 5)); + gtk_container_set_border_width(GTK_CONTAINER(data->vbox), 0); + gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(data->vbox), FALSE, FALSE, 0); + + g_signal_connect(G_OBJECT(data->window), "response", response_cb, data); g_object_unref(data->sg); - gtk_widget_show_all(data->window); + return vbox; +} + +static void +rebuild_chat_entries(PidginChatData *data, const char *default_chat_name) +{ + PurpleConnection *gc; + GList *list = NULL, *tmp; + GHashTable *defaults = NULL; + struct proto_chat_entry *pce; + gboolean focus = TRUE; + + g_return_if_fail(data->rq_data.account != NULL); + + gc = purple_account_get_connection(data->rq_data.account); + + gtk_container_foreach(GTK_CONTAINER(data->rq_data.vbox), (GtkCallback)gtk_widget_destroy, NULL); + + g_list_free(data->entries); + data->entries = NULL; + + if (PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info != NULL) + list = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info(gc); + + if (PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info_defaults != NULL) + defaults = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info_defaults(gc, default_chat_name); + + for (tmp = list; tmp; tmp = tmp->next) + { + GtkWidget *input; + + pce = tmp->data; + + if (pce->is_int) + { + GtkObject *adjust; + adjust = gtk_adjustment_new(pce->min, pce->min, pce->max, + 1, 10, 10); + input = gtk_spin_button_new(GTK_ADJUSTMENT(adjust), 1, 0); + gtk_widget_set_size_request(input, 50, -1); + pidgin_add_widget_to_vbox(GTK_BOX(data->rq_data.vbox), pce->label, data->rq_data.sg, input, FALSE, NULL); + } + else + { + char *value; + input = gtk_entry_new(); + gtk_entry_set_activates_default(GTK_ENTRY(input), TRUE); + value = g_hash_table_lookup(defaults, pce->identifier); + if (value != NULL) + gtk_entry_set_text(GTK_ENTRY(input), value); + if (pce->secret) + { + gtk_entry_set_visibility(GTK_ENTRY(input), FALSE); +#if !GTK_CHECK_VERSION(2,16,0) + if (gtk_entry_get_invisible_char(GTK_ENTRY(input)) == '*') + gtk_entry_set_invisible_char(GTK_ENTRY(input), PIDGIN_INVISIBLE_CHAR); +#endif /* Less than GTK+ 2.16 */ + } + pidgin_add_widget_to_vbox(data->rq_data.vbox, pce->label, data->rq_data.sg, input, TRUE, NULL); + g_signal_connect(G_OBJECT(input), "changed", + G_CALLBACK(set_sensitive_if_input_cb), data); + } + + /* Do the following for any type of input widget */ + if (focus) + { + gtk_widget_grab_focus(input); + focus = FALSE; + } + g_object_set_data(G_OBJECT(input), "identifier", (gpointer)pce->identifier); + g_object_set_data(G_OBJECT(input), "is_spin", GINT_TO_POINTER(pce->is_int)); + g_object_set_data(G_OBJECT(input), "required", GINT_TO_POINTER(pce->required)); + data->entries = g_list_append(data->entries, input); + + g_free(pce); + } + + g_list_free(list); + g_hash_table_destroy(defaults); + + /* Set whether the "OK" button should be clickable initially */ + set_sensitive_if_input_cb(NULL, data); + + gtk_widget_show_all(GTK_WIDGET(data->rq_data.vbox)); +} + +static void +chat_select_account_cb(GObject *w, PurpleAccount *account, + PidginChatData *data) +{ + if (strcmp(purple_account_get_protocol_id(data->rq_data.account), + purple_account_get_protocol_id(account)) == 0) + { + data->rq_data.account = account; + } + else + { + data->rq_data.account = account; + rebuild_chat_entries(data, data->default_chat_name); + } +} + +void +pidgin_blist_joinchat_show(void) +{ + PidginChatData *data = NULL; + + data = g_new0(PidginChatData, 1); + + make_blist_request_dialog((PidginBlistRequestData *)data, NULL, + _("Join a Chat"), "join_chat", + _("Please enter the appropriate information about the chat " + "you would like to join.\n"), + G_CALLBACK(chat_select_account_cb), + chat_account_filter_func, (GCallback)do_joinchat); + gtk_dialog_add_buttons(GTK_DIALOG(data->rq_data.window), + _("Room _List"), 1, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + PIDGIN_STOCK_CHAT, GTK_RESPONSE_OK, NULL); + data->default_chat_name = NULL; + data->rq_data.account = pidgin_account_option_menu_get_selected(data->rq_data.account_menu); + + rebuild_chat_entries(data, NULL); + + gtk_widget_show_all(data->rq_data.window); } static void gtk_blist_row_expanded_cb(GtkTreeView *tv, GtkTreeIter *iter, GtkTreePath *path, gpointer user_data) @@ -6734,7 +6759,7 @@ PidginAddBuddyData *data) { /* Save our account */ - data->account = account; + data->rq_data.account = account; } static void @@ -6747,6 +6772,7 @@ add_buddy_cb(GtkWidget *w, int resp, PidginAddBuddyData *data) { const char *grp, *who, *whoalias; + PurpleAccount *account; PurpleGroup *g; PurpleBuddy *b; PurpleConversation *c; @@ -6760,6 +6786,8 @@ if (*whoalias == '\0') whoalias = NULL; + account = data->rq_data.account; + g = NULL; if ((grp != NULL) && (*grp != '\0')) { @@ -6769,20 +6797,20 @@ purple_blist_add_group(g, NULL); } - b = purple_find_buddy_in_group(data->account, who, g); + b = purple_find_buddy_in_group(account, who, g); } - else if ((b = purple_find_buddy(data->account, who)) != NULL) + else if ((b = purple_find_buddy(account, who)) != NULL) { g = purple_buddy_get_group(b); } if (b == NULL) { - b = purple_buddy_new(data->account, who, whoalias); + b = purple_buddy_new(account, who, whoalias); purple_blist_add_buddy(b, NULL, g, NULL); } - purple_account_add_buddy(data->account, b); + purple_account_add_buddy(account, b); /* Offer to merge people with the same alias. */ if (whoalias != NULL && g != NULL) @@ -6803,7 +6831,7 @@ * Or something. --Mark */ - c = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, who, data->account); + c = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, who, data->rq_data.account); if (c != NULL) { icon = purple_conv_im_get_icon(PURPLE_CONV_IM(c)); if (icon != NULL) @@ -6811,103 +6839,52 @@ } } - gtk_widget_destroy(data->window); + gtk_widget_destroy(data->rq_data.window); } static void pidgin_blist_request_add_buddy(PurpleAccount *account, const char *username, const char *group, const char *alias) { - GtkWidget *table; - GtkWidget *label; - GtkWidget *hbox; - GtkWidget *vbox; - GtkWidget *img; - PidginBuddyList *gtkblist; PidginAddBuddyData *data = g_new0(PidginAddBuddyData, 1); - data->account = + make_blist_request_dialog((PidginBlistRequestData *)data, (account != NULL - ? account - : purple_connection_get_account(purple_connections_get_all()->data)); - - img = gtk_image_new_from_stock(PIDGIN_STOCK_DIALOG_QUESTION, - gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_HUGE)); - - gtkblist = PIDGIN_BLIST(purple_get_blist()); - - data->window = gtk_dialog_new_with_buttons(_("Add Buddy"), - gtkblist ? GTK_WINDOW(gtkblist->window) : NULL, GTK_DIALOG_NO_SEPARATOR, + ? account : purple_connection_get_account(purple_connections_get_all()->data)), + _("Add Buddy"), "add_buddy", + _("Add a buddy.\n"), + G_CALLBACK(add_buddy_select_account_cb), NULL, + G_CALLBACK(add_buddy_cb)); + gtk_dialog_add_buttons(GTK_DIALOG(data->rq_data.window), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_ADD, GTK_RESPONSE_OK, NULL); - if (gtkblist) - gtk_window_set_transient_for(GTK_WINDOW(data->window), GTK_WINDOW(gtkblist->window)); - gtk_dialog_set_default_response(GTK_DIALOG(data->window), GTK_RESPONSE_OK); - gtk_container_set_border_width(GTK_CONTAINER(data->window), PIDGIN_HIG_BOX_SPACE); - gtk_window_set_resizable(GTK_WINDOW(data->window), FALSE); - gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(data->window)->vbox), PIDGIN_HIG_BORDER); - gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(data->window)->vbox), PIDGIN_HIG_BOX_SPACE); - gtk_window_set_role(GTK_WINDOW(data->window), "add_buddy"); - gtk_window_set_type_hint(GTK_WINDOW(data->window), - GDK_WINDOW_TYPE_HINT_DIALOG); - - hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BORDER); - gtk_container_add(GTK_CONTAINER(GTK_DIALOG(data->window)->vbox), hbox); - gtk_box_pack_start(GTK_BOX(hbox), img, FALSE, FALSE, 0); - gtk_misc_set_alignment(GTK_MISC(img), 0, 0); - - vbox = gtk_vbox_new(FALSE, 0); - gtk_container_add(GTK_CONTAINER(hbox), vbox); - - g_signal_connect(G_OBJECT(data->window), "destroy", + g_signal_connect(G_OBJECT(data->rq_data.window), "destroy", G_CALLBACK(destroy_add_buddy_dialog_cb), data); - label = gtk_label_new(_("Add a buddy.\n")); - gtk_misc_set_alignment(GTK_MISC(label), 0, 0); - gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0); - - table = gtk_table_new(4, 2, FALSE); - gtk_table_set_row_spacings(GTK_TABLE(table), 5); - gtk_table_set_col_spacings(GTK_TABLE(table), 5); - gtk_container_set_border_width(GTK_CONTAINER(table), 0); - gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0); - - data->account_box = pidgin_account_option_menu_new(account, FALSE, - G_CALLBACK(add_buddy_select_account_cb), NULL, data); - - gtk_table_attach_defaults(GTK_TABLE(table), data->account_box, 0, 2, 0, 1); - - label = gtk_label_new_with_mnemonic(_("Buddy's _username:")); - gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); - gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 1, 2); - data->entry = gtk_entry_new(); - gtk_table_attach_defaults(GTK_TABLE(table), data->entry, 1, 2, 1, 2); + + pidgin_add_widget_to_vbox(data->rq_data.vbox, _("Buddy's _username:"), + data->rq_data.sg, data->entry, TRUE, NULL); gtk_widget_grab_focus(data->entry); if (username != NULL) gtk_entry_set_text(GTK_ENTRY(data->entry), username); else - gtk_dialog_set_response_sensitive(GTK_DIALOG(data->window), + gtk_dialog_set_response_sensitive(GTK_DIALOG(data->rq_data.window), GTK_RESPONSE_OK, FALSE); gtk_entry_set_activates_default (GTK_ENTRY(data->entry), TRUE); - gtk_label_set_mnemonic_widget(GTK_LABEL(label), data->entry); - pidgin_set_accessible_label (data->entry, label); g_signal_connect(G_OBJECT(data->entry), "changed", G_CALLBACK(pidgin_set_sensitive_if_input), - data->window); - - label = gtk_label_new_with_mnemonic(_("(Optional) A_lias:")); - gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); - gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 2, 3); + data->rq_data.window); data->entry_for_alias = gtk_entry_new(); - gtk_table_attach_defaults(GTK_TABLE(table), - data->entry_for_alias, 1, 2, 2, 3); + pidgin_add_widget_to_vbox(data->rq_data.vbox, _("(Optional) A_lias:"), + data->rq_data.sg, data->entry_for_alias, TRUE, + NULL); if (alias != NULL) gtk_entry_set_text(GTK_ENTRY(data->entry_for_alias), alias); @@ -6915,23 +6892,11 @@ if (username != NULL) gtk_widget_grab_focus(GTK_WIDGET(data->entry_for_alias)); - gtk_entry_set_activates_default (GTK_ENTRY(data->entry_for_alias), TRUE); - gtk_label_set_mnemonic_widget(GTK_LABEL(label), data->entry_for_alias); - pidgin_set_accessible_label (data->entry_for_alias, label); - - label = gtk_label_new_with_mnemonic(_("Add buddy to _group:")); - gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); - gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 3, 4); - data->combo = pidgin_text_combo_box_entry_new(group, groups_tree()); - gtk_table_attach_defaults(GTK_TABLE(table), data->combo, 1, 2, 3, 4); - gtk_label_set_mnemonic_widget(GTK_LABEL(label), GTK_BIN(data->combo)->child); - pidgin_set_accessible_label (data->combo, label); - - g_signal_connect(G_OBJECT(data->window), "response", - G_CALLBACK(add_buddy_cb), data); - - gtk_widget_show_all(data->window); + pidgin_add_widget_to_vbox(data->rq_data.vbox, _("Add buddy to _group:"), + data->rq_data.sg, data->combo, TRUE, NULL); + + gtk_widget_show_all(data->rq_data.window); } static void @@ -6947,7 +6912,7 @@ components = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); - for (tmp = data->entries; tmp; tmp = tmp->next) + for (tmp = data->chat_data.entries; tmp; tmp = tmp->next) { if (g_object_get_data(tmp->data, "is_spin")) { @@ -6966,7 +6931,7 @@ } } - chat = purple_chat_new(data->account, + chat = purple_chat_new(data->chat_data.rq_data.account, gtk_entry_get_text(GTK_ENTRY(data->alias_entry)), components); @@ -6990,9 +6955,9 @@ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->persistent))) purple_blist_node_set_bool((PurpleBlistNode*)chat, "gtk-persistent", TRUE); - gtk_widget_destroy(data->window); - g_free(data->default_chat_name); - g_list_free(data->entries); + gtk_widget_destroy(data->chat_data.rq_data.window); + g_free(data->chat_data.default_chat_name); + g_list_free(data->chat_data.entries); g_free(data); } @@ -7005,166 +6970,25 @@ } else if (resp == 1) { - pidgin_roomlist_dialog_show_with_account(data->account); + pidgin_roomlist_dialog_show_with_account(data->chat_data.rq_data.account); } else { - gtk_widget_destroy(data->window); - g_free(data->default_chat_name); - g_list_free(data->entries); + gtk_widget_destroy(data->chat_data.rq_data.window); + g_free(data->chat_data.default_chat_name); + g_list_free(data->chat_data.entries); g_free(data); } } -/* - * Check the values of all the text entry boxes. If any required input - * strings are empty then don't allow the user to click on "OK." - */ -static void -addchat_set_sensitive_if_input_cb(GtkWidget *entry, gpointer user_data) -{ - PurplePluginProtocolInfo *prpl_info; - PurpleConnection *gc; - PidginAddChatData *data; - GList *tmp; - const char *text; - gboolean required; - gboolean sensitive = TRUE; - - data = user_data; - - for (tmp = data->entries; tmp != NULL; tmp = tmp->next) - { - if (!g_object_get_data(tmp->data, "is_spin")) - { - required = GPOINTER_TO_INT(g_object_get_data(tmp->data, "required")); - text = gtk_entry_get_text(tmp->data); - if (required && (*text == '\0')) - sensitive = FALSE; - } - } - - gtk_dialog_set_response_sensitive(GTK_DIALOG(data->window), GTK_RESPONSE_OK, sensitive); - - gc = purple_account_get_connection(data->account); - prpl_info = (gc != NULL) ? PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl) : NULL; - sensitive = (prpl_info != NULL && prpl_info->roomlist_get_list != NULL); - - gtk_dialog_set_response_sensitive(GTK_DIALOG(data->window), 1, sensitive); -} - -static void -rebuild_addchat_entries(PidginAddChatData *data) -{ - PurpleConnection *gc; - GList *list = NULL, *tmp; - GHashTable *defaults = NULL; - struct proto_chat_entry *pce; - gboolean focus = TRUE; - - g_return_if_fail(data->account != NULL); - - gc = purple_account_get_connection(data->account); - - gtk_container_foreach(GTK_CONTAINER(data->entries_box), (GtkCallback)gtk_widget_destroy, NULL); - - g_list_free(data->entries); - - data->entries = NULL; - - if (PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info != NULL) - list = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info(gc); - - if (PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info_defaults != NULL) - defaults = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info_defaults(gc, data->default_chat_name); - - for (tmp = list; tmp; tmp = tmp->next) - { - GtkWidget *input; - - pce = tmp->data; - - if (pce->is_int) - { - GtkObject *adjust; - adjust = gtk_adjustment_new(pce->min, pce->min, pce->max, - 1, 10, 10); - input = gtk_spin_button_new(GTK_ADJUSTMENT(adjust), 1, 0); - gtk_widget_set_size_request(input, 50, -1); - pidgin_add_widget_to_vbox(GTK_BOX(data->entries_box), pce->label, data->sg, input, FALSE, NULL); - } - else - { - char *value; - input = gtk_entry_new(); - gtk_entry_set_activates_default(GTK_ENTRY(input), TRUE); - value = g_hash_table_lookup(defaults, pce->identifier); - if (value != NULL) - gtk_entry_set_text(GTK_ENTRY(input), value); - if (pce->secret) - { - gtk_entry_set_visibility(GTK_ENTRY(input), FALSE); -#if !GTK_CHECK_VERSION(2,16,0) - if (gtk_entry_get_invisible_char(GTK_ENTRY(input)) == '*') - gtk_entry_set_invisible_char(GTK_ENTRY(input), PIDGIN_INVISIBLE_CHAR); -#endif /* Less than GTK+ 2.16 */ - } - pidgin_add_widget_to_vbox(GTK_BOX(data->entries_box), pce->label, data->sg, input, TRUE, NULL); - g_signal_connect(G_OBJECT(input), "changed", - G_CALLBACK(addchat_set_sensitive_if_input_cb), data); - } - - /* Do the following for any type of input widget */ - if (focus) - { - gtk_widget_grab_focus(input); - focus = FALSE; - } - g_object_set_data(G_OBJECT(input), "identifier", (gpointer)pce->identifier); - g_object_set_data(G_OBJECT(input), "is_spin", GINT_TO_POINTER(pce->is_int)); - g_object_set_data(G_OBJECT(input), "required", GINT_TO_POINTER(pce->required)); - data->entries = g_list_append(data->entries, input); - - g_free(pce); - } - - g_list_free(list); - g_hash_table_destroy(defaults); - - /* Set whether the "OK" button should be clickable initially */ - addchat_set_sensitive_if_input_cb(NULL, data); - - gtk_widget_show_all(data->entries_box); -} - -static void -addchat_select_account_cb(GObject *w, PurpleAccount *account, - PidginAddChatData *data) -{ - if (strcmp(purple_account_get_protocol_id(data->account), - purple_account_get_protocol_id(account)) == 0) - { - data->account = account; - } - else - { - data->account = account; - rebuild_addchat_entries(data); - } -} - static void pidgin_blist_request_add_chat(PurpleAccount *account, PurpleGroup *group, const char *alias, const char *name) { PidginAddChatData *data; - PidginBuddyList *gtkblist; GList *l; PurpleConnection *gc; - GtkWidget *label; - GtkWidget *hbox; - GtkWidget *vbox; - GtkWidget *img; + GtkBox *vbox; if (account != NULL) { gc = purple_account_get_connection(account); @@ -7193,82 +7017,44 @@ } data = g_new0(PidginAddChatData, 1); - data->account = account; - data->default_chat_name = g_strdup(name); - - img = gtk_image_new_from_stock(PIDGIN_STOCK_DIALOG_QUESTION, - gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_HUGE)); - - gtkblist = PIDGIN_BLIST(purple_get_blist()); - - data->sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); - - data->window = gtk_dialog_new_with_buttons(_("Add Chat"), - gtkblist ? GTK_WINDOW(gtkblist->window) : NULL, GTK_DIALOG_NO_SEPARATOR, - _("Room _List"), 1, + vbox = GTK_BOX(make_blist_request_dialog((PidginBlistRequestData *)data, account, + _("Add Chat"), "add_chat", + _("Please enter an alias, and the appropriate information " + "about the chat you would like to add to your buddy list.\n"), + G_CALLBACK(chat_select_account_cb), chat_account_filter_func, + G_CALLBACK(add_chat_resp_cb))); + gtk_dialog_add_buttons(GTK_DIALOG(data->chat_data.rq_data.window), + _("Room List"), 1, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_ADD, GTK_RESPONSE_OK, NULL); - if (gtkblist) - gtk_window_set_transient_for(GTK_WINDOW(data->window), GTK_WINDOW(gtkblist->window)); - gtk_dialog_set_default_response(GTK_DIALOG(data->window), GTK_RESPONSE_OK); - gtk_container_set_border_width(GTK_CONTAINER(data->window), PIDGIN_HIG_BOX_SPACE); - gtk_window_set_resizable(GTK_WINDOW(data->window), FALSE); - gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(data->window)->vbox), PIDGIN_HIG_BORDER); - gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(data->window)->vbox), PIDGIN_HIG_BOX_SPACE); - gtk_window_set_role(GTK_WINDOW(data->window), "add_chat"); - gtk_window_set_type_hint(GTK_WINDOW(data->window), - GDK_WINDOW_TYPE_HINT_DIALOG); - - hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BORDER); - gtk_container_add(GTK_CONTAINER(GTK_DIALOG(data->window)->vbox), hbox); - gtk_box_pack_start(GTK_BOX(hbox), img, FALSE, FALSE, 0); - gtk_misc_set_alignment(GTK_MISC(img), 0, 0); - - vbox = gtk_vbox_new(FALSE, 5); - gtk_container_add(GTK_CONTAINER(hbox), vbox); - - label = gtk_label_new( - _("Please enter an alias, and the appropriate information " - "about the chat you would like to add to your buddy list.\n")); - gtk_widget_set_size_request(label, 400, -1); - gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); - gtk_misc_set_alignment(GTK_MISC(label), 0, 0); - gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0); - - data->account_menu = pidgin_account_option_menu_new(account, FALSE, - G_CALLBACK(addchat_select_account_cb), - chat_account_filter_func, data); - pidgin_add_widget_to_vbox(GTK_BOX(vbox), _("_Account:"), data->sg, data->account_menu, TRUE, NULL); - - data->entries_box = gtk_vbox_new(FALSE, 5); - gtk_container_set_border_width(GTK_CONTAINER(data->entries_box), 0); - gtk_box_pack_start(GTK_BOX(vbox), data->entries_box, TRUE, TRUE, 0); - - rebuild_addchat_entries(data); + data->chat_data.default_chat_name = g_strdup(name); + + rebuild_chat_entries((PidginChatData *)data, name); data->alias_entry = gtk_entry_new(); if (alias != NULL) gtk_entry_set_text(GTK_ENTRY(data->alias_entry), alias); gtk_entry_set_activates_default(GTK_ENTRY(data->alias_entry), TRUE); - pidgin_add_widget_to_vbox(GTK_BOX(vbox), _("A_lias:"), data->sg, data->alias_entry, TRUE, NULL); + pidgin_add_widget_to_vbox(GTK_BOX(vbox), _("A_lias:"), + data->chat_data.rq_data.sg, data->alias_entry, + TRUE, NULL); if (name != NULL) gtk_widget_grab_focus(data->alias_entry); data->group_combo = pidgin_text_combo_box_entry_new(group ? group->name : NULL, groups_tree()); - pidgin_add_widget_to_vbox(GTK_BOX(vbox), _("_Group:"), data->sg, data->group_combo, TRUE, NULL); + pidgin_add_widget_to_vbox(GTK_BOX(vbox), _("_Group:"), + data->chat_data.rq_data.sg, data->group_combo, + TRUE, NULL); data->autojoin = gtk_check_button_new_with_mnemonic(_("Auto_join when account becomes online.")); data->persistent = gtk_check_button_new_with_mnemonic(_("_Remain in chat after window is closed.")); gtk_box_pack_start(GTK_BOX(vbox), data->autojoin, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox), data->persistent, FALSE, FALSE, 0); - g_signal_connect(G_OBJECT(data->window), "response", - G_CALLBACK(add_chat_resp_cb), data); - - gtk_widget_show_all(data->window); + gtk_widget_show_all(data->chat_data.rq_data.window); } static void @@ -8195,4 +7981,3 @@ if (activeitem) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(activeitem), TRUE); } - diff -r 0bce1b58e1fe -r 47d963966c9a pidgin/gtkconv.c --- a/pidgin/gtkconv.c Fri May 15 16:21:27 2009 +0000 +++ b/pidgin/gtkconv.c Sun May 17 21:49:20 2009 +0000 @@ -6309,6 +6309,10 @@ if (!smiley) return; + smiley->data = g_realloc(smiley->data, smiley->datasize + size); + g_memmove(smiley->data + smiley->datasize, data, size); + smiley->datasize += size; + loader = smiley->loader; if (!loader) return; diff -r 0bce1b58e1fe -r 47d963966c9a pidgin/gtkimhtml.c --- a/pidgin/gtkimhtml.c Fri May 15 16:21:27 2009 +0000 +++ b/pidgin/gtkimhtml.c Sun May 17 21:49:20 2009 +0000 @@ -82,6 +82,11 @@ GtkTextMark *mark; }; +typedef struct { + GtkIMHtmlScalable *image; + gpointer data; + gsize datasize; +} GtkIMHtmlImageSave; struct im_image_data { int id; @@ -3641,96 +3646,109 @@ } static void -image_save_yes_cb(GtkIMHtmlImage *image, const char *filename) -{ - gchar *type = NULL; +image_save_yes_cb(GtkIMHtmlImageSave *save, const char *filename) +{ GError *error = NULL; -#if GTK_CHECK_VERSION(2,2,0) - GSList *formats = gdk_pixbuf_get_formats(); -#else - char *basename = g_path_get_basename(filename); - char *ext = strrchr(basename, '.'); -#endif - char *newfilename; + GtkIMHtmlImage *image = (GtkIMHtmlImage *)save->image; gtk_widget_destroy(image->filesel); image->filesel = NULL; + if (save->data && save->datasize) { +#if GLIB_CHECK_VERSION(2,8,0) + g_file_set_contents(filename, save->data, save->datasize, &error); +#else + purple_util_write_data_to_file_absolute(filename, save->data, save->datasize); +#endif + } else { + gchar *type = NULL; #if GTK_CHECK_VERSION(2,2,0) - while (formats) { - GdkPixbufFormat *format = formats->data; - gchar **extensions = gdk_pixbuf_format_get_extensions(format); - gpointer p = extensions; - - while(gdk_pixbuf_format_is_writable(format) && extensions && extensions[0]){ - gchar *fmt_ext = extensions[0]; - const gchar* file_ext = filename + strlen(filename) - strlen(fmt_ext); - - if(!g_ascii_strcasecmp(fmt_ext, file_ext)){ - type = gdk_pixbuf_format_get_name(format); + GSList *formats = gdk_pixbuf_get_formats(); +#else + char *basename = g_path_get_basename(filename); + char *ext = strrchr(basename, '.'); +#endif + char *newfilename; + +#if GTK_CHECK_VERSION(2,2,0) + while (formats) { + GdkPixbufFormat *format = formats->data; + gchar **extensions = gdk_pixbuf_format_get_extensions(format); + gpointer p = extensions; + + while(gdk_pixbuf_format_is_writable(format) && extensions && extensions[0]){ + gchar *fmt_ext = extensions[0]; + const gchar* file_ext = filename + strlen(filename) - strlen(fmt_ext); + + if(!g_ascii_strcasecmp(fmt_ext, file_ext)){ + type = gdk_pixbuf_format_get_name(format); + break; + } + + extensions++; + } + + g_strfreev(p); + + if (type) break; - } - - extensions++; + + formats = formats->next; } - g_strfreev(p); - - if (type) - break; - - formats = formats->next; - } - - g_slist_free(formats); + g_slist_free(formats); +#else + /* this is really ugly code, but I think it will work */ + if (ext) { + ext++; + if (!g_ascii_strcasecmp(ext, "jpeg") || !g_ascii_strcasecmp(ext, "jpg")) + type = g_strdup("jpeg"); + else if (!g_ascii_strcasecmp(ext, "png")) + type = g_strdup("png"); + } + + g_free(basename); +#endif + + /* If I can't find a valid type, I will just tell the user about it and then assume + it's a png */ + if (!type){ + char *basename, *tmp; + char *dirname; +#if GTK_CHECK_VERSION(2,4,0) + GtkWidget *dialog = gtk_message_dialog_new_with_markup(NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, + _("Unrecognized file type\n\nDefaulting to PNG.")); #else - /* this is really ugly code, but I think it will work */ - if (ext) { - ext++; - if (!g_ascii_strcasecmp(ext, "jpeg") || !g_ascii_strcasecmp(ext, "jpg")) - type = g_strdup("jpeg"); - else if (!g_ascii_strcasecmp(ext, "png")) + GtkWidget *dialog = gtk_message_dialog_new(NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, + _("Unrecognized file type\n\nDefaulting to PNG.")); +#endif + + g_signal_connect_swapped(dialog, "response", G_CALLBACK (gtk_widget_destroy), dialog); + gtk_widget_show(dialog); + type = g_strdup("png"); + dirname = g_path_get_dirname(filename); + basename = g_path_get_basename(filename); + tmp = strrchr(basename, '.'); + if (tmp != NULL) + tmp[0] = '\0'; + newfilename = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s.png", dirname, basename); + g_free(dirname); + g_free(basename); + } else { + /* + * We're able to save the file in it's original format, so we + * can use the original file name. + */ + newfilename = g_strdup(filename); + } + + gdk_pixbuf_save(image->pixbuf, newfilename, type, &error, NULL); + + g_free(newfilename); + g_free(type); } - g_free(basename); -#endif - - /* If I can't find a valid type, I will just tell the user about it and then assume - it's a png */ - if (!type){ - char *basename, *tmp; -#if GTK_CHECK_VERSION(2,4,0) - GtkWidget *dialog = gtk_message_dialog_new_with_markup(NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, - _("Unrecognized file type\n\nDefaulting to PNG.")); -#else - GtkWidget *dialog = gtk_message_dialog_new(NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, - _("Unrecognized file type\n\nDefaulting to PNG.")); -#endif - - g_signal_connect_swapped(dialog, "response", G_CALLBACK (gtk_widget_destroy), dialog); - gtk_widget_show(dialog); - - type = g_strdup("png"); - basename = g_path_get_basename(filename); - tmp = strrchr(basename, '.'); - if (tmp != NULL) - tmp[0] = '\0'; - newfilename = g_strdup_printf("%s.png", basename); - g_free(basename); - } else { - /* - * We're able to save the file in it's original format, so we - * can use the original file name. - */ - newfilename = g_strdup(filename); - } - - gdk_pixbuf_save(image->pixbuf, newfilename, type, &error, NULL); - - g_free(newfilename); - g_free(type); - if (error){ #if GTK_CHECK_VERSION(2,4,0) GtkWidget *dialog = gtk_message_dialog_new_with_markup(NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, @@ -3747,9 +3765,10 @@ #if GTK_CHECK_VERSION(2,4,0) /* FILECHOOSER */ static void -image_save_check_if_exists_cb(GtkWidget *widget, gint response, GtkIMHtmlImage *image) +image_save_check_if_exists_cb(GtkWidget *widget, gint response, GtkIMHtmlImageSave *save) { gchar *filename; + GtkIMHtmlImage *image = (GtkIMHtmlImage *)save->image; if (response != GTK_RESPONSE_ACCEPT) { gtk_widget_destroy(widget); @@ -3760,9 +3779,10 @@ filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(widget)); #else /* FILECHOOSER */ static void -image_save_check_if_exists_cb(GtkWidget *button, GtkIMHtmlImage *image) +image_save_check_if_exists_cb(GtkWidget *button, GtkIMHtmlImageSave *save) { gchar *filename; + GtkIMHtmlImage *image = (GtkIMHtmlImage *)save->image; filename = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(image->filesel))); @@ -3795,7 +3815,7 @@ image_save_yes_cb(image, filename); */ - image_save_yes_cb(image, filename); + image_save_yes_cb(save, filename); g_free(filename); } @@ -3810,8 +3830,10 @@ #endif /* FILECHOOSER */ static void -gtk_imhtml_image_save(GtkWidget *w, GtkIMHtmlImage *image) -{ +gtk_imhtml_image_save(GtkWidget *w, GtkIMHtmlImageSave *save) +{ + GtkIMHtmlImage *image = (GtkIMHtmlImage *)save->image; + if (image->filesel != NULL) { gtk_window_present(GTK_WINDOW(image->filesel)); return; @@ -3828,7 +3850,7 @@ if (image->filename != NULL) gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(image->filesel), image->filename); g_signal_connect(G_OBJECT(GTK_FILE_CHOOSER(image->filesel)), "response", - G_CALLBACK(image_save_check_if_exists_cb), image); + G_CALLBACK(image_save_check_if_exists_cb), save); #else /* FILECHOOSER */ image->filesel = gtk_file_selection_new(_("Save Image")); if (image->filename != NULL) @@ -3838,7 +3860,7 @@ g_signal_connect_swapped(G_OBJECT(GTK_FILE_SELECTION(image->filesel)->cancel_button), "clicked", G_CALLBACK(image_save_cancel_cb), image); g_signal_connect(G_OBJECT(GTK_FILE_SELECTION(image->filesel)->ok_button), "clicked", - G_CALLBACK(image_save_check_if_exists_cb), image); + G_CALLBACK(image_save_check_if_exists_cb), save); #endif /* FILECHOOSER */ gtk_widget_show(image->filesel); @@ -3860,30 +3882,29 @@ * embedded in the conversation. Someone should make the Purple core handle * all of that. */ -static gboolean gtk_imhtml_image_clicked(GtkWidget *w, GdkEvent *event, GtkIMHtmlImage *image) +static gboolean gtk_imhtml_image_clicked(GtkWidget *w, GdkEvent *event, GtkIMHtmlImageSave *save) { GdkEventButton *event_button = (GdkEventButton *) event; + GtkIMHtmlImage *image = (GtkIMHtmlImage *)save->image; if (event->type == GDK_BUTTON_RELEASE) { if(event_button->button == 3) { GtkWidget *img, *item, *menu; - gchar *text = g_strdup_printf(_("_Save Image...")); menu = gtk_menu_new(); /* buttons and such */ img = gtk_image_new_from_stock(GTK_STOCK_SAVE, GTK_ICON_SIZE_MENU); - item = gtk_image_menu_item_new_with_mnemonic(text); + item = gtk_image_menu_item_new_with_mnemonic(_("_Save Image...")); gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img); - g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(gtk_imhtml_image_save), image); + g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(gtk_imhtml_image_save), save); gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); /* Add menu item for adding custom smiley to local smileys */ /* we only add the menu if the image is of "custom smiley size" <= 96x96 pixels */ if (image->width <= 96 && image->height <= 96) { - text = g_strdup_printf(_("_Add Custom Smiley...")); img = gtk_image_new_from_stock(GTK_STOCK_ADD, GTK_ICON_SIZE_MENU); - item = gtk_image_menu_item_new_with_mnemonic(text); + item = gtk_image_menu_item_new_with_mnemonic(_("_Add Custom Smiley...")); gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img); g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(gtk_imhtml_custom_smiley_save), image); @@ -3894,7 +3915,6 @@ gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, event_button->button, event_button->time); - g_free(text); return TRUE; } } @@ -3909,7 +3929,7 @@ static gboolean gtk_imhtml_smiley_clicked(GtkWidget *w, GdkEvent *event, GtkIMHtmlSmiley *smiley) { GdkPixbufAnimation *anim = NULL; - GtkIMHtmlScalable *image = NULL; + GtkIMHtmlImageSave *save = NULL; gboolean ret; if (event->type != GDK_BUTTON_RELEASE || ((GdkEventButton*)event)->button != 3) @@ -3919,9 +3939,14 @@ if (!anim) return FALSE; - image = gtk_imhtml_animation_new(anim, smiley->smile, 0); - ret = gtk_imhtml_image_clicked(w, event, (GtkIMHtmlImage*)image); - g_object_set_data_full(G_OBJECT(w), "image-data", image, (GDestroyNotify)gtk_imhtml_animation_free); + save = g_new0(GtkIMHtmlImageSave, 1); + save->image = (GtkIMHtmlScalable *)gtk_imhtml_animation_new(anim, smiley->smile, 0); + save->data = smiley->data; /* Do not need to memdup here, since the smiley is not + destroyed before this GtkIMHtmlImageSave */ + save->datasize = smiley->datasize; + ret = gtk_imhtml_image_clicked(w, event, save); + g_object_set_data_full(G_OBJECT(w), "image-data", save->image, (GDestroyNotify)gtk_imhtml_animation_free); + g_object_set_data_full(G_OBJECT(w), "image-save-data", save, (GDestroyNotify)g_free); return ret; } @@ -3955,6 +3980,7 @@ GtkWidget *box = gtk_event_box_new(); char *tag; GtkTextChildAnchor *anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, iter); + GtkIMHtmlImageSave *save; gtk_container_add(GTK_CONTAINER(box), GTK_WIDGET(image->image)); @@ -3969,7 +3995,11 @@ g_object_set_data(G_OBJECT(anchor), "gtkimhtml_plaintext", "[Image]"); gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), box, anchor); - g_signal_connect(G_OBJECT(box), "event", G_CALLBACK(gtk_imhtml_image_clicked), image); + + save = g_new0(GtkIMHtmlImageSave, 1); + save->image = scale; + g_signal_connect(G_OBJECT(box), "event", G_CALLBACK(gtk_imhtml_image_clicked), save); + g_object_set_data_full(G_OBJECT(box), "image-save-data", save, (GDestroyNotify)g_free); } GtkIMHtmlScalable *gtk_imhtml_hr_new() @@ -5773,6 +5803,7 @@ g_object_unref(smiley->icon); if (smiley->loader) g_object_unref(smiley->loader); + g_free(smiley->data); g_free(smiley); } @@ -5887,13 +5918,25 @@ void gtk_imhtml_set_populate_primary_clipboard(GtkIMHtml *imhtml, gboolean populate) { + gulong signal_id; + signal_id = g_signal_handler_find(imhtml->text_buffer, + G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_UNBLOCKED, 0, 0, NULL, + mark_set_so_update_selection_cb, NULL); if (populate) { - g_signal_handlers_unblock_matched(imhtml->text_buffer, - G_SIGNAL_MATCH_FUNC, 0, 0, NULL, - mark_set_so_update_selection_cb, NULL); + if (!signal_id) { + /* We didn't find an unblocked signal handler, which means there + is a blocked handler. Now unblock it. + This is necessary to avoid a mutex-lock when the debug message + saying 'no handler is blocked' is printed in the debug window. + -- sad + */ + g_signal_handlers_unblock_matched(imhtml->text_buffer, + G_SIGNAL_MATCH_FUNC, 0, 0, NULL, + mark_set_so_update_selection_cb, NULL); + } } else { - g_signal_handlers_block_matched(imhtml->text_buffer, - G_SIGNAL_MATCH_FUNC, 0, 0, NULL, - mark_set_so_update_selection_cb, NULL); + /* Block only if we found an unblocked handler */ + if (signal_id) + g_signal_handler_block(imhtml->text_buffer, signal_id); } } diff -r 0bce1b58e1fe -r 47d963966c9a pidgin/gtkimhtml.h --- a/pidgin/gtkimhtml.h Fri May 15 16:21:27 2009 +0000 +++ b/pidgin/gtkimhtml.h Sun May 17 21:49:20 2009 +0000 @@ -188,6 +188,8 @@ GSList *anchors; GtkIMHtmlSmileyFlags flags; GtkIMHtml *imhtml; + gpointer data; /** @Since 2.6.0 */ + gsize datasize; /** @Since 2.6.0 */ }; struct _GtkIMHtmlScalable { diff -r 0bce1b58e1fe -r 47d963966c9a pidgin/gtkstatusbox.c --- a/pidgin/gtkstatusbox.c Fri May 15 16:21:27 2009 +0000 +++ b/pidgin/gtkstatusbox.c Sun May 17 21:49:20 2009 +0000 @@ -93,6 +93,7 @@ static void do_colorshift (GdkPixbuf *dest, GdkPixbuf *src, int shift); static void icon_choose_cb(const char *filename, gpointer data); static void remove_buddy_icon_cb(GtkWidget *w, PidginStatusBox *box); +static void choose_buddy_icon_cb(GtkWidget *w, PidginStatusBox *box); enum { /** A PidginStatusBoxItemType */ @@ -317,6 +318,10 @@ box->icon_box_menu = gtk_menu_new(); + menu_item = pidgin_new_item_from_stock(box->icon_box_menu, _("Select Buddy Icon"), GTK_STOCK_ADD, + G_CALLBACK(choose_buddy_icon_cb), + box, 0, 0, NULL); + menu_item = pidgin_new_item_from_stock(box->icon_box_menu, _("Remove"), GTK_STOCK_REMOVE, G_CALLBACK(remove_buddy_icon_cb), box, 0, 0, NULL); @@ -327,13 +332,7 @@ event->button, event->time); } else { - if (box->buddy_icon_sel) { - gtk_window_present(GTK_WINDOW(box->buddy_icon_sel)); - return FALSE; - } - - box->buddy_icon_sel = pidgin_buddy_icon_chooser_new(GTK_WINDOW(gtk_widget_get_toplevel(widget)), icon_choose_cb, box); - gtk_widget_show_all(box->buddy_icon_sel); + choose_buddy_icon_cb(widget, box); } return FALSE; } @@ -1529,6 +1528,17 @@ } static void +choose_buddy_icon_cb(GtkWidget *w, PidginStatusBox *box) +{ + if (box->buddy_icon_sel) { + gtk_window_present(GTK_WINDOW(box->buddy_icon_sel)); + } else { + box->buddy_icon_sel = pidgin_buddy_icon_chooser_new(GTK_WINDOW(gtk_widget_get_toplevel(w)), icon_choose_cb, box); + gtk_widget_show_all(box->buddy_icon_sel); + } +} + +static void icon_choose_cb(const char *filename, gpointer data) { PidginStatusBox *box = data; diff -r 0bce1b58e1fe -r 47d963966c9a po/ca.po --- a/po/ca.po Fri May 15 16:21:27 2009 +0000 +++ b/po/ca.po Sun May 17 21:49:20 2009 +0000 @@ -33,8 +33,8 @@ msgstr "" "Project-Id-Version: Pidgin\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2009-05-06 19:49+0200\n" -"PO-Revision-Date: 2009-05-06 23:20+0200\n" +"POT-Creation-Date: 2009-05-17 14:59+0200\n" +"PO-Revision-Date: 2009-05-17 15:05+0200\n" "Last-Translator: Josep Puigdemont i Casamajó \n" "Language-Team: Catalan \n" "MIME-Version: 1.0\n" @@ -1595,7 +1595,7 @@ "Fetching TinyURL..." msgstr "" "\n" -"S'està aconseguint una TinyURL..." +"S'està aconseguint un TinyURL..." msgid "Only create TinyURL for urls of this length or greater" msgstr "Crea TinyURL per a URL així de llargues o més" @@ -1816,6 +1816,8 @@ msgid "+++ %s signed off" msgstr "+++ %s se n'ha anat" +#. Unknown error +#. Unknown error! msgid "Unknown error" msgstr "Error desconegut" @@ -2717,7 +2719,7 @@ #. *< priority #. *< id msgid "One Time Password Support" -msgstr "Contrasenyes d'un sol us" +msgstr "Contrasenyes d'un sol ús" #. *< name #. *< version @@ -2731,7 +2733,7 @@ "are only used in a single successful connection.\n" "Note: The account password must not be saved for this to work." msgstr "" -"Us permet forçar que les contrasenyes siguin d'un sol us per a comptes dels " +"Us permet forçar que les contrasenyes siguin d'un sol ús per a comptes dels " "quals no es desin les contrasenyes.\n" "Nota: per poder fer servir això, cal que no es desi la contrasenya del " "compte." @@ -3777,14 +3779,14 @@ msgstr "Aquesta versió del protocol BOSH no està implementada" msgid "Unable to establish a connection with the server" -msgstr "No s'ha pogut establir una connexió amb al servidor" +msgstr "No s'ha pogut establir una connexió amb el servidor" #, c-format msgid "" "Could not establish a connection with the server:\n" "%s" msgstr "" -"No s'ha pogut establir una connexió amb al servidor:\n" +"No s'ha pogut establir una connexió amb el servidor:\n" "%s" msgid "Unable to establish SSL connection" @@ -4037,6 +4039,13 @@ msgid "Resource" msgstr "Recurs" +#, c-format +msgid "%s ago" +msgstr "fa %s" + +msgid "Logged off" +msgstr "Desconnectat" + # Segons la viquipèdia msgid "Middle Name" msgstr "Nom del mig" @@ -4812,9 +4821,8 @@ msgid "Error in chat %s" msgstr "S'ha produït un error en el xat %s" -#, fuzzy msgid "An error occured on the in-band bytestream transfer\n" -msgstr "S'ha produït un error en obrir el fitxer." +msgstr "" msgid "Transfer was closed." msgstr "La transferència s'ha tancat." @@ -5774,6 +5782,8 @@ msgstr "S'ha perdut la connexió amb el servidor" #. Can't write _()'d strings in array initializers. Workaround. +#. khc: then use N_() in the array initializer and use _() when they are +#. used msgid "New mail messages" msgstr "Missatges de correu nous" @@ -5971,15 +5981,15 @@ #. * connotation, for example, "he was zapped by electricity when #. * he put a fork in the toaster." msgid "Zap" -msgstr "" +msgstr "Enrampar" #, c-format msgid "%s has zapped you!" -msgstr "" +msgstr "%s us ha enrampat!" #, c-format msgid "Zapping %s..." -msgstr "" +msgstr "S'està enrampant %s..." #. Whack means "to hit or strike someone with a sharp blow" msgid "Whack" @@ -6619,9 +6629,6 @@ msgid "iChat AV" msgstr "iChat AV" -msgid "Live Video" -msgstr "Vídeo en directe" - msgid "Camera" msgstr "Càmera" @@ -9603,6 +9610,30 @@ msgid "Add buddy rejected" msgstr "S'ha rebutjat afegir l'amic" +#. Some error in the received stream +msgid "Received invalid data" +msgstr "S'han rebut dades invàlides" + +#. Password incorrect +msgid "Incorrect Password" +msgstr "La contrasenya no és correcta" + +#. security lock from too many failed login attempts +msgid "Account locked: Too many failed login attempts" +msgstr "S'ha blocat el compte: s'ha intentat entrar massa vegades" + +#. the username does not exist +msgid "Username does not exist" +msgstr "L'usuari no existeix" + +#. indicates a lock of some description +msgid "Account locked: See the debug log" +msgstr "El compte està blocat: vegeu el registre de depuració" + +#. username or password missing +msgid "Username or password missing" +msgstr "Manquen el nom d'uruari o la contrasenya" + #, c-format msgid "" "The Yahoo server has requested the use of an unrecognized authentication " @@ -10518,8 +10549,8 @@ msgid "Please update the necessary fields." msgstr "Actualitzeu els camps necessaris." -msgid "Room _List" -msgstr "_Llista de sales" +msgid "A_ccount" +msgstr "_Compte" msgid "" "Please enter the appropriate information about the chat you would like to " @@ -10527,8 +10558,8 @@ msgstr "" "Introduïu la informació necessària sobre el xat al qual vulgueu entrar.\n" -msgid "_Account:" -msgstr "C_ompte:" +msgid "Room _List" +msgstr "_Llista de sales" msgid "_Block" msgstr "_Bloca" @@ -12003,11 +12034,9 @@ msgid "Save Image" msgstr "Desa imatge" -#, c-format msgid "_Save Image..." msgstr "_Desa la imatge..." -#, c-format msgid "_Add Custom Smiley..." msgstr "_Afegeix una emoticona personalitzada..." @@ -12442,6 +12471,9 @@ msgid "Pounce on Whom" msgstr "Avisa dels Whom" +msgid "_Account:" +msgstr "C_ompte:" + msgid "_Buddy name:" msgstr "_Nom de l'amic:" @@ -12721,7 +12753,7 @@ #. TURN server msgid "Relay Server (TURN)" -msgstr "" +msgstr "Servidor repetidor (TURN)" msgid "Proxy Server & Browser" msgstr "Servidor intermediari i navegador" @@ -13118,6 +13150,9 @@ msgid "Custom Smiley Manager" msgstr "Gestor d'emoticones personalitzades" +msgid "Select Buddy Icon" +msgstr "Seleccioneu una icona per a l'amic" + msgid "Click to change your buddyicon for this account." msgstr "Feu clic per canviar la icona d'amic d'aquest compte." @@ -14284,6 +14319,9 @@ msgid "This plugin is useful for debbuging XMPP servers or clients." msgstr "Aquest connector és útil per a depurar servidors i clients XMPP." +#~ msgid "Live Video" +#~ msgstr "Vídeo en directe" + #~ msgid "Invite message" #~ msgstr "Missatge d'invitació" @@ -14763,9 +14801,6 @@ #~ "llista d'amics. Opcionalment podeu entrar un àlies, o sobrenom, per a " #~ "l'amic. El sobrenom substituirà el nom d'usuari allà on sigui possible.\n" -#~ msgid "A_ccount:" -#~ msgstr "_Compte:" - #~ msgid "User has typed something and stopped" #~ msgstr "L'usuari ha escrit alguna cosa i s'ha aturat" diff -r 0bce1b58e1fe -r 47d963966c9a po/de.po --- a/po/de.po Fri May 15 16:21:27 2009 +0000 +++ b/po/de.po Sun May 17 21:49:20 2009 +0000 @@ -11,8 +11,8 @@ msgstr "" "Project-Id-Version: de\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2009-04-30 10:37-0400\n" -"PO-Revision-Date: 2009-04-26 12:11+0200\n" +"POT-Creation-Date: 2009-05-15 19:56+0200\n" +"PO-Revision-Date: 2009-05-15 19:56+0200\n" "Last-Translator: Jochen Kemnade \n" "Language-Team: Deutsch \n" "MIME-Version: 1.0\n" @@ -1562,7 +1562,6 @@ msgid "Lastlog plugin." msgstr "Verlauf-Plugin." -#, c-format msgid "" "\n" "Fetching TinyURL..." @@ -1890,7 +1889,6 @@ "Fehler beim Lesen vom Auflösungsprozess:\n" "%s" -#, c-format msgid "Resolver process exited without answering our request" msgstr "Auflösungsprozess hat sich beendet ohne die Anfrage zu beantworten" @@ -3760,11 +3758,8 @@ msgid "Unsupported version of BOSH protocol" msgstr "Nicht-unterstützte Version" -#, fuzzy msgid "Unable to establish a connection with the server" -msgstr "" -"Die Verbindung mit dem Server konnte nicht hergestellt werden:\n" -"%s" +msgstr "Die Verbindung mit dem Server konnte nicht hergestellt werden" #, c-format msgid "" @@ -3774,9 +3769,8 @@ "Die Verbindung mit dem Server konnte nicht hergestellt werden:\n" "%s" -#, fuzzy msgid "Unable to establish SSL connection" -msgstr "Kann Verbindung nicht erstellen" +msgstr "Kann SSL-Verbindung nicht erstellen" msgid "Unable to create socket" msgstr "Kann Socket nicht erstellen" @@ -4012,6 +4006,14 @@ msgid "Resource" msgstr "Ressource" +#, fuzzy, c-format +msgid "%s ago" +msgstr "vor %s" + +#, fuzzy +msgid "Logged off" +msgstr "Abgemeldet" + msgid "Middle Name" msgstr "Zweiter Name" @@ -4181,6 +4183,17 @@ msgid "Find Rooms" msgstr "Finde Räume" +#, fuzzy +msgid "Affiliations:" +msgstr "Alias:" + +msgid "No users found" +msgstr "Keine Benutzer gefunden" + +#, fuzzy +msgid "Roles:" +msgstr "Funktion" + msgid "You require encryption, but it is not available on this server." msgstr "" "Sie fordern Verschlüsselung, aber diese ist auf dem Server nicht verfügbar." @@ -4191,7 +4204,6 @@ msgid "Read Error" msgstr "Fehler beim Lesen" -#, c-format msgid "" "Could not find alternative XMPP connection methods after failing to connect " "directly.\n" @@ -4645,16 +4657,18 @@ msgid "ban <user> [reason]: Ban a user from the room." msgstr "ban <Benutzer> [Grund]: Verbanne einen Benutzer aus dem Raum." -msgid "" -"affiliate <user> <owner|admin|member|outcast|none>: Set a user's " -"affiliation with the room." +#, fuzzy +msgid "" +"affiliate <owner|admin|member|outcast|none> [nick1] [nick2] ...: Get " +"the users with an affiliation or set users' affiliation with the room." msgstr "" "affiliate <Benutzer> <owner|admin|member|outcast|none>: Setze " "eine Benutzerzugehörigkeit für den Raum." -msgid "" -"role <user> <moderator|participant|visitor|none>: Set a user's " -"role in the room." +#, fuzzy +msgid "" +"role <moderator|participant|visitor|none> [nick1] [nick2] ...: Get the " +"users with an role or set users' role with the room." msgstr "" "role <Benutzer> <moderator|participant|visitor|none>: Setze eine " "Rolle für den Benutzer im Raum." @@ -4888,219 +4902,166 @@ "%s ist auf der lokalen Liste, aber nicht auf der Serverliste. Möchten Sie, " "dass der Buddy hinzugefügt wird?" -#, c-format msgid "Unable to parse message" msgstr "Kann die Nachricht nicht parsen" -#, c-format msgid "Syntax Error (probably a client bug)" msgstr "Syntaxfehler (wahrscheinlich ein Client-Bug)" -#, c-format msgid "Invalid email address" msgstr "Ungültige E-Mail-Adresse" -#, c-format msgid "User does not exist" msgstr "Benutzer existiert nicht" -#, c-format msgid "Fully qualified domain name missing" msgstr "Der Fully Qualified Domain Name fehlt" -#, c-format msgid "Already logged in" msgstr "Schon angemeldet" -#, c-format msgid "Invalid username" msgstr "Ungültiger Benutzername" -#, c-format msgid "Invalid friendly name" msgstr "Ungültiger Freundesname" -#, c-format msgid "List full" msgstr "Liste voll" -#, c-format msgid "Already there" msgstr "Schon da" -#, c-format msgid "Not on list" msgstr "Nicht auf der Liste" -#, c-format msgid "User is offline" msgstr "Benutzer ist offline" -#, c-format msgid "Already in the mode" msgstr "Bereits in diesem Modus" -#, c-format msgid "Already in opposite list" msgstr "Bereits in der „Gegenteil-Liste“" -#, c-format msgid "Too many groups" msgstr "Zu viele Gruppen" -#, c-format msgid "Invalid group" msgstr "Ungültige Gruppe" -#, c-format msgid "User not in group" msgstr "Benutzer ist nicht in der Gruppe" -#, c-format msgid "Group name too long" msgstr "Name der Gruppe ist zu lang" -#, c-format msgid "Cannot remove group zero" msgstr "Kann die Gruppe „Null“ nicht entfernen" -#, c-format msgid "Tried to add a user to a group that doesn't exist" msgstr "" "Versuchte einen Benutzer zu einer nichtexistierenden Gruppe hinzuzufügen" -#, c-format msgid "Switchboard failed" msgstr "Vermittlung gescheitert" -#, c-format msgid "Notify transfer failed" msgstr "Übertragung der Benachrichtigung gescheitert" -#, c-format msgid "Required fields missing" msgstr "Notwendige Felder fehlen" -#, c-format msgid "Too many hits to a FND" msgstr "Zu viele Treffer zu einem FND" -#, c-format msgid "Not logged in" msgstr "Nicht angemeldet" -#, c-format msgid "Service temporarily unavailable" msgstr "Dienst momentan nicht verfügbar" -#, c-format msgid "Database server error" msgstr "Fehler des Datenbank-Servers" -#, c-format msgid "Command disabled" msgstr "Kommando abgeschaltet" -#, c-format msgid "File operation error" msgstr "Dateiverarbeitungsfehler" -#, c-format msgid "Memory allocation error" msgstr "Fehler bei der Speicheranforderung" -#, c-format msgid "Wrong CHL value sent to server" msgstr "Falscher CHL-Wert zum Server gesendet" -#, c-format msgid "Server busy" msgstr "Server beschäftigt" -#, c-format msgid "Server unavailable" msgstr "Server unerreichbar" -#, c-format msgid "Peer notification server down" msgstr "Peer-Benachrichtigungsserver nicht erreichbar" -#, c-format msgid "Database connect error" msgstr "Datenbank-Verbindungsfehler" -#, c-format msgid "Server is going down (abandon ship)" msgstr "Server fährt runter (melden Sie sich ab)" -#, c-format msgid "Error creating connection" msgstr "Fehler beim Herstellen der Verbindung" -#, c-format msgid "CVR parameters are either unknown or not allowed" msgstr "CVR-Parameter sind entweder unbekannt oder nicht erlaubt" -#, c-format msgid "Unable to write" msgstr "Schreiben nicht möglich" -#, c-format msgid "Session overload" msgstr "Sitzung überlastet" -#, c-format msgid "User is too active" msgstr "Benutzer ist zu aktiv" -#, c-format msgid "Too many sessions" msgstr "Zu viele Sitzungen" -#, c-format msgid "Passport not verified" msgstr "Passport (MSN Benutzerausweis) wurde nicht überprüft" -#, c-format msgid "Bad friend file" msgstr "Falsche Friends-Datei" -#, c-format msgid "Not expected" msgstr "Nicht erwartet" -#, c-format msgid "Friendly name changes too rapidly" msgstr "Benutzernamen werden zu oft geändert" -#, c-format msgid "Server too busy" msgstr "Server ist zu beschäftigt" -#, c-format msgid "Authentication failed" msgstr "Authentifizierung fehlgeschlagen" -#, c-format msgid "Not allowed when offline" msgstr "Nicht erlaubt im Offline-Modus" -#, c-format msgid "Not accepting new users" msgstr "Akzeptiert keine neuen Benutzer" -#, c-format msgid "Kids Passport without parental consent" msgstr "Kinder-Passwort ohne die Zustimmung der Eltern" -#, c-format msgid "Passport account not yet verified" msgstr "Passport-Konto wurde noch nicht überprüft" msgid "Passport account suspended" msgstr "Passport-Konto gesperrt" -#, c-format msgid "Bad ticket" msgstr "Falsches Ticket" @@ -5477,14 +5438,17 @@ msgid "%s just sent you a Nudge!" msgstr "%s hat Sie gerade angestoßen!" -#. char *adl = g_strndup(payload, len); +#, c-format +msgid "Unknown error (%d): %s" +msgstr "Unbekannter Fehler (%d): %s" + +msgid "Unable to add user" +msgstr "Kann den Benutzer nicht hinzufügen" + #, c-format msgid "Unknown error (%d)" msgstr "Unbekannter Fehler (%d)" -msgid "Unable to add user" -msgstr "Kann den Benutzer nicht hinzufügen" - msgid "The following users are missing from your addressbook" msgstr "Die folgenden Benutzer fehlen in Ihrem Adressbuch" @@ -5749,6 +5713,8 @@ msgstr "Verbindung zum Server verloren" #. Can't write _()'d strings in array initializers. Workaround. +#. khc: then use N_() in the array initializer and use _() when they are +#. used msgid "New mail messages" msgstr "Neue Mail-Nachrichten" @@ -6591,9 +6557,6 @@ msgid "iChat AV" msgstr "iChat AV" -msgid "Live Video" -msgstr "Live-Video" - msgid "Camera" msgstr "Kamera" @@ -8653,7 +8616,6 @@ msgid "
Channel Topic:
%s" msgstr "
Thema des Kanals:
%s" -#, c-format msgid "
Channel Modes: " msgstr "
Kanal-Modi: " @@ -8678,7 +8640,6 @@ msgid "Channel Public Keys List" msgstr "Liste der öffentlichen Schlüssel des Kanals" -#, c-format msgid "" "Channel authentication is used to secure the channel from unauthorized " "access. The authentication may be based on passphrase and digital " @@ -9080,7 +9041,6 @@ msgid "Your Current Mood" msgstr "Ihre momentane Stimmung" -#, c-format msgid "Normal" msgstr "Normal" @@ -9466,47 +9426,37 @@ msgid "No server statistics available" msgstr "Keine Serverstatistik verfügbar" -#, c-format msgid "Failure: Version mismatch, upgrade your client" msgstr "Fehler: Unterschiedliche Version, aktualisieren Sie Ihren Client" -#, c-format msgid "Failure: Remote does not trust/support your public key" msgstr "" "Fehler: Die entfernte Seite vertraut Ihrem öffentlichen Schlüssel nicht" -#, c-format msgid "Failure: Remote does not support proposed KE group" msgstr "" "Fehler: Entferntes Programm unterstützt nicht die vorgeschlagen KE-Gruppe" -#, c-format msgid "Failure: Remote does not support proposed cipher" msgstr "" "Fehler: Entferntes Programm unterstützt die vorgeschlagene Cipher nicht" -#, c-format msgid "Failure: Remote does not support proposed PKCS" msgstr "Fehler: Entferntes Programm unterstützt die vorgeschlagene PKCS nicht" -#, c-format msgid "Failure: Remote does not support proposed hash function" msgstr "" "Fehler: Entferntes Programm unterstützt die vorgeschlagen Hashfunktion nicht" -#, c-format msgid "Failure: Remote does not support proposed HMAC" msgstr "Fehler: Entferntes Programm unterstützt das vorgeschlagene HMAC nicht" -#, c-format msgid "Failure: Incorrect signature" msgstr "Fehler: Falsche Signatur" -#, c-format msgid "Failure: Invalid cookie" msgstr "Fehler: Ungültiger Cookie" -#, c-format msgid "Failure: Authentication failed" msgstr "Fehler: Authentifizierung fehlgeschlagen" @@ -10322,29 +10272,24 @@ msgstr " (%s)" #. 10053 -#, c-format msgid "Connection interrupted by other software on your computer." msgstr "" "Die Verbindung wurde von einer anderen Software auf ihrem Computer " "unterbrochen." #. 10054 -#, c-format msgid "Remote host closed connection." msgstr "Der entfernte Host hat die Verbindung beendet." #. 10060 -#, c-format msgid "Connection timed out." msgstr "Verbindungsabbruch wegen Zeitüberschreitung." #. 10061 -#, c-format msgid "Connection refused." msgstr "Verbindung abgelehnt." #. 10048 -#, c-format msgid "Address already in use." msgstr "Adresse wird bereits benutzt." @@ -11620,7 +11565,6 @@ "geschützt. Die Datei 'COPYRIGHT' enthält die komplette Liste der " "Mitwirkenden. Wir übernehmen keine Haftung für dieses Programm.

" -#, c-format msgid "" "FAQ:
http://developer.pidgin.im/wiki/FAQ

" @@ -11628,7 +11572,6 @@ "FAQ: http://developer.pidgin.im/wiki/FAQ

" -#, c-format msgid "" "Help via e-mail: support@pidgin.im

" @@ -11636,13 +11579,11 @@ "Hilfe per E-Mail: support@pidgin.im

" -#, c-format msgid "" "IRC Channel: #pidgin on irc.freenode.net

" msgstr "" "IRC-Kanal: #pidgin auf irc.freenode.net

" -#, c-format msgid "XMPP MUC: devel@conference.pidgin.im

" msgstr "XMPP-MUC: devel@conference.pidgin.im

" @@ -12001,11 +11942,9 @@ msgid "Save Image" msgstr "Bild speichern" -#, c-format msgid "_Save Image..." msgstr "Bild _speichern..." -#, c-format msgid "_Add Custom Smiley..." msgstr "Benutzerdefinierten Smiley _hinzufügen..." @@ -12305,7 +12244,6 @@ msgid "Pidgin" msgstr "Pidgin" -#, c-format msgid "Exiting because another libpurple client is already running.\n" msgstr "Wird geschlossen, da bereits ein anderer libpurple-Client läuft\n" @@ -12493,47 +12431,36 @@ msgid "Pounce Target" msgstr "Alarm-Ziel" -#, c-format msgid "Started typing" msgstr "Beginnt zu tippen" -#, c-format msgid "Paused while typing" msgstr "Hat beim Tippen angehalten" -#, c-format msgid "Signed on" msgstr "Hat sich anmeldet" -#, c-format msgid "Returned from being idle" msgstr "Ist nicht mehr inaktiv" -#, c-format msgid "Returned from being away" msgstr "Ist wieder anwesend" -#, c-format msgid "Stopped typing" msgstr "Hat das Tippen gestoppt" -#, c-format msgid "Signed off" msgstr "Hat sich abmeldet" -#, c-format msgid "Became idle" msgstr "Wurde untätig" -#, c-format msgid "Went away" msgstr "Ging hinaus" -#, c-format msgid "Sent a message" msgstr "Eine Nachricht senden" -#, c-format msgid "Unknown.... Please report this!" msgstr "Unbekannt.... Bitte berichten Sie dieses Problem!" @@ -12814,27 +12741,21 @@ msgid "Sound Selection" msgstr "Klang-Auswahl" -#, c-format msgid "Quietest" msgstr "Am leisesten" -#, c-format msgid "Quieter" msgstr "Leiser" -#, c-format msgid "Quiet" msgstr "Leise" -#, c-format msgid "Loud" msgstr "Laut" -#, c-format msgid "Louder" msgstr "Lauter" -#, c-format msgid "Loudest" msgstr "Am lautesten" @@ -13871,7 +13792,6 @@ msgid "Select Color" msgstr "Farbe auswählen" -#, c-format msgid "Select Interface Font" msgstr "Schriftart wählen" @@ -14096,7 +14016,6 @@ msgid "Timestamp Format Options" msgstr "Zeitstempelformat-Optionen" -#, c-format msgid "_Force 24-hour time format" msgstr "_Erzwinge 24-Stunden Zeitformat" @@ -14265,6 +14184,9 @@ msgstr "" "Dieses Plugin ist nützlich zur Fehlersuche in XMPP-Servern oder -Clients." +#~ msgid "Live Video" +#~ msgstr "Live-Video" + #~ msgid "Invite message" #~ msgstr "Einladungsnachricht"