Mon, 01 Oct 2007 17:49:01 +0000
merge of '34b818f1b8b8e5ce50a83a03052188ad479bec8e'
and 'fa4b1205a719e569e710e124ee000c27729c4614'
| libpurple/dnssrv.c | file | annotate | diff | comparison | revisions | |
| libpurple/protocols/jabber/.todo | file | annotate | diff | comparison | revisions | |
| libpurple/protocols/oscar/.todo | file | annotate | diff | comparison | revisions | |
| po/sr@Latn.po | file | annotate | diff | comparison | revisions |
--- a/COPYRIGHT Mon Oct 01 17:02:03 2007 +0000 +++ b/COPYRIGHT Mon Oct 01 17:49:01 2007 +0000 @@ -246,6 +246,7 @@ Kevin Miller Paul Miller Arkadiusz Miskiewicz +David Mohr Andrew Molloy Michael Monreal Benjamin Moody @@ -290,6 +291,7 @@ Nathan Poznick Jory A. Pratt Brent Priddy +Justin Pryzby Federicco Mena Quintero Yosef Radchenko David Raeman
--- a/ChangeLog Mon Oct 01 17:02:03 2007 +0000 +++ b/ChangeLog Mon Oct 01 17:49:01 2007 +0000 @@ -1,5 +1,26 @@ Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul +Version 2.2.1: + http://developer.pidgin.im/query?status=closed&milestone=2.2.1 + NOTE: Due to the backporting that happened for the actual + release, it is possible bugs marked as fixed in 2.2.1 + will not be fixed until 2.2.2. + + libpurple: + * A few build issues on Solaris were fixed. + * Cancelling the password prompt for an account will no longer leave + it in an ambiguous state. (It will be disabled.) + * Fixed an erroneous size display for MSN file transfers. (galt) + * Gmail notifications are better tracked + + Pidgin: + * Fixed keyboard tab reordering to move tabs one step instead of two. + * You should no longer lose proxy settings when Pidgin is restarted. + + Finch: + * Pressing 'Insert' in the buddylist will bring up the 'Add Buddy' + dialog. + Version 2.2.0 (09/13/2007): http://developer.pidgin.im/query?status=closed&milestone=2.2.0
--- a/NEWS Mon Oct 01 17:02:03 2007 +0000 +++ b/NEWS Mon Oct 01 17:49:01 2007 +0000 @@ -1,5 +1,24 @@ Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul +2.2.1 (9/28/2007): + Richard: We have some new code in the pipeline, but it's not quite + ready for a general release. Instead, this is basically a bug fix + release. + + Luke: Unfortunately the necessity of this bug fix release means + some of the tickets that have been closed as part of the 2.2.1 + milestone are not actually fixed yet. We have grabbed as many + of the changes as we could while avoiding those that are as + yet unstable though, and this should still be a marked + improvement over 2.2.0. We have spent a lot of time since the + last release looking at the tickets that have been submitted + and many of them have been closed. + + Stu: I haven't NEWS'd in a while. I haven't actually done much for + too long also, maybe I'll find some time soon. This release is + basically what 2.2.0 should have been - it actually compiles this + time. + 2.2.0 (9/13/2007): Sean: 2.2.0 contains the results of several major Google Summer of Code branches bringing some new, extraordinary features. We
--- a/autogen.sh Mon Oct 01 17:02:03 2007 +0000 +++ b/autogen.sh Mon Oct 01 17:49:01 2007 +0000 @@ -58,7 +58,7 @@ done libtoolize -c -f --automake -glib-gettextize --force --copy --previous +glib-gettextize --force --copy intltoolize --force --copy aclocal $ACLOCAL_FLAGS || exit; autoheader || exit;
--- a/configure.ac Mon Oct 01 17:02:03 2007 +0000 +++ b/configure.ac Mon Oct 01 17:49:01 2007 +0000 @@ -46,7 +46,7 @@ m4_define([purple_lt_current], [2]) m4_define([purple_major_version], [2]) m4_define([purple_minor_version], [2]) -m4_define([purple_micro_version], [0]) +m4_define([purple_micro_version], [1]) m4_define([purple_version_suffix], []) m4_define([purple_version], [purple_major_version.purple_minor_version.purple_micro_version]) @@ -55,7 +55,7 @@ m4_define([gnt_lt_current], [2]) m4_define([gnt_major_version], [2]) m4_define([gnt_minor_version], [2]) -m4_define([gnt_micro_version], [0]) +m4_define([gnt_micro_version], [1]) m4_define([gnt_version_suffix], []) m4_define([gnt_version], [gnt_major_version.gnt_minor_version.gnt_micro_version]) @@ -136,7 +136,7 @@ ;; esac -ALL_LINGUAS="af am ar az be@latin bg bn bs ca ca@valencia cs da de dz el en_AU en_CA en_GB eo es et eu fa fi fr gl gu he hi hu id it ja ka kn ko ku lt mk my_MM nb ne nl nn pa pl pt_BR pt ps ro ru sk sl sq sr sr@Latn sv ta te th tr uk vi xh zh_CN zh_HK zh_TW" +ALL_LINGUAS="af am ar az be@latin bg bn bs ca ca@valencia cs da de dz el en_AU en_CA en_GB eo es et eu fa fi fr gl gu he hi hu id it ja ka kn ko ku lo lt mk my_MM nb ne nl nn pa pl pt_BR pt ps ro ru sk sl sq sr sr@latin sv ta te th tr uk vi xh zh_CN zh_HK zh_TW" AM_GLIB_GNU_GETTEXT dnl If we don't have msgfmt, then po/ is going to fail -- ensure that
--- a/doc/finch.1.in Mon Oct 01 17:02:03 2007 +0000 +++ b/doc/finch.1.in Mon Oct 01 17:49:01 2007 +0000 @@ -457,6 +457,11 @@ .B status for the status window. +.SH FAQ +FAQ for \fBfinch\fR is located at +.br +\fIhttp://developer.pidgin.im/wiki/Using%20Finch\fR + .SH BUGS Known bugs are listed at .br
--- a/doc/pidgin.1.in Mon Oct 01 17:02:03 2007 +0000 +++ b/doc/pidgin.1.in Mon Oct 01 17:49:01 2007 +0000 @@ -140,7 +140,7 @@ If \fIAuto-Login\fR is chosen, this account will automatically login upon starting Pidgin. -Each protocol has it's own specific options that can be found in the +Each protocol has its own specific options that can be found in the modify screen. .SH PREFERENCES
--- a/finch/finch.c Mon Oct 01 17:02:03 2007 +0000 +++ b/finch/finch.c Mon Oct 01 17:49:01 2007 +0000 @@ -297,6 +297,7 @@ if (opt_version) { /* Translators may want to transliterate the name. It is not to be translated. */ + gnt_quit(); printf("%s %s\n", _("Finch"), VERSION); return 0; } @@ -419,13 +420,13 @@ gnt_init(); - gnt_start(&argc, &argv); - - gnt_main(); + if (gnt_start(&argc, &argv)) { + gnt_main(); #ifdef STANDALONE - purple_core_quit(); + purple_core_quit(); #endif + } return 0; }
--- a/finch/finch.h Mon Oct 01 17:02:03 2007 +0000 +++ b/finch/finch.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,7 +1,8 @@ /** * @defgroup finch Finch (GNT User Interface) - * - * finch + */ + +/* finch * * Finch is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/finch/gntaccount.c Mon Oct 01 17:02:03 2007 +0000 +++ b/finch/gntaccount.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gntaccount.c GNT Account API * @ingroup finch - * - * finch + */ + +/* finch * * Finch is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/finch/gntaccount.h Mon Oct 01 17:02:03 2007 +0000 +++ b/finch/gntaccount.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gntaccount.h GNT Account API * @ingroup finch - * - * finch + */ + +/* finch * * Finch is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/finch/gntblist.c Mon Oct 01 17:02:03 2007 +0000 +++ b/finch/gntblist.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gntblist.c GNT BuddyList API * @ingroup finch - * - * finch + */ + +/* finch * * Finch is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/finch/gntblist.h Mon Oct 01 17:02:03 2007 +0000 +++ b/finch/gntblist.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gntblist.h GNT BuddyList API * @ingroup finch - * - * finch + */ + +/* finch * * Finch is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/finch/gntcertmgr.c Mon Oct 01 17:02:03 2007 +0000 +++ b/finch/gntcertmgr.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gntcertmgr.c GNT Certificate Manager API * @ingroup finch - * - * finch + */ + +/* finch * * Finch is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/finch/gntcertmgr.h Mon Oct 01 17:02:03 2007 +0000 +++ b/finch/gntcertmgr.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gntcertmgr.h GNT Certificate Manager API * @ingroup finch - * - * finch + */ + +/* finch * * Finch is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/finch/gntconn.c Mon Oct 01 17:02:03 2007 +0000 +++ b/finch/gntconn.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gntconn.c GNT Connection API * @ingroup finch - * - * finch + */ + +/* finch * * Finch is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this @@ -104,10 +105,11 @@ { FinchAutoRecon *info; PurpleAccount *account = purple_connection_get_account(gc); - - info = g_hash_table_lookup(hash, account); + GList *list; if (!gc->wants_to_die) { + info = g_hash_table_lookup(hash, account); + if (info == NULL) { info = g_new0(FinchAutoRecon, 1); g_hash_table_insert(hash, account, info); @@ -140,6 +142,17 @@ g_free(secondary); purple_account_set_enabled(account, FINCH_UI, FALSE); } + + /* If we have any open chats, we probably want to rejoin when we get back online. */ + list = purple_get_chats(); + while (list) { + PurpleConversation *conv = list->data; + list = list->next; + if (conv->account != account || + purple_conv_chat_has_left(PURPLE_CONV_CHAT(conv))) + continue; + purple_conversation_set_data(conv, "want-to-rejoin", GINT_TO_POINTER(TRUE)); + } } static void
--- a/finch/gntconn.h Mon Oct 01 17:02:03 2007 +0000 +++ b/finch/gntconn.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gntconn.h GNT Connection API * @ingroup finch - * - * finch + */ + +/* finch * * Finch is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/finch/gntconv.c Mon Oct 01 17:02:03 2007 +0000 +++ b/finch/gntconv.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gntconv.c GNT Conversation API * @ingroup finch - * - * finch + */ + +/* finch * * Finch is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this @@ -310,13 +311,41 @@ static void account_signed_on_off(PurpleConnection *gc, gpointer null) { - GList *ims = purple_get_ims(); - while (ims) { - PurpleConversation *conv = ims->data; + GList *list = purple_get_ims(); + while (list) { + PurpleConversation *conv = list->data; PurpleConversation *cc = find_conv_with_contact(conv->account, conv->name); if (cc) generate_send_to_menu(cc->ui_data); - ims = ims->next; + list = list->next; + } + + if (PURPLE_CONNECTION_IS_CONNECTED(gc)) { + /* We just signed on. Let's see if there's any chat that we have open, + * and hadn't left before the disconnect. */ + list = purple_get_chats(); + while (list) { + PurpleConversation *conv = list->data; + gboolean del = FALSE; + PurpleChat *chat; + + list = list->next; + if (conv->account != gc->account || + !purple_conversation_get_data(conv, "want-to-rejoin")) + continue; + + chat = purple_blist_find_chat(conv->account, conv->name); + if (chat == NULL) { + GHashTable *hash = NULL; + if (PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info_defaults != NULL) + hash = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info_defaults(gc, conv->name); + chat = purple_chat_new(gc->account, conv->name, hash); + del = TRUE; + } + serv_join_chat(gc, chat->components); + if (del) + purple_blist_remove_chat(chat); + } } }
--- a/finch/gntconv.h Mon Oct 01 17:02:03 2007 +0000 +++ b/finch/gntconv.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gntconv.h GNT Conversation API * @ingroup finch - * - * finch + */ + +/* finch * * Finch is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/finch/gntdebug.c Mon Oct 01 17:02:03 2007 +0000 +++ b/finch/gntdebug.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gntdebug.c GNT Debug API * @ingroup finch - * - * finch + */ + +/* finch * * Finch is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/finch/gntdebug.h Mon Oct 01 17:02:03 2007 +0000 +++ b/finch/gntdebug.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gntdebug.h GNT Debug API * @ingroup finch - * - * finch + */ + +/* finch * * Finch is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/finch/gntft.c Mon Oct 01 17:02:03 2007 +0000 +++ b/finch/gntft.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gntft.c GNT File Transfer UI * @ingroup finch - * - * finch + */ + +/* finch * * Finch is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/finch/gntft.h Mon Oct 01 17:02:03 2007 +0000 +++ b/finch/gntft.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gntft.h GNT File Transfer UI * @ingroup finch - * - * finch + */ + +/* finch * * Finch is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/finch/gntidle.h Mon Oct 01 17:02:03 2007 +0000 +++ b/finch/gntidle.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gntidle.h GNT Idle API * @ingroup finch - * - * finch + */ + +/* finch * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/finch/gntnotify.c Mon Oct 01 17:02:03 2007 +0000 +++ b/finch/gntnotify.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gntnotify.c GNT Notify API * @ingroup finch - * - * finch + */ + +/* finch * * Finch is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this @@ -351,14 +352,17 @@ gnt_box_add_widget(GNT_BOX(window), gnt_label_new_with_format(secondary, GNT_TEXT_FLAG_NORMAL)); - columns = purple_notify_searchresults_get_columns_count(results); + columns = g_list_length(results->columns); tree = gnt_tree_new_with_columns(columns); gnt_tree_set_show_title(GNT_TREE(tree), TRUE); gnt_box_add_widget(GNT_BOX(window), tree); - for (i = 0; i < columns; i++) - gnt_tree_set_column_title(GNT_TREE(tree), i, - purple_notify_searchresults_column_get_title(results, i)); + i = 0; + for (iter = results->columns; iter; iter = iter->next) + { + gnt_tree_set_column_title(GNT_TREE(tree), i, iter->data); + i++; + } box = gnt_hbox_new(TRUE);
--- a/finch/gntnotify.h Mon Oct 01 17:02:03 2007 +0000 +++ b/finch/gntnotify.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gntnotify.h GNT Notify API * @ingroup finch - * - * finch + */ + +/* finch * * Finch is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/finch/gntplugin.c Mon Oct 01 17:02:03 2007 +0000 +++ b/finch/gntplugin.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gntplugin.c GNT Plugins API * @ingroup finch - * - * finch + */ + +/* finch * * Finch is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/finch/gntplugin.h Mon Oct 01 17:02:03 2007 +0000 +++ b/finch/gntplugin.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gntplugin.h GNT Plugins API * @ingroup finch - * - * finch + */ + +/* finch * * Finch is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/finch/gntpounce.c Mon Oct 01 17:02:03 2007 +0000 +++ b/finch/gntpounce.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gntpounce.c GNT Buddy Pounce API * @ingroup finch - * - * finch + */ + +/* finch * * Finch is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/finch/gntpounce.h Mon Oct 01 17:02:03 2007 +0000 +++ b/finch/gntpounce.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gntpounce.h GNT Buddy Pounce API * @ingroup finch - * - * finch + */ + +/* finch * * Finch is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/finch/gntprefs.c Mon Oct 01 17:02:03 2007 +0000 +++ b/finch/gntprefs.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gntprefs.c GNT Preferences API * @ingroup finch - * - * finch + */ + +/* finch * * Finch is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/finch/gntprefs.h Mon Oct 01 17:02:03 2007 +0000 +++ b/finch/gntprefs.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gntprefs.h GNT Preferences API * @ingroup finch - * - * finch + */ + +/* finch * * Finch is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/finch/gntrequest.c Mon Oct 01 17:02:03 2007 +0000 +++ b/finch/gntrequest.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gntrequest.c GNT Request API * @ingroup finch - * - * finch + */ + +/* finch * * Finch is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/finch/gntrequest.h Mon Oct 01 17:02:03 2007 +0000 +++ b/finch/gntrequest.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gntrequest.h GNT Request API * @ingroup finch - * - * finch + */ + +/* finch * * Finch is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/finch/gntsound.c Mon Oct 01 17:02:03 2007 +0000 +++ b/finch/gntsound.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gntsound.c GNT Sound API * @ingroup finch - * - * finch + */ + +/* finch * * Finch is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/finch/gntsound.h Mon Oct 01 17:02:03 2007 +0000 +++ b/finch/gntsound.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gntsound.h GNT Sound API * @ingroup finch - * - * finch + */ + +/* finch * * Finch is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/finch/gntstatus.c Mon Oct 01 17:02:03 2007 +0000 +++ b/finch/gntstatus.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gntstatus.c GNT Status API * @ingroup finch - * - * finch + */ + +/* finch * * Finch is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/finch/gntstatus.h Mon Oct 01 17:02:03 2007 +0000 +++ b/finch/gntstatus.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gntstatus.h GNT Status API * @ingroup finch - * - * finch + */ + +/* finch * * Finch is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/finch/libgnt/gntentry.c Mon Oct 01 17:02:03 2007 +0000 +++ b/finch/libgnt/gntentry.c Mon Oct 01 17:49:01 2007 +0000 @@ -100,6 +100,15 @@ return changed; } +static int +max_common_prefix(const char *s, const char *t) +{ + const char *f = s; + while (*f && *t && *f == *t++) + f++; + return f - s; +} + static gboolean show_suggest_dropdown(GntEntry *entry) { @@ -110,6 +119,7 @@ GList *iter; const char *text = NULL; const char *sgst = NULL; + int max = -1; if (entry->word) { @@ -121,14 +131,13 @@ else suggest = g_strdup(entry->start); len = strlen(suggest); /* Don't need to use the utf8-function here */ - + if (entry->ddown == NULL) { GntWidget *box = gnt_vbox_new(FALSE); entry->ddown = gnt_tree_new(); gnt_tree_set_compare_func(GNT_TREE(entry->ddown), (GCompareFunc)g_utf8_collate); gnt_box_add_widget(GNT_BOX(box), entry->ddown); - /* XXX: Connect to the "activate" signal for the dropdown tree */ GNT_WIDGET_SET_FLAGS(box, GNT_WIDGET_TRANSIENT); @@ -151,6 +160,10 @@ gnt_tree_create_row(GNT_TREE(entry->ddown), text), NULL, NULL); count++; + if (max == -1) + max = strlen(text) - len; + else if (max) + max = MIN(max, max_common_prefix(sgst + len, text + len)); sgst = text; } } @@ -163,6 +176,17 @@ destroy_suggest(entry); return complete_suggest(entry, sgst); } else { + if (max > 0) { + GntWidget *ddown = entry->ddown; + char *match = g_strndup(sgst + len, max); + entry->ddown = NULL; + gnt_entry_key_pressed(GNT_WIDGET(entry), match); + g_free(match); + if (entry->ddown) + gnt_widget_destroy(ddown); + else + entry->ddown = ddown; + } gnt_widget_draw(entry->ddown->parent); }
--- a/finch/libgnt/gntmain.c Mon Oct 01 17:02:03 2007 +0000 +++ b/finch/libgnt/gntmain.c Mon Oct 01 17:49:01 2007 +0000 @@ -409,7 +409,8 @@ case SIGWINCH: erase(); g_idle_add(refresh_screen, NULL); - org_winch_handler(sig); + if (org_winch_handler) + org_winch_handler(sig); signal(SIGWINCH, sighandler); break; #endif
--- a/finch/libgnt/gntstyle.c Mon Oct 01 17:02:03 2007 +0000 +++ b/finch/libgnt/gntstyle.c Mon Oct 01 17:49:01 2007 +0000 @@ -26,7 +26,6 @@ #include <glib.h> #include <ctype.h> -#include <glib/gprintf.h> #include <stdlib.h> #include <string.h>
--- a/finch/libgnt/gntwm.c Mon Oct 01 17:02:03 2007 +0000 +++ b/finch/libgnt/gntwm.c Mon Oct 01 17:49:01 2007 +0000 @@ -27,8 +27,8 @@ #include "config.h" +#include <glib.h> #include <ctype.h> -#include <glib/gprintf.h> #include <gmodule.h> #include <stdlib.h> #include <string.h>
--- a/finch/plugins/lastlog.c Mon Oct 01 17:02:03 2007 +0000 +++ b/finch/plugins/lastlog.c Mon Oct 01 17:49:01 2007 +0000 @@ -96,6 +96,7 @@ { cmd = purple_cmd_register("lastlog", "s", PURPLE_CMD_P_DEFAULT, PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_IM, NULL, + /* Translator Note: The "backlog" is the conversation buffer/history. */ lastlog_cb, _("lastlog: Searches for a substring in the backlog."), NULL); return TRUE; }
--- a/libpurple/account.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/account.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file account.c Account API * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this @@ -916,7 +917,7 @@ purple_account_set_register_callback(PurpleAccount *account, PurpleAccountRegistrationCb cb, void *user_data) { g_return_if_fail(account != NULL); - + account->registration_cb = cb; account->registration_cb_user_data = user_data; } @@ -936,10 +937,10 @@ purple_account_unregister(PurpleAccount *account, PurpleAccountUnregistrationCb cb, void *user_data) { g_return_if_fail(account != NULL); - + purple_debug_info("account", "Unregistering account %s\n", purple_account_get_username(account)); - + purple_connection_new_unregister(account, purple_account_get_password(account), cb, user_data); } @@ -959,13 +960,21 @@ } if(remember) - purple_account_set_remember_password(account, TRUE); + purple_account_set_remember_password(account, TRUE); purple_account_set_password(account, entry); purple_connection_new(account, FALSE, entry); } +static void +request_password_cancel_cb(PurpleAccount *account, PurpleRequestFields *fields) +{ + /* Disable the account as the user has canceled connecting */ + purple_account_set_enabled(account, purple_core_get_ui(), FALSE); +} + + void purple_account_request_password(PurpleAccount *account, GCallback ok_cb, GCallback cancel_cb, void *user_data) @@ -1039,7 +1048,7 @@ if ((password == NULL) && !(prpl_info->options & OPT_PROTO_NO_PASSWORD) && !(prpl_info->options & OPT_PROTO_PASSWORD_OPTIONAL)) - purple_account_request_password(account, G_CALLBACK(request_password_ok_cb), NULL, account); + purple_account_request_password(account, G_CALLBACK(request_password_ok_cb), G_CALLBACK(request_password_cancel_cb), account); else purple_connection_new(account, FALSE, password); } @@ -1110,18 +1119,18 @@ g_free(info); } -void +void purple_account_request_close_with_account(PurpleAccount *account) { GList *l, *l_next; - + g_return_if_fail(account != NULL); - + for (l = handles; l != NULL; l = l_next) { PurpleAccountRequestInfo *info = l->data; - + l_next = l->next; - + if (info->account == account) { handles = g_list_remove(handles, info); purple_account_request_close_info(info); @@ -1129,18 +1138,18 @@ } } -void +void purple_account_request_close(void *ui_handle) { GList *l, *l_next; - + g_return_if_fail(ui_handle != NULL); - + for (l = handles; l != NULL; l = l_next) { PurpleAccountRequestInfo *info = l->data; - + l_next = l->next; - + if (info->ui_handle == ui_handle) { handles = g_list_remove(handles, info); purple_account_request_close_info(info); @@ -1171,7 +1180,7 @@ handles = g_list_append(handles, info); return info->ui_handle; } - + return NULL; } @@ -2442,7 +2451,7 @@ purple_value_new(PURPLE_TYPE_SUBTYPE, PURPLE_SUBTYPE_ACCOUNT), purple_value_new(PURPLE_TYPE_STRING)); - + load_accounts(); }
--- a/libpurple/account.h Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/account.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file account.h Account API * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/accountopt.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/accountopt.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file accountopt.c Account Options API * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/accountopt.h Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/accountopt.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file accountopt.h Account Options API * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this @@ -49,8 +50,10 @@ } default_value; - gboolean masked; - + gboolean masked; /**< Whether the value entered should be + * obscured from view (for passwords and + * similar options) + */ } PurpleAccountOption; /** @@ -184,10 +187,12 @@ const char *value); /** - * Sets the masking for an account option. + * Sets the masking for an account option. Setting this to %TRUE acts + * as a hint to the UI that the option's value should be obscured from + * view, like a password. * * @param option The account option. - * @param masked The masking. + * @param masked The masking. */ void purple_account_option_set_masked(PurpleAccountOption *option, gboolean masked); @@ -282,11 +287,13 @@ const PurpleAccountOption *option); /** - * Returns the masking for an account option. + * Returns whether an option's value should be masked from view, like a + * password. If so, the UI might display each character of the option + * as a '*' (for example). * * @param option The account option. * - * @return The masking. + * @return %TRUE if the option's value should be obscured. */ gboolean purple_account_option_get_masked(const PurpleAccountOption *option);
--- a/libpurple/blist.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/blist.c Mon Oct 01 17:49:01 2007 +0000 @@ -843,6 +843,13 @@ ops->update(purplebuddylist, (PurpleBlistNode *)buddy); } +static gboolean +purple_strings_are_different(const char *one, const char *two) +{ + return !((one && two && g_utf8_collate(one, two) == 0) || + ((one == NULL || *one == '\0') && (two == NULL || *two == '\0'))); +} + void purple_blist_alias_contact(PurpleContact *contact, const char *alias) { PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); @@ -852,6 +859,9 @@ g_return_if_fail(contact != NULL); + if (!purple_strings_are_different(contact->alias, alias)) + return; + old_alias = contact->alias; if ((alias != NULL) && (*alias != '\0')) @@ -886,6 +896,9 @@ g_return_if_fail(chat != NULL); + if (!purple_strings_are_different(chat->alias, alias)) + return; + old_alias = chat->alias; if ((alias != NULL) && (*alias != '\0')) @@ -911,6 +924,9 @@ g_return_if_fail(buddy != NULL); + if (!purple_strings_are_different(buddy->alias, alias)) + return; + old_alias = buddy->alias; if ((alias != NULL) && (*alias != '\0')) @@ -941,6 +957,9 @@ g_return_if_fail(buddy != NULL); + if (!purple_strings_are_different(buddy->server_alias, alias)) + return; + old_alias = buddy->server_alias; if ((alias != NULL) && (*alias != '\0') && g_utf8_validate(alias, -1, NULL)) @@ -1428,6 +1447,9 @@ g_return_if_fail(contact != NULL); + if (!purple_strings_are_different(contact->alias, alias)) + return; + old_alias = contact->alias; if ((alias != NULL) && (*alias != '\0'))
--- a/libpurple/blist.h Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/blist.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file blist.h Buddy List API * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/buddyicon.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/buddyicon.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file icon.c Buddy Icon API * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/buddyicon.h Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/buddyicon.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file buddyicon.h Buddy Icon API * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/certificate.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/certificate.c Mon Oct 01 17:49:01 2007 +0000 @@ -540,7 +540,7 @@ /* Determine whether the name matches */ if (purple_certificate_check_subject_name(crt, vrq->subject_name)) { - cn_match = _(""); + cn_match = ""; } else { cn_match = _("(DOES NOT MATCH)"); } @@ -1460,15 +1460,14 @@ tls_peers = purple_certificate_find_pool(x509_tls_cached.scheme_name,tls_peers_name); - /* TODO: This should probably just prompt the user instead of throwing - an angry fit */ if (!tls_peers) { purple_debug_error("certificate/x509/tls_cached", - "Couldn't find local peers cache %s\nReturning INVALID to callback\n", + "Couldn't find local peers cache %s\nPrompting the user\n", tls_peers_name); - purple_certificate_verify_complete(vrq, - PURPLE_CERTIFICATE_INVALID); + + /* vrq now becomes the problem of unknown_peer */ + x509_tls_cached_unknown_peer(vrq); return; }
--- a/libpurple/cipher.h Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/cipher.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file cipher.h Purple Cipher API * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/circbuffer.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/circbuffer.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /* * @file circbuffer.h Buffer Utility Functions * @ingroup core - * - * Purple is the legal property of its developers, whose names are too numerous + */ + +/* Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this * source distribution. *
--- a/libpurple/circbuffer.h Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/circbuffer.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ -/* +/** * @file circbuffer.h Buffer Utility Functions * @ingroup core - * - * Purple is the legal property of its developers, whose names are too numerous + */ + +/* Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this * source distribution. *
--- a/libpurple/cmds.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/cmds.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file cmds.c Commands API * @ingroup core - * - * Copyright (C) 2003-2004 Timothy Ringenbach <omarvo@hotmail.com + */ + +/* Copyright (C) 2003-2004 Timothy Ringenbach <omarvo@hotmail.com * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by
--- a/libpurple/cmds.h Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/cmds.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file cmds.h Commands API * @ingroup core - * - * Copyright (C) 2003 Timothy Ringenbach <omarvo@hotmail.com> + */ + +/* Copyright (C) 2003 Timothy Ringenbach <omarvo@hotmail.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -66,10 +67,20 @@ PURPLE_CMD_P_VERY_HIGH = 6000, }; +/** Flags used to set various properties of commands. Every command should + * have at least one of #PURPLE_CMD_FLAG_IM and #PURPLE_CMD_FLAG_CHAT set in + * order to be even slighly useful. + * + * @see purple_cmd_register + */ enum _PurpleCmdFlag { + /** Command is usable in IMs. */ PURPLE_CMD_FLAG_IM = 0x01, + /** Command is usable in multi-user chats. */ PURPLE_CMD_FLAG_CHAT = 0x02, + /** Command is usable only for a particular prpl. */ PURPLE_CMD_FLAG_PRPL_ONLY = 0x04, + /** Incorrect arguments to this command should be accepted anyway. */ PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS = 0x08, }; @@ -91,36 +102,49 @@ * The command will only happen if commands are enabled, * which is a UI pref. UIs don't have to support commands at all. * - * @param cmd The command. This should be a UTF8 (or ASCII) string, with no spaces + * @param cmd The command. This should be a UTF-8 (or ASCII) string, with no spaces * or other white space. - * @param args This tells Purple how to parse the arguments to the command for you. - * If what the user types doesn't match, Purple will keep looking for another - * command, unless the flag @c PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS is passed in f. - * This string contains no whitespace, and uses a single character for each argument. - * The recognized characters are: - * 'w' Matches a single word. - * 'W' Matches a single word, with formatting. - * 's' Matches the rest of the arguments after this point, as a single string. - * 'S' Same as 's' but with formatting. + * @param args A string of characters describing to libpurple how to parse this + * command's arguments. If what the user types doesn't match this + * pattern, libpurple will keep looking for another command, unless + * the flag #PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS is passed in @a f. + * This string should contain no whitespace, and use a single + * character for each argument. The recognized characters are: + * <ul> + * <li><tt>'w'</tt>: Matches a single word.</li> + * <li><tt>'W'</tt>: Matches a single word, with formatting.</li> + * <li><tt>'s'</tt>: Matches the rest of the arguments after this + * point, as a single string.</li> + * <li><tt>'S'</tt>: Same as <tt>'s'</tt> but with formatting.</li> + * </ul> * If args is the empty string, then the command accepts no arguments. - * The args passed to callback func will be a @c NULL terminated array of null - * terminated strings, and will always match the number of arguments asked for, - * unless PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS is passed. - * @param p This is the priority. Higher priority commands will be run first, and usually the - * first command will stop any others from being called. - * @param f These are the flags. You need to at least pass one of PURPLE_CMD_FLAG_IM or - * PURPLE_CMD_FLAG_CHAT (can may pass both) in order for the command to ever actually - * be called. - * @param prpl_id This is the prpl's id string. This is only meaningful if the proper flag is set. + * The args passed to the callback @a func will be a @c NULL + * terminated array of @c NULL terminated strings, and will always + * match the number of arguments asked for, unless + * #PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS is passed. + * @param p This is the priority. Higher priority commands will be run first, + * and usually the first command will stop any others from being + * called. + * @param f Flags specifying various options about this command, combined with + * <tt>|</tt> (bitwise OR). You need to at least pass one of + * #PURPLE_CMD_FLAG_IM or #PURPLE_CMD_FLAG_CHAT (you may pass both) in + * order for the command to ever actually be called. + * @param prpl_id If the #PURPLE_CMD_FLAG_PRPL_ONLY flag is set, this is the id + * of the prpl to which the command applies (such as + * <tt>"prpl-msn"</tt>). If the flag is not set, this parameter + * is ignored; pass @c NULL (or a humourous string of your + * choice!). * @param func This is the function to call when someone enters this command. - * @param helpstr This is a whitespace sensitive, UTF-8, HTML string describing how to use the command. - * The preferred format of this string shall be the commands name, followed by a space - * and any arguments it accepts (if it takes any arguments, otherwise no space), followed - * by a colon, two spaces, and a description of the command in sentence form. No slash - * before the command name. - * @param data User defined data to pass to the PurpleCmdFunc - * @return A PurpleCmdId. This is only used for calling purple_cmd_unregister. - * Returns 0 on failure. + * @param helpstr a whitespace sensitive, UTF-8, HTML string describing how to + * use the command. The preferred format of this string is the + * command's name, followed by a space and any arguments it + * accepts (if it takes any arguments, otherwise no space), + * followed by a colon, two spaces, and a description of the + * command in sentence form. Do not include a slash before the + * command name. + * @param data User defined data to pass to the #PurpleCmdFunc @a f. + * @return A #PurpleCmdId, which is only used for calling + * #purple_cmd_unregister, or @a 0 on failure. */ PurpleCmdId purple_cmd_register(const gchar *cmd, const gchar *args, PurpleCmdPriority p, PurpleCmdFlag f, const gchar *prpl_id, PurpleCmdFunc func, const gchar *helpstr, void *data); @@ -132,7 +156,7 @@ * or something else that might go away. Normally this is called when the plugin * unloads itself. * - * @param id The PurpleCmdId to unregister. + * @param id The #PurpleCmdId to unregister, as returned by #purple_cmd_register. */ void purple_cmd_unregister(PurpleCmdId id); @@ -152,7 +176,7 @@ * include both the default formatting and any extra manual formatting. * @param errormsg If the command failed errormsg is filled in with the appropriate error * message. It must be freed by the caller with g_free(). - * @return A PurpleCmdStatus indicated if the command succeeded or failed. + * @return A #PurpleCmdStatus indicated if the command succeeded or failed. */ PurpleCmdStatus purple_cmd_do_command(PurpleConversation *conv, const gchar *cmdline, const gchar *markup, gchar **errormsg); @@ -160,13 +184,15 @@ /** * List registered commands. * - * Returns a GList (which must be freed by the caller) of all commands - * that are valid in the context of conv, or all commands, if conv is - * @c NULL. Don't keep this list around past the main loop, or anything else - * that might unregister a command, as the char*'s used get freed then. + * Returns a <tt>GList</tt> (which must be freed by the caller) of all commands + * that are valid in the context of @a conv, or all commands, if @a conv is @c + * NULL. Don't keep this list around past the main loop, or anything else that + * might unregister a command, as the <tt>const char *</tt>'s used get freed + * then. * * @param conv The conversation, or @c NULL. - * @return A GList of const char*, which must be freed with g_list_free(). + * @return A @c GList of <tt>const char *</tt>, which must be freed with + * <tt>g_list_free()</tt>. */ GList *purple_cmd_list(PurpleConversation *conv); @@ -179,7 +205,7 @@ * @param conv The conversation, or @c NULL for no context. * @param cmd The command. No wildcards accepted, but returns help for all * commands if @c NULL. - * @return A GList of const char*s, which is the help string + * @return A <tt>GList</tt> of <tt>const char *</tt>s, which is the help string * for that command. */ GList *purple_cmd_help(PurpleConversation *conv, const gchar *cmd);
--- a/libpurple/connection.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/connection.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file connection.c Connection API * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/connection.h Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/connection.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file connection.h Connection API * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/conversation.h Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/conversation.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file conversation.h Conversation API * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/core.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/core.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file core.c Purple Core API * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/core.h Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/core.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,7 +1,8 @@ /** * @defgroup core libpurple - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/dbus-bindings.h Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/dbus-bindings.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file dbus-bindings.h Purple DBUS Bindings * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/dbus-server.h Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/dbus-server.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file dbus-server.h Purple DBUS Server * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/debug.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/debug.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file debug.c Debug API * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/debug.h Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/debug.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file debug.h Debug API * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/desktopitem.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/desktopitem.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file purple-desktop-item.c Functions for managing .desktop files * @ingroup core - * - * Purple is the legal property of its developers, whose names are too numerous + */ + +/* Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this * source distribution. *
--- a/libpurple/desktopitem.h Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/desktopitem.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file desktopitem.h Functions for managing .desktop files * @ingroup core - * - * Purple is the legal property of its developers, whose names are too numerous + */ + +/* Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this * source distribution. *
--- a/libpurple/dnsquery.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/dnsquery.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file dnsquery.c DNS query API * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/dnsquery.h Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/dnsquery.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file dnsquery.h DNS query API * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/dnssrv.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/dnssrv.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,7 +1,8 @@ /** * @file dnssrv.c - * - * purple + */ + +/* purple * * Copyright (C) 2005 Thomas Butter <butter@uni-mannheim.de> *
--- a/libpurple/dnssrv.h Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/dnssrv.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,10 +1,11 @@ /** * @file dnssrv.h - * - * purple + */ + +/* purple * * Copyright (C) 2005, Thomas Butter <butter@uni-mannheim.de> - *i + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or
--- a/libpurple/eventloop.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/eventloop.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file eventloop.c Purple Event Loop API * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/eventloop.h Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/eventloop.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file eventloop.h Purple Event Loop API * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/ft.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/ft.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,7 +1,8 @@ /** * @file ft.c File Transfer API - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/ft.h Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/ft.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file ft.h File Transfer API * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/gaim-compat.h Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/gaim-compat.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gaim-compat.h Gaim Compat macros * @ingroup core - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/idle.h Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/idle.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file idle.h Idle API * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/imgstore.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/imgstore.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file imgstore.h IM Image Store API * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/imgstore.h Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/imgstore.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file imgstore.h IM Image Store API * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/internal.h Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/internal.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file internal.h Internal definitions and includes * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/log.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/log.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file log.c Logging API * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/log.h Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/log.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file log.h Logging API * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/nat-pmp.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/nat-pmp.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file nat-pmp.c NAT-PMP Implementation * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/nat-pmp.h Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/nat-pmp.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file nat-pmp.h NAT-PMP Implementation * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/network.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/network.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file network.c Network Implementation * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/network.h Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/network.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file network.h Network API * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/notify.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/notify.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file notify.c Notification API * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/notify.h Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/notify.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file notify.h Notification API * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this @@ -292,7 +293,17 @@ /** * Returns a number of the rows in the search results object. - * + * + * @deprecated This function will be removed in Pidgin 3.0.0 unless + * there is sufficient demand to keep it. Using this + * function encourages looping through the results + * inefficiently. Instead of using this function you + * should iterate through the results using a loop + * similar to this: + * for (l = results->rows; l != NULL; l = l->next) + * If you really need to get the number of rows you + * can use g_list_length(results->rows). + * * @param results The search results object. * * @return Number of the result rows. @@ -302,6 +313,16 @@ /** * Returns a number of the columns in the search results object. * + * @deprecated This function will be removed in Pidgin 3.0.0 unless + * there is sufficient demand to keep it. Using this + * function encourages looping through the columns + * inefficiently. Instead of using this function you + * should iterate through the columns using a loop + * similar to this: + * for (l = results->columns; l != NULL; l = l->next) + * If you really need to get the number of columns you + * can use g_list_length(results->columns). + * * @param results The search results object. * * @return Number of the columns. @@ -311,6 +332,16 @@ /** * Returns a row of the results from the search results object. * + * @deprecated This function will be removed in Pidgin 3.0.0 unless + * there is sufficient demand to keep it. Using this + * function encourages looping through the results + * inefficiently. Instead of using this function you + * should iterate through the results using a loop + * similar to this: + * for (l = results->rows; l != NULL; l = l->next) + * If you really need to get the data for a particular + * row you can use g_list_nth_data(results->rows, row_id). + * * @param results The search results object. * @param row_id Index of the row to be returned. * @@ -321,7 +352,15 @@ /** * Returns a title of the search results object's column. - * + * + * @deprecated This function will be removed in Pidgin 3.0.0 unless + * there is sufficient demand to keep it. Using this + * function encourages looping through the columns + * inefficiently. Instead of using this function you + * should iterate through the name of a particular + * column you can use + * g_list_nth_data(results->columns, row_id). + * * @param results The search results object. * @param column_id Index of the column. *
--- a/libpurple/ntlm.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/ntlm.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,7 +1,8 @@ /** * @file ntlm.c - * - * purple + */ + +/* purple * * Copyright (C) 2005 Thomas Butter <butter@uni-mannheim.de> *
--- a/libpurple/ntlm.h Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/ntlm.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,7 +1,8 @@ /** * @file ntlm.h - * - * purple + */ + +/* purple * * Copyright (C) 2005, Thomas Butter <butter@uni-mannheim.de> *
--- a/libpurple/plugin.h Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/plugin.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file plugin.h Plugin API * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/pluginpref.h Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/pluginpref.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file pluginpref.h Plugin Preferences API * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/plugins/debug_example.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/plugins/debug_example.c Mon Oct 01 17:49:01 2007 +0000 @@ -27,6 +27,16 @@ /* We're including glib.h again for the gboolean type. */ #include <glib.h> +/* This will prevent compiler errors in some instances and is better explained in the + * how-to documents on the wiki */ +#ifndef G_GNUC_NULL_TERMINATED +# if __GNUC__ >= 4 +# define G_GNUC_NULL_TERMINATED __attribute__((__sentinel__)) +# else +# define G_GNUC_NULL_TERMINATED +# endif +#endif + /* This is the required definition of PURPLE_PLUGINS as required for a plugin, * but we protect it with an #ifndef because config.h may define it for us * already and this would cause an unneeded compiler warning. */
--- a/libpurple/plugins/helloworld.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/plugins/helloworld.c Mon Oct 01 17:49:01 2007 +0000 @@ -33,6 +33,16 @@ #include <glib.h> +/* This will prevent compiler errors in some instances and is better explained in the + * how-to documents on the wiki */ +#ifndef G_GNUC_NULL_TERMINATED +# if __GNUC__ >= 4 +# define G_GNUC_NULL_TERMINATED __attribute__((__sentinel__)) +# else +# define G_GNUC_NULL_TERMINATED +# endif +#endif + #include <notify.h> #include <plugin.h> #include <version.h>
--- a/libpurple/plugins/notify_example.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/plugins/notify_example.c Mon Oct 01 17:49:01 2007 +0000 @@ -26,6 +26,16 @@ #include <glib.h> +/* This will prevent compiler errors in some instances and is better explained in the + * how-to documents on the wiki */ +#ifndef G_GNUC_NULL_TERMINATED +# if __GNUC__ >= 4 +# define G_GNUC_NULL_TERMINATED __attribute__((__sentinel__)) +# else +# define G_GNUC_NULL_TERMINATED +# endif +#endif + /* This is the required definition of PURPLE_PLUGINS as required for a plugin, * but we protect it with an #ifndef because config.h may define it for us * already and this would cause an unneeded compiler warning. */
--- a/libpurple/plugins/ssl/ssl-gnutls.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/plugins/ssl/ssl-gnutls.c Mon Oct 01 17:49:01 2007 +0000 @@ -111,7 +111,7 @@ PurpleSslGnutlsData *gnutls_data = PURPLE_SSL_GNUTLS_DATA(gsc); ssize_t ret; - purple_debug_info("gnutls", "Handshaking with %s\n", gsc->host); + /*purple_debug_info("gnutls", "Handshaking with %s\n", gsc->host);*/ ret = gnutls_handshake(gnutls_data->session); if(ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED) @@ -163,9 +163,9 @@ g_list_free(peers); { - const gnutls_datum_t *cert_list; + const gnutls_datum *cert_list; unsigned int cert_list_size = 0; - gnutls_session_t session=gnutls_data->session; + gnutls_session session=gnutls_data->session; int i; cert_list = @@ -182,7 +182,7 @@ gchar tbuf[256]; gsize tsz=sizeof(tbuf); gchar * tasc = NULL; - gnutls_x509_crt_t cert; + gnutls_x509_crt cert; gnutls_x509_crt_init(&cert); gnutls_x509_crt_import (cert, &cert_list[i], @@ -271,6 +271,8 @@ gnutls_data->handshake_handler = purple_input_add(gsc->fd, PURPLE_INPUT_READ, ssl_gnutls_handshake_cb, gsc); + purple_debug_info("gnutls", "Starting handshake with %s\n", gsc->host); + /* Orborde asks: Why are we configuring a callback, then immediately calling it? @@ -363,7 +365,7 @@ /* Forward declarations are fun! */ static PurpleCertificate * -x509_import_from_datum(const gnutls_datum_t dt, gnutls_x509_crt_fmt_t mode); +x509_import_from_datum(const gnutls_datum dt, gnutls_x509_crt_fmt mode); static GList * ssl_gnutls_get_peer_certificates(PurpleSslConnection * gsc) @@ -374,7 +376,7 @@ GList * peer_certs = NULL; /* List of raw certificates as given by GnuTLS */ - const gnutls_datum_t *cert_list; + const gnutls_datum *cert_list; unsigned int cert_list_size = 0; unsigned int i; @@ -412,7 +414,7 @@ /** Refcounted GnuTLS certificate data instance */ typedef struct { gint refcount; - gnutls_x509_crt_t crt; + gnutls_x509_crt crt; } x509_crtdata_t; /** Helper functions for reference counting */ @@ -434,9 +436,6 @@ /* If the refcount reaches zero, kill the structure */ if (cd->refcount <= 0) { - purple_debug_info("gnutls/x509", - "Freeing unused cert data at %p\n", - cd); /* Kill the internal data */ gnutls_x509_crt_deinit( cd->crt ); /* And kill the struct */ @@ -447,7 +446,7 @@ /** Helper macro to retrieve the GnuTLS crt_t from a PurpleCertificate */ #define X509_GET_GNUTLS_DATA(pcrt) ( ((x509_crtdata_t *) (pcrt->data))->crt) -/** Transforms a gnutls_datum_t containing an X.509 certificate into a Certificate instance under the x509_gnutls scheme +/** Transforms a gnutls_datum containing an X.509 certificate into a Certificate instance under the x509_gnutls scheme * * @param dt Datum to transform * @param mode GnuTLS certificate format specifier (GNUTLS_X509_FMT_PEM for @@ -457,7 +456,7 @@ * @return A newly allocated Certificate structure of the x509_gnutls scheme */ static PurpleCertificate * -x509_import_from_datum(const gnutls_datum_t dt, gnutls_x509_crt_fmt_t mode) +x509_import_from_datum(const gnutls_datum dt, gnutls_x509_crt_fmt mode) { /* Internal certificate data structure */ x509_crtdata_t *certdat; @@ -492,7 +491,7 @@ PurpleCertificate *crt; /* Certificate being constructed */ gchar *buf; /* Used to load the raw file data */ gsize buf_sz; /* Size of the above */ - gnutls_datum_t dt; /* Struct to pass down to GnuTLS */ + gnutls_datum dt; /* Struct to pass down to GnuTLS */ purple_debug_info("gnutls", "Attempting to load X.509 certificate from %s\n", @@ -533,7 +532,7 @@ static gboolean x509_export_certificate(const gchar *filename, PurpleCertificate *crt) { - gnutls_x509_crt_t crt_dat; /* GnuTLS cert struct */ + gnutls_x509_crt crt_dat; /* GnuTLS cert struct */ int ret; gchar * out_buf; /* Data to output */ size_t out_size; /* Output size */ @@ -640,8 +639,8 @@ x509_certificate_signed_by(PurpleCertificate * crt, PurpleCertificate * issuer) { - gnutls_x509_crt_t crt_dat; - gnutls_x509_crt_t issuer_dat; + gnutls_x509_crt crt_dat; + gnutls_x509_crt issuer_dat; unsigned int verify; /* used to store result from GnuTLS verifier */ int ret; @@ -674,10 +673,10 @@ purple_debug_info("gnutls/x509", "Certificate for %s claims to be " "issued by %s, but the certificate " - "for %s does not match. A strcmp " - "says %d\n", - crt_id, crt_issuer_id, issuer_id, - strcmp(crt_issuer_id, issuer_id)); + "for %s does not match.\n", + crt_id ? crt_id : "(null)", + crt_issuer_id ? crt_issuer_id : "(null)", + issuer_id ? issuer_id : "(null)"); g_free(crt_id); g_free(issuer_id); g_free(crt_issuer_id); @@ -727,7 +726,7 @@ { size_t hashlen = 20; /* SHA1 hashes are 20 bytes */ size_t tmpsz = hashlen; /* Throw-away variable for GnuTLS to stomp on*/ - gnutls_x509_crt_t crt_dat; + gnutls_x509_crt crt_dat; GByteArray *hash; /**< Final hash container */ guchar hashbuf[hashlen]; /**< Temporary buffer to contain hash */ @@ -754,7 +753,7 @@ static gchar * x509_cert_dn (PurpleCertificate *crt) { - gnutls_x509_crt_t cert_dat; + gnutls_x509_crt cert_dat; gchar *dn = NULL; size_t dn_size; @@ -770,7 +769,10 @@ gnutls_x509_crt_get_dn(cert_dat, dn, &dn_size); /* Now allocate and get the Distinguished Name */ - dn = g_new0(gchar, dn_size); + /* Old versions of GnuTLS have an off-by-one error in reporting + the size of the needed buffer in some functions, so allocate + an extra byte */ + dn = g_new0(gchar, ++dn_size); if (0 != gnutls_x509_crt_get_dn(cert_dat, dn, &dn_size)) { purple_debug_error("gnutls/x509", "Failed to get Distinguished Name\n"); @@ -784,7 +786,7 @@ static gchar * x509_issuer_dn (PurpleCertificate *crt) { - gnutls_x509_crt_t cert_dat; + gnutls_x509_crt cert_dat; gchar *dn = NULL; size_t dn_size; @@ -800,7 +802,10 @@ gnutls_x509_crt_get_issuer_dn(cert_dat, dn, &dn_size); /* Now allocate and get the Distinguished Name */ - dn = g_new0(gchar, dn_size); + /* Old versions of GnuTLS have an off-by-one error in reporting + the size of the needed buffer in some functions, so allocate + an extra byte */ + dn = g_new0(gchar, ++dn_size); if (0 != gnutls_x509_crt_get_issuer_dn(cert_dat, dn, &dn_size)) { purple_debug_error("gnutls/x509", "Failed to get issuer's Distinguished " @@ -815,7 +820,7 @@ static gchar * x509_common_name (PurpleCertificate *crt) { - gnutls_x509_crt_t cert_dat; + gnutls_x509_crt cert_dat; gchar *cn = NULL; size_t cn_size; int ret; @@ -836,7 +841,10 @@ cn, &cn_size); /* Now allocate and get the Common Name */ - cn = g_new0(gchar, cn_size); + /* Old versions of GnuTLS have an off-by-one error in reporting + the size of the needed buffer in some functions, so allocate + an extra byte */ + cn = g_new0(gchar, ++cn_size); ret = gnutls_x509_crt_get_dn_by_oid(cert_dat, GNUTLS_OID_X520_COMMON_NAME, 0, /* First CN found, please */ @@ -855,7 +863,7 @@ static gboolean x509_check_name (PurpleCertificate *crt, const gchar *name) { - gnutls_x509_crt_t crt_dat; + gnutls_x509_crt crt_dat; g_return_val_if_fail(crt, FALSE); g_return_val_if_fail(crt->scheme == &x509_gnutls, FALSE); @@ -873,7 +881,7 @@ static gboolean x509_times (PurpleCertificate *crt, time_t *activation, time_t *expiration) { - gnutls_x509_crt_t crt_dat; + gnutls_x509_crt crt_dat; /* GnuTLS time functions return this on error */ const time_t errval = (time_t) (-1);
--- a/libpurple/pounce.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/pounce.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file pounce.c Buddy Pounce API * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/pounce.h Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/pounce.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file pounce.h Buddy Pounce API * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/prefs.h Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/prefs.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file prefs.h Prefs API * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/privacy.h Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/privacy.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file privacy.h Privacy API * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/protocols/jabber/.todo Mon Oct 01 17:02:03 2007 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ -<todo version="0.1.19"> - <note priority="medium" time="1036044198"> - Browsing - </note> - <note priority="medium" time="1036044416"> - Server Admin operations (messages, etc.) - </note> - <note priority="medium" time="1036044448"> - Add option for user info to be published or not in JUD. - </note> - <note priority="medium" time="1036044583"> - Delete server account. - </note> - <note priority="medium" time="1036045649"> - Permit/Deny buddy support. - </note> - <note priority="medium" time="1036046413"> - a populate roster from local blist. most useful if you want to migrate a blist from one account to another, also useful if something freaky happens and the server blist is lost. - </note> - <note priority="medium" time="1037892911"> - info - <note priority="medium" time="1037893000"> - formatted. enhancement-request so that the birthday field in the setinfo form would split up into relevant fields allowing for a strict syntax (like year--month--day or so, perhaps even dropdown menus) - </note> - </note> - <note priority="verylow" time="1036044192"> - Jabber Transports (having them show up on the buddy list should be fairly easy; having an appropriate right-click menu for them should also be somewhat easy. Providing a UI for adding transports should be rather difficult.) - </note> -</todo>
--- a/libpurple/protocols/jabber/adhoccommands.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/protocols/jabber/adhoccommands.c Mon Oct 01 17:49:01 2007 +0000 @@ -151,8 +151,11 @@ /* display result */ xmlnode *note = xmlnode_get_child(command,"note"); - if(note) - purple_notify_info(NULL, xmlnode_get_attrib(packet, "from"), xmlnode_get_data(note), NULL); + if(note) { + char *data = xmlnode_get_data(note); + purple_notify_info(NULL, xmlnode_get_attrib(packet, "from"), data, NULL); + g_free(data); + } if(xdata) jabber_x_data_request(js, xdata, (jabber_x_data_cb)do_adhoc_ignoreme, NULL);
--- a/libpurple/protocols/jabber/auth.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/protocols/jabber/auth.c Mon Oct 01 17:49:01 2007 +0000 @@ -23,6 +23,7 @@ #include "account.h" #include "debug.h" #include "cipher.h" +#include "core.h" #include "conversation.h" #include "request.h" #include "sslconn.h" @@ -66,10 +67,10 @@ auth = xmlnode_new("auth"); xmlnode_set_namespace(auth, "urn:ietf:params:xml:ns:xmpp-sasl"); - + xmlnode_set_attrib(auth, "xmlns:ga", "http://www.google.com/talk/protocol/auth"); xmlnode_set_attrib(auth, "ga:client-uses-full-bind-result", "true"); - + response = g_string_new(""); response = g_string_append_len(response, "\0", 1); response = g_string_append(response, js->user->node); @@ -202,7 +203,7 @@ return TRUE; } - + static void auth_pass_cb(PurpleConnection *conn, PurpleRequestFields *fields) { JabberStream *js; @@ -236,7 +237,7 @@ if (!auth_pass_generic(js, fields)) return; - + /* Restart our connection */ jabber_auth_start_old(js); } @@ -253,7 +254,8 @@ js = conn->proto_data; - purple_connection_error(conn, _("Password is required to sign on.")); + /* Disable the account as the user has canceled connecting */ + purple_account_set_enabled(conn->account, purple_core_get_ui(), FALSE); } static void jabber_auth_start_cyrus(JabberStream *js) @@ -621,7 +623,7 @@ * to OPTIONAL for this protocol. So, we need to do our own * password prompting here */ - + if (!purple_account_get_password(js->gc->account)) { purple_account_request_password(js->gc->account, G_CALLBACK(auth_old_pass_cb), G_CALLBACK(auth_no_pass_cb), js->gc); return;
--- a/libpurple/protocols/jabber/buddy.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/protocols/jabber/buddy.c Mon Oct 01 17:49:01 2007 +0000 @@ -1455,10 +1455,13 @@ return; img = purple_base64_decode(b64data, &size); - if(!img) + if(!img) { + g_free(b64data); return; + } purple_buddy_icons_set_for_user(purple_connection_get_account(js->gc), from, img, size, checksum); + g_free(b64data); } void jabber_buddy_avatar_update_metadata(JabberStream *js, const char *from, xmlnode *items) { @@ -1653,8 +1656,10 @@ if(!strcmp(ns, "jabber:iq:last")) { if(!strcmp(jbr->client.name, "Trillian")) { - if(!strcmp(jbr->client.version, "3.1.0.121")) { - /* verified by nwalp 2007/05/09 */ + /* verified by nwalp 2007/05/09 */ + if(!strcmp(jbr->client.version, "3.1.0.121") || + /* verified by nwalp 2007/09/19 */ + !strcmp(jbr->client.version, "3.1.7.0")) { return TRUE; } }
--- a/libpurple/protocols/jabber/google.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/protocols/jabber/google.c Mon Oct 01 17:49:01 2007 +0000 @@ -39,6 +39,8 @@ char *subject; const char *in_str; char *to_name; + char *default_tos[1]; + int i, count = 1, returned_count; const char **tos, **froms, **urls; @@ -55,15 +57,21 @@ if (in_str && *in_str) count = atoi(in_str); - if (count == 0) - return; + /* If Gmail doesn't tell us who the mail is to, let's use our JID */ + to = xmlnode_get_attrib(packet, "to"); + default_tos[0] = jabber_get_bare_jid(to); message = xmlnode_get_child(child, "mail-thread-info"); + if (count == 0 || !message) { + if (count > 0) + purple_notify_emails(js->gc, count, FALSE, NULL, NULL, (const char**) default_tos, NULL, NULL, NULL); + g_free(default_tos[0]); + return; + } + /* Loop once to see how many messages were returned so we can allocate arrays * accordingly */ - if (!message) - return; for (returned_count = 0; message; returned_count++, message=xmlnode_get_next_twin(message)); froms = g_new0(const char* , returned_count); @@ -115,9 +123,13 @@ if (i>0) purple_notify_emails(js->gc, count, count == i, (const char**) subjects, froms, tos, urls, NULL, NULL); + else + purple_notify_emails(js->gc, count, FALSE, NULL, NULL, (const char**) default_tos, NULL, NULL, NULL); + g_free(to_name); g_free(tos); + g_free(default_tos[0]); g_free(froms); for (; i > 0; i--) g_free(subjects[i - 1]); @@ -241,7 +253,8 @@ if (grt && (*grt == 'H' || *grt == 'h')) { PurpleBuddy *buddy = purple_find_buddy(account, jid_norm); - purple_blist_remove_buddy(buddy); + if (buddy) + purple_blist_remove_buddy(buddy); g_free(jid_norm); return FALSE; }
--- a/libpurple/protocols/jabber/iq.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/protocols/jabber/iq.c Mon Oct 01 17:49:01 2007 +0000 @@ -255,7 +255,7 @@ if(type && !strcmp(type, "get")) { GHashTable *ui_info; const char *ui_name = NULL, *ui_version = NULL; - +#if 0 if(!purple_prefs_get_bool("/plugins/prpl/jabber/hide_os")) { struct utsname osinfo; @@ -263,7 +263,7 @@ os = g_strdup_printf("%s %s %s", osinfo.sysname, osinfo.release, osinfo.machine); } - +#endif from = xmlnode_get_attrib(packet, "from"); id = xmlnode_get_attrib(packet, "id");
--- a/libpurple/protocols/jabber/jabber.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/protocols/jabber/jabber.c Mon Oct 01 17:49:01 2007 +0000 @@ -141,6 +141,7 @@ if(jabber_process_starttls(js, packet)) return; } else if(purple_account_get_bool(js->gc->account, "require_tls", FALSE) && !js->gsc) { + js->gc->wants_to_die = TRUE; purple_connection_error(js->gc, _("You require encryption, but it is not available on this server.")); return; } @@ -813,7 +814,7 @@ if(account->registration_cb) (account->registration_cb)(account, FALSE, account->registration_cb_user_data); jabber_connection_schedule_close(cbdata->js); -} + } g_free(cbdata->who); g_free(cbdata); } @@ -882,12 +883,12 @@ if((href = xmlnode_get_data(url))) { purple_notify_uri(NULL, href); g_free(href); - if(js->registration) { - js->gc->wants_to_die = TRUE; - if(account->registration_cb) /* succeeded, but we have no login info */ - (account->registration_cb)(account, TRUE, account->registration_cb_user_data); - jabber_connection_schedule_close(js); - } + if(js->registration) { + js->gc->wants_to_die = TRUE; + if(account->registration_cb) /* succeeded, but we have no login info */ + (account->registration_cb)(account, TRUE, account->registration_cb_user_data); + jabber_connection_schedule_close(js); + } return; } } @@ -987,14 +988,14 @@ purple_request_field_group_add_field(group, field); } - if((y = xmlnode_get_child(query, "instructions"))) - instructions = xmlnode_get_data(y); + if((y = xmlnode_get_child(query, "instructions"))) + instructions = xmlnode_get_data(y); else if(registered) instructions = g_strdup(_("Please fill out the information below " "to change your account registration.")); - else - instructions = g_strdup(_("Please fill out the information below " - "to register your new account.")); + else + instructions = g_strdup(_("Please fill out the information below " + "to register your new account.")); cbdata = g_new0(JabberRegisterCBData, 1); cbdata->js = js; @@ -1019,8 +1020,8 @@ g_free(title); } - g_free(instructions); - } + g_free(instructions); +} void jabber_register_start(JabberStream *js) { @@ -1531,15 +1532,15 @@ "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), "mood", _("Mood"), purple_value_new(PURPLE_TYPE_STRING), "moodtext", _("Mood Text"), purple_value_new(PURPLE_TYPE_STRING), - "tune_artist", _("Tune Artist"), purple_value_new(PURPLE_TYPE_STRING), - "tune_title", _("Tune Title"), purple_value_new(PURPLE_TYPE_STRING), - "tune_album", _("Tune Album"), purple_value_new(PURPLE_TYPE_STRING), - "tune_genre", _("Tune Genre"), purple_value_new(PURPLE_TYPE_STRING), - "tune_comment", _("Tune Comment"), purple_value_new(PURPLE_TYPE_STRING), - "tune_track", _("Tune Track"), purple_value_new(PURPLE_TYPE_STRING), - "tune_time", _("Tune Time"), purple_value_new(PURPLE_TYPE_INT), - "tune_year", _("Tune Year"), purple_value_new(PURPLE_TYPE_INT), - "tune_url", _("Tune URL"), purple_value_new(PURPLE_TYPE_STRING), + PURPLE_TUNE_ARTIST, _("Tune Artist"), purple_value_new(PURPLE_TYPE_STRING), + PURPLE_TUNE_TITLE, _("Tune Title"), purple_value_new(PURPLE_TYPE_STRING), + PURPLE_TUNE_ALBUM, _("Tune Album"), purple_value_new(PURPLE_TYPE_STRING), + PURPLE_TUNE_GENRE, _("Tune Genre"), purple_value_new(PURPLE_TYPE_STRING), + PURPLE_TUNE_COMMENT, _("Tune Comment"), purple_value_new(PURPLE_TYPE_STRING), + PURPLE_TUNE_TRACK, _("Tune Track"), purple_value_new(PURPLE_TYPE_STRING), + PURPLE_TUNE_TIME, _("Tune Time"), purple_value_new(PURPLE_TYPE_INT), + PURPLE_TUNE_YEAR, _("Tune Year"), purple_value_new(PURPLE_TYPE_INT), + PURPLE_TUNE_URL, _("Tune URL"), purple_value_new(PURPLE_TYPE_STRING), "nick", _("Nickname"), purple_value_new(PURPLE_TYPE_STRING), "buzz", _("Allow Buzz"), purple_value_new(PURPLE_TYPE_BOOLEAN), NULL); @@ -1554,15 +1555,15 @@ "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), "mood", _("Mood"), purple_value_new(PURPLE_TYPE_STRING), "moodtext", _("Mood Text"), purple_value_new(PURPLE_TYPE_STRING), - "tune_artist", _("Tune Artist"), purple_value_new(PURPLE_TYPE_STRING), - "tune_title", _("Tune Title"), purple_value_new(PURPLE_TYPE_STRING), - "tune_album", _("Tune Album"), purple_value_new(PURPLE_TYPE_STRING), - "tune_genre", _("Tune Genre"), purple_value_new(PURPLE_TYPE_STRING), - "tune_comment", _("Tune Comment"), purple_value_new(PURPLE_TYPE_STRING), - "tune_track", _("Tune Track"), purple_value_new(PURPLE_TYPE_STRING), - "tune_time", _("Tune Time"), purple_value_new(PURPLE_TYPE_INT), - "tune_year", _("Tune Year"), purple_value_new(PURPLE_TYPE_INT), - "tune_url", _("Tune URL"), purple_value_new(PURPLE_TYPE_STRING), + PURPLE_TUNE_ARTIST, _("Tune Artist"), purple_value_new(PURPLE_TYPE_STRING), + PURPLE_TUNE_TITLE, _("Tune Title"), purple_value_new(PURPLE_TYPE_STRING), + PURPLE_TUNE_ALBUM, _("Tune Album"), purple_value_new(PURPLE_TYPE_STRING), + PURPLE_TUNE_GENRE, _("Tune Genre"), purple_value_new(PURPLE_TYPE_STRING), + PURPLE_TUNE_COMMENT, _("Tune Comment"), purple_value_new(PURPLE_TYPE_STRING), + PURPLE_TUNE_TRACK, _("Tune Track"), purple_value_new(PURPLE_TYPE_STRING), + PURPLE_TUNE_TIME, _("Tune Time"), purple_value_new(PURPLE_TYPE_INT), + PURPLE_TUNE_YEAR, _("Tune Year"), purple_value_new(PURPLE_TYPE_INT), + PURPLE_TUNE_URL, _("Tune URL"), purple_value_new(PURPLE_TYPE_STRING), "nick", _("Nickname"), purple_value_new(PURPLE_TYPE_STRING), "buzz", _("Allow Buzz"), purple_value_new(PURPLE_TYPE_BOOLEAN), NULL); @@ -1577,15 +1578,15 @@ "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), "mood", _("Mood"), purple_value_new(PURPLE_TYPE_STRING), "moodtext", _("Mood Text"), purple_value_new(PURPLE_TYPE_STRING), - "tune_artist", _("Tune Artist"), purple_value_new(PURPLE_TYPE_STRING), - "tune_title", _("Tune Title"), purple_value_new(PURPLE_TYPE_STRING), - "tune_album", _("Tune Album"), purple_value_new(PURPLE_TYPE_STRING), - "tune_genre", _("Tune Genre"), purple_value_new(PURPLE_TYPE_STRING), - "tune_comment", _("Tune Comment"), purple_value_new(PURPLE_TYPE_STRING), - "tune_track", _("Tune Track"), purple_value_new(PURPLE_TYPE_STRING), - "tune_time", _("Tune Time"), purple_value_new(PURPLE_TYPE_INT), - "tune_year", _("Tune Year"), purple_value_new(PURPLE_TYPE_INT), - "tune_url", _("Tune URL"), purple_value_new(PURPLE_TYPE_STRING), + PURPLE_TUNE_ARTIST, _("Tune Artist"), purple_value_new(PURPLE_TYPE_STRING), + PURPLE_TUNE_TITLE, _("Tune Title"), purple_value_new(PURPLE_TYPE_STRING), + PURPLE_TUNE_ALBUM, _("Tune Album"), purple_value_new(PURPLE_TYPE_STRING), + PURPLE_TUNE_GENRE, _("Tune Genre"), purple_value_new(PURPLE_TYPE_STRING), + PURPLE_TUNE_COMMENT, _("Tune Comment"), purple_value_new(PURPLE_TYPE_STRING), + PURPLE_TUNE_TRACK, _("Tune Track"), purple_value_new(PURPLE_TYPE_STRING), + PURPLE_TUNE_TIME, _("Tune Time"), purple_value_new(PURPLE_TYPE_INT), + PURPLE_TUNE_YEAR, _("Tune Year"), purple_value_new(PURPLE_TYPE_INT), + PURPLE_TUNE_URL, _("Tune URL"), purple_value_new(PURPLE_TYPE_STRING), "nick", _("Nickname"), purple_value_new(PURPLE_TYPE_STRING), "buzz", _("Allow Buzz"), purple_value_new(PURPLE_TYPE_BOOLEAN), NULL); @@ -1600,15 +1601,15 @@ "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), "mood", _("Mood"), purple_value_new(PURPLE_TYPE_STRING), "moodtext", _("Mood Text"), purple_value_new(PURPLE_TYPE_STRING), - "tune_artist", _("Tune Artist"), purple_value_new(PURPLE_TYPE_STRING), - "tune_title", _("Tune Title"), purple_value_new(PURPLE_TYPE_STRING), - "tune_album", _("Tune Album"), purple_value_new(PURPLE_TYPE_STRING), - "tune_genre", _("Tune Genre"), purple_value_new(PURPLE_TYPE_STRING), - "tune_comment", _("Tune Comment"), purple_value_new(PURPLE_TYPE_STRING), - "tune_track", _("Tune Track"), purple_value_new(PURPLE_TYPE_STRING), - "tune_time", _("Tune Time"), purple_value_new(PURPLE_TYPE_INT), - "tune_year", _("Tune Year"), purple_value_new(PURPLE_TYPE_INT), - "tune_url", _("Tune URL"), purple_value_new(PURPLE_TYPE_STRING), + PURPLE_TUNE_ARTIST, _("Tune Artist"), purple_value_new(PURPLE_TYPE_STRING), + PURPLE_TUNE_TITLE, _("Tune Title"), purple_value_new(PURPLE_TYPE_STRING), + PURPLE_TUNE_ALBUM, _("Tune Album"), purple_value_new(PURPLE_TYPE_STRING), + PURPLE_TUNE_GENRE, _("Tune Genre"), purple_value_new(PURPLE_TYPE_STRING), + PURPLE_TUNE_COMMENT, _("Tune Comment"), purple_value_new(PURPLE_TYPE_STRING), + PURPLE_TUNE_TRACK, _("Tune Track"), purple_value_new(PURPLE_TYPE_STRING), + PURPLE_TUNE_TIME, _("Tune Time"), purple_value_new(PURPLE_TYPE_INT), + PURPLE_TUNE_YEAR, _("Tune Year"), purple_value_new(PURPLE_TYPE_INT), + PURPLE_TUNE_URL, _("Tune URL"), purple_value_new(PURPLE_TYPE_STRING), "nick", _("Nickname"), purple_value_new(PURPLE_TYPE_STRING), "buzz", _("Allow Buzz"), purple_value_new(PURPLE_TYPE_BOOLEAN), NULL); @@ -1623,15 +1624,15 @@ "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), "mood", _("Mood"), purple_value_new(PURPLE_TYPE_STRING), "moodtext", _("Mood Text"), purple_value_new(PURPLE_TYPE_STRING), - "tune_artist", _("Tune Artist"), purple_value_new(PURPLE_TYPE_STRING), - "tune_title", _("Tune Title"), purple_value_new(PURPLE_TYPE_STRING), - "tune_album", _("Tune Album"), purple_value_new(PURPLE_TYPE_STRING), - "tune_genre", _("Tune Genre"), purple_value_new(PURPLE_TYPE_STRING), - "tune_comment", _("Tune Comment"), purple_value_new(PURPLE_TYPE_STRING), - "tune_track", _("Tune Track"), purple_value_new(PURPLE_TYPE_STRING), - "tune_time", _("Tune Time"), purple_value_new(PURPLE_TYPE_INT), - "tune_year", _("Tune Year"), purple_value_new(PURPLE_TYPE_INT), - "tune_url", _("Tune URL"), purple_value_new(PURPLE_TYPE_STRING), + PURPLE_TUNE_ARTIST, _("Tune Artist"), purple_value_new(PURPLE_TYPE_STRING), + PURPLE_TUNE_TITLE, _("Tune Title"), purple_value_new(PURPLE_TYPE_STRING), + PURPLE_TUNE_ALBUM, _("Tune Album"), purple_value_new(PURPLE_TYPE_STRING), + PURPLE_TUNE_GENRE, _("Tune Genre"), purple_value_new(PURPLE_TYPE_STRING), + PURPLE_TUNE_COMMENT, _("Tune Comment"), purple_value_new(PURPLE_TYPE_STRING), + PURPLE_TUNE_TRACK, _("Tune Track"), purple_value_new(PURPLE_TYPE_STRING), + PURPLE_TUNE_TIME, _("Tune Time"), purple_value_new(PURPLE_TYPE_INT), + PURPLE_TUNE_YEAR, _("Tune Year"), purple_value_new(PURPLE_TYPE_INT), + PURPLE_TUNE_URL, _("Tune URL"), purple_value_new(PURPLE_TYPE_STRING), "nick", _("Nickname"), purple_value_new(PURPLE_TYPE_STRING), "buzz", _("Allow Buzz"), purple_value_new(PURPLE_TYPE_BOOLEAN), NULL); @@ -2239,6 +2240,44 @@ return PURPLE_CMD_RET_FAILED; } +GList *jabber_attention_types(PurpleAccount *account) +{ + static GList *types = NULL; + PurpleAttentionType *attn; + + if (!types) { + attn = g_new0(PurpleAttentionType, 1); + attn->name = _("Buzz"); + attn->incoming_description = _("%s has buzzed you!"); + attn->outgoing_description = _("Buzzing %s..."); + types = g_list_append(types, attn); + } + + return types; +} + +gboolean jabber_send_attention(PurpleConnection *gc, const char *username, guint code) +{ + PurpleConversation *conv; + char *error; + char *args[1]; + PurpleCmdRet ret; + + conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY, username, gc->account); + + args[0] = (char *)username; + + ret = jabber_cmd_buzz(conv, "buzz", args, &error, NULL); + + if (ret == PURPLE_CMD_RET_FAILED) { + purple_debug_error("jabber", "jabber_send_attention: jabber_cmd_buzz failed with error: %s\n", error ? error : "(NULL)"); + return FALSE; + } else { + return TRUE; + } +} + + gboolean jabber_offline_message(const PurpleBuddy *buddy) { return TRUE;
--- a/libpurple/protocols/jabber/jabber.h Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/protocols/jabber/jabber.h Mon Oct 01 17:49:01 2007 +0000 @@ -66,6 +66,9 @@ #define CAPS0115_NODE "http://pidgin.im/caps" +/* Index into attention_types list */ +#define JABBER_BUZZ 0 + typedef enum { JABBER_STREAM_OFFLINE, JABBER_STREAM_CONNECTING, @@ -231,6 +234,8 @@ void jabber_register_gateway(JabberStream *js, const char *gateway); void jabber_register_account(PurpleAccount *account); void jabber_unregister_account(PurpleAccount *account, PurpleAccountUnregistrationCb cb, void *user_data); +gboolean jabber_send_attention(PurpleConnection *gc, const char *username, guint code); +GList *jabber_attention_types(PurpleAccount *account); void jabber_convo_closed(PurpleConnection *gc, const char *who); PurpleChat *jabber_find_blist_chat(PurpleAccount *account, const char *name); gboolean jabber_offline_message(const PurpleBuddy *buddy);
--- a/libpurple/protocols/jabber/jutil.h Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/protocols/jabber/jutil.h Mon Oct 01 17:49:01 2007 +0000 @@ -22,8 +22,6 @@ #ifndef _PURPLE_JABBER_JUTIL_H_ #define _PURPLE_JABBER_JUTIL_H_ -#include "account.h" - typedef struct _JabberID { char *node; char *domain;
--- a/libpurple/protocols/jabber/libxmpp.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/protocols/jabber/libxmpp.c Mon Oct 01 17:49:01 2007 +0000 @@ -113,10 +113,10 @@ jabber_prpl_send_raw, /* send_raw */ jabber_roomlist_room_serialize, /* roomlist_room_serialize */ jabber_unregister_account, /* unregister_user */ + jabber_attention_types, /* attention_types */ + jabber_send_attention, /* send_attention */ /* padding */ - NULL, - NULL, NULL };
--- a/libpurple/protocols/jabber/message.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/protocols/jabber/message.c Mon Oct 01 17:49:01 2007 +0000 @@ -324,7 +324,7 @@ if(type) { if(!strcmp(type, "normal")) jm->type = JABBER_MESSAGE_NORMAL; - else if(!strcmp(type, "chat")) + else if(!strcmp(type, "chat")) jm->type = JABBER_MESSAGE_CHAT; else if(!strcmp(type, "groupchat")) jm->type = JABBER_MESSAGE_GROUPCHAT;
--- a/libpurple/protocols/jabber/presence.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/protocols/jabber/presence.c Mon Oct 01 17:49:01 2007 +0000 @@ -192,16 +192,11 @@ jabber_tune_set(js->gc, &tuneinfo); /* update old values */ - if(js->old_artist) - g_free(js->old_artist); - if(js->old_title) - g_free(js->old_title); - if(js->old_source) - g_free(js->old_source); - if(js->old_uri) - g_free(js->old_uri); - if(js->old_track) - g_free(js->old_track); + g_free(js->old_artist); + g_free(js->old_title); + g_free(js->old_source); + g_free(js->old_uri); + g_free(js->old_track); js->old_artist = g_strdup(artist); js->old_title = g_strdup(title); js->old_source = g_strdup(source);
--- a/libpurple/protocols/jabber/usernick.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/protocols/jabber/usernick.c Mon Oct 01 17:49:01 2007 +0000 @@ -33,7 +33,7 @@ xmlnode *item = xmlnode_get_child(items, "item"); JabberBuddy *buddy = jabber_buddy_find(js, from, FALSE); xmlnode *nick; - const char *nickname = NULL; + char *nickname = NULL; /* ignore the tune of people not on our buddy list */ if (!buddy || !item) @@ -43,8 +43,8 @@ if (!nick) return; nickname = xmlnode_get_data(nick); - serv_got_alias(js->gc, from, nickname); + g_free(nickname); } static void do_nick_set(JabberStream *js, const char *nick) { @@ -64,7 +64,7 @@ } static void do_nick_got_own_nick_cb(JabberStream *js, const char *from, xmlnode *items) { - const char *oldnickname = NULL; + char *oldnickname = NULL; xmlnode *item = xmlnode_get_child(items,"item"); if(item) { @@ -77,6 +77,7 @@ _("This information is visible to all contacts on your contact list, so choose something appropriate."), oldnickname, FALSE, FALSE, NULL, _("Set"), PURPLE_CALLBACK(do_nick_set), _("Cancel"), NULL, purple_connection_get_account(js->gc), NULL, NULL, js); + g_free(oldnickname); } static void do_nick_set_nick(PurplePluginAction *action) {
--- a/libpurple/protocols/jabber/usertune.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/protocols/jabber/usertune.c Mon Oct 01 17:49:01 2007 +0000 @@ -41,48 +41,61 @@ if (!buddy || !item) return; - tuneinfodata.artist = ""; - tuneinfodata.title = ""; - tuneinfodata.album = ""; - tuneinfodata.track = ""; + tuneinfodata.artist = NULL; + tuneinfodata.title = NULL; + tuneinfodata.album = NULL; + tuneinfodata.track = NULL; tuneinfodata.time = -1; - tuneinfodata.url = ""; - + tuneinfodata.url = NULL; + tune = xmlnode_get_child_with_namespace(item, "tune", "http://jabber.org/protocol/tune"); if (!tune) return; + resource = jabber_buddy_find_resource(buddy, NULL); + if(!resource) + return; /* huh? */ for (tuneinfo = tune->child; tuneinfo; tuneinfo = tuneinfo->next) { if (tuneinfo->type == XMLNODE_TYPE_TAG) { if (!strcmp(tuneinfo->name, "artist")) { - if (tuneinfodata.artist[0] == '\0') /* only pick the first one */ + if (tuneinfodata.artist == NULL) /* only pick the first one */ tuneinfodata.artist = xmlnode_get_data(tuneinfo); } else if (!strcmp(tuneinfo->name, "length")) { if (tuneinfodata.time == -1) { char *length = xmlnode_get_data(tuneinfo); if (length) tuneinfodata.time = strtol(length, NULL, 10); + g_free(length); } } else if (!strcmp(tuneinfo->name, "source")) { - if (tuneinfodata.album[0] == '\0') /* only pick the first one */ + if (tuneinfodata.album == NULL) /* only pick the first one */ tuneinfodata.album = xmlnode_get_data(tuneinfo); } else if (!strcmp(tuneinfo->name, "title")) { - if (tuneinfodata.title[0] == '\0') /* only pick the first one */ + if (tuneinfodata.title == NULL) /* only pick the first one */ tuneinfodata.title = xmlnode_get_data(tuneinfo); } else if (!strcmp(tuneinfo->name, "track")) { - if (tuneinfodata.track[0] == '\0') /* only pick the first one */ + if (tuneinfodata.track == NULL) /* only pick the first one */ tuneinfodata.track = xmlnode_get_data(tuneinfo); } else if (!strcmp(tuneinfo->name, "uri")) { - if (tuneinfodata.url[0] == '\0') /* only pick the first one */ + if (tuneinfodata.url == NULL) /* only pick the first one */ tuneinfodata.url = xmlnode_get_data(tuneinfo); } } } - resource = jabber_buddy_find_resource(buddy, NULL); - if(!resource) - return; /* huh? */ status_id = jabber_buddy_state_get_status_id(resource->state); - purple_prpl_got_user_status(js->gc->account, from, status_id, PURPLE_TUNE_ARTIST, tuneinfodata.artist, PURPLE_TUNE_TITLE, tuneinfodata.title, PURPLE_TUNE_ALBUM, tuneinfodata.album, PURPLE_TUNE_TRACK, tuneinfodata.track, PURPLE_TUNE_TIME, tuneinfodata.time, PURPLE_TUNE_URL, tuneinfodata.url, NULL); + purple_prpl_got_user_status(js->gc->account, from, status_id, + PURPLE_TUNE_ARTIST, tuneinfodata.artist, + PURPLE_TUNE_TITLE, tuneinfodata.title, + PURPLE_TUNE_ALBUM, tuneinfodata.album, + PURPLE_TUNE_TRACK, tuneinfodata.track, + PURPLE_TUNE_TIME, tuneinfodata.time, + PURPLE_TUNE_URL, tuneinfodata.url, NULL); + + g_free(tuneinfodata.artist); + g_free(tuneinfodata.title); + g_free(tuneinfodata.album); + g_free(tuneinfodata.track); + g_free(tuneinfodata.url); } void jabber_tune_init(void) {
--- a/libpurple/protocols/msn/directconn.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/protocols/msn/directconn.c Mon Oct 01 17:49:01 2007 +0000 @@ -405,6 +405,15 @@ } } +static void +directconn_connect_cb(gpointer data, gint source, const gchar *error_message) +{ + if (error_message) + purple_debug_error("msn", "Error making direct connection: %s\n", error_message); + + connect_cb(data, source, PURPLE_INPUT_READ); +} + gboolean msn_directconn_connect(MsnDirectConn *directconn, const char *host, int port) { @@ -424,14 +433,9 @@ #endif directconn->connect_data = purple_proxy_connect(NULL, session->account, - host, port, connect_cb, directconn); + host, port, directconn_connect_cb, directconn); - if (directconn->connect_data != NULL) - { - return TRUE; - } - else - return FALSE; + return (directconn->connect_data != NULL); } #if 0
--- a/libpurple/protocols/msn/httpconn.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/protocols/msn/httpconn.c Mon Oct 01 17:49:01 2007 +0000 @@ -663,6 +663,8 @@ httpconn->tx_buf = purple_circ_buffer_new(MSN_BUF_LEN); httpconn->tx_handler = 0; + httpconn->fd = -1; + return httpconn; }
--- a/libpurple/protocols/msn/msn.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/protocols/msn/msn.c Mon Oct 01 17:49:01 2007 +0000 @@ -2196,8 +2196,7 @@ prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); - /* TODO: Mark translatable as soon as 2.2.0 is released and we're not string frozen */ - option = purple_account_option_string_new("HTTP Method Server", + option = purple_account_option_string_new(_("HTTP Method Server"), "http_method_server", MSN_HTTPCONN_SERVER); prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
--- a/libpurple/protocols/msn/servconn.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/protocols/msn/servconn.c Mon Oct 01 17:49:01 2007 +0000 @@ -53,6 +53,8 @@ servconn->tx_buf = purple_circ_buffer_new(MSN_BUF_LEN); servconn->tx_handler = 0; + servconn->fd = -1; + return servconn; }
--- a/libpurple/protocols/msn/slp.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/protocols/msn/slp.c Mon Oct 01 17:49:01 2007 +0000 @@ -343,7 +343,7 @@ if (xfer) { bin = (char *)purple_base64_decode(context, &bin_len); - file_size = GUINT32_FROM_LE(*(gsize *)(bin + 2)); + file_size = GUINT32_FROM_LE(*(gsize *)(bin + 8)); uni_name = (gunichar2 *)(bin + 20); while(*uni_name != 0 && ((char *)uni_name - (bin + 20)) < MAX_FILE_NAME_LEN) {
--- a/libpurple/protocols/msn/switchboard.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/protocols/msn/switchboard.c Mon Oct 01 17:49:01 2007 +0000 @@ -947,25 +947,14 @@ nudge_msg(MsnCmdProc *cmdproc, MsnMessage *msg) { MsnSwitchBoard *swboard; - char *username, *str; PurpleAccount *account; - PurpleBuddy *buddy; const char *user; - str = NULL; - swboard = cmdproc->data; account = cmdproc->session->account; user = msg->remote_user; - if ((buddy = purple_find_buddy(account, user)) != NULL) - username = g_markup_escape_text(purple_buddy_get_alias(buddy), -1); - else - username = g_markup_escape_text(user, -1); - - serv_got_attention(account->gc, buddy->name, MSN_NUDGE); - g_free(username); - g_free(str); + serv_got_attention(account->gc, user, MSN_NUDGE); } /**************************************************************************
--- a/libpurple/protocols/myspace/markup.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/protocols/myspace/markup.c Mon Oct 01 17:49:01 2007 +0000 @@ -258,8 +258,8 @@ } - *begin = gs_begin->str; - *end = gs_end->str; + *begin = g_string_free(gs_begin,FALSE); + *end = g_string_free(gs_end, FALSE); } /** Convert a msim markup color to a color suitable for libpurple. @@ -426,13 +426,14 @@ html_tag_to_msim_markup(MsimSession *session, xmlnode *root, gchar **begin, gchar **end) { - /* TODO: Coalesce nested tags into one <f> tag! - * Currently, the 's' value will be overwritten when b/i/u is nested - * within another one, and only the inner-most formatting will be - * applied to the text. */ - if (!purple_utf8_strcasecmp(root->name, "root")) { - *begin = g_strdup(""); - *end = g_strdup(""); + if (!purple_utf8_strcasecmp(root->name, "root") || + !purple_utf8_strcasecmp(root->name, "html")) { + *begin = g_strdup(""); + *end = g_strdup(""); + /* TODO: Coalesce nested tags into one <f> tag! + * Currently, the 's' value will be overwritten when b/i/u is nested + * within another one, and only the inner-most formatting will be + * applied to the text. */ } else if (!purple_utf8_strcasecmp(root->name, "b")) { *begin = g_strdup_printf("<f s='%d'>", MSIM_TEXT_BOLD); *end = g_strdup("</f>"); @@ -503,8 +504,20 @@ /* TODO: color (bg uses <body>), emoticons */ } else { - *begin = g_strdup_printf("[%s]", root->name); - *end = g_strdup_printf("[/%s]", root->name); + gchar *err; + +#ifdef MSIM_MARKUP_SHOW_UNKNOWN_TAGS + *begin = g_strdup_printf("[%s]", root->name); + *end = g_strdup_printf("[/%s]", root->name); +#else + *begin = g_strdup(""); + *end = g_strdup(""); +#endif + + err = g_strdup_printf("html_tag_to_msim_markup: unrecognized " + "HTML tag %s was sent by the IM client; ignoring", (root->name ? root->name : "(NULL)")); + msim_unrecognized(NULL, NULL, err); + g_free(err); } } @@ -582,7 +595,7 @@ purple_debug_info("msim", "msim_markup_xmlnode_to_gtkhtml: RETURNING %s\n", (final && final->str) ? final->str : "(NULL)"); - return final->str; + return g_string_free(final, FALSE); } /** Convert XML to something based on MSIM_XMLNODE_CONVERT. */
--- a/libpurple/protocols/myspace/markup.h Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/protocols/myspace/markup.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,27 +1,27 @@ -/* MySpaceIM Protocol Plugin - markup - * - * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ - -#ifndef _MYSPACE_MARKUP_H -#define _MYSPACE_MARKUP_H - -/* High-level msim markup <=> Purple html conversion functions. */ -gchar *msim_markup_to_html(MsimSession *, const gchar *raw); -gchar *html_to_msim_markup(MsimSession *, const gchar *raw); - -#endif /* !_MYSPACE_MARKUP_H */ +/* MySpaceIM Protocol Plugin - markup + * + * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ + +#ifndef _MYSPACE_MARKUP_H +#define _MYSPACE_MARKUP_H + +/* High-level msim markup <=> Purple html conversion functions. */ +gchar *msim_markup_to_html(MsimSession *, const gchar *raw); +gchar *html_to_msim_markup(MsimSession *, const gchar *raw); + +#endif /* !_MYSPACE_MARKUP_H */
--- a/libpurple/protocols/myspace/message.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/protocols/myspace/message.c Mon Oct 01 17:49:01 2007 +0000 @@ -80,7 +80,7 @@ purple_debug_info("msim", "msim_escape: msg=%s, ret=%s\n", msg, gs->str); #endif - return gs->str; + return g_string_free(gs, FALSE); } /** @@ -120,7 +120,7 @@ purple_debug_info("msim", "msim_unescape: msg=%s, ret=%s\n", msg, gs->str); #endif - return gs->str; + return g_string_free(gs, FALSE); } /** Create a new MsimMessage. @@ -691,7 +691,7 @@ ++i; } - string = gs->str; + string = g_string_free(gs, FALSE); break; default: @@ -798,7 +798,7 @@ g_string_append(gs, "|"); } - return gs->str; + return g_string_free(gs, FALSE); default: purple_debug_info("msim", "field %s, unknown type %d\n", @@ -1337,9 +1337,7 @@ gs = (GString *)elem->data; /* Duplicate data, so caller can g_free() it. */ - *binary_data = g_new0(char, gs->len); - memcpy(*binary_data, gs->str, gs->len); - + *binary_data = g_memdup(gs->str, gs->len); *binary_length = gs->len; return TRUE;
--- a/libpurple/protocols/myspace/myspace.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/protocols/myspace/myspace.c Mon Oct 01 17:49:01 2007 +0000 @@ -43,7 +43,7 @@ static int msim_send_really_raw(PurpleConnection *gc, const char *buf, int total_bytes); static gboolean msim_login_challenge(MsimSession *session, MsimMessage *msg); -static const gchar *msim_compute_login_response(const gchar nonce[2 * NONCE_SIZE], const gchar *email, const gchar *password, guint *response_len); +static gchar *msim_compute_login_response(const gchar nonce[2 * NONCE_SIZE], const gchar *email, const gchar *password, guint *response_len); static gboolean msim_incoming_bm_record_cv(MsimSession *session, MsimMessage *msg); static gboolean msim_incoming_bm(MsimSession *session, MsimMessage *msg); @@ -331,10 +331,11 @@ msim_login_challenge(MsimSession *session, MsimMessage *msg) { PurpleAccount *account; - const gchar *response; + gchar *response; guint response_len; gchar *nc; gsize nc_len; + gboolean ret; g_return_val_if_fail(MSIM_SESSION_VALID(session), FALSE); g_return_val_if_fail(msg != NULL, FALSE); @@ -362,11 +363,11 @@ g_free(nc); - return msim_send(session, + ret = msim_send(session, "login2", MSIM_TYPE_INTEGER, MSIM_AUTH_ALGORITHM, /* This is actually user's email address. */ "username", MSIM_TYPE_STRING, g_strdup(account->username), - /* GString and gchar * response will be freed in msim_msg_free() in msim_send(). */ + /* GString will be freed in msim_msg_free() in msim_send(). */ "response", MSIM_TYPE_BINARY, g_string_new_len(response, response_len), "clientver", MSIM_TYPE_INTEGER, MSIM_CLIENT_VERSION, "langid", MSIM_TYPE_INTEGER, MSIM_LANGUAGE_ID_ENGLISH, @@ -375,6 +376,10 @@ "status", MSIM_TYPE_INTEGER, 100, "id", MSIM_TYPE_INTEGER, 1, NULL); + + g_free(response); + + return ret; } /** @@ -388,7 +393,7 @@ * @return Binary login challenge response, ready to send to the server. * Must be g_free()'d when finished. NULL if error. */ -static const gchar * +static gchar * msim_compute_login_response(const gchar nonce[2 * NONCE_SIZE], const gchar *email, const gchar *password, guint *response_len) { @@ -453,6 +458,7 @@ purple_cipher_context_append(key_context, hash_pw, HASH_SIZE); purple_cipher_context_append(key_context, (guchar *)(nonce + NONCE_SIZE), NONCE_SIZE); purple_cipher_context_digest(key_context, sizeof(key), key, NULL); + purple_cipher_context_destroy(key_context); #ifdef MSIM_DEBUG_LOGIN_CHALLENGE purple_debug_info("msim", "key = "); @@ -485,8 +491,13 @@ purple_cipher_context_encrypt(rc4, (const guchar *)data, data_len, data_out, &data_out_len); purple_cipher_context_destroy(rc4); - - g_assert(data_out_len == data_len); + g_free(data); + + if (data_out_len != data_len) { + purple_debug_info("msim", "msim_compute_login_response: " + "data length mismatch: %d != %d\n", + data_out_len, data_len); + } #ifdef MSIM_DEBUG_LOGIN_CHALLENGE purple_debug_info("msim", "response=<%s>\n", data_out); @@ -494,7 +505,7 @@ *response_len = data_out_len; - return (const gchar *)data_out; + return (gchar *)data_out; } /** @@ -1029,7 +1040,7 @@ PurpleStatusType *type; MsimSession *session; guint status_code; - const gchar *statstring; + gchar *statstring; session = (MsimSession *)account->gc->proto_data; @@ -1063,7 +1074,7 @@ break; } - statstring = purple_status_get_attr_string(status, "message"); + statstring = (gchar *)purple_status_get_attr_string(status, "message"); if (!statstring) { statstring = ""; @@ -1072,7 +1083,7 @@ /* Status strings are plain text. */ statstring = purple_markup_strip_html(statstring); - msim_set_status_code(session, status_code, g_strdup(statstring)); + msim_set_status_code(session, status_code, statstring); } /** Go idle. */ @@ -1203,7 +1214,7 @@ if (uid == wanted_uid) { ret = g_strdup(name); - break; + break; } } @@ -1295,7 +1306,6 @@ msim_check_inbox_cb(MsimSession *session, MsimMessage *reply, gpointer data) { MsimMessage *body; - GString *notification; guint old_inbox_status; guint i, n; const gchar *froms[5], *tos[5], *urls[5], *subjects[5]; @@ -1329,8 +1339,6 @@ body = msim_msg_get_dictionary(reply, "body"); g_return_if_fail(body != NULL); - notification = g_string_new(""); - old_inbox_status = session->inbox_status; n = 0; @@ -1860,6 +1868,7 @@ purple_blist_add_buddy(buddy, NULL, NULL, NULL); user = msim_get_user_from_buddy(buddy); + /* TODO: free user. memory leak? */ /* All buddies on list should have 'uid' integer associated with them. */ purple_blist_node_set_int(&buddy->node, "UserID", msim_msg_get_integer(msg, "f")); @@ -2856,7 +2865,7 @@ } /** Callbacks called by Purple, to access this plugin. */ -PurplePluginProtocolInfo prpl_info = { +static PurplePluginProtocolInfo prpl_info = { /* options */ OPT_PROTO_USE_POINTSIZE /* specify font size in sane point size */ | OPT_PROTO_MAIL_CHECK, @@ -3004,7 +3013,7 @@ msg = msim_msg_new(NULL); /* Create a new, empty message. */ /* Append some new elements. */ - msg = msim_msg_append(msg, "bx", MSIM_TYPE_BINARY, g_string_new_len(g_strdup("XXX"), 3)); + msg = msim_msg_append(msg, "bx", MSIM_TYPE_BINARY, g_string_new_len("XXX", 3)); msg = msim_msg_append(msg, "k1", MSIM_TYPE_STRING, g_strdup("v1")); msg = msim_msg_append(msg, "k1", MSIM_TYPE_INTEGER, GUINT_TO_POINTER(42)); msg = msim_msg_append(msg, "k1", MSIM_TYPE_STRING, g_strdup("v43"));
--- a/libpurple/protocols/myspace/myspace.h Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/protocols/myspace/myspace.h Mon Oct 01 17:49:01 2007 +0000 @@ -67,6 +67,10 @@ /*#define MSIM_DEBUG_LOGIN_CHALLENGE*/ /*#define MSIM_DEBUG_RXBUF */ +/* Encode unknown HTML tags from IM clients in messages as [tag], instead of + * ignoring. Useful for debugging */ +/*#define MSIM_MARKUP_SHOW_UNKNOWN_TAGS */ + /* Define to cause init_plugin() to run some tests and print * the results to the Purple debug log, then exit. Useful to * run with 'pidgin -d' to see the output. Don't define if
--- a/libpurple/protocols/myspace/session.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/protocols/myspace/session.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,95 +1,95 @@ -/* MySpaceIM Protocol Plugin, session - * - * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ - - -#include "myspace.h" - -/* Session methods */ - -/** - * Create a new MSIM session. - * - * @param acct The account to create the session from. - * - * @return Pointer to a new session. Free with msim_session_destroy. - */ -MsimSession * -msim_session_new(PurpleAccount *acct) -{ - MsimSession *session; - - g_return_val_if_fail(acct != NULL, NULL); - - session = g_new0(MsimSession, 1); - - session->magic = MSIM_SESSION_STRUCT_MAGIC; - session->account = acct; - session->gc = purple_account_get_connection(acct); - session->sesskey = 0; - session->userid = 0; - session->username = NULL; - session->fd = -1; - - /* TODO: Remove. */ - session->user_lookup_cb = g_hash_table_new_full(g_direct_hash, - g_direct_equal, NULL, NULL); /* do NOT free function pointers! (values) */ - session->user_lookup_cb_data = g_hash_table_new_full(g_direct_hash, - g_direct_equal, NULL, NULL);/* TODO: we don't know what the values are, - they could be integers inside gpointers - or strings, so I don't freed them. - Figure this out, once free cache. */ - - /* Created in msim_process_server_info() */ - session->server_info = NULL; - - session->rxoff = 0; - session->rxbuf = g_new0(gchar, MSIM_READ_BUF_SIZE); - session->next_rid = 1; - session->last_comm = time(NULL); - session->inbox_status = 0; - - return session; -} - -/** - * Free a session. - * - * @param session The session to destroy. - */ -void -msim_session_destroy(MsimSession *session) -{ - g_return_if_fail(MSIM_SESSION_VALID(session)); - - session->magic = -1; - - g_free(session->rxbuf); - g_free(session->username); - - /* TODO: Remove. */ - g_hash_table_destroy(session->user_lookup_cb); - g_hash_table_destroy(session->user_lookup_cb_data); - - if (session->server_info) { - msim_msg_free(session->server_info); - } - - g_free(session); -} - +/* MySpaceIM Protocol Plugin, session + * + * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ + + +#include "myspace.h" + +/* Session methods */ + +/** + * Create a new MSIM session. + * + * @param acct The account to create the session from. + * + * @return Pointer to a new session. Free with msim_session_destroy. + */ +MsimSession * +msim_session_new(PurpleAccount *acct) +{ + MsimSession *session; + + g_return_val_if_fail(acct != NULL, NULL); + + session = g_new0(MsimSession, 1); + + session->magic = MSIM_SESSION_STRUCT_MAGIC; + session->account = acct; + session->gc = purple_account_get_connection(acct); + session->sesskey = 0; + session->userid = 0; + session->username = NULL; + session->fd = -1; + + /* TODO: Remove. */ + session->user_lookup_cb = g_hash_table_new_full(g_direct_hash, + g_direct_equal, NULL, NULL); /* do NOT free function pointers! (values) */ + session->user_lookup_cb_data = g_hash_table_new_full(g_direct_hash, + g_direct_equal, NULL, NULL);/* TODO: we don't know what the values are, + they could be integers inside gpointers + or strings, so I don't freed them. + Figure this out, once free cache. */ + + /* Created in msim_process_server_info() */ + session->server_info = NULL; + + session->rxoff = 0; + session->rxbuf = g_new0(gchar, MSIM_READ_BUF_SIZE); + session->next_rid = 1; + session->last_comm = time(NULL); + session->inbox_status = 0; + + return session; +} + +/** + * Free a session. + * + * @param session The session to destroy. + */ +void +msim_session_destroy(MsimSession *session) +{ + g_return_if_fail(MSIM_SESSION_VALID(session)); + + session->magic = -1; + + g_free(session->rxbuf); + g_free(session->username); + + /* TODO: Remove. */ + g_hash_table_destroy(session->user_lookup_cb); + g_hash_table_destroy(session->user_lookup_cb_data); + + if (session->server_info) { + msim_msg_free(session->server_info); + } + + g_free(session); +} +
--- a/libpurple/protocols/myspace/session.h Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/protocols/myspace/session.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,57 +1,57 @@ -/* MySpaceIM Protocol Plugin, session - * - * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ - -#ifndef _MYSPACE_SESSION_H -#define _MYSPACE_SESSION_H - -/* Random number in every MsimSession, to ensure it is valid. */ -#define MSIM_SESSION_STRUCT_MAGIC 0xe4a6752b - -/* Everything needed to keep track of a session (proto_data field in PurpleConnection) */ -typedef struct _MsimSession -{ - guint magic; /**< MSIM_SESSION_STRUCT_MAGIC */ - PurpleAccount *account; - PurpleConnection *gc; - guint sesskey; /**< Session key from server */ - guint userid; /**< This user's numeric user ID */ - gchar *username; /**< This user's unique username */ - gint fd; /**< File descriptor to/from server */ - - /* TODO: Remove. */ - GHashTable *user_lookup_cb; /**< Username -> userid lookup callback */ - GHashTable *user_lookup_cb_data; /**< Username -> userid lookup callback data */ - - MsimMessage *server_info; /**< Parameters from server */ - - gchar *rxbuf; /**< Receive buffer */ - guint rxoff; /**< Receive buffer offset */ - guint next_rid; /**< Next request/response ID */ - time_t last_comm; /**< Time received last communication */ - guint inbox_status; /**< Bit field of inbox notifications */ -} MsimSession; - -/* Check if an MsimSession is valid */ -#define MSIM_SESSION_VALID(s) (session != NULL && session->magic == MSIM_SESSION_STRUCT_MAGIC) - - -MsimSession *msim_session_new(PurpleAccount *acct); -void msim_session_destroy(MsimSession *session); - -#endif /* !_MYSPACE_SESSION_H */ +/* MySpaceIM Protocol Plugin, session + * + * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ + +#ifndef _MYSPACE_SESSION_H +#define _MYSPACE_SESSION_H + +/* Random number in every MsimSession, to ensure it is valid. */ +#define MSIM_SESSION_STRUCT_MAGIC 0xe4a6752b + +/* Everything needed to keep track of a session (proto_data field in PurpleConnection) */ +typedef struct _MsimSession +{ + guint magic; /**< MSIM_SESSION_STRUCT_MAGIC */ + PurpleAccount *account; + PurpleConnection *gc; + guint sesskey; /**< Session key from server */ + guint userid; /**< This user's numeric user ID */ + gchar *username; /**< This user's unique username */ + gint fd; /**< File descriptor to/from server */ + + /* TODO: Remove. */ + GHashTable *user_lookup_cb; /**< Username -> userid lookup callback */ + GHashTable *user_lookup_cb_data; /**< Username -> userid lookup callback data */ + + MsimMessage *server_info; /**< Parameters from server */ + + gchar *rxbuf; /**< Receive buffer */ + guint rxoff; /**< Receive buffer offset */ + guint next_rid; /**< Next request/response ID */ + time_t last_comm; /**< Time received last communication */ + guint inbox_status; /**< Bit field of inbox notifications */ +} MsimSession; + +/* Check if an MsimSession is valid */ +#define MSIM_SESSION_VALID(s) (session != NULL && session->magic == MSIM_SESSION_STRUCT_MAGIC) + + +MsimSession *msim_session_new(PurpleAccount *acct); +void msim_session_destroy(MsimSession *session); + +#endif /* !_MYSPACE_SESSION_H */
--- a/libpurple/protocols/myspace/user.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/protocols/myspace/user.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,437 +1,454 @@ -/* MySpaceIM Protocol Plugin, header file - * - * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ - -#include "myspace.h" - -static void msim_store_user_info_each(const gchar *key_str, gchar *value_str, MsimUser *user); -static gchar *msim_format_now_playing(gchar *band, gchar *song); -static void msim_downloaded_buddy_icon(PurpleUtilFetchUrlData *url_data, gpointer user_data, const gchar *url_text, - gsize len, const gchar *error_message); - -/** Format the "now playing" indicator, showing the artist and song. - * @return Return a new string (must be g_free()'d), or NULL. - */ -static gchar * -msim_format_now_playing(gchar *band, gchar *song) -{ - if ((band && strlen(band)) || (song && strlen(song))) { - return g_strdup_printf("%s - %s", - (band && strlen(band)) ? band : "Unknown Artist", - (song && strlen(song)) ? song : "Unknown Song"); - } else { - return NULL; - } -} -/** Get the MsimUser from a PurpleBuddy, creating it if needed. */ -MsimUser * -msim_get_user_from_buddy(PurpleBuddy *buddy) -{ - MsimUser *user; - - if (!buddy) { - return NULL; - } - - if (!buddy->proto_data) { - /* No MsimUser for this buddy; make one. */ - - /* TODO: where is this freed? */ - user = g_new0(MsimUser, 1); - user->buddy = buddy; - buddy->proto_data = (gpointer)user; - } - - user = (MsimUser *)(buddy->proto_data); - - return user; -} - -/** Find and return an MsimUser * representing a user on the buddy list, or NULL. */ -MsimUser * -msim_find_user(MsimSession *session, const gchar *username) -{ - PurpleBuddy *buddy; - MsimUser *user; - - buddy = purple_find_buddy(session->account, username); - if (!buddy) { - return NULL; - } - - user = msim_get_user_from_buddy(buddy); - - return user; -} - -/** Append user information to a PurpleNotifyUserInfo, given an MsimUser. - * Used by msim_tooltip_text() and msim_get_info_cb() to show a user's profile. - */ -void -msim_append_user_info(MsimSession *session, PurpleNotifyUserInfo *user_info, MsimUser *user, gboolean full) -{ - gchar *str; - guint uid; - guint cv; - - /* Useful to identify the account the tooltip refers to. - * Other prpls show this. */ - if (user->username) { - purple_notify_user_info_add_pair(user_info, _("User"), user->username); - } - - uid = purple_blist_node_get_int(&user->buddy->node, "UserID"); - - if (full) { - /* TODO: link to username, if available */ - purple_notify_user_info_add_pair(user_info, _("Profile"), - g_strdup_printf("<a href=\"http://myspace.com/%d\">http://myspace.com/%d</a>", - uid, uid)); - } - - - /* a/s/l...the vitals */ - if (user->age) { - purple_notify_user_info_add_pair(user_info, _("Age"), - g_strdup_printf("%d", user->age)); - } - - if (user->gender && strlen(user->gender)) { - purple_notify_user_info_add_pair(user_info, _("Gender"), user->gender); - } - - if (user->location && strlen(user->location)) { - purple_notify_user_info_add_pair(user_info, _("Location"), user->location); - } - - /* Other information */ - if (user->headline && strlen(user->headline)) { - purple_notify_user_info_add_pair(user_info, _("Headline"), user->headline); - } - - str = msim_format_now_playing(user->band_name, user->song_name); - if (str && strlen(str)) { - purple_notify_user_info_add_pair(user_info, _("Song"), str); - } - - /* Note: total friends only available if looked up by uid, not username. */ - if (user->total_friends) { - purple_notify_user_info_add_pair(user_info, _("Total Friends"), - g_strdup_printf("%d", user->total_friends)); - } - - if (full) { - /* Client information */ - - str = user->client_info; - cv = user->client_cv; - - if (str && cv != 0) { - purple_notify_user_info_add_pair(user_info, _("Client Version"), - g_strdup_printf("%s (build %d)", str, cv)); - } else if (str) { - purple_notify_user_info_add_pair(user_info, _("Client Version"), - g_strdup(str)); - } else if (cv) { - purple_notify_user_info_add_pair(user_info, _("Client Version"), - g_strdup_printf("Build %d", cv)); - } - } -} - -/** Store a field of information about a buddy. */ -void -msim_store_user_info_each(const gchar *key_str, gchar *value_str, MsimUser *user) -{ - if (g_str_equal(key_str, "UserID") || g_str_equal(key_str, "ContactID")) { - /* Save to buddy list, if it exists, for quick cached uid lookup with msim_uid2username_from_blist(). */ - if (user->buddy) - { - purple_debug_info("msim", "associating uid %s with username %s\n", key_str, user->buddy->name); - purple_blist_node_set_int(&user->buddy->node, "UserID", atol(value_str)); - } - /* Need to store in MsimUser, too? What if not on blist? */ - } else if (g_str_equal(key_str, "Age")) { - user->age = atol(value_str); - } else if (g_str_equal(key_str, "Gender")) { - user->gender = g_strdup(value_str); - } else if (g_str_equal(key_str, "Location")) { - user->location = g_strdup(value_str); - } else if (g_str_equal(key_str, "TotalFriends")) { - user->total_friends = atol(value_str); - } else if (g_str_equal(key_str, "DisplayName")) { - user->display_name = g_strdup(value_str); - } else if (g_str_equal(key_str, "BandName")) { - user->band_name = g_strdup(value_str); - } else if (g_str_equal(key_str, "SongName")) { - user->song_name = g_strdup(value_str); - } else if (g_str_equal(key_str, "UserName") || g_str_equal(key_str, "IMName") || g_str_equal(key_str, "NickName")) { - /* Ignore because PurpleBuddy knows this already */ - ; - } else if (g_str_equal(key_str, "ImageURL") || g_str_equal(key_str, "AvatarURL")) { - const gchar *previous_url; - - user->image_url = g_strdup(value_str); - - /* Instead of showing 'no photo' picture, show nothing. */ - if (g_str_equal(user->image_url, "http://x.myspace.com/images/no_pic.gif")) - { - purple_buddy_icons_set_for_user(user->buddy->account, - user->buddy->name, - NULL, 0, NULL); - return; - } - - /* TODO: use ETag for checksum */ - previous_url = purple_buddy_icons_get_checksum_for_user(user->buddy); - - /* Only download if URL changed */ - if (!previous_url || !g_str_equal(previous_url, user->image_url)) { - purple_util_fetch_url(user->image_url, TRUE, NULL, TRUE, msim_downloaded_buddy_icon, (gpointer)user); - } - } else if (g_str_equal(key_str, "LastImageUpdated")) { - /* TODO: use somewhere */ - user->last_image_updated = atol(value_str); - } else if (g_str_equal(key_str, "Headline")) { - user->headline = g_strdup(value_str); - } else { - /* TODO: other fields in MsimUser */ - gchar *msg; - - msg = g_strdup_printf("msim_store_user_info_each: unknown field %s=%s", - key_str, value_str); - - msim_unrecognized(NULL, NULL, msg); - - g_free(msg); - } -} - -/** Save buddy information to the buddy list from a user info reply message. - * - * @param session - * @param msg The user information reply, with any amount of information. - * @param user The structure to save to, or NULL to save in PurpleBuddy->proto_data. - * - * Variable information is saved to the passed MsimUser structure. Permanent - * information (UserID) is stored in the blist node of the buddy list (and - * ends up in blist.xml, persisted to disk) if it exists. - * - * If the function has no buddy information, this function - * is a no-op (and returns FALSE). - * - */ -gboolean -msim_store_user_info(MsimSession *session, MsimMessage *msg, MsimUser *user) -{ - gchar *username; - MsimMessage *body, *body_node; - - g_return_val_if_fail(MSIM_SESSION_VALID(session), FALSE); - g_return_val_if_fail(msg != NULL, FALSE); - - body = msim_msg_get_dictionary(msg, "body"); - if (!body) { - return FALSE; - } - - username = msim_msg_get_string(body, "UserName"); - - if (!username) { - purple_debug_info("msim", - "msim_process_reply: not caching body, no UserName\n"); - msim_msg_free(body); - g_free(username); - return FALSE; - } - - /* Null user = find and store in PurpleBuddy's proto_data */ - if (!user) { - user = msim_find_user(session, username); - if (!user) { - msim_msg_free(body); - g_free(username); - return FALSE; - } - } - - /* TODO: make looping over MsimMessage's easier. */ - for (body_node = body; - body_node != NULL; - body_node = msim_msg_get_next_element_node(body_node)) - { - const gchar *key_str; - gchar *value_str; - MsimMessageElement *elem; - - elem = (MsimMessageElement *)body_node->data; - key_str = elem->name; - - value_str = msim_msg_get_string_from_element(elem); - msim_store_user_info_each(key_str, value_str, user); - g_free(value_str); - } - - if (msim_msg_get_integer(msg, "dsn") == MG_OWN_IM_INFO_DSN && - msim_msg_get_integer(msg, "lid") == MG_OWN_IM_INFO_LID) { - /* TODO: do something with our own IM info, if we need it for some - * specific purpose. Otherwise it is available on the buddy list, - * if the user has themselves as their own buddy. - * - * However, much of the info is already available in MsimSession, - * stored in msim_we_are_logged_on(). */ - } else if (msim_msg_get_integer(msg, "dsn") == MG_OWN_MYSPACE_INFO_DSN && - msim_msg_get_integer(msg, "lid") == MG_OWN_MYSPACE_INFO_LID) { - /* TODO: same as above, but for MySpace info. */ - } - - msim_msg_free(body); - - return TRUE; -} - -/** - * Asynchronously lookup user information, calling callback when receive result. - * - * @param session - * @param user The user id, email address, or username. Not freed. - * @param cb Callback, called with user information when available. - * @param data An arbitray data pointer passed to the callback. - */ -/* TODO: change to not use callbacks */ -void -msim_lookup_user(MsimSession *session, const gchar *user, MSIM_USER_LOOKUP_CB cb, gpointer data) -{ - MsimMessage *body; - gchar *field_name; - guint rid, cmd, dsn, lid; - - g_return_if_fail(MSIM_SESSION_VALID(session)); - g_return_if_fail(user != NULL); - /* Callback can be null to not call anything, just lookup & store information. */ - /*g_return_if_fail(cb != NULL);*/ - - purple_debug_info("msim", "msim_lookup_userid: " - "asynchronously looking up <%s>\n", user); - - msim_msg_dump("msim_lookup_user: data=%s\n", (MsimMessage *)data); - - /* Setup callback. Response will be associated with request using 'rid'. */ - rid = msim_new_reply_callback(session, cb, data); - - /* Send request */ - - cmd = MSIM_CMD_GET; - - if (msim_is_userid(user)) { - field_name = "UserID"; - dsn = MG_MYSPACE_INFO_BY_ID_DSN; - lid = MG_MYSPACE_INFO_BY_ID_LID; - } else if (msim_is_email(user)) { - field_name = "Email"; - dsn = MG_MYSPACE_INFO_BY_STRING_DSN; - lid = MG_MYSPACE_INFO_BY_STRING_LID; - } else { - field_name = "UserName"; - dsn = MG_MYSPACE_INFO_BY_STRING_DSN; - lid = MG_MYSPACE_INFO_BY_STRING_LID; - } - - body = msim_msg_new( - field_name, MSIM_TYPE_STRING, g_strdup(user), - NULL); - - g_return_if_fail(msim_send(session, - "persist", MSIM_TYPE_INTEGER, 1, - "sesskey", MSIM_TYPE_INTEGER, session->sesskey, - "cmd", MSIM_TYPE_INTEGER, 1, - "dsn", MSIM_TYPE_INTEGER, dsn, - "uid", MSIM_TYPE_INTEGER, session->userid, - "lid", MSIM_TYPE_INTEGER, lid, - "rid", MSIM_TYPE_INTEGER, rid, - "body", MSIM_TYPE_DICTIONARY, body, - NULL)); -} - - -/** - * Check if a string is a userid (all numeric). - * - * @param user The user id, email, or name. - * - * @return TRUE if is userid, FALSE if not. - */ -gboolean -msim_is_userid(const gchar *user) -{ - g_return_val_if_fail(user != NULL, FALSE); - - return strspn(user, "0123456789") == strlen(user); -} - -/** - * Check if a string is an email address (contains an @). - * - * @param user The user id, email, or name. - * - * @return TRUE if is an email, FALSE if not. - * - * This function is not intended to be used as a generic - * means of validating email addresses, but to distinguish - * between a user represented by an email address from - * other forms of identification. - */ -gboolean -msim_is_email(const gchar *user) -{ - g_return_val_if_fail(user != NULL, FALSE); - - return strchr(user, '@') != NULL; -} - - -/** Callback for when a buddy icon finished being downloaded. */ -static void -msim_downloaded_buddy_icon(PurpleUtilFetchUrlData *url_data, - gpointer user_data, - const gchar *url_text, - gsize len, - const gchar *error_message) -{ - MsimUser *user; - - user = (MsimUser *)user_data; - - purple_debug_info("msim_downloaded_buddy_icon", - "Downloaded %d bytes\n", len); - - if (!url_text) { - purple_debug_info("msim_downloaded_buddy_icon", - "failed to download icon for %s", - user->buddy->name); - return; - } - - purple_buddy_icons_set_for_user(user->buddy->account, - user->buddy->name, - g_memdup((gchar *)url_text, len), len, - /* Use URL itself as buddy icon "checksum" (TODO: ETag) */ - user->image_url); /* checksum */ -} - - +/* MySpaceIM Protocol Plugin, header file + * + * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ + +#include "myspace.h" + +static void msim_store_user_info_each(const gchar *key_str, gchar *value_str, MsimUser *user); +static gchar *msim_format_now_playing(gchar *band, gchar *song); +static void msim_downloaded_buddy_icon(PurpleUtilFetchUrlData *url_data, gpointer user_data, const gchar *url_text, + gsize len, const gchar *error_message); + +/** Format the "now playing" indicator, showing the artist and song. + * @return Return a new string (must be g_free()'d), or NULL. + */ +static gchar * +msim_format_now_playing(gchar *band, gchar *song) +{ + if ((band && strlen(band)) || (song && strlen(song))) { + return g_strdup_printf("%s - %s", + (band && strlen(band)) ? band : "Unknown Artist", + (song && strlen(song)) ? song : "Unknown Song"); + } else { + return NULL; + } +} +/** Get the MsimUser from a PurpleBuddy, creating it if needed. */ +MsimUser * +msim_get_user_from_buddy(PurpleBuddy *buddy) +{ + MsimUser *user; + + if (!buddy) { + return NULL; + } + + if (!buddy->proto_data) { + /* No MsimUser for this buddy; make one. */ + + /* TODO: where is this freed? */ + user = g_new0(MsimUser, 1); + user->buddy = buddy; + buddy->proto_data = (gpointer)user; + } + + user = (MsimUser *)(buddy->proto_data); + + return user; +} + +/** Find and return an MsimUser * representing a user on the buddy list, or NULL. */ +MsimUser * +msim_find_user(MsimSession *session, const gchar *username) +{ + PurpleBuddy *buddy; + MsimUser *user; + + buddy = purple_find_buddy(session->account, username); + if (!buddy) { + return NULL; + } + + user = msim_get_user_from_buddy(buddy); + + return user; +} + +/** Append user information to a PurpleNotifyUserInfo, given an MsimUser. + * Used by msim_tooltip_text() and msim_get_info_cb() to show a user's profile. + */ +void +msim_append_user_info(MsimSession *session, PurpleNotifyUserInfo *user_info, MsimUser *user, gboolean full) +{ + gchar *str; + guint uid; + guint cv; + + /* Useful to identify the account the tooltip refers to. + * Other prpls show this. */ + if (user->username) { + purple_notify_user_info_add_pair(user_info, _("User"), user->username); + } + + uid = purple_blist_node_get_int(&user->buddy->node, "UserID"); + + if (full) { + /* TODO: link to username, if available */ + purple_notify_user_info_add_pair(user_info, _("Profile"), + g_strdup_printf("<a href=\"http://myspace.com/%d\">http://myspace.com/%d</a>", + uid, uid)); + } + + + /* a/s/l...the vitals */ + if (user->age) { + purple_notify_user_info_add_pair(user_info, _("Age"), + g_strdup_printf("%d", user->age)); + } + + if (user->gender && strlen(user->gender)) { + purple_notify_user_info_add_pair(user_info, _("Gender"), user->gender); + } + + if (user->location && strlen(user->location)) { + purple_notify_user_info_add_pair(user_info, _("Location"), user->location); + } + + /* Other information */ + if (user->headline && strlen(user->headline)) { + purple_notify_user_info_add_pair(user_info, _("Headline"), user->headline); + } + + str = msim_format_now_playing(user->band_name, user->song_name); + if (str && strlen(str)) { + purple_notify_user_info_add_pair(user_info, _("Song"), str); + } + + /* Note: total friends only available if looked up by uid, not username. */ + if (user->total_friends) { + purple_notify_user_info_add_pair(user_info, _("Total Friends"), + g_strdup_printf("%d", user->total_friends)); + } + + if (full) { + /* Client information */ + + str = user->client_info; + cv = user->client_cv; + + if (str && cv != 0) { + purple_notify_user_info_add_pair(user_info, _("Client Version"), + g_strdup_printf("%s (build %d)", str, cv)); + } else if (str) { + purple_notify_user_info_add_pair(user_info, _("Client Version"), + g_strdup(str)); + } else if (cv) { + purple_notify_user_info_add_pair(user_info, _("Client Version"), + g_strdup_printf("Build %d", cv)); + } + } +} + +/** Store a field of information about a buddy. + * + * @param key_str Key to store. + * @param value_str Value string, either user takes ownership of this string + * or it is freed if MsimUser doesn't store the string. + * @param user User to store data in. Existing data will be replaced. + * */ +void +msim_store_user_info_each(const gchar *key_str, gchar *value_str, MsimUser *user) +{ + if (g_str_equal(key_str, "UserID") || g_str_equal(key_str, "ContactID")) { + /* Save to buddy list, if it exists, for quick cached uid lookup with msim_uid2username_from_blist(). */ + if (user->buddy) + { + purple_debug_info("msim", "associating uid %s with username %s\n", key_str, user->buddy->name); + purple_blist_node_set_int(&user->buddy->node, "UserID", atol(value_str)); + } + /* Need to store in MsimUser, too? What if not on blist? */ + } else if (g_str_equal(key_str, "Age")) { + user->age = atol(value_str); + g_free(value_str); + } else if (g_str_equal(key_str, "Gender")) { + g_free(user->gender); + user->gender = value_str; + } else if (g_str_equal(key_str, "Location")) { + g_free(user->location); + user->location = value_str; + } else if (g_str_equal(key_str, "TotalFriends")) { + user->total_friends = atol(value_str); + } else if (g_str_equal(key_str, "DisplayName")) { + g_free(user->display_name); + user->display_name = value_str; + } else if (g_str_equal(key_str, "BandName")) { + g_free(user->band_name); + user->band_name = value_str; + } else if (g_str_equal(key_str, "SongName")) { + g_free(user->song_name); + user->song_name = value_str; + } else if (g_str_equal(key_str, "UserName") || g_str_equal(key_str, "IMName") || g_str_equal(key_str, "NickName")) { + /* Ignore because PurpleBuddy knows this already */ + g_free(value_str); + } else if (g_str_equal(key_str, "ImageURL") || g_str_equal(key_str, "AvatarURL")) { + const gchar *previous_url; + + g_free(user->image_url); + + user->image_url = value_str; + + /* Instead of showing 'no photo' picture, show nothing. */ + if (g_str_equal(user->image_url, "http://x.myspace.com/images/no_pic.gif")) + { + purple_buddy_icons_set_for_user(user->buddy->account, + user->buddy->name, + NULL, 0, NULL); + return; + } + + /* TODO: use ETag for checksum */ + previous_url = purple_buddy_icons_get_checksum_for_user(user->buddy); + + /* Only download if URL changed */ + if (!previous_url || !g_str_equal(previous_url, user->image_url)) { + purple_util_fetch_url(user->image_url, TRUE, NULL, TRUE, msim_downloaded_buddy_icon, (gpointer)user); + } + } else if (g_str_equal(key_str, "LastImageUpdated")) { + /* TODO: use somewhere */ + user->last_image_updated = atol(value_str); + g_free(value_str); + } else if (g_str_equal(key_str, "Headline")) { + g_free(user->headline); + user->headline = value_str; + } else { + /* TODO: other fields in MsimUser */ + gchar *msg; + + msg = g_strdup_printf("msim_store_user_info_each: unknown field %s=%s", + key_str, value_str); + g_free(value_str); + + msim_unrecognized(NULL, NULL, msg); + + g_free(msg); + } +} + +/** Save buddy information to the buddy list from a user info reply message. + * + * @param session + * @param msg The user information reply, with any amount of information. + * @param user The structure to save to, or NULL to save in PurpleBuddy->proto_data. + * + * Variable information is saved to the passed MsimUser structure. Permanent + * information (UserID) is stored in the blist node of the buddy list (and + * ends up in blist.xml, persisted to disk) if it exists. + * + * If the function has no buddy information, this function + * is a no-op (and returns FALSE). + * + */ +gboolean +msim_store_user_info(MsimSession *session, MsimMessage *msg, MsimUser *user) +{ + gchar *username; + MsimMessage *body, *body_node; + + g_return_val_if_fail(MSIM_SESSION_VALID(session), FALSE); + g_return_val_if_fail(msg != NULL, FALSE); + + body = msim_msg_get_dictionary(msg, "body"); + if (!body) { + return FALSE; + } + + username = msim_msg_get_string(body, "UserName"); + + if (!username) { + purple_debug_info("msim", + "msim_process_reply: not caching body, no UserName\n"); + msim_msg_free(body); + g_free(username); + return FALSE; + } + + /* Null user = find and store in PurpleBuddy's proto_data */ + if (!user) { + user = msim_find_user(session, username); + if (!user) { + msim_msg_free(body); + g_free(username); + return FALSE; + } + } + + /* TODO: make looping over MsimMessage's easier. */ + for (body_node = body; + body_node != NULL; + body_node = msim_msg_get_next_element_node(body_node)) + { + const gchar *key_str; + gchar *value_str; + MsimMessageElement *elem; + + elem = (MsimMessageElement *)body_node->data; + key_str = elem->name; + + value_str = msim_msg_get_string_from_element(elem); + msim_store_user_info_each(key_str, value_str, user); + } + + if (msim_msg_get_integer(msg, "dsn") == MG_OWN_IM_INFO_DSN && + msim_msg_get_integer(msg, "lid") == MG_OWN_IM_INFO_LID) { + /* TODO: do something with our own IM info, if we need it for some + * specific purpose. Otherwise it is available on the buddy list, + * if the user has themselves as their own buddy. + * + * However, much of the info is already available in MsimSession, + * stored in msim_we_are_logged_on(). */ + } else if (msim_msg_get_integer(msg, "dsn") == MG_OWN_MYSPACE_INFO_DSN && + msim_msg_get_integer(msg, "lid") == MG_OWN_MYSPACE_INFO_LID) { + /* TODO: same as above, but for MySpace info. */ + } + + msim_msg_free(body); + g_free(username); + + return TRUE; +} + +/** + * Asynchronously lookup user information, calling callback when receive result. + * + * @param session + * @param user The user id, email address, or username. Not freed. + * @param cb Callback, called with user information when available. + * @param data An arbitray data pointer passed to the callback. + */ +/* TODO: change to not use callbacks */ +void +msim_lookup_user(MsimSession *session, const gchar *user, MSIM_USER_LOOKUP_CB cb, gpointer data) +{ + MsimMessage *body; + gchar *field_name; + guint rid, cmd, dsn, lid; + + g_return_if_fail(MSIM_SESSION_VALID(session)); + g_return_if_fail(user != NULL); + /* Callback can be null to not call anything, just lookup & store information. */ + /*g_return_if_fail(cb != NULL);*/ + + purple_debug_info("msim", "msim_lookup_userid: " + "asynchronously looking up <%s>\n", user); + + msim_msg_dump("msim_lookup_user: data=%s\n", (MsimMessage *)data); + + /* Setup callback. Response will be associated with request using 'rid'. */ + rid = msim_new_reply_callback(session, cb, data); + + /* Send request */ + + cmd = MSIM_CMD_GET; + + if (msim_is_userid(user)) { + field_name = "UserID"; + dsn = MG_MYSPACE_INFO_BY_ID_DSN; + lid = MG_MYSPACE_INFO_BY_ID_LID; + } else if (msim_is_email(user)) { + field_name = "Email"; + dsn = MG_MYSPACE_INFO_BY_STRING_DSN; + lid = MG_MYSPACE_INFO_BY_STRING_LID; + } else { + field_name = "UserName"; + dsn = MG_MYSPACE_INFO_BY_STRING_DSN; + lid = MG_MYSPACE_INFO_BY_STRING_LID; + } + + body = msim_msg_new( + field_name, MSIM_TYPE_STRING, g_strdup(user), + NULL); + + g_return_if_fail(msim_send(session, + "persist", MSIM_TYPE_INTEGER, 1, + "sesskey", MSIM_TYPE_INTEGER, session->sesskey, + "cmd", MSIM_TYPE_INTEGER, 1, + "dsn", MSIM_TYPE_INTEGER, dsn, + "uid", MSIM_TYPE_INTEGER, session->userid, + "lid", MSIM_TYPE_INTEGER, lid, + "rid", MSIM_TYPE_INTEGER, rid, + "body", MSIM_TYPE_DICTIONARY, body, + NULL)); +} + + +/** + * Check if a string is a userid (all numeric). + * + * @param user The user id, email, or name. + * + * @return TRUE if is userid, FALSE if not. + */ +gboolean +msim_is_userid(const gchar *user) +{ + g_return_val_if_fail(user != NULL, FALSE); + + return strspn(user, "0123456789") == strlen(user); +} + +/** + * Check if a string is an email address (contains an @). + * + * @param user The user id, email, or name. + * + * @return TRUE if is an email, FALSE if not. + * + * This function is not intended to be used as a generic + * means of validating email addresses, but to distinguish + * between a user represented by an email address from + * other forms of identification. + */ +gboolean +msim_is_email(const gchar *user) +{ + g_return_val_if_fail(user != NULL, FALSE); + + return strchr(user, '@') != NULL; +} + + +/** Callback for when a buddy icon finished being downloaded. */ +static void +msim_downloaded_buddy_icon(PurpleUtilFetchUrlData *url_data, + gpointer user_data, + const gchar *url_text, + gsize len, + const gchar *error_message) +{ + MsimUser *user; + + user = (MsimUser *)user_data; + + purple_debug_info("msim_downloaded_buddy_icon", + "Downloaded %d bytes\n", len); + + if (!url_text) { + purple_debug_info("msim_downloaded_buddy_icon", + "failed to download icon for %s", + user->buddy->name); + return; + } + + purple_buddy_icons_set_for_user(user->buddy->account, + user->buddy->name, + g_memdup((gchar *)url_text, len), len, + /* Use URL itself as buddy icon "checksum" (TODO: ETag) */ + user->image_url); /* checksum */ +} + +
--- a/libpurple/protocols/myspace/user.h Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/protocols/myspace/user.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,55 +1,55 @@ -/* MySpaceIM Protocol Plugin, header file - * - * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ - -#ifndef _MYSPACE_USER_H -#define _MYSPACE_USER_H - -/* Hold ephemeral information about buddies, for proto_data of PurpleBuddy. */ -/* GHashTable? */ -typedef struct _MsimUser -{ - PurpleBuddy *buddy; - guint client_cv; - gchar *client_info; - guint age; - gchar *gender; - gchar *location; - guint total_friends; - gchar *headline; - gchar *display_name; - /* Note: uid is in &buddy->node (set_blist_node_int), since it never changes */ - gchar *username; - gchar *band_name, *song_name; - gchar *image_url; - guint last_image_updated; -} MsimUser; - -/* Callback function pointer type for when a user's information is received, - * initiated from a user lookup. */ -typedef void (*MSIM_USER_LOOKUP_CB)(MsimSession *session, MsimMessage *userinfo, gpointer data); - -MsimUser *msim_get_user_from_buddy(PurpleBuddy *buddy); -MsimUser *msim_find_user(MsimSession *session, const gchar *username); -void msim_append_user_info(MsimSession *session, PurpleNotifyUserInfo *user_info, MsimUser *user, gboolean full); -gboolean msim_store_user_info(MsimSession *session, MsimMessage *msg, MsimUser *user); -gboolean msim_is_userid(const gchar *user); -gboolean msim_is_email(const gchar *user); -void msim_lookup_user(MsimSession *session, const gchar *user, MSIM_USER_LOOKUP_CB cb, gpointer data); - -#endif /* !_MYSPACE_USER_H */ +/* MySpaceIM Protocol Plugin, header file + * + * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ + +#ifndef _MYSPACE_USER_H +#define _MYSPACE_USER_H + +/* Hold ephemeral information about buddies, for proto_data of PurpleBuddy. */ +/* GHashTable? */ +typedef struct _MsimUser +{ + PurpleBuddy *buddy; + guint client_cv; + gchar *client_info; + guint age; + gchar *gender; + gchar *location; + guint total_friends; + gchar *headline; + gchar *display_name; + /* Note: uid is in &buddy->node (set_blist_node_int), since it never changes */ + gchar *username; + gchar *band_name, *song_name; + gchar *image_url; + guint last_image_updated; +} MsimUser; + +/* Callback function pointer type for when a user's information is received, + * initiated from a user lookup. */ +typedef void (*MSIM_USER_LOOKUP_CB)(MsimSession *session, MsimMessage *userinfo, gpointer data); + +MsimUser *msim_get_user_from_buddy(PurpleBuddy *buddy); +MsimUser *msim_find_user(MsimSession *session, const gchar *username); +void msim_append_user_info(MsimSession *session, PurpleNotifyUserInfo *user_info, MsimUser *user, gboolean full); +gboolean msim_store_user_info(MsimSession *session, MsimMessage *msg, MsimUser *user); +gboolean msim_is_userid(const gchar *user); +gboolean msim_is_email(const gchar *user); +void msim_lookup_user(MsimSession *session, const gchar *user, MSIM_USER_LOOKUP_CB cb, gpointer data); + +#endif /* !_MYSPACE_USER_H */
--- a/libpurple/protocols/myspace/zap.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/protocols/myspace/zap.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,208 +1,208 @@ -/* MySpaceIM Protocol Plugin - zap support - * - * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ - -#include "myspace.h" -#include "zap.h" - -static gboolean msim_send_zap(MsimSession *session, const gchar *username, guint code); -static void msim_send_zap_from_menu(PurpleBlistNode *node, gpointer zap_num_ptr); - - -/** Get zap types. */ -GList * -msim_attention_types(PurpleAccount *acct) -{ - static GList *types = NULL; - MsimAttentionType* attn; - - if (!types) { -#define _MSIM_ADD_NEW_ATTENTION(icn, nme, incoming, outgoing) \ - attn = g_new0(MsimAttentionType, 1); \ - attn->icon_name = icn; \ - attn->name = nme; \ - attn->incoming_description = incoming; \ - attn->outgoing_description = outgoing; \ - types = g_list_append(types, attn); - - /* TODO: icons for each zap */ - _MSIM_ADD_NEW_ATTENTION(NULL, _("Zap"), _("%s has zapped you!"), _("Zapping %s...")); - _MSIM_ADD_NEW_ATTENTION(NULL, _("Whack"), _("%s has whacked you!"), _("Whacking %s...")); - _MSIM_ADD_NEW_ATTENTION(NULL, _("Torch"), _("%s has torched you!"), _("Torching %s...")); - _MSIM_ADD_NEW_ATTENTION(NULL, _("Smooch"), _("%s has smooched you!"), _("Smooching %s...")); - _MSIM_ADD_NEW_ATTENTION(NULL, _("Hug"), _("%s has hugged you!"), _("Hugging %s...")); - _MSIM_ADD_NEW_ATTENTION(NULL, _("Slap"), _("%s has slapped you!"), _("Slapping %s...")); - _MSIM_ADD_NEW_ATTENTION(NULL, _("Goose"), _("%s has goosed you!"), _("Goosing %s...")); - _MSIM_ADD_NEW_ATTENTION(NULL, _("High-five"), _("%s has high-fived you!"), _("High-fiving %s...")); - _MSIM_ADD_NEW_ATTENTION(NULL, _("Punk"), _("%s has punk'd you!"), _("Punking %s...")); - _MSIM_ADD_NEW_ATTENTION(NULL, _("Raspberry"), _("%s has raspberried you!"), _("Raspberrying %s...")); - } - - return types; -} - -/** Send a zap */ -gboolean -msim_send_attention(PurpleConnection *gc, const gchar *username, guint code) -{ - GList *types; - MsimSession *session; - MsimAttentionType *attn; - PurpleBuddy *buddy; - - session = (MsimSession *)gc->proto_data; - - /* Look for this attention type, by the code index given. */ - types = msim_attention_types(gc->account); - attn = (MsimAttentionType *)g_list_nth_data(types, code); - - if (!attn) { - purple_debug_info("msim_send_attention", "got invalid zap code %d\n", code); - return FALSE; - } - - buddy = purple_find_buddy(session->account, username); - if (!buddy) { - return FALSE; - } - - msim_send_zap(session, username, code); - - return TRUE; -} - -/** Send a zap to a user. */ -static gboolean -msim_send_zap(MsimSession *session, const gchar *username, guint code) -{ - gchar *zap_string; - gboolean rc; - - g_return_val_if_fail(session != NULL, FALSE); - g_return_val_if_fail(username != NULL, FALSE); - - /* Construct and send the actual zap command. */ - zap_string = g_strdup_printf("!!!ZAP_SEND!!!=RTE_BTN_ZAPS_%d", code); - - if (!msim_send_bm(session, username, zap_string, MSIM_BM_ACTION)) { - purple_debug_info("msim_send_zap_from_menu", "msim_send_bm failed: zapping %s with %s\n", - username, zap_string); - rc = FALSE; - } else { - rc = TRUE; - } - - g_free(zap_string); - - return rc; - -} - -/** Zap someone. Callback from msim_blist_node_menu zap menu. */ -static void -msim_send_zap_from_menu(PurpleBlistNode *node, gpointer zap_num_ptr) -{ - PurpleBuddy *buddy; - PurpleAccount *account; - PurpleConnection *gc; - MsimSession *session; - guint zap; - - if (!PURPLE_BLIST_NODE_IS_BUDDY(node)) { - /* Only know about buddies for now. */ - return; - } - - g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); - - buddy = (PurpleBuddy *)node; - - /* Find the session */ - account = buddy->account; - gc = purple_account_get_connection(account); - session = (MsimSession *)gc->proto_data; - - zap = GPOINTER_TO_INT(zap_num_ptr); - - serv_send_attention(session->gc, buddy->name, zap); -} - -/** Return menu, if any, for a buddy list node. */ -GList * -msim_blist_node_menu(PurpleBlistNode *node) -{ - GList *menu, *zap_menu; - GList *types; - PurpleMenuAction *act; - guint i; - - if (!PURPLE_BLIST_NODE_IS_BUDDY(node)) { - /* Only know about buddies for now. */ - return NULL; - } - - zap_menu = NULL; - - /* TODO: get rid of once is accessible directly in GUI */ - types = msim_attention_types(NULL); - i = 0; - do - { - MsimAttentionType *attn; - - attn = (MsimAttentionType *)types->data; - - act = purple_menu_action_new(attn->name, PURPLE_CALLBACK(msim_send_zap_from_menu), - GUINT_TO_POINTER(i), NULL); - zap_menu = g_list_append(zap_menu, act); - - ++i; - } while ((types = g_list_next(types))); - - act = purple_menu_action_new(_("Zap"), NULL, NULL, zap_menu); - menu = g_list_append(NULL, act); - - return menu; -} - -/** Process an incoming zap. */ -gboolean -msim_incoming_zap(MsimSession *session, MsimMessage *msg) -{ - gchar *msg_text, *username; - gint zap; - - msg_text = msim_msg_get_string(msg, "msg"); - username = msim_msg_get_string(msg, "_username"); - - g_return_val_if_fail(msg_text != NULL, FALSE); - g_return_val_if_fail(username != NULL, FALSE); - - g_return_val_if_fail(sscanf(msg_text, "!!!ZAP_SEND!!!=RTE_BTN_ZAPS_%d", &zap) == 1, FALSE); - - zap = CLAMP(zap, 0, 9); - - serv_got_attention(session->gc, username, zap); - - g_free(msg_text); - g_free(username); - - return TRUE; -} - - +/* MySpaceIM Protocol Plugin - zap support + * + * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ + +#include "myspace.h" +#include "zap.h" + +static gboolean msim_send_zap(MsimSession *session, const gchar *username, guint code); +static void msim_send_zap_from_menu(PurpleBlistNode *node, gpointer zap_num_ptr); + + +/** Get zap types. */ +GList * +msim_attention_types(PurpleAccount *acct) +{ + static GList *types = NULL; + MsimAttentionType* attn; + + if (!types) { +#define _MSIM_ADD_NEW_ATTENTION(icn, nme, incoming, outgoing) \ + attn = g_new0(MsimAttentionType, 1); \ + attn->icon_name = icn; \ + attn->name = nme; \ + attn->incoming_description = incoming; \ + attn->outgoing_description = outgoing; \ + types = g_list_append(types, attn); + + /* TODO: icons for each zap */ + _MSIM_ADD_NEW_ATTENTION(NULL, _("Zap"), _("%s has zapped you!"), _("Zapping %s...")); + _MSIM_ADD_NEW_ATTENTION(NULL, _("Whack"), _("%s has whacked you!"), _("Whacking %s...")); + _MSIM_ADD_NEW_ATTENTION(NULL, _("Torch"), _("%s has torched you!"), _("Torching %s...")); + _MSIM_ADD_NEW_ATTENTION(NULL, _("Smooch"), _("%s has smooched you!"), _("Smooching %s...")); + _MSIM_ADD_NEW_ATTENTION(NULL, _("Hug"), _("%s has hugged you!"), _("Hugging %s...")); + _MSIM_ADD_NEW_ATTENTION(NULL, _("Slap"), _("%s has slapped you!"), _("Slapping %s...")); + _MSIM_ADD_NEW_ATTENTION(NULL, _("Goose"), _("%s has goosed you!"), _("Goosing %s...")); + _MSIM_ADD_NEW_ATTENTION(NULL, _("High-five"), _("%s has high-fived you!"), _("High-fiving %s...")); + _MSIM_ADD_NEW_ATTENTION(NULL, _("Punk"), _("%s has punk'd you!"), _("Punking %s...")); + _MSIM_ADD_NEW_ATTENTION(NULL, _("Raspberry"), _("%s has raspberried you!"), _("Raspberrying %s...")); + } + + return types; +} + +/** Send a zap */ +gboolean +msim_send_attention(PurpleConnection *gc, const gchar *username, guint code) +{ + GList *types; + MsimSession *session; + MsimAttentionType *attn; + PurpleBuddy *buddy; + + session = (MsimSession *)gc->proto_data; + + /* Look for this attention type, by the code index given. */ + types = msim_attention_types(gc->account); + attn = (MsimAttentionType *)g_list_nth_data(types, code); + + if (!attn) { + purple_debug_info("msim_send_attention", "got invalid zap code %d\n", code); + return FALSE; + } + + buddy = purple_find_buddy(session->account, username); + if (!buddy) { + return FALSE; + } + + msim_send_zap(session, username, code); + + return TRUE; +} + +/** Send a zap to a user. */ +static gboolean +msim_send_zap(MsimSession *session, const gchar *username, guint code) +{ + gchar *zap_string; + gboolean rc; + + g_return_val_if_fail(session != NULL, FALSE); + g_return_val_if_fail(username != NULL, FALSE); + + /* Construct and send the actual zap command. */ + zap_string = g_strdup_printf("!!!ZAP_SEND!!!=RTE_BTN_ZAPS_%d", code); + + if (!msim_send_bm(session, username, zap_string, MSIM_BM_ACTION)) { + purple_debug_info("msim_send_zap_from_menu", "msim_send_bm failed: zapping %s with %s\n", + username, zap_string); + rc = FALSE; + } else { + rc = TRUE; + } + + g_free(zap_string); + + return rc; + +} + +/** Zap someone. Callback from msim_blist_node_menu zap menu. */ +static void +msim_send_zap_from_menu(PurpleBlistNode *node, gpointer zap_num_ptr) +{ + PurpleBuddy *buddy; + PurpleAccount *account; + PurpleConnection *gc; + MsimSession *session; + guint zap; + + if (!PURPLE_BLIST_NODE_IS_BUDDY(node)) { + /* Only know about buddies for now. */ + return; + } + + g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); + + buddy = (PurpleBuddy *)node; + + /* Find the session */ + account = buddy->account; + gc = purple_account_get_connection(account); + session = (MsimSession *)gc->proto_data; + + zap = GPOINTER_TO_INT(zap_num_ptr); + + serv_send_attention(session->gc, buddy->name, zap); +} + +/** Return menu, if any, for a buddy list node. */ +GList * +msim_blist_node_menu(PurpleBlistNode *node) +{ + GList *menu, *zap_menu; + GList *types; + PurpleMenuAction *act; + guint i; + + if (!PURPLE_BLIST_NODE_IS_BUDDY(node)) { + /* Only know about buddies for now. */ + return NULL; + } + + zap_menu = NULL; + + /* TODO: get rid of once is accessible directly in GUI */ + types = msim_attention_types(NULL); + i = 0; + do + { + MsimAttentionType *attn; + + attn = (MsimAttentionType *)types->data; + + act = purple_menu_action_new(attn->name, PURPLE_CALLBACK(msim_send_zap_from_menu), + GUINT_TO_POINTER(i), NULL); + zap_menu = g_list_append(zap_menu, act); + + ++i; + } while ((types = g_list_next(types))); + + act = purple_menu_action_new(_("Zap"), NULL, NULL, zap_menu); + menu = g_list_append(NULL, act); + + return menu; +} + +/** Process an incoming zap. */ +gboolean +msim_incoming_zap(MsimSession *session, MsimMessage *msg) +{ + gchar *msg_text, *username; + gint zap; + + msg_text = msim_msg_get_string(msg, "msg"); + username = msim_msg_get_string(msg, "_username"); + + g_return_val_if_fail(msg_text != NULL, FALSE); + g_return_val_if_fail(username != NULL, FALSE); + + g_return_val_if_fail(sscanf(msg_text, "!!!ZAP_SEND!!!=RTE_BTN_ZAPS_%d", &zap) == 1, FALSE); + + zap = CLAMP(zap, 0, 9); + + serv_got_attention(session->gc, username, zap); + + g_free(msg_text); + g_free(username); + + return TRUE; +} + +
--- a/libpurple/protocols/myspace/zap.h Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/protocols/myspace/zap.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,28 +1,28 @@ -/* MySpaceIM Protocol Plugin - zap support - * - * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ - -#ifndef _MYSPACE_ZAP_H -#define _MYSPACE_ZAP_H - -GList *msim_attention_types(PurpleAccount *acct); -gboolean msim_send_attention(PurpleConnection *gc, const gchar *username, guint code); -GList *msim_blist_node_menu(PurpleBlistNode *node); -gboolean msim_incoming_zap(MsimSession *session, MsimMessage *msg); - -#endif /* !_MYSPACE_ZAP_H */ +/* MySpaceIM Protocol Plugin - zap support + * + * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ + +#ifndef _MYSPACE_ZAP_H +#define _MYSPACE_ZAP_H + +GList *msim_attention_types(PurpleAccount *acct); +gboolean msim_send_attention(PurpleConnection *gc, const gchar *username, guint code); +GList *msim_blist_node_menu(PurpleBlistNode *node); +gboolean msim_incoming_zap(MsimSession *session, MsimMessage *msg); + +#endif /* !_MYSPACE_ZAP_H */
--- a/libpurple/protocols/oscar/.todo Mon Oct 01 17:02:03 2007 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -<todo version="0.1.19"> - <note priority="high" time="1036040788"> - watch for aol's upcoming increased aim/icq merge - </note> - <note priority="medium" time="1036040405"> - AIM - <note priority="high" time="1036040899"> - option to ignore chat room invitations. (this is something you could vary conceivably want to be done per account, so perhaps a protocol action would be best) - </note> - <note priority="medium" time="1092939731"> - buddies in Recent Buddies don't seem to delete right - </note> - <note priority="low" time="1036040980"> - direct im - <note priority="veryhigh" time="1036040919"> - some way to close direct connect w/out closing convo. - </note> - <note priority="low" time="1036041084"> - failed direct im attempt should allow new attempt some way to cancel an attempt that isn't happening - </note> - </note> - <note priority="verylow" time="1036041121"> - Voice Chat - </note> - </note> - <note priority="medium" time="1036040416"> - ICQ - <note priority="veryhigh" time="1036041206"> - more privacy options - </note> - <note priority="veryhigh" time="1036041223"> - increased authorization support - <note priority="medium" time="1038877503"> - add info to dialog requesting autorization to allow you to check the info of the person who is requesting - </note> - </note> - <note priority="high" time="1036041199"> - color support - </note> - <note priority="high" time="1036041251"> - set status message and of course when libpurple can set them, it needs to be able to get the ones it sets. (yes this is redundant. its a reflection of my current mood) - </note> - <note priority="medium" time="1036041165"> - Chat (this is different from aim chat) - </note> - <note priority="medium" time="1036041190"> - New User Registration - </note> - <note priority="medium" time="1036041215"> - more info support - </note> - <note priority="medium" time="1036041260"> - search for users - </note> - <note priority="low" time="1036041152"> - set the Nickname to be the self-alias - </note> - <note priority="low" time="1092939688"> - icq i18n without breaking aim - </note> - </note> - <note priority="medium" time="1036040870"> - The order of groups and buddies in the server list is not updated when groups and buddies are re-arranged locally in libpurple. - </note> -</todo>
--- a/libpurple/protocols/oscar/AUTHORS Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/protocols/oscar/AUTHORS Mon Oct 01 17:49:01 2007 +0000 @@ -1,3 +1,7 @@ + +N: ComBOTS Product GmbH (htfv) +T: 2007 +E: foss@combots.com N: Jonathan Clark T: 2005-2006
--- a/libpurple/protocols/oscar/family_auth.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/protocols/oscar/family_auth.c Mon Oct 01 17:49:01 2007 +0000 @@ -438,10 +438,6 @@ * login request instead of the normal SNAC one. * * As soon as AOL makes ICQ log in the same way as AIM, this is /gone/. - * - * XXX This may cause problems if the client relies on callbacks only - * being called from the context of aim_rxdispatch()... - * */ static int goddamnicq(OscarData *od, FlapConnection *conn, const char *sn)
--- a/libpurple/protocols/oscar/family_feedbag.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/protocols/oscar/family_feedbag.c Mon Oct 01 17:49:01 2007 +0000 @@ -1424,7 +1424,7 @@ aim_tlvlist_free(data); if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) - ret = userfunc(od, conn, frame, type, name); + ret = userfunc(od, conn, frame, snac->subtype, type, name); g_free(name); } @@ -1434,8 +1434,6 @@ /* * Subtype 0x0009 - Incoming SSI mod. - * - * XXX - It would probably be good for the client to actually do something when it gets this. */ static int parsemod(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { @@ -1485,7 +1483,7 @@ } if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) - ret = userfunc(od, conn, frame); + ret = userfunc(od, conn, frame, snac->subtype, type, name); g_free(name); aim_tlvlist_free(data);
--- a/libpurple/protocols/oscar/oscar.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/protocols/oscar/oscar.c Mon Oct 01 17:49:01 2007 +0000 @@ -4,8 +4,9 @@ * Some code copyright (C) 1998-1999, Mark Spencer <markster@marko.net> * Some code copyright (C) 1999-2001, Eric Warmenhoven * Some code copyright (C) 2001-2003, Sean Egan - * Some code copyright (C) 2001-2005, Mark Doliner <thekingant@users.sourceforge.net> + * Some code copyright (C) 2001-2007, Mark Doliner <thekingant@users.sourceforge.net> * Some code copyright (C) 2005, Jonathan Clark <ardentlygnarly@users.sourceforge.net> + * Some code copyright (C) 2007, ComBOTS Product GmbH (htfv) <foss@combots.com> * * Most libfaim code copyright (C) 1998-2001 Adam Fritzler <afritz@auk.cx> * Some libfaim code copyright (C) 2001-2004 Mark Doliner <thekingant@users.sourceforge.net> @@ -188,7 +189,7 @@ static int purple_ssi_parserights (OscarData *, FlapConnection *, FlapFrame *, ...); static int purple_ssi_parselist (OscarData *, FlapConnection *, FlapFrame *, ...); static int purple_ssi_parseack (OscarData *, FlapConnection *, FlapFrame *, ...); -static int purple_ssi_parseadd (OscarData *, FlapConnection *, FlapFrame *, ...); +static int purple_ssi_parseaddmod (OscarData *, FlapConnection *, FlapFrame *, ...); static int purple_ssi_authgiven (OscarData *, FlapConnection *, FlapFrame *, ...); static int purple_ssi_authrequest (OscarData *, FlapConnection *, FlapFrame *, ...); static int purple_ssi_authreply (OscarData *, FlapConnection *, FlapFrame *, ...); @@ -1219,7 +1220,8 @@ oscar_data_addhandler(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_RIGHTSINFO, purple_ssi_parserights, 0); oscar_data_addhandler(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_LIST, purple_ssi_parselist, 0); oscar_data_addhandler(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_SRVACK, purple_ssi_parseack, 0); - oscar_data_addhandler(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_ADD, purple_ssi_parseadd, 0); + oscar_data_addhandler(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_ADD, purple_ssi_parseaddmod, 0); + oscar_data_addhandler(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_MOD, purple_ssi_parseaddmod, 0); oscar_data_addhandler(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_RECVAUTH, purple_ssi_authgiven, 0); oscar_data_addhandler(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_RECVAUTHREQ, purple_ssi_authrequest, 0); oscar_data_addhandler(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_RECVAUTHREP, purple_ssi_authreply, 0); @@ -1632,7 +1634,8 @@ { PurpleConnection *gc; PurpleAccount *account; - ClientInfo info = CLIENTINFO_PURPLE; + ClientInfo aiminfo = CLIENTINFO_PURPLE_AIM; + ClientInfo icqinfo = CLIENTINFO_PURPLE_ICQ; va_list ap; char *key; gboolean truncate_pass; @@ -1647,7 +1650,7 @@ aim_send_login(od, conn, purple_account_get_username(account), purple_connection_get_password(gc), truncate_pass, - &info, key); + od->icq ? &icqinfo : &aiminfo, key); purple_connection_update_progress(gc, _("Password sent"), 2, OSCAR_CONNECT_STEPS); ck[2] = 0x6c; @@ -1870,6 +1873,10 @@ saved_b16 = purple_buddy_icons_get_checksum_for_user(b); if (!b16 || !saved_b16 || strcmp(b16, saved_b16)) { + /* Invalidate the old icon for this user */ + purple_buddy_icons_set_for_user(account, info->sn, NULL, 0, NULL); + + /* Fetch the new icon (if we're not already doing so) */ if (g_slist_find_custom(od->requesticon, info->sn, (GCompareFunc)aim_sncmp) == NULL) { @@ -4932,10 +4939,7 @@ b = purple_find_buddy_in_group(gc->account, curitem->name, g); if (b) { /* Get server stored alias */ - if (alias_utf8) { - g_free(b->alias); - b->alias = g_strdup(alias_utf8); - } + purple_blist_alias_buddy(b, alias_utf8); } else { b = purple_buddy_new(gc->account, curitem->name, alias_utf8); @@ -5079,16 +5083,23 @@ return 1; } -static int purple_ssi_parseadd(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { - PurpleConnection *gc = od->gc; +static int +purple_ssi_parseaddmod(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) +{ + PurpleConnection *gc; + PurpleAccount *account; char *gname, *gname_utf8, *alias, *alias_utf8; PurpleBuddy *b; PurpleGroup *g; va_list ap; - guint16 type; + guint16 snac_subtype, type; const char *name; + gc = od->gc; + account = purple_connection_get_account(gc); + va_start(ap, fr); + snac_subtype = (guint16)va_arg(ap, int); type = (guint16)va_arg(ap, int); name = va_arg(ap, char *); va_end(ap); @@ -5097,7 +5108,7 @@ return 1; gname = aim_ssi_itemlist_findparentname(od->ssi.local, name); - gname_utf8 = gname ? oscar_utf8_try_convert(gc->account, gname) : NULL; + gname_utf8 = gname ? oscar_utf8_try_convert(account, gname) : NULL; alias = aim_ssi_getalias(od->ssi.local, gname, name); if (alias != NULL) @@ -5105,22 +5116,26 @@ if (g_utf8_validate(alias, -1, NULL)) alias_utf8 = g_strdup(alias); else - alias_utf8 = oscar_utf8_try_convert(purple_connection_get_account(gc), alias); + alias_utf8 = oscar_utf8_try_convert(account, alias); } else alias_utf8 = NULL; - - b = purple_find_buddy(gc->account, name); g_free(alias); + b = purple_find_buddy(account, name); if (b) { - /* Get server stored alias */ - if (alias_utf8) { - g_free(b->alias); - b->alias = g_strdup(alias_utf8); - } - } else { - b = purple_buddy_new(gc->account, name, alias_utf8); + /* + * You're logged in somewhere else and you aliased one + * of your buddies, so update our local buddy list with + * the person's new alias. + */ + purple_blist_alias_buddy(b, alias_utf8); + } else if (snac_subtype == 0x0008) { + /* + * You're logged in somewhere else and you added a buddy to + * your server list, so add them to your local buddy list. + */ + b = purple_buddy_new(account, name, alias_utf8); if (!(g = purple_find_group(gname_utf8 ? gname_utf8 : _("Orphans")))) { g = purple_group_new(gname_utf8 ? gname_utf8 : _("Orphans")); @@ -5131,6 +5146,7 @@ "ssi: adding buddy %s to group %s to local list\n", name, gname_utf8 ? gname_utf8 : _("Orphans")); purple_blist_add_buddy(b, NULL, g, NULL); } + g_free(gname_utf8); g_free(alias_utf8);
--- a/libpurple/protocols/oscar/oscar.h Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/protocols/oscar/oscar.h Mon Oct 01 17:49:01 2007 +0000 @@ -3,6 +3,8 @@ * This file is the legal property of its developers. * Please see the AUTHORS file distributed alongside this file. * + * Some code copyright (C) 2007, ComBOTS Product GmbH (htfv) <foss@combots.com> + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either @@ -270,6 +272,15 @@ "us", "en", \ } +#define CLIENTINFO_ICQBASIC_14_34_3000 { \ + "ICQBasic", \ + 0x010a, \ + 0x0014, 0x0034, \ + 0x0000, 0x0bb8, \ + 0x0000043d, \ + "us", "en", \ +} + #define CLIENTINFO_NETSCAPE_7_0_1 { \ "Netscape 2000 an approved user of AOL Instant Messenger (SM)", \ 0x1d0d, \ @@ -280,10 +291,11 @@ } /* - * TODO: Use PURPLE_MAJOR_VERSION, PURPLE_MINOR_VERSION, and - * PURPLE_MICRO_VERSION? Or did that break things? + * We need to use the major-minor-micro versions from the official + * AIM and ICQ programs here or AOL won't let us use certain features. */ -#define CLIENTINFO_PURPLE { \ + +#define CLIENTINFO_PURPLE_AIM { \ "Purple/" VERSION, \ 0x0109, \ 0x0005, 0x0001, \ @@ -292,6 +304,15 @@ "us", "en", \ } +#define CLIENTINFO_PURPLE_ICQ { \ + "Purple/" VERSION, \ + 0x010a, \ + 0x0014, 0x0034, \ + 0x0000, 0x0bb8, \ + 0x0000043d, \ + "us", "en", \ +} + #define CLIENTINFO_AIM_KNOWNGOOD CLIENTINFO_AIM_5_1_3036 #define CLIENTINFO_ICQ_KNOWNGOOD CLIENTINFO_ICQ_5_45_3777
--- a/libpurple/protocols/yahoo/yahoo.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/protocols/yahoo/yahoo.c Mon Oct 01 17:49:01 2007 +0000 @@ -860,10 +860,13 @@ /* If a Doodle session doesn't exist between this user */ if(wb == NULL) { + doodle_session *ds; wb = purple_whiteboard_create(gc->account, im->from, DOODLE_STATE_REQUESTED); - - yahoo_doodle_command_send_request(gc, im->from); - yahoo_doodle_command_send_ready(gc, im->from); + ds = wb->proto_data; + ds->imv_key = g_strdup(imv); + + yahoo_doodle_command_send_request(gc, im->from, imv); + yahoo_doodle_command_send_ready(gc, im->from, imv); } } }
--- a/libpurple/protocols/yahoo/yahoo_aliases.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/protocols/yahoo/yahoo_aliases.c Mon Oct 01 17:49:01 2007 +0000 @@ -45,7 +45,7 @@ */ struct callback_data { PurpleConnection *gc; - const char *id; + char *id; }; @@ -56,11 +56,16 @@ static void yahoo_fetch_aliases_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data,const gchar *url_text, size_t len, const gchar *error_message) { + struct callback_data *cb = user_data; + PurpleConnection *gc = cb->gc; + struct yahoo_data *yd = gc->proto_data; + + yd->url_datas = g_slist_remove(yd->url_datas, url_data); + if (len == 0) { purple_debug_info("yahoo","No Aliases to process\n"); } else { const char *yid, *full_name, *nick_name, *alias, *id, *fn, *ln, *nn; - struct callback_data *cb = user_data; PurpleBuddy *b = NULL; xmlnode *item, *contacts; @@ -123,8 +128,9 @@ } } xmlnode_free(contacts); - g_free(cb); } + g_free(cb->id); + g_free(cb); } void @@ -134,6 +140,7 @@ struct callback_data *cb; char *url, *request, *webpage, *webaddress, *strtmp; int inttmp; + PurpleUtilFetchUrlData *url_data; /* Using callback_data so I have access to gc in the callback function */ cb = g_new0(struct callback_data, 1); @@ -150,7 +157,12 @@ webpage, yd->cookie_t,yd->cookie_y, webaddress); /* We have a URL and some header information, let's connect and get some aliases */ - purple_util_fetch_url_request(url, FALSE, NULL, TRUE, request, FALSE, yahoo_fetch_aliases_cb, cb); + url_data = purple_util_fetch_url_request(url, FALSE, NULL, TRUE, request, FALSE, yahoo_fetch_aliases_cb, cb); + if (url_data != NULL) { + yd->url_datas = g_slist_prepend(yd->url_datas, url_data); + } else { + g_free(cb); + } g_free(url); g_free(request); @@ -165,6 +177,11 @@ { xmlnode *node, *result; struct callback_data *cb = user_data; + PurpleConnection *gc = cb->gc; + struct yahoo_data *yd; + + yd = gc->proto_data; + yd->url_datas = g_slist_remove(yd->url_datas, url_data); result = xmlnode_from_str(url_text, -1); @@ -184,6 +201,7 @@ purple_debug_info("yahoo", "Alias update failed (No contact record returned)\n"); } + g_free(cb->id); g_free(cb); xmlnode_free(result); } @@ -197,6 +215,7 @@ int inttmp; struct callback_data *cb; PurpleBuddy *buddy; + PurpleUtilFetchUrlData *url_data; g_return_if_fail(alias!= NULL); g_return_if_fail(who!=NULL); @@ -216,6 +235,7 @@ /* Using callback_data so I have access to gc in the callback function */ cb = g_new0(struct callback_data, 1); cb->id = g_strdup(yu->id); + cb->gc = gc; /* Build all the info to make the web request */ url = g_strdup(YAHOO_ALIAS_UPDATE_URL); @@ -236,7 +256,13 @@ strlen(content), content); /* We have a URL and some header information, let's connect and update the alias */ - purple_util_fetch_url_request(url, FALSE, NULL, TRUE, request, FALSE, yahoo_update_alias_cb, cb); + url_data = purple_util_fetch_url_request(url, FALSE, NULL, TRUE, request, FALSE, yahoo_update_alias_cb, cb); + if (url_data != NULL) { + yd->url_datas = g_slist_prepend(yd->url_datas, url_data); + } else { + g_free(cb->id); + g_free(cb); + } g_free(content); g_free(url);
--- a/libpurple/protocols/yahoo/yahoo_doodle.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/protocols/yahoo/yahoo_doodle.c Mon Oct 01 17:49:01 2007 +0000 @@ -118,19 +118,19 @@ /* Insert this 'session' in the list. At this point, it's only a * requested session. */ - purple_whiteboard_create(account, to, DOODLE_STATE_REQUESTING); + wb = purple_whiteboard_create(account, to, DOODLE_STATE_REQUESTING); } /* NOTE Perhaps some careful handling of remote assumed established * sessions */ - yahoo_doodle_command_send_ready(gc, to); - yahoo_doodle_command_send_request(gc, to); + yahoo_doodle_command_send_ready(gc, to, DOODLE_IMV_KEY); + yahoo_doodle_command_send_request(gc, to, DOODLE_IMV_KEY); } -static void yahoo_doodle_command_got_request(PurpleConnection *gc, const char *from) +static void yahoo_doodle_command_got_request(PurpleConnection *gc, const char *from, const char *imv_key) { PurpleAccount *account; PurpleWhiteboard *wb; @@ -147,6 +147,7 @@ /* If a session with the remote user doesn't exist */ if(wb == NULL) { + doodle_session *ds; /* Ask user if they wish to accept the request for a doodle session */ /* TODO Ask local user to start Doodle session with remote user */ /* NOTE This if/else statement won't work right--must use dialog @@ -160,9 +161,11 @@ dialog_message, NULL, NULL, NULL); */ - purple_whiteboard_create(account, from, DOODLE_STATE_REQUESTED); + wb = purple_whiteboard_create(account, from, DOODLE_STATE_REQUESTED); + ds = wb->proto_data; + ds->imv_key = g_strdup(imv_key); - yahoo_doodle_command_send_ready(gc, from); + yahoo_doodle_command_send_ready(gc, from, imv_key); } /* TODO Might be required to clear the canvas of an existing doodle @@ -170,7 +173,7 @@ */ } -static void yahoo_doodle_command_got_ready(PurpleConnection *gc, const char *from) +static void yahoo_doodle_command_got_ready(PurpleConnection *gc, const char *from, const char *imv_key) { PurpleAccount *account; PurpleWhiteboard *wb; @@ -189,11 +192,15 @@ if(wb->state == DOODLE_STATE_REQUESTING) { + doodle_session *ds = wb->proto_data; purple_whiteboard_start(wb); wb->state = DOODLE_STATE_ESTABLISHED; - yahoo_doodle_command_send_confirm(gc, from); + yahoo_doodle_command_send_confirm(gc, from, imv_key); + /* Let's steal the imv_key and reuse it */ + g_free(ds->imv_key); + ds->imv_key = g_strdup(imv_key); } else if(wb->state == DOODLE_STATE_ESTABLISHED) { @@ -208,7 +215,7 @@ else if(wb->state == DOODLE_STATE_REQUESTED) { /* purple_whiteboard_start(wb); */ - yahoo_doodle_command_send_ready(gc, from); + yahoo_doodle_command_send_ready(gc, from, imv_key); } } @@ -296,14 +303,14 @@ static void -yahoo_doodle_command_got_extra(PurpleConnection *gc, const char *from, const char *message) +yahoo_doodle_command_got_extra(PurpleConnection *gc, const char *from, const char *message, const char *imv_key) { purple_debug_info("yahoo", "doodle: Got Extra (%s)\n", from); /* I do not like these 'extra' features, so I'll only handle them in one * way, which is returning them with the command/packet to turn them off */ - yahoo_doodle_command_send_extra(gc, from, DOODLE_EXTRA_NONE); + yahoo_doodle_command_send_extra(gc, from, DOODLE_EXTRA_NONE, imv_key); } static void yahoo_doodle_command_got_confirm(PurpleConnection *gc, const char *from) @@ -399,34 +406,34 @@ yahoo_packet_send_and_free(pkt, yd); } -void yahoo_doodle_command_send_ready(PurpleConnection *gc, const char *to) +void yahoo_doodle_command_send_ready(PurpleConnection *gc, const char *to, const char *imv_key) { - yahoo_doodle_command_send_generic("Ready", gc, to, "1", DOODLE_CMD_READY, NULL, "1"); + yahoo_doodle_command_send_generic("Ready", gc, to, "1", DOODLE_CMD_READY, imv_key, "1"); } -void yahoo_doodle_command_send_request(PurpleConnection *gc, const char *to) +void yahoo_doodle_command_send_request(PurpleConnection *gc, const char *to, const char *imv_key) { - yahoo_doodle_command_send_generic("Request", gc, to, "", DOODLE_CMD_REQUEST, NULL, "0"); + yahoo_doodle_command_send_generic("Request", gc, to, "", DOODLE_CMD_REQUEST, imv_key, "0"); } -void yahoo_doodle_command_send_draw(PurpleConnection *gc, const char *to, const char *message) +void yahoo_doodle_command_send_draw(PurpleConnection *gc, const char *to, const char *message, const char *imv_key) { - yahoo_doodle_command_send_generic("Draw", gc, to, message, DOODLE_CMD_DRAW, NULL, "1"); + yahoo_doodle_command_send_generic("Draw", gc, to, message, DOODLE_CMD_DRAW, imv_key, "1"); } -void yahoo_doodle_command_send_clear(PurpleConnection *gc, const char *to) +void yahoo_doodle_command_send_clear(PurpleConnection *gc, const char *to, const char *imv_key) { - yahoo_doodle_command_send_generic("Clear", gc, to, " ", DOODLE_CMD_CLEAR, NULL, "1"); + yahoo_doodle_command_send_generic("Clear", gc, to, " ", DOODLE_CMD_CLEAR, imv_key, "1"); } -void yahoo_doodle_command_send_extra(PurpleConnection *gc, const char *to, const char *message) +void yahoo_doodle_command_send_extra(PurpleConnection *gc, const char *to, const char *message, const char *imv_key) { - yahoo_doodle_command_send_generic("Extra", gc, to, message, DOODLE_CMD_EXTRA, NULL, "1"); + yahoo_doodle_command_send_generic("Extra", gc, to, message, DOODLE_CMD_EXTRA, imv_key, "1"); } -void yahoo_doodle_command_send_confirm(PurpleConnection *gc, const char *to) +void yahoo_doodle_command_send_confirm(PurpleConnection *gc, const char *to, const char *imv_key) { - yahoo_doodle_command_send_generic("Confirm", gc, to, "1", DOODLE_CMD_CONFIRM, NULL, "1"); + yahoo_doodle_command_send_generic("Confirm", gc, to, "1", DOODLE_CMD_CONFIRM, imv_key, "1"); } void yahoo_doodle_command_send_shutdown(PurpleConnection *gc, const char *to) @@ -450,12 +457,14 @@ void yahoo_doodle_end(PurpleWhiteboard *wb) { PurpleConnection *gc = purple_account_get_connection(wb->account); + doodle_session *ds = wb->proto_data; /* g_debug_debug("yahoo", "doodle: yahoo_doodle_end()\n"); */ if (gc && wb->state != DOODLE_STATE_CANCELED) yahoo_doodle_command_send_shutdown(gc, wb->who); + g_free(ds->imv_key); g_free(wb->proto_data); } @@ -492,13 +501,14 @@ g_return_if_fail(draw_list != NULL); message = yahoo_doodle_build_draw_string(ds, draw_list); - yahoo_doodle_command_send_draw(wb->account->gc, wb->who, message); + yahoo_doodle_command_send_draw(wb->account->gc, wb->who, message, ds->imv_key); g_free(message); } void yahoo_doodle_clear(PurpleWhiteboard *wb) { - yahoo_doodle_command_send_clear(wb->account->gc, wb->who); + doodle_session *ds = wb->proto_data; + yahoo_doodle_command_send_clear(wb->account->gc, wb->who, ds->imv_key); } @@ -551,14 +561,14 @@ void yahoo_doodle_get_brush(const PurpleWhiteboard *wb, int *size, int *color) { - doodle_session *ds = (doodle_session *)wb->proto_data; + doodle_session *ds = wb->proto_data; *size = ds->brush_size; *color = ds->brush_color; } void yahoo_doodle_set_brush(PurpleWhiteboard *wb, int size, int color) { - doodle_session *ds = (doodle_session *)wb->proto_data; + doodle_session *ds = wb->proto_data; ds->brush_size = size; ds->brush_color = color; @@ -567,7 +577,7 @@ } void yahoo_doodle_process(PurpleConnection *gc, const char *me, const char *from, - const char *command, const char *message) + const char *command, const char *message, const char *imv_key) { if(!command) return; @@ -576,11 +586,11 @@ switch(atoi(command)) { case DOODLE_CMD_REQUEST: - yahoo_doodle_command_got_request(gc, from); + yahoo_doodle_command_got_request(gc, from, imv_key); break; case DOODLE_CMD_READY: - yahoo_doodle_command_got_ready(gc, from); + yahoo_doodle_command_got_ready(gc, from, imv_key); break; case DOODLE_CMD_CLEAR: @@ -592,7 +602,7 @@ break; case DOODLE_CMD_EXTRA: - yahoo_doodle_command_got_extra(gc, from, message); + yahoo_doodle_command_got_extra(gc, from, message, imv_key); break; case DOODLE_CMD_CONFIRM:
--- a/libpurple/protocols/yahoo/yahoo_doodle.h Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/protocols/yahoo/yahoo_doodle.h Mon Oct 01 17:49:01 2007 +0000 @@ -31,7 +31,7 @@ #include "whiteboard.h" #include "cmds.h" -#define DOODLE_IMV_KEY "doodle;103" +#define DOODLE_IMV_KEY "doodle;106" /****************************************************************************** * Defines @@ -94,6 +94,7 @@ { int brush_size; /* Size of drawing brush */ int brush_color; /* Color of drawing brush */ + gchar *imv_key; } doodle_session; /****************************************************************************** @@ -104,17 +105,17 @@ char **error, void *data); void yahoo_doodle_process(PurpleConnection *gc, const char *me, const char *from, - const char *command, const char *message); + const char *command, const char *message, const char *imv_key); void yahoo_doodle_initiate(PurpleConnection *gc, const char *to); void yahoo_doodle_command_got_shutdown(PurpleConnection *gc, const char *from); -void yahoo_doodle_command_send_request(PurpleConnection *gc, const char *to); -void yahoo_doodle_command_send_ready(PurpleConnection *gc, const char *to); -void yahoo_doodle_command_send_draw(PurpleConnection *gc, const char *to, const char *message); -void yahoo_doodle_command_send_clear(PurpleConnection *gc, const char *to); -void yahoo_doodle_command_send_extra(PurpleConnection *gc, const char *to, const char *message); -void yahoo_doodle_command_send_confirm(PurpleConnection *gc, const char *to); +void yahoo_doodle_command_send_request(PurpleConnection *gc, const char *to, const char *imv_key); +void yahoo_doodle_command_send_ready(PurpleConnection *gc, const char *to, const char *imv_key); +void yahoo_doodle_command_send_draw(PurpleConnection *gc, const char *to, const char *message, const char *imv_key); +void yahoo_doodle_command_send_clear(PurpleConnection *gc, const char *to, const char *imv_key); +void yahoo_doodle_command_send_extra(PurpleConnection *gc, const char *to, const char *message, const char *imv_key); +void yahoo_doodle_command_send_confirm(PurpleConnection *gc, const char *to, const char *imv_key); void yahoo_doodle_command_send_shutdown(PurpleConnection *gc, const char *to); void yahoo_doodle_start(PurpleWhiteboard *wb);
--- a/libpurple/proxy.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/proxy.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file proxy.c Proxy API * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/proxy.h Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/proxy.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file proxy.h Proxy API * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/prpl.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/prpl.c Mon Oct 01 17:49:01 2007 +0000 @@ -226,6 +226,9 @@ { if (!purple_account_is_disconnected(account)) purple_account_disconnect(account); + /* Clear out the unsaved password if we're already disconnected and we switch to offline status */ + else if (!purple_account_get_remember_password(account)) + purple_account_set_password(account, NULL); return; }
--- a/libpurple/prpl.h Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/prpl.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file prpl.h Protocol Plugin functions * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/request.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/request.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file request.c Request API * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/request.h Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/request.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file request.h Request API * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/roomlist.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/roomlist.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file roomlist.c Room List API * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/roomlist.h Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/roomlist.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file roomlist.h Room List API * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/savedstatuses.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/savedstatuses.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file savedstatuses.c Saved Status API * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/savedstatuses.h Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/savedstatuses.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file savedstatuses.h Saved Status API * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/server.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/server.c Mon Oct 01 17:49:01 2007 +0000 @@ -143,6 +143,7 @@ */ auto_reply_pref = purple_prefs_get_string("/purple/away/auto_reply"); if ((gc->flags & PURPLE_CONNECTION_AUTO_RESP) && + flags & PURPLE_MESSAGE_AUTO_RESP && !purple_presence_is_available(presence) && strcmp(auto_reply_pref, "never")) {
--- a/libpurple/server.h Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/server.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file server.h Server API * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/signals.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/signals.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file signals.c Signal API * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/signals.h Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/signals.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file signals.h Signal API * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/sound.h Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/sound.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file sound.h Sound API * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/sslconn.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/sslconn.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file sslconn.c SSL API * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/sslconn.h Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/sslconn.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file sslconn.h SSL API * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/status.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/status.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file status.c Status API * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this @@ -600,7 +601,7 @@ { time_t current_time = time(NULL); const char *buddy_alias = purple_buddy_get_alias(buddy); - char *tmp; + char *tmp, *logtmp; PurpleLog *log; if (old_status != NULL) @@ -608,6 +609,10 @@ tmp = g_strdup_printf(_("%s changed status from %s to %s"), buddy_alias, purple_status_get_name(old_status), purple_status_get_name(new_status)); + logtmp = g_strdup_printf(_("%s (%s) changed status from %s to %s"), buddy_alias, buddy->name, + purple_status_get_name(old_status), + purple_status_get_name(new_status)); + } else { @@ -617,11 +622,16 @@ { tmp = g_strdup_printf(_("%s is now %s"), buddy_alias, purple_status_get_name(new_status)); + logtmp = g_strdup_printf(_("%s (%s) is now %s"), buddy_alias, buddy->name, + purple_status_get_name(new_status)); + } else { tmp = g_strdup_printf(_("%s is no longer %s"), buddy_alias, purple_status_get_name(new_status)); + logtmp = g_strdup_printf(_("%s (%s) is no longer %s"), buddy_alias, buddy->name, + purple_status_get_name(new_status)); } } @@ -629,10 +639,11 @@ if (log != NULL) { purple_log_write(log, PURPLE_MESSAGE_SYSTEM, buddy_alias, - current_time, tmp); + current_time, logtmp); } g_free(tmp); + g_free(logtmp); } }
--- a/libpurple/stringref.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/stringref.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file stringref.c Reference-counted immutable strings * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/stringref.h Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/stringref.h Mon Oct 01 17:49:01 2007 +0000 @@ -3,8 +3,9 @@ /** * @file stringref.h Reference-counted immutable strings * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/stun.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/stun.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file stun.c STUN (RFC3489) Implementation * @ingroup core - * - * purple + */ + +/* purple * * STUN implementation inspired by jstun [http://jstun.javawi.de/] *
--- a/libpurple/stun.h Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/stun.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file stun.h STUN API * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/upnp.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/upnp.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file upnp.c UPnP Implementation * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/upnp.h Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/upnp.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file upnp.h Universal Plug N Play API * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/util.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/util.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /* * @file util.h Utility Functions * @ingroup core - * - * Purple is the legal property of its developers, whose names are too numerous + */ + +/* Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this * source distribution. * @@ -67,7 +68,7 @@ }; static char *custom_user_dir = NULL; -static char *home_dir = NULL; +static char *user_dir = NULL; PurpleMenuAction * purple_menu_action_new(const char *label, PurpleCallback callback, gpointer data, @@ -1542,7 +1543,8 @@ while(*p && *p != '>') { if(!g_ascii_strncasecmp(p, "href=", strlen("href="))) { const char *q = p + strlen("href="); - g_string_free(url, TRUE); + if (url) + g_string_free(url, TRUE); url = g_string_new(""); cdata = g_string_new(""); if(*q == '\'' || *q == '\"') @@ -2463,10 +2465,10 @@ { if (custom_user_dir != NULL) return custom_user_dir; - else if (!home_dir) - home_dir = g_build_filename(purple_home_dir(), ".purple", NULL); - - return home_dir; + else if (!user_dir) + user_dir = g_build_filename(purple_home_dir(), ".purple", NULL); + + return user_dir; } void purple_util_set_user_dir(const char *dir)
--- a/libpurple/util.h Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/util.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file util.h Utility Functions * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/value.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/value.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file value.c Value wrapper API * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/value.h Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/value.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file value.h Value wrapper API * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/version.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/version.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /* * @file version.c Version Functions * @ingroup core - * - * Purple is the legal property of its developers, whose names are too numerous + */ + +/* Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this * source distribution. *
--- a/libpurple/whiteboard.h Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/whiteboard.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,7 +1,8 @@ /** * @file whiteboard.h The PurpleWhiteboard core object - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/win32/win32dep.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/win32/win32dep.c Mon Oct 01 17:49:01 2007 +0000 @@ -43,7 +43,6 @@ /* * DEFINES & MACROS */ -#define WIN32_PROXY_REGKEY "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings" /* For shfolder.dll */ typedef HRESULT (CALLBACK* LPFNSHGETFOLDERPATHA)(HWND, int, HANDLE, DWORD, LPSTR); @@ -57,9 +56,6 @@ static HINSTANCE libpurpledll_hInstance = 0; -static HANDLE proxy_change_event = NULL; -static HKEY proxy_regkey = NULL; - /* * PUBLIC CODE */ @@ -431,86 +427,93 @@ return result; } -static void wpurple_refresh_proxy(void) { - gboolean set_proxy = FALSE; - DWORD enabled = 0; +/* the winapi headers don't yet have winhttp.h, so we use the struct from msdn directly */ +typedef struct { + BOOL fAutoDetect; + LPWSTR lpszAutoConfigUrl; + LPWSTR lpszProxy; + LPWSTR lpszProxyBypass; +} WINHTTP_CURRENT_USER_IE_PROXY_CONFIG; - wpurple_read_reg_dword(HKEY_CURRENT_USER, WIN32_PROXY_REGKEY, - "ProxyEnable", &enabled); - - if (enabled & 1) { - char *c = NULL; - char *tmp = wpurple_read_reg_string(HKEY_CURRENT_USER, WIN32_PROXY_REGKEY, - "ProxyServer"); +typedef BOOL (CALLBACK* LPFNWINHTTPGETIEPROXYCONFIG)(/*IN OUT*/ WINHTTP_CURRENT_USER_IE_PROXY_CONFIG* pProxyConfig); - /* There are proxy settings for several protocols */ - if (tmp && (c = g_strstr_len(tmp, strlen(tmp), "http="))) { - char *d; - c += strlen("http="); - d = strchr(c, ';'); - if (d) - *d = '\0'; - /* c now points the proxy server (and port) */ +gboolean wpurple_check_for_proxy_changes(void) { + static gboolean loaded = FALSE; + static LPFNWINHTTPGETIEPROXYCONFIG MyWinHttpGetIEProxyConfig = NULL; - /* There is only a global proxy */ - } else if (tmp && strlen(tmp) > 0 && !strchr(tmp, ';')) { - c = tmp; + WINHTTP_CURRENT_USER_IE_PROXY_CONFIG ie_proxy_config; + char *tmp = NULL, *c = NULL; + gboolean changed = FALSE; + + if (!loaded) { + loaded = TRUE; + + if (getenv("HTTP_PROXY") || getenv("http_proxy") || getenv("HTTPPROXY")) { + purple_debug_info("wpurple", "HTTP_PROXY env. var already set. Ignoring win32 Internet Settings.\n"); + return FALSE; } - if (c) { + MyWinHttpGetIEProxyConfig = (LPFNWINHTTPGETIEPROXYCONFIG) + wpurple_find_and_loadproc("winhttp.dll", "WinHttpGetIEProxyConfigForCurrentUser"); + if (!MyWinHttpGetIEProxyConfig) + purple_debug_info("wpurple", "Unable to read Windows Proxy Settings.\n"); + } + + if (!MyWinHttpGetIEProxyConfig) + return FALSE; + + ZeroMemory(&ie_proxy_config, sizeof(ie_proxy_config)); + if (!MyWinHttpGetIEProxyConfig(&ie_proxy_config)) { + purple_debug_error("wpurple", "Error reading Windows Proxy Settings(%u).\n", GetLastError()); + return FALSE; + } + + /* We can't do much if it is autodetect*/ + if (ie_proxy_config.fAutoDetect) + purple_debug_error("wpurple", "Windows Proxy Settings set to autodetect (not supported).\n"); + else if (ie_proxy_config.lpszProxy) { + tmp = g_utf16_to_utf8(ie_proxy_config.lpszProxy, -1, + NULL, NULL, NULL); + /* We can't do anything about the bypass list, as we don't have the url */ + } else + purple_debug_info("wpurple", "No Windows Proxy Set.\n"); + + if (ie_proxy_config.lpszAutoConfigUrl) + GlobalFree(ie_proxy_config.lpszAutoConfigUrl); + if (ie_proxy_config.lpszProxy) + GlobalFree(ie_proxy_config.lpszProxy); + if (ie_proxy_config.lpszProxyBypass) + GlobalFree(ie_proxy_config.lpszProxyBypass); + + /* There are proxy settings for several protocols */ + if (tmp && (c = g_strstr_len(tmp, strlen(tmp), "http="))) { + char *d; + c += strlen("http="); + d = strchr(c, ';'); + if (d) + *d = '\0'; + /* c now points the proxy server (and port) */ + /* There is only a global proxy */ + } else if (tmp && strlen(tmp) > 0 && !strchr(tmp, ';')) { + c = tmp; + } + + if (c && *c) { + const char *current = g_getenv("HTTP_PROXY"); + if (!current || strcmp(current, c)) { purple_debug_info("wpurple", "Setting HTTP Proxy: 'http://%s'\n", c); g_setenv("HTTP_PROXY", c, TRUE); - set_proxy = TRUE; + changed = TRUE; } - g_free(tmp); } - /* If there previously was a proxy set and there isn't one now, clear it */ - if (getenv("HTTP_PROXY") && !set_proxy) { + else if (getenv("HTTP_PROXY")) { purple_debug_info("wpurple", "Clearing HTTP Proxy\n"); g_unsetenv("HTTP_PROXY"); - } -} - -static void watch_for_proxy_changes(void) { - LONG rv; - DWORD filter = REG_NOTIFY_CHANGE_NAME | - REG_NOTIFY_CHANGE_LAST_SET; - - if (!proxy_regkey && - !(proxy_regkey = _reg_open_key(HKEY_CURRENT_USER, - WIN32_PROXY_REGKEY, KEY_NOTIFY))) { - return; - } - - if (!(proxy_change_event = CreateEvent(NULL, TRUE, FALSE, NULL))) { - char *errmsg = g_win32_error_message(GetLastError()); - purple_debug_error("wpurple", "Unable to watch for proxy changes: %s\n", errmsg); - g_free(errmsg); - return; + changed = TRUE; } - rv = RegNotifyChangeKeyValue(proxy_regkey, TRUE, filter, proxy_change_event, TRUE); - if (rv != ERROR_SUCCESS) { - char *errmsg = g_win32_error_message(rv); - purple_debug_error("wpurple", "Unable to watch for proxy changes: %s\n", errmsg); - g_free(errmsg); - CloseHandle(proxy_change_event); - proxy_change_event = NULL; - } - -} - -gboolean wpurple_check_for_proxy_changes(void) { - gboolean changed = FALSE; - - if (proxy_change_event && WaitForSingleObject(proxy_change_event, 0) == WAIT_OBJECT_0) { - CloseHandle(proxy_change_event); - proxy_change_event = NULL; - changed = TRUE; - wpurple_refresh_proxy(); - watch_for_proxy_changes(); - } + g_free(tmp); return changed; } @@ -555,15 +558,6 @@ if (!g_thread_supported()) g_thread_init(NULL); - /* If the proxy server environment variables are already set, - * we shouldn't override them */ - if (!getenv("HTTP_PROXY") && !getenv("http_proxy") && !getenv("HTTPPROXY")) { - wpurple_refresh_proxy(); - watch_for_proxy_changes(); - } else { - purple_debug_info("wpurple", "HTTP_PROXY env. var already set. Ignoring win32 Internet Settings.\n"); - } - purple_debug_info("wpurple", "wpurple_init end\n"); } @@ -578,11 +572,6 @@ g_free(app_data_dir); app_data_dir = NULL; - if (proxy_regkey) { - RegCloseKey(proxy_regkey); - proxy_regkey = NULL; - } - libpurpledll_hInstance = NULL; }
--- a/libpurple/xmlnode.c Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/xmlnode.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,7 +1,8 @@ /** * @file xmlnode.c XML DOM functions - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/xmlnode.h Mon Oct 01 17:02:03 2007 +0000 +++ b/libpurple/xmlnode.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file xmlnode.h XML DOM functions * @ingroup core - * - * purple + */ + +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/Makefile.am Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/Makefile.am Mon Oct 01 17:49:01 2007 +0000 @@ -29,6 +29,7 @@ win32/nsis/langmacros.nsh \ win32/nsis/translations/afrikaans.nsh \ win32/nsis/translations/albanian.nsh \ + win32/nsis/translations/arabic.nsh \ win32/nsis/translations/basque.nsh \ win32/nsis/translations/bulgarian.nsh \ win32/nsis/translations/catalan.nsh \
--- a/pidgin/gtkaccount.c Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtkaccount.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gtkaccount.c GTK+ Account Editor UI * @ingroup pidgin - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this @@ -249,9 +250,6 @@ new_plugin = purple_find_prpl(id); - if (new_plugin == dialog->plugin) - return; - dialog->plugin = new_plugin; if (dialog->plugin != NULL) @@ -269,6 +267,8 @@ add_user_options(dialog, dialog->top_vbox); add_protocol_options(dialog, dialog->bottom_vbox); + gtk_widget_grab_focus(dialog->protocol_menu); + if (!dialog->prpl_info || !dialog->prpl_info->register_user || g_object_get_data(G_OBJECT(item), "fake")) { gtk_widget_hide(dialog->register_button);
--- a/pidgin/gtkaccount.h Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtkaccount.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gtkaccount.h GTK+ Account Editor UI * @ingroup pidgin - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkblist.c Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtkblist.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /* * @file gtkblist.c GTK+ BuddyList API * @ingroup pidgin - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this @@ -87,6 +88,8 @@ GtkWidget *group_combo; GtkWidget *entries_box; GtkSizeGroup *sg; + GtkWidget *autojoin; + GtkWidget *persistent; GList *entries; @@ -137,13 +140,23 @@ static void redo_buddy_list(PurpleBuddyList *list, gboolean remove, gboolean rerender); static void pidgin_blist_collapse_contact_cb(GtkWidget *w, PurpleBlistNode *node); static char *pidgin_get_group_title(PurpleBlistNode *gnode, gboolean expanded); - -struct _pidgin_blist_node { +static void pidgin_blist_expand_contact_cb(GtkWidget *w, PurpleBlistNode *node); + +typedef enum { + PIDGIN_BLIST_NODE_HAS_PENDING_MESSAGE = 1 << 0, /* Whether there's pending message in a conversation */ +} PidginBlistNodeFlags; + +typedef struct _pidgin_blist_node { GtkTreeRowReference *row; gboolean contact_expanded; gboolean recent_signonoff; gint recent_signonoff_timer; -}; + struct { + PurpleConversation *conv; + time_t last_message; /* timestamp for last displayed message */ + PidginBlistNodeFlags flags; + } conv; +} PidginBlistNode; static char dim_grey_string[8] = ""; static char *dim_grey() @@ -305,12 +318,36 @@ serv_send_file(b->account->gc, b->name, NULL); } +static void gtk_blist_menu_move_to_cb(GtkWidget *w, PurpleBlistNode *node) +{ + PurpleGroup *group = g_object_get_data(G_OBJECT(w), "groupnode"); + purple_blist_add_contact((PurpleContact *)node, group, NULL); + +} + static void gtk_blist_menu_autojoin_cb(GtkWidget *w, PurpleChat *chat) { purple_blist_node_set_bool((PurpleBlistNode*)chat, "gtk-autojoin", gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w))); } +static void gtk_blist_menu_persistent_cb(GtkWidget *w, PurpleChat *chat) +{ + purple_blist_node_set_bool((PurpleBlistNode*)chat, "gtk-persistent", + gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w))); +} + +static PurpleConversation * +find_conversation_with_buddy(PurpleBuddy *buddy) +{ + PidginBlistNode *ui = buddy->node.ui_data; + if (ui) + return ui->conv.conv; + return purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, + purple_buddy_get_name(buddy), + purple_buddy_get_account(buddy)); +} + static void gtk_blist_join_chat(PurpleChat *chat) { PurpleConversation *conv; @@ -394,6 +431,105 @@ } #endif +static void +gtk_blist_do_personize(GList *merges) +{ + PurpleBlistNode *contact = NULL; + int max = 0; + GList *tmp; + + /* First, we find the contact to merge the rest of the buddies into. + * This will be the contact with the most buddies in it; ties are broken + * by which contact is higher in the list + */ + for (tmp = merges; tmp; tmp = tmp->next) { + PurpleBlistNode *node = tmp->data; + PurpleBlistNode *b; + int i = 0; + + if (node->type == PURPLE_BLIST_BUDDY_NODE) + node = node->parent; + + if (node->type != PURPLE_BLIST_CONTACT_NODE) + continue; + + + for (b = node->child; b; b = b->next) + i++; + if (i > max) { + contact = node; + max = i; + } + } + + if (contact == NULL) + return; + + /* Merge all those buddies into this contact */ + for (tmp = merges; tmp; tmp = tmp->next) { + PurpleBlistNode *node = tmp->data; + if (node->type == PURPLE_BLIST_BUDDY_NODE) + node = node->parent; + + if (node == contact) + continue; + + purple_blist_merge_contact((PurpleContact *)node, contact); + } + + /* And show the expanded contact, so the people know what's going on */ + pidgin_blist_expand_contact_cb(NULL, contact); + g_list_free(merges); +} + +static void +gtk_blist_auto_personize(PurpleBlistNode *group, const char *alias) +{ + PurpleBlistNode *contact; + PurpleBlistNode *buddy; + GList *merges = NULL; + int i = 0; + char *a = g_utf8_casefold(alias, -1); + + for (contact = group->child; contact; contact = contact->next) { + char *node_alias; + if (contact->type != PURPLE_BLIST_CONTACT_NODE) + continue; + + node_alias = g_utf8_casefold(purple_contact_get_alias((PurpleContact *)contact), -1); + if (node_alias && !g_utf8_collate(node_alias, a)) { + merges = g_list_append(merges, contact); + i++; + g_free(node_alias); + continue; + } + g_free(node_alias); + + for (buddy = contact->child; buddy; buddy = buddy->next) { + if (buddy->type != PURPLE_BLIST_BUDDY_NODE) + continue; + + node_alias = g_utf8_casefold(purple_buddy_get_alias((PurpleBuddy *)buddy), -1); + if (node_alias && !g_utf8_collate(node_alias, a)) { + merges = g_list_append(merges, buddy); + i++; + } + g_free(node_alias); + } + } + g_free(a); + + if (i > 1) + { + char *msg = g_strdup_printf(ngettext("You currently have %d contact named %s. Would you like to merge them?", "You currently have %d contacts named %s. Would you like to merge them?", i), i, alias); + purple_request_action(NULL, NULL, msg, _("Merging these contacts will cause them to share a single entry on the buddy list and use a single conversation window. " + "You can separate them again by choosing 'Expand' from the contact's context menu"), 0, NULL, NULL, NULL, + merges, 2, _("_Merge"), PURPLE_CALLBACK(gtk_blist_do_personize), _("_Cancel"), PURPLE_CALLBACK(g_list_free)); + g_free(msg); + } else + g_list_free(merges); +} + static void gtk_blist_renderer_edited_cb(GtkCellRendererText *text_rend, char *arg1, char *arg2, PurpleBuddyList *list) { @@ -420,13 +556,14 @@ PurpleContact *contact = (PurpleContact *)node; struct _pidgin_blist_node *gtknode = (struct _pidgin_blist_node *)node->ui_data; - if (contact->alias || gtknode->contact_expanded) + if (contact->alias || gtknode->contact_expanded) { purple_blist_alias_contact(contact, arg2); - else - { + gtk_blist_auto_personize(node->parent, arg2); + } else { PurpleBuddy *buddy = purple_contact_get_priority_buddy(contact); purple_blist_alias_buddy(buddy, arg2); serv_alias_buddy(buddy); + gtk_blist_auto_personize(node->parent, arg2); } } break; @@ -434,6 +571,7 @@ case PURPLE_BLIST_BUDDY_NODE: purple_blist_alias_buddy((PurpleBuddy*)node, arg2); serv_alias_buddy((PurpleBuddy *)node); + gtk_blist_auto_personize(node->parent->parent, arg2); break; case PURPLE_BLIST_GROUP_NODE: dest = purple_find_group(arg2); @@ -1118,6 +1256,34 @@ g_list_free(ll); } + + +static void +pidgin_append_blist_node_move_to_menu(GtkWidget *menu, PurpleBlistNode *node) +{ + GtkWidget *submenu; + GtkWidget *menuitem; + PurpleBlistNode *group; + + menuitem = gtk_menu_item_new_with_label(_("Move to")); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); + gtk_widget_show(menuitem); + + submenu = gtk_menu_new(); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu); + + for (group = purple_blist_get_root(); group; group = group->next) { + if (group->type != PURPLE_BLIST_GROUP_NODE) + continue; + if (group == node->parent) + continue; + menuitem = pidgin_new_item_from_stock(submenu, purple_group_get_name((PurpleGroup *)group), NULL, + G_CALLBACK(gtk_blist_menu_move_to_cb), node, 0, 0, NULL); + g_object_set_data(G_OBJECT(menuitem), "groupnode", group); + } + gtk_widget_show_all(submenu); +} + void pidgin_blist_make_buddy_menu(GtkWidget *menu, PurpleBuddy *buddy, gboolean sub) { PurplePluginProtocolInfo *prpl_info; @@ -1169,6 +1335,9 @@ (PurpleBlistNode *)buddy); pidgin_append_blist_node_extended_menu(menu, (PurpleBlistNode *)buddy); + if (!contact_expanded) + pidgin_append_blist_node_move_to_menu(menu, (PurpleBlistNode *)contact); + if (((PurpleBlistNode*)buddy)->parent && ((PurpleBlistNode*)buddy)->parent->child->next && !sub && !contact_expanded) { pidgin_separator(menu); @@ -1255,16 +1424,19 @@ create_chat_menu(PurpleBlistNode *node, PurpleChat *c) { GtkWidget *menu; - gboolean autojoin; + gboolean autojoin, persistent; menu = gtk_menu_new(); autojoin = (purple_blist_node_get_bool(node, "gtk-autojoin") || (purple_blist_node_get_string(node, "gtk-autojoin") != NULL)); + persistent = purple_blist_node_get_bool(node, "gtk-persistent"); pidgin_new_item_from_stock(menu, _("_Join"), PIDGIN_STOCK_CHAT, G_CALLBACK(gtk_blist_menu_join_cb), node, 0, 0, NULL); pidgin_new_check_item(menu, _("Auto-Join"), G_CALLBACK(gtk_blist_menu_autojoin_cb), node, autojoin); + pidgin_new_check_item(menu, _("Persistent"), + G_CALLBACK(gtk_blist_menu_persistent_cb), node, persistent); pidgin_new_item_from_stock(menu, _("View _Log"), NULL, G_CALLBACK(gtk_blist_menu_showlog_cb), node, 0, 0, NULL); @@ -1306,7 +1478,6 @@ node, 0, 0, NULL); pidgin_append_blist_node_extended_menu(menu, node); - return menu; } @@ -2264,18 +2435,19 @@ if (prpl_info && prpl_info->icon_spec.scale_rules & PURPLE_ICON_SCALE_DISPLAY) purple_buddy_icon_get_scale_size(&prpl_info->icon_spec, &scale_width, &scale_height); - if (scaled) { + if (scaled || scale_height > 200 || scale_width > 200) { + float scale_size = scaled ? 32.0 : 200.0; if(scale_height > scale_width) { - scale_width = 32.0 * (double)scale_width / (double)scale_height; - scale_height = 32; + scale_width = scale_size * (double)scale_width / (double)scale_height; + scale_height = scale_size; } else { - scale_height = 32.0 * (double)scale_height / (double)scale_width; - scale_width = 32; + scale_height = scale_size * (double)scale_height / (double)scale_width; + scale_width = scale_size; } - ret = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, 32, 32); + ret = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, scale_size, scale_size); gdk_pixbuf_fill(ret, 0x00000000); - gdk_pixbuf_scale(buf, ret, (32-scale_width)/2, (32-scale_height)/2, scale_width, scale_height, (32-scale_width)/2, (32-scale_height)/2, (double)scale_width/(double)orig_width, (double)scale_height/(double)orig_height, GDK_INTERP_BILINEAR); + gdk_pixbuf_scale(buf, ret, (scale_size-scale_width)/2, (scale_size-scale_height)/2, scale_width, scale_height, (scale_size-scale_width)/2, (scale_size-scale_height)/2, (double)scale_width/(double)orig_width, (double)scale_height/(double)orig_height, GDK_INTERP_BILINEAR); if (pidgin_gdk_pixbuf_is_opaque(ret)) pidgin_gdk_pixbuf_make_round(ret); } else { @@ -2905,7 +3077,7 @@ { N_("/_Help"), NULL, NULL, 0, "<Branch>", NULL }, { N_("/Help/Online _Help"), "F1", gtk_blist_show_onlinehelp_cb, 0, "<StockItem>", GTK_STOCK_HELP }, { N_("/Help/_Debug Window"), NULL, toggle_debug, 0, "<Item>", NULL }, -#if GTK_CHECK_VERSION(2,6,0) +#if GTK_CHECK_VERSION(2,6,0) { N_("/Help/_About"), NULL, pidgin_dialogs_about, 0, "<StockItem>", GTK_STOCK_ABOUT }, #else { N_("/Help/_About"), NULL, pidgin_dialogs_about, 0, "<Item>", NULL }, @@ -3143,8 +3315,6 @@ GdkPixbuf *ret; PurplePresence *p; - - if(PURPLE_BLIST_NODE_IS_CONTACT(node)) { if(!gtknode->contact_expanded) { buddy = purple_contact_get_priority_buddy((PurpleContact*)node); @@ -3186,6 +3356,13 @@ return ret; } + if (purple_status_get_attr_string(purple_presence_get_active_status(p), PURPLE_TUNE_TITLE)) { + path = g_build_filename(DATADIR, "pixmaps", "pidgin", "emblems", "16", "music.png", NULL); + ret = gdk_pixbuf_new_from_file(path, NULL); + g_free(path); + return ret; + } + prpl = purple_find_prpl(purple_account_get_protocol_id(buddy->account)); if (!prpl) return NULL; @@ -3259,22 +3436,22 @@ } if(buddy) { - PurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, - purple_buddy_get_name(buddy), - purple_buddy_get_account(buddy)); + PurpleConversation *conv = find_conversation_with_buddy(buddy); PurplePresence *p; gboolean trans; if(conv != NULL) { PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv); - if((gtkconv == NULL || pidgin_conv_is_hidden(gtkconv)) && size == PIDGIN_STATUS_ICON_SMALL) { - return gtk_widget_render_icon (GTK_WIDGET(gtkblist->treeview), PIDGIN_STOCK_STATUS_MESSAGE, - icon_size, "GtkTreeView"); + if (gtkconv == NULL && size == PIDGIN_STATUS_ICON_SMALL) { + PidginBlistNode *ui = buddy->node.ui_data; + if (ui == NULL || (ui->conv.flags & PIDGIN_BLIST_NODE_HAS_PENDING_MESSAGE)) + return gtk_widget_render_icon (GTK_WIDGET(gtkblist->treeview), + PIDGIN_STOCK_STATUS_MESSAGE, icon_size, "GtkTreeView"); } } p = purple_buddy_get_presence(buddy); - trans = (purple_presence_is_idle(p) && size == PIDGIN_STATUS_ICON_SMALL); + trans = purple_presence_is_idle(p); if (PURPLE_BUDDY_IS_ONLINE(buddy) && gtkbuddynode && gtkbuddynode->recent_signonoff) icon = PIDGIN_STOCK_STATUS_LOGIN; @@ -3325,16 +3502,17 @@ struct _pidgin_blist_node *gtkcontactnode = NULL; char *idletime = NULL, *statustext = NULL; time_t t; - PurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, - purple_buddy_get_name(b), - purple_buddy_get_account(b)); - PidginConversation *gtkconv; + PurpleConversation *conv = find_conversation_with_buddy(b); gboolean hidden_conv = FALSE; - if(conv != NULL) { - gtkconv = PIDGIN_CONVERSATION(conv); - if(gtkconv == NULL || pidgin_conv_is_hidden(gtkconv)) { - hidden_conv = TRUE; + if (conv != NULL) { + PidginBlistNode *ui = b->node.ui_data; + if (ui) { + if (ui->conv.flags & PIDGIN_BLIST_NODE_HAS_PENDING_MESSAGE) + hidden_conv = TRUE; + } else { + if (PIDGIN_CONVERSATION(conv) == NULL) + hidden_conv = TRUE; } } @@ -3669,7 +3847,7 @@ menu = NULL; } - convs = pidgin_conversations_find_unseen_list(PURPLE_CONV_TYPE_IM, PIDGIN_UNSEEN_TEXT, TRUE, 0); + convs = pidgin_conversations_find_unseen_list(PURPLE_CONV_TYPE_ANY, PIDGIN_UNSEEN_TEXT, TRUE, 0); if (!convs) /* no conversations added, don't show the menu */ return; @@ -3725,7 +3903,7 @@ gtkblist->menutrayicon = NULL; } - convs = pidgin_conversations_find_unseen_list(PURPLE_CONV_TYPE_IM, PIDGIN_UNSEEN_TEXT, TRUE, 0); + convs = pidgin_conversations_find_unseen_list(PURPLE_CONV_TYPE_ANY, PIDGIN_UNSEEN_TEXT, TRUE, 0); if (convs) { GtkWidget *img = NULL; GString *tooltip_text = NULL; @@ -3733,14 +3911,10 @@ tooltip_text = g_string_new(""); l = convs; while (l != NULL) { - if (PIDGIN_IS_PIDGIN_CONVERSATION(l->data)) { - PidginConversation *gtkconv = PIDGIN_CONVERSATION((PurpleConversation *)l->data); - - g_string_append_printf(tooltip_text, - ngettext("%d unread message from %s\n", "%d unread messages from %s\n", gtkconv->unseen_count), - gtkconv->unseen_count, - gtk_label_get_text(GTK_LABEL(gtkconv->tab_label))); - } + int count = GPOINTER_TO_INT(purple_conversation_get_data(l->data, "unseen-count")); + g_string_append_printf(tooltip_text, + ngettext("%d unread message from %s\n", "%d unread messages from %s\n", count), + count, purple_conversation_get_name(l->data)); l = l->next; } if(tooltip_text->len > 0) { @@ -3768,6 +3942,88 @@ conversation_updated_cb(conv, PURPLE_CONV_UPDATE_UNSEEN, gtkblist); } +static void +conversation_deleted_update_ui_cb(PurpleConversation *conv, struct _pidgin_blist_node *ui) +{ + if (ui->conv.conv != conv) + return; + ui->conv.conv = NULL; + ui->conv.flags = 0; + ui->conv.last_message = 0; +} + +static void +written_msg_update_ui_cb(PurpleAccount *account, const char *who, const char *message, + PurpleConversation *conv, PurpleMessageFlags flag, PurpleBlistNode *node) +{ + PidginBlistNode *ui = node->ui_data; + if (ui->conv.conv != conv || PIDGIN_CONVERSATION(conv) || + !(flag & (PURPLE_MESSAGE_SEND | PURPLE_MESSAGE_RECV))) + return; + ui->conv.flags |= PIDGIN_BLIST_NODE_HAS_PENDING_MESSAGE; + ui->conv.last_message = time(NULL); /* XXX: for lack of better data */ + pidgin_blist_update(purple_get_blist(), node); +} + +static void +displayed_msg_update_ui_cb(PurpleAccount *account, const char *who, const char *message, + PurpleConversation *conv, PurpleMessageFlags flag, PurpleBlistNode *node) +{ + PidginBlistNode *ui = node->ui_data; + if (ui->conv.conv != conv) + return; + ui->conv.flags &= ~PIDGIN_BLIST_NODE_HAS_PENDING_MESSAGE; + pidgin_blist_update(purple_get_blist(), node); +} + +static void +conversation_created_cb(PurpleConversation *conv, PidginBuddyList *gtkblist) +{ + switch (conv->type) { + case PURPLE_CONV_TYPE_IM: + { + GSList *buddies = purple_find_buddies(conv->account, conv->name); + while (buddies) { + PurpleBlistNode *buddy = buddies->data; + struct _pidgin_blist_node *ui = buddy->ui_data; + buddies = g_slist_delete_link(buddies, buddies); + if (!ui) + continue; + ui->conv.conv = conv; + ui->conv.flags = 0; + ui->conv.last_message = 0; + purple_signal_connect(purple_conversations_get_handle(), "deleting-conversation", + ui, PURPLE_CALLBACK(conversation_deleted_update_ui_cb), ui); + purple_signal_connect(purple_conversations_get_handle(), "wrote-im-msg", + ui, PURPLE_CALLBACK(written_msg_update_ui_cb), buddy); + purple_signal_connect(pidgin_conversations_get_handle(), "displayed-im-msg", + ui, PURPLE_CALLBACK(displayed_msg_update_ui_cb), buddy); + } + } + case PURPLE_CONV_TYPE_CHAT: + { + PurpleChat *chat = purple_blist_find_chat(conv->account, conv->name); + struct _pidgin_blist_node *ui; + if (!chat) + break; + ui = chat->node.ui_data; + if (!ui) + break; + ui->conv.conv = conv; + ui->conv.flags = 0; + ui->conv.last_message = 0; + purple_signal_connect(purple_conversations_get_handle(), "deleting-conversation", + ui, PURPLE_CALLBACK(conversation_deleted_update_ui_cb), ui); + purple_signal_connect(purple_conversations_get_handle(), "wrote-chat-msg", + ui, PURPLE_CALLBACK(written_msg_update_ui_cb), chat); + purple_signal_connect(pidgin_conversations_get_handle(), "displayed-chat-msg", + ui, PURPLE_CALLBACK(displayed_msg_update_ui_cb), chat); + } + default: + break; + } +} + /********************************************************************************** * Public API Functions * **********************************************************************************/ @@ -4536,7 +4792,7 @@ "visible", EMBLEM_VISIBLE_COLUMN, NULL); rend = gtk_cell_renderer_pixbuf_new(); - gtk_tree_view_column_pack_start(column, rend, FALSE); + gtk_tree_view_column_pack_start(column, rend, FALSE); gtk_tree_view_column_set_attributes(column, rend, "pixbuf", PROTOCOL_ICON_COLUMN, "visible", PROTOCOL_ICON_VISIBLE_COLUMN, @@ -4681,6 +4937,9 @@ purple_signal_connect(purple_conversations_get_handle(), "deleting-conversation", gtkblist, PURPLE_CALLBACK(conversation_deleting_cb), gtkblist); + purple_signal_connect(purple_conversations_get_handle(), "conversation-created", + gtkblist, PURPLE_CALLBACK(conversation_created_cb), + gtkblist); gtk_widget_hide(gtkblist->headline_hbox); gtk_widget_hide(gtkblist->error_buttons); @@ -4787,6 +5046,7 @@ if(gtknode->recent_signonoff_timer > 0) purple_timeout_remove(gtknode->recent_signonoff_timer); + purple_signals_disconnect_by_handle(node->ui_data); g_free(node->ui_data); node->ui_data = NULL; } @@ -4951,7 +5211,7 @@ STATUS_ICON_COLUMN, NULL, NAME_COLUMN, title, NODE_COLUMN, gnode, - BGCOLOR_COLUMN, &bgcolor, + /* BGCOLOR_COLUMN, &bgcolor, */ GROUP_EXPANDER_COLUMN, TRUE, GROUP_EXPANDER_VISIBLE_COLUMN, TRUE, CONTACT_EXPANDER_VISIBLE_COLUMN, FALSE, @@ -4977,7 +5237,7 @@ group = (PurpleGroup*)gnode; textcolor = gtkblist->treeview->style->fg[GTK_STATE_ACTIVE]; - + if (gtk_tree_selection_get_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(gtkblist->treeview)), NULL, &iter)) { gtk_tree_model_get(GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &selected_node, -1); @@ -5211,14 +5471,17 @@ GdkPixbuf *emblem; char *mark; gboolean showicons = purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_buddy_icons"); - const char *name = purple_chat_get_name(chat); - PurpleConversation *conv = - purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, name, chat->account); - gboolean hidden = (conv && !PIDGIN_CONVERSATION(conv)); - - if(!insert_node(list, node, &iter)) + PidginBlistNode *ui; + PurpleConversation *conv; + gboolean hidden; + + if (!insert_node(list, node, &iter)) return; + ui = node->ui_data; + conv = ui->conv.conv; + hidden = (conv && (ui->conv.flags & PIDGIN_BLIST_NODE_HAS_PENDING_MESSAGE)); + status = pidgin_blist_get_status_icon(node, PIDGIN_STATUS_ICON_SMALL); emblem = pidgin_blist_get_emblem(node); @@ -5419,7 +5682,8 @@ if (*whoalias == '\0') whoalias = NULL; - if ((g = purple_find_group(grp)) == NULL) + g = NULL; + if ((grp != NULL) && (*grp != '\0') && ((g = purple_find_group(grp)) == NULL)) { g = purple_group_new(grp); purple_blist_add_group(g, NULL); @@ -5629,7 +5893,8 @@ group_name = pidgin_text_combo_box_entry_get_text(data->group_combo); - if ((group = purple_find_group(group_name)) == NULL) + group = NULL; + if ((group_name != NULL) && (*group_name != '\0') && ((group = purple_find_group(group_name)) == NULL)) { group = purple_group_new(group_name); purple_blist_add_group(group, NULL); @@ -5640,6 +5905,12 @@ purple_blist_add_chat(chat, group, NULL); } + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->autojoin))) + purple_blist_node_set_bool((PurpleBlistNode*)chat, "gtk-autojoin", TRUE); + + 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); @@ -5934,6 +6205,11 @@ gtk_label_set_mnemonic_widget(GTK_LABEL(label), GTK_BIN(data->group_combo)->child); pidgin_set_accessible_label (data->group_combo, label); gtk_box_pack_end(GTK_BOX(rowbox), data->group_combo, TRUE, TRUE, 0); + + data->autojoin = gtk_check_button_new_with_mnemonic(_("Autojoin when account becomes online.")); + data->persistent = gtk_check_button_new_with_mnemonic(_("Hide chat when the 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); @@ -6015,9 +6291,13 @@ gtkblist->headline_callback = callback; gtkblist->headline_data = user_data; gtkblist->headline_destroy = destroy; - if (!GTK_WIDGET_HAS_FOCUS(gtkblist->window)) - pidgin_set_urgent(GTK_WINDOW(gtkblist->window), TRUE); - gtk_widget_show_all(gtkblist->headline_hbox); + if (text != NULL || pixbuf != NULL) { + if (!GTK_WIDGET_HAS_FOCUS(gtkblist->window)) + pidgin_set_urgent(GTK_WINDOW(gtkblist->window), TRUE); + gtk_widget_show_all(gtkblist->headline_hbox); + } else { + gtk_widget_hide(gtkblist->headline_hbox); + } } static PurpleBlistUiOps blist_ui_ops =
--- a/pidgin/gtkblist.h Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtkblist.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gtkblist.h GTK+ Buddy List API * @ingroup pidgin - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkcellrendererexpander.c Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtkcellrendererexpander.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /* * @file gtkcellrendererexpander.c GTK+ Cell Renderer Expander * @ingroup pidgin - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this @@ -269,6 +270,9 @@ cell_area->x + cell->xpad + (width / 2), cell_area->y + cell->ypad + (height / 2), cell->is_expanded ? GTK_EXPANDER_EXPANDED : GTK_EXPANDER_COLLAPSED); + if (cell->is_expanded) + gtk_paint_hline (widget->style, window, state, NULL, widget, NULL, 0, + widget->allocation.width, cell_area->y + cell_area->height); } static gboolean pidgin_cell_renderer_expander_activate(GtkCellRenderer *r,
--- a/pidgin/gtkcellrendererprogress.c Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtkcellrendererprogress.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /* * @file gtkcellrendererprogress.c GTK+ Cell Renderer Progress * @ingroup pidgin - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkcertmgr.c Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtkcertmgr.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /* * @file gtkcertmgr.c GTK+ Certificate Manager API * @ingroup pidgin - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkconn.c Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtkconn.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /* * @file gtkconn.c GTK+ Connection API * @ingroup pidgin - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this @@ -52,7 +53,7 @@ * The key is a pointer to the PurpleAccount and the * value is a pointer to a PidginAutoRecon. */ -static GHashTable *hash = NULL; +static GHashTable *auto_reconns = NULL; static void pidgin_connection_connect_progress(PurpleConnection *gc, @@ -79,7 +80,7 @@ pidgin_status_box_set_connecting(PIDGIN_STATUS_BOX(gtkblist->statusbox), (purple_connections_get_connecting() != NULL)); - g_hash_table_remove(hash, account); + g_hash_table_remove(auto_reconns, account); pidgin_blist_update_account_error_state(account, NULL); } @@ -119,7 +120,7 @@ purple_debug_info("autorecon", "do_signon called\n"); g_return_val_if_fail(account != NULL, FALSE); - info = g_hash_table_lookup(hash, account); + info = g_hash_table_lookup(auto_reconns, account); if (info) info->timeout = 0; @@ -142,13 +143,13 @@ PidginAutoRecon *info; account = purple_connection_get_account(gc); - info = g_hash_table_lookup(hash, account); + info = g_hash_table_lookup(auto_reconns, account); pidgin_blist_update_account_error_state(account, text); if (!gc->wants_to_die) { if (info == NULL) { info = g_new0(PidginAutoRecon, 1); - g_hash_table_insert(hash, account, info); + g_hash_table_insert(auto_reconns, account, info); info->delay = g_random_int_range(INITIAL_RECON_DELAY_MIN, INITIAL_RECON_DELAY_MAX); } else { info->delay = MIN(2 * info->delay, MAX_RECON_DELAY); @@ -159,7 +160,7 @@ } else { char *p, *s, *n=NULL ; if (info != NULL) - g_hash_table_remove(hash, account); + g_hash_table_remove(auto_reconns, account); if (purple_account_get_alias(account)) { @@ -203,7 +204,7 @@ while (list) { PurpleAccount *account = (PurpleAccount*)list->data; - g_hash_table_remove(hash, account); + g_hash_table_remove(auto_reconns, account); if (purple_account_is_disconnected(account)) do_signon(account); list = list->next; @@ -264,7 +265,7 @@ static void account_removed_cb(PurpleAccount *account, gpointer user_data) { - g_hash_table_remove(hash, account); + g_hash_table_remove(auto_reconns, account); pidgin_blist_update_account_error_state(account, NULL); } @@ -285,7 +286,7 @@ void pidgin_connection_init(void) { - hash = g_hash_table_new_full( + auto_reconns = g_hash_table_new_full( g_direct_hash, g_direct_equal, NULL, free_auto_recon); @@ -299,5 +300,5 @@ { purple_signals_disconnect_by_handle(pidgin_connection_get_handle()); - g_hash_table_destroy(hash); + g_hash_table_destroy(auto_reconns); }
--- a/pidgin/gtkconn.h Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtkconn.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,7 +1,8 @@ /** * @file gtkconn.h GTK+ Connection API - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkconv.c Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtkconv.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gtkconv.c GTK+ Conversation API * @ingroup pidgin - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this @@ -69,6 +70,8 @@ #include "gtknickcolors.h" +#define CLOSE_CONV_TIMEOUT_SECS (10 * 60) + #define AUTO_RESPONSE "<AUTO-REPLY> : " typedef enum @@ -122,7 +125,6 @@ static GtkWidget *invite_dialog = NULL; static GtkWidget *warn_close_dialog = NULL; -static PidginWindow *hidden_convwin = NULL; static GList *window_list = NULL; /* Lists of status icons at all available sizes for use as window icons */ @@ -160,6 +162,7 @@ static gboolean infopane_press_cb(GtkWidget *widget, GdkEventButton *e, PidginConversation *conv); static gboolean pidgin_userlist_motion_cb (GtkWidget *w, GdkEventMotion *event, PidginConversation *gtkconv); static void pidgin_conv_leave_cb (GtkWidget *w, GdkEventCrossing *e, PidginConversation *gtkconv); +static void hide_conv(PidginConversation *gtkconv, gboolean closetimer); static void pidgin_conv_set_position_size(PidginWindow *win, int x, int y, int width, int height); @@ -207,12 +210,49 @@ **************************************************************************/ static gboolean -close_conv_cb(GtkWidget *w, GdkEventButton *event, PidginConversation *gtkconv) -{ +close_this_sucker(gpointer data) +{ + PidginConversation *gtkconv = data; GList *list = g_list_copy(gtkconv->convs); - g_list_foreach(list, (GFunc)purple_conversation_destroy, NULL); g_list_free(list); + return FALSE; +} + +static gboolean +close_conv_cb(GtkWidget *w, GdkEventButton *dontuse, PidginConversation *gtkconv) +{ + /* We are going to destroy the conversations immediately only if the 'close immediately' + * preference is selected. Otherwise, close the conversation after a reasonable timeout + * (I am going to consider 10 minutes as a 'reasonable timeout' here. + * For chats, close immediately if the chat is not in the buddylist, or if the chat is + * not marked 'Persistent' */ + PurpleConversation *conv = gtkconv->active_conv; + PurpleAccount *account = purple_conversation_get_account(conv); + const char *name = purple_conversation_get_name(conv); + + switch (purple_conversation_get_type(conv)) { + case PURPLE_CONV_TYPE_IM: + { + if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/im/close_immediately")) + close_this_sucker(gtkconv); + else + hide_conv(gtkconv, TRUE); + break; + } + case PURPLE_CONV_TYPE_CHAT: + { + PurpleChat *chat = purple_blist_find_chat(account, name); + if (!chat || + !purple_blist_node_get_bool(&chat->node, "gtk-persistent")) + close_this_sucker(gtkconv); + else + hide_conv(gtkconv, FALSE); + break; + } + default: + ; + } return TRUE; } @@ -1314,18 +1354,33 @@ add_remove_cb(NULL, PIDGIN_CONVERSATION(conv)); } -#if 0 -static void -menu_hide_conv_cb(gpointer data, guint action, GtkWidget *widget) -{ - PidginWindow *win = data; - PidginConversation *gtkconv = pidgin_conv_window_get_active_gtkconv(win); - PurpleConversation *conv = pidgin_conv_window_get_active_conversation(win); +static gboolean +close_already(gpointer data) +{ + purple_conversation_destroy(data); + return FALSE; +} + +static void +hide_conv(PidginConversation *gtkconv, gboolean closetimer) +{ + GList *list; + purple_signal_emit(pidgin_conversations_get_handle(), "conversation-hiding", gtkconv); - purple_conversation_set_ui_ops(conv, NULL); -} -#endif + + for (list = g_list_copy(gtkconv->convs); list; list = g_list_delete_link(list, list)) { + PurpleConversation *conv = list->data; + if (closetimer) { + guint timer = GPOINTER_TO_INT(purple_conversation_get_data(conv, "close-timer")); + if (timer) + purple_timeout_remove(timer); + timer = purple_timeout_add_seconds(CLOSE_CONV_TIMEOUT_SECS, close_already, conv); + purple_conversation_set_data(conv, "close-timer", GINT_TO_POINTER(timer)); + } + purple_conversation_set_ui_ops(conv, NULL); + } +} static void menu_close_conv_cb(gpointer data, guint action, GtkWidget *widget) @@ -1858,6 +1913,7 @@ gtk_notebook_reorder_child(GTK_NOTEBOOK(win->notebook), gtk_notebook_get_nth_page(GTK_NOTEBOOK(win->notebook), curconv), curconv - 1); + return TRUE; break; case GDK_period: @@ -1868,6 +1924,7 @@ #else (curconv + 1) % g_list_length(GTK_NOTEBOOK(win->notebook)->children)); #endif + return TRUE; break; } /* End of switch */ @@ -2340,63 +2397,69 @@ return get_prpl_icon_list(account); } -GdkPixbuf * -pidgin_conv_get_tab_icon(PurpleConversation *conv, gboolean small_icon) -{ - PurpleAccount *account = NULL; - const char *name = NULL; - GdkPixbuf *status = NULL; - PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); - const char *icon_size = small_icon ? PIDGIN_ICON_SIZE_TANGO_MICROSCOPIC : PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL; - g_return_val_if_fail(conv != NULL, NULL); - - account = purple_conversation_get_account(conv); - name = purple_conversation_get_name(conv); - - g_return_val_if_fail(account != NULL, NULL); - g_return_val_if_fail(name != NULL, NULL); - - /* Use the buddy icon, if possible */ - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { - PurpleBuddy *b = purple_find_buddy(account, name); - if (b != NULL) { +static GdkPixbuf * +pidgin_conv_get_icon(PurpleConversation *conv, GtkWidget *parent, const char *icon_size) +{ + PurpleAccount *account = NULL; + const char *name = NULL; + GdkPixbuf *status = NULL; + PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); + g_return_val_if_fail(conv != NULL, NULL); + + account = purple_conversation_get_account(conv); + name = purple_conversation_get_name(conv); + + g_return_val_if_fail(account != NULL, NULL); + g_return_val_if_fail(name != NULL, NULL); + + /* Use the buddy icon, if possible */ + if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { + PurpleBuddy *b = purple_find_buddy(account, name); + if (b != NULL) { PurplePresence *p = purple_buddy_get_presence(b); - /* I hate this hack. It fixes a bug where the pending message icon - * displays in the conv tab even though it shouldn't. - * A better solution would be great. */ - if (ops && ops->update) - ops->update(NULL, (PurpleBlistNode*)b); + /* I hate this hack. It fixes a bug where the pending message icon + * displays in the conv tab even though it shouldn't. + * A better solution would be great. */ + if (ops && ops->update) + ops->update(NULL, (PurpleBlistNode*)b); /* XXX Seanegan: We really need a util function to return a pixbuf for a Presence to avoid all this switching */ if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_AWAY)) - status = pidgin_create_status_icon(PURPLE_STATUS_AWAY, PIDGIN_CONVERSATION(conv)->icon, icon_size); + status = pidgin_create_status_icon(PURPLE_STATUS_AWAY, parent, icon_size); else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_EXTENDED_AWAY)) - status = pidgin_create_status_icon(PURPLE_STATUS_EXTENDED_AWAY, PIDGIN_CONVERSATION(conv)->icon, icon_size); - else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_OFFLINE)) - status = pidgin_create_status_icon(PURPLE_STATUS_OFFLINE, PIDGIN_CONVERSATION(conv)->icon, icon_size); - else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_AVAILABLE)) - status = pidgin_create_status_icon(PURPLE_STATUS_AVAILABLE, PIDGIN_CONVERSATION(conv)->icon, icon_size); - else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_INVISIBLE)) - status = pidgin_create_status_icon(PURPLE_STATUS_INVISIBLE, PIDGIN_CONVERSATION(conv)->icon, icon_size); - else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_UNAVAILABLE)) - status = pidgin_create_status_icon(PURPLE_STATUS_UNAVAILABLE, PIDGIN_CONVERSATION(conv)->icon, icon_size); - } - } - - /* If they don't have a buddy icon, then use the PRPL icon */ - if (status == NULL) { + status = pidgin_create_status_icon(PURPLE_STATUS_EXTENDED_AWAY, parent, icon_size); + else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_OFFLINE)) + status = pidgin_create_status_icon(PURPLE_STATUS_OFFLINE, parent, icon_size); + else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_AVAILABLE)) + status = pidgin_create_status_icon(PURPLE_STATUS_AVAILABLE, parent, icon_size); + else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_INVISIBLE)) + status = pidgin_create_status_icon(PURPLE_STATUS_INVISIBLE, parent, icon_size); + else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_UNAVAILABLE)) + status = pidgin_create_status_icon(PURPLE_STATUS_UNAVAILABLE, parent, icon_size); + } + } + + /* If they don't have a buddy icon, then use the PRPL icon */ + if (status == NULL) { GtkIconSize size = gtk_icon_size_from_name(icon_size); if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { - status = gtk_widget_render_icon (PIDGIN_CONVERSATION(conv)->icon, PIDGIN_STOCK_STATUS_PERSON, - size, "GtkWidget"); + status = gtk_widget_render_icon (parent, PIDGIN_STOCK_STATUS_PERSON, + size, "GtkWidget"); } else { - status = gtk_widget_render_icon (PIDGIN_CONVERSATION(conv)->icon, PIDGIN_STOCK_STATUS_CHAT, - size, "GtkWidget"); + status = gtk_widget_render_icon (parent, PIDGIN_STOCK_STATUS_CHAT, + size, "GtkWidget"); } } return status; } +GdkPixbuf * +pidgin_conv_get_tab_icon(PurpleConversation *conv, gboolean small_icon) +{ + const char *icon_size = small_icon ? PIDGIN_ICON_SIZE_TANGO_MICROSCOPIC : PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL; + return pidgin_conv_get_icon(conv, PIDGIN_CONVERSATION(conv)->icon, icon_size); +} + static void update_tab_icon(PurpleConversation *conv) @@ -2748,9 +2811,9 @@ PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv); GdkModifierType state; - if(gtkconv->win==hidden_convwin) { - pidgin_conv_window_remove_gtkconv(hidden_convwin, gtkconv); - pidgin_conv_placement_place(gtkconv); + if (gtkconv == NULL) { + pidgin_conv_attach_to_conversation(conv); + gtkconv = PIDGIN_CONVERSATION(conv); } pidgin_conv_switch_active_conversation(conv); @@ -2783,15 +2846,19 @@ PurpleConversation *conv = (PurpleConversation*)l->data; PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv); - if(gtkconv == NULL || gtkconv->active_conv != conv) + if (gtkconv != NULL && gtkconv->active_conv != conv) continue; - - if (gtkconv->unseen_state >= min_state - && (!hidden_only || - (hidden_only && gtkconv->win == hidden_convwin))) { - + if (gtkconv == NULL) { + if (!hidden_only || + !purple_conversation_get_data(conv, "unseen-count")) + continue; r = g_list_prepend(r, conv); c++; + } else { + if (gtkconv->unseen_state >= min_state && !hidden_only) { + r = g_list_prepend(r, conv); + c++; + } } } @@ -2831,11 +2898,11 @@ PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv); GtkWidget *icon = gtk_image_new(); - GdkPixbuf *pbuf = pidgin_conv_get_tab_icon(conv, TRUE); + GdkPixbuf *pbuf = pidgin_conv_get_icon(conv, icon, PIDGIN_ICON_SIZE_TANGO_MICROSCOPIC); GtkWidget *item; gchar *text = g_strdup_printf("%s (%d)", - gtk_label_get_text(GTK_LABEL(gtkconv->tab_label)), - gtkconv->unseen_count); + gtkconv ? gtk_label_get_text(GTK_LABEL(gtkconv->tab_label)) : purple_conversation_get_name(conv), + gtkconv ? gtkconv->unseen_count : GPOINTER_TO_INT(purple_conversation_get_data(conv, "unseen-count"))); gtk_image_set_from_pixbuf(GTK_IMAGE(icon), pbuf); g_object_unref(pbuf); @@ -3093,7 +3160,7 @@ PurpleConversation *conv; GtkWidget *item; - if (win->window == NULL || win == hidden_convwin) + if (win->window == NULL) return; gtkconv = pidgin_conv_window_get_active_gtkconv(win); @@ -4423,7 +4490,7 @@ g_signal_connect(G_OBJECT(list), "motion-notify-event", G_CALLBACK(pidgin_userlist_motion_cb), gtkconv); g_signal_connect(G_OBJECT(list), "leave-notify-event", - G_CALLBACK(pidgin_userlist_motion_cb), gtkconv); + G_CALLBACK(pidgin_conv_leave_cb), gtkconv); g_signal_connect(G_OBJECT(list), "popup-menu", G_CALLBACK(gtkconv_chat_popup_menu_cb), gtkconv); g_signal_connect(G_OBJECT(lbox), "size-allocate", G_CALLBACK(lbox_size_allocate_cb), gtkconv); @@ -4551,10 +4618,8 @@ model = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkchat->list)); - gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(gtkchat->list), - tooltip.userlistx, tooltip.userlisty, &path, &column, &x, &y); - - if (path == NULL) + if (!gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(gtkchat->list), + tooltip.userlistx, tooltip.userlisty, &path, &column, &x, &y)) return FALSE; gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, path); @@ -4942,6 +5007,9 @@ GtkWidget *tab_cont; PurpleBlistNode *convnode; + if (hidden) + return; + if (conv_type == PURPLE_CONV_TYPE_IM && (gtkconv = pidgin_conv_find_gtkconv(conv))) { conv->ui_data = gtkconv; if (!g_list_find(gtkconv->convs, conv)) @@ -5041,10 +5109,7 @@ G_CALLBACK(gtk_widget_grab_focus), gtkconv->entry); - if (hidden) - pidgin_conv_window_add_gtkconv(hidden_convwin, gtkconv); - else - pidgin_conv_placement_place(gtkconv); + pidgin_conv_placement_place(gtkconv); if (nick_colors == NULL) { nbr_nick_colors = NUM_NICK_COLORS; @@ -5052,11 +5117,13 @@ } } +#if 0 static void pidgin_conv_new_hidden(PurpleConversation *conv) { private_gtkconv_new(conv, TRUE); } +#endif void pidgin_conv_new(PurpleConversation *conv) @@ -5069,26 +5136,22 @@ PurpleConversation *conv, PurpleMessageFlags flags) { PurpleConversationUiOps *ui_ops = pidgin_conversations_get_conv_ui_ops(); - if (conv != NULL) - return; /* create hidden conv if hide_new pref is always */ - if (strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/im/hide_new"), "always") == 0) - { - ui_ops->create_conversation = pidgin_conv_new_hidden; - purple_conversation_new(PURPLE_CONV_TYPE_IM, account, sender); - ui_ops->create_conversation = pidgin_conv_new; - return; - } - - /* create hidden conv if hide_new pref is away and account is away */ - if (strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/im/hide_new"), "away") == 0 && - !purple_status_is_available(purple_account_get_active_status(account))) - { - ui_ops->create_conversation = pidgin_conv_new_hidden; - purple_conversation_new(PURPLE_CONV_TYPE_IM, account, sender); - ui_ops->create_conversation = pidgin_conv_new; - return; + /* or if hide_new pref is away and account is away */ + if ((strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/im/hide_new"), "always") == 0) || + (strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/im/hide_new"), "away") == 0 && + !purple_status_is_available(purple_account_get_active_status(account)))) { + if (!conv) { + ui_ops->create_conversation = NULL; + conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, sender); + purple_conversation_set_ui_ops(conv, NULL); + ui_ops->create_conversation = pidgin_conv_new; + } + } else { + /* new message for an IM */ + if (conv && conv->type == PURPLE_CONV_TYPE_IM) + pidgin_conv_attach_to_conversation(conv); } } @@ -5097,6 +5160,9 @@ { PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv); + if (!gtkconv) + return; + gtkconv->convs = g_list_remove(gtkconv->convs, conv); /* Don't destroy ourselves until all our convos are gone */ if (gtkconv->convs) { @@ -6349,8 +6415,13 @@ if ((purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) && (gtkconv->u.im->anim)) { + PurpleBuddy *buddy = purple_find_buddy(conv->account, conv->name); window_icon = gdk_pixbuf_animation_get_static_image(gtkconv->u.im->anim); + + if (buddy && !PURPLE_BUDDY_IS_ONLINE(buddy)) + gdk_pixbuf_saturate_and_pixelate(window_icon, window_icon, 0.0, FALSE); + g_object_ref(window_icon); l = g_list_append(l, window_icon); } else { @@ -6569,6 +6640,19 @@ pidgin_conv_update_fields(conv, flags); } +static void +wrote_msg_update_unseen_cb(PurpleAccount *account, const char *who, const char *message, + PurpleConversation *conv, PurpleMessageFlags flag, gpointer null) +{ + if (conv == NULL || PIDGIN_IS_PIDGIN_CONVERSATION(conv)) + return; + if (flag & (PURPLE_MESSAGE_SEND | PURPLE_MESSAGE_RECV)) { + purple_conversation_set_data(conv, "unseen-count", + GINT_TO_POINTER(GPOINTER_TO_INT(purple_conversation_get_data(conv, "unseen-count")) + 1)); + purple_conversation_update(conv, PURPLE_CONV_UPDATE_UNSEEN); + } +} + static PurpleConversationUiOps conversation_ui_ops = { pidgin_conv_new, @@ -6752,7 +6836,9 @@ event = gtk_event_box_new(); gtk_container_add(GTK_CONTAINER(gtkconv->u.im->icon_container), event); +#if GTK_CHECK_VERSION(2,4,0) gtk_event_box_set_visible_window(GTK_EVENT_BOX(event), FALSE); +#endif gtk_widget_add_events(event, GDK_POINTER_MOTION_MASK | GDK_LEAVE_NOTIFY_MASK); g_signal_connect(G_OBJECT(event), "button-press-event", @@ -7066,6 +7152,7 @@ account_status_changed_cb(PurpleAccount *account, PurpleStatus *oldstatus, PurpleStatus *newstatus) { +#if 0 GList *l; PurpleConversation *conv = NULL; PidginConversation *gtkconv; @@ -7075,27 +7162,7 @@ if(purple_status_is_available(oldstatus) || !purple_status_is_available(newstatus)) return; - - while ((l = hidden_convwin->gtkconvs) != NULL) - { - gtkconv = l->data; - - conv = gtkconv->active_conv; - - while(l && !purple_status_is_available( - purple_account_get_active_status( - purple_conversation_get_account(conv)))) - l = l->next; - if (!l) - break; - - pidgin_conv_window_remove_gtkconv(hidden_convwin, gtkconv); - pidgin_conv_placement_place(gtkconv); - - /* TODO: do we need to do anything for any other conversations that are in the same gtkconv here? - * I'm a little concerned that not doing so will cause the "pending" indicator in the gtkblist not to be cleared. -DAA*/ - purple_conversation_update(conv, PURPLE_CONV_UPDATE_UNSEEN); - } +#endif } static void @@ -7103,32 +7170,25 @@ gconstpointer value, gpointer data) { GList *l; - PurpleConversation *conv = NULL; - PidginConversation *gtkconv; gboolean when_away = FALSE; - if(!hidden_convwin) - return; - if(strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/im/hide_new"), "always")==0) return; if(strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/im/hide_new"), "away")==0) when_away = TRUE; - while ((l = hidden_convwin->gtkconvs) != NULL) + for (l = purple_get_conversations(); l; l = l->next) { - gtkconv = l->data; - - conv = gtkconv->active_conv; - + PurpleConversation *conv = l->data; + PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv); + if (gtkconv) + continue; if(when_away && !purple_status_is_available( purple_account_get_active_status( purple_conversation_get_account(conv)))) continue; - - pidgin_conv_window_remove_gtkconv(hidden_convwin, gtkconv); - pidgin_conv_placement_place(gtkconv); + pidgin_conv_attach_to_conversation(conv); } } @@ -7311,9 +7371,15 @@ PidginConversation *gtkconv = data; int count = 0; int timer = gtkconv->attach.timer; + time_t when = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(gtkconv->entry), "attach-start-time")); + gtkconv->attach.timer = 0; while (gtkconv->attach.current && count < 100) { /* XXX: 100 is a random value here */ PurpleConvMessage *msg = gtkconv->attach.current->data; + if (when && when < msg->when) { + gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), "<BR><HR>", 0); + g_object_set_data(G_OBJECT(gtkconv->entry), "attach-start-time", NULL); + } pidgin_conv_write_conv(gtkconv->active_conv, msg->who, msg->who, msg->what, msg->flags, msg->when); gtkconv->attach.current = gtkconv->attach.current->prev; count++; @@ -7333,18 +7399,21 @@ { GList *list; PidginConversation *gtkconv; + int timer; if (PIDGIN_IS_PIDGIN_CONVERSATION(conv)) return FALSE; + purple_conversation_set_data(conv, "unseen-count", NULL); purple_conversation_set_ui_ops(conv, pidgin_conversations_get_conv_ui_ops()); private_gtkconv_new(conv, FALSE); gtkconv = PIDGIN_CONVERSATION(conv); list = purple_conversation_get_message_history(conv); if (list) { - list = g_list_last(list); - gtkconv->attach.current = list; + g_object_set_data(G_OBJECT(gtkconv->entry), "attach-start-time", + GINT_TO_POINTER(((PurpleConvMessage*)(list->data))->when)); + gtkconv->attach.current = g_list_last(list); gtkconv->attach.timer = g_idle_add(add_message_history_to_gtkconv, gtkconv); } else { purple_signal_emit(pidgin_conversations_get_handle(), @@ -7356,6 +7425,10 @@ pidgin_conv_chat_add_users(conv, PURPLE_CONV_CHAT(conv)->in_room, TRUE); } + timer = GPOINTER_TO_INT(purple_conversation_get_data(conv, "close-timer")); + if (timer) + purple_timeout_remove(timer); + return TRUE; } @@ -7421,6 +7494,7 @@ purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/im/show_buddy_icons", TRUE); purple_prefs_add_string(PIDGIN_PREFS_ROOT "/conversations/im/hide_new", "never"); + purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/im/close_immediately", FALSE); #ifdef _WIN32 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/win32/minimize_new_convs", FALSE); @@ -7584,9 +7658,6 @@ purple_conversations_set_ui_ops(&conversation_ui_ops); - hidden_convwin = pidgin_conv_window_new(); - window_list = g_list_remove(window_list, hidden_convwin); - purple_signal_connect(purple_accounts_get_handle(), "account-status-changed", handle, PURPLE_CALLBACK(account_status_changed_cb), NULL); @@ -7622,6 +7693,10 @@ purple_signal_connect_priority(purple_conversations_get_handle(), "conversation-updated", handle, PURPLE_CALLBACK(pidgin_conv_updated), NULL, PURPLE_SIGNAL_PRIORITY_LOWEST); + purple_signal_connect(purple_conversations_get_handle(), "wrote-im-msg", handle, + PURPLE_CALLBACK(wrote_msg_update_unseen_cb), NULL); + purple_signal_connect(purple_conversations_get_handle(), "wrote-chat-msg", handle, + PURPLE_CALLBACK(wrote_msg_update_unseen_cb), NULL); } void @@ -7630,8 +7705,6 @@ purple_prefs_disconnect_by_handle(pidgin_conversations_get_handle()); purple_signals_disconnect_by_handle(pidgin_conversations_get_handle()); purple_signals_unregister_by_instance(pidgin_conversations_get_handle()); - pidgin_conv_window_destroy(hidden_convwin); - hidden_convwin=NULL; } @@ -8763,15 +8836,10 @@ if (win->gtkconvs) { while (win->gtkconvs) { - GList *nextgtk = win->gtkconvs->next; - PidginConversation *gtkconv = win->gtkconvs->data; - GList *nextcore = gtkconv->convs->next; - PurpleConversation *conv = gtkconv->convs->data; - purple_conversation_destroy(conv); - if (!nextgtk && !nextcore) - /* we'll end up invoking ourselves when we destroy our last child */ - /* so don't destroy ourselves right now */ - return; + gboolean last = (win->gtkconvs->next == NULL); + close_conv_cb(NULL, NULL, win->gtkconvs->data); + if (last) + break; } return; } @@ -8858,7 +8926,9 @@ /* Close button. */ gtkconv->close = gtk_event_box_new(); +#if GTK_CHECK_VERSION(2,4,0) gtk_event_box_set_visible_window(GTK_EVENT_BOX(gtkconv->close), FALSE); +#endif gtk_widget_set_events(gtkconv->close, GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK); close_image = gtk_label_new("×"); g_signal_connect(G_OBJECT(gtkconv->close), "enter-notify-event", G_CALLBACK(close_button_entered_cb), close_image); @@ -9048,7 +9118,7 @@ if (win->gtkconvs && win->gtkconvs->next == NULL) pidgin_conv_tab_pack(win, win->gtkconvs->data); - if (!win->gtkconvs && win != hidden_convwin) + if (!win->gtkconvs) pidgin_conv_window_destroy(win); } @@ -9587,9 +9657,7 @@ gboolean pidgin_conv_is_hidden(PidginConversation *gtkconv) { - g_return_val_if_fail(gtkconv != NULL, FALSE); - - return (gtkconv->win == hidden_convwin); + return (gtkconv == NULL); } @@ -9690,3 +9758,4 @@ return colors; } +
--- a/pidgin/gtkconv.h Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtkconv.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gtkconv.h GTK+ Conversation API * @ingroup pidgin - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkconvwin.h Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtkconvwin.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gtkconvwin.h GTK+ Conversation Window API * @ingroup pidgin - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkdebug.c Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtkdebug.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gtkdebug.c GTK+ Debug API * @ingroup pidgin - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkdebug.h Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtkdebug.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gtkdebug.h GTK+ Debug API * @ingroup pidgin - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkdialogs.c Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtkdialogs.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /* * @file gtkdialogs.c GTK+ Dialogs * @ingroup pidgin - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this @@ -130,7 +131,7 @@ /* Order: Code, then Alphabetical by Last Name */ static struct translator current_translators[] = { {N_("Afrikaans"), "af", "Friedel Wolff", "friedel@translate.org.za"}, - {N_("Arabic"), "ar", "Mohamed Magdy", "alnokta@yahoo.com"}, + {N_("Arabic"), "ar", "Khaled Hosny", "khaledhosny@eglug.org"}, {N_("Belarusian Latin"), "be@latin", "Ihar Hrachyshka", "ihar.hrachyshka@gmail.com"}, {N_("Bulgarian"), "bg", "Vladimira Girginova", "missing@here.is"}, {N_("Bulgarian"), "bg", "Vladimir (Kaladan) Petkov", "vpetkov@i-space.org"}, @@ -181,10 +182,12 @@ {N_("Kurdish"), "ku", "Erdal Ronahi", "erdal.ronahi@gmail.com"}, {N_("Kurdish"), "ku", "Amed Ç. Jiyan", "amedcj@hotmail.com"}, {N_("Kurdish"), "ku", "Rizoyê Xerzî", "rizoxerzi@hotmail.com"}, + {N_("Lao"), "lo", "Anousak Souphavah", "anousak@gmail.com"}, {N_("Lithuanian"), "lt", "Laurynas Biveinis", "laurynas.biveinis@gmail.com"}, {N_("Macedonian"), "mk", "Arangel Angov ", "arangel@linux.net.mk"}, + {N_("Macedonian"), "mk", "Ivana Kirkovska", "ivana.kirkovska@gmail.com"}, {N_("Macedonian"), "mk", "Jovan Naumovski", "jovan@lugola.net"}, - {N_("Bokmål Norwegian"), "nb", "Hallvard Glad", "hallvard.glad@gmail.com"}, + {N_("Bokmål Norwegian"), "nb", "Espen Stefansen", "espenas@gmail.com"}, {N_("Nepali"), "ne", "Shyam Krishna Bal", "shyamkrishna_bal@yahoo.com"}, {N_("Dutch, Flemish"), "nl", "Vincent van Adrighem", "V.vanAdrighem@dirck.mine.nu"}, {N_("Norwegian Nynorsk"), "nn", "Yngve Spjeld Landro", "nynorsk@strilen.net"}, @@ -200,8 +203,8 @@ {N_("Slovak"), "sk", "loptosko", "loptosko@gmail.com"}, {N_("Slovenian"), "sl", "Martin Srebotnjak", "miles@filmsi.net"}, {N_("Albanian"), "sq", "Besnik Bleta", "besnik@programeshqip.org"}, - {N_("Serbian"), "sr", "Danilo Šegan", "dsegan@gmx.net"}, - {N_("Serbian"), "sr", "Aleksandar Urosevic", "urke@users.sourceforge.net"}, + {N_("Serbian"), "sr", "Miloš Popović", "gpopac@gmail.com"}, + {N_("Serbian"), "sr@Latn", "Miloš Popović", "gpopac@gmail.com"}, {N_("Swedish"), "sv", "Peter Hjalmarsson", "xake@telia.com"}, {N_("Tamil"), "ta", "Viveka Nathan K", "vivekanathan@users.sourceforge.net"}, {N_("Telugu"), "te", "Mr. Subbaramaih", "info.gist@cdac.in"}, @@ -220,6 +223,7 @@ static struct translator past_translators[] = { {N_("Amharic"), "am", "Daniel Yacob", NULL}, + {N_("Arabic"), "ar", "Mohamed Magdy", "alnokta@yahoo.com"}, {N_("Bulgarian"), "bg", "Hristo Todorov", NULL}, {N_("Catalan"), "ca", "JM Pérez Cáncer", NULL}, {N_("Catalan"), "ca", "Robert Millan", NULL}, @@ -248,7 +252,8 @@ {N_("Lithuanian"), "lt", "Andrius Štikonas", NULL}, {N_("Lithuanian"), "lt", "Gediminas Čičinskas", NULL}, {N_("Macedonian"), "mk", "Tomislav Markovski", NULL}, - {N_("Bokmål Norwegian"), "nb", "Petter Johan Olsen", NULL}, + {N_("Bokmål Norwegian"), "nb", "Hallvard Glad", "hallvard.glad@gmail.com"}, + {N_("Bokmål Norwegian"), "nb", "Petter Johan Olsen", NULL}, {N_("Polish"), "pl", "Przemysław Sułek", NULL}, {N_("Russian"), "ru", "Alexandre Prokoudine", NULL}, {N_("Russian"), "ru", "Sergey Volozhanin", NULL}, @@ -256,6 +261,8 @@ {N_("Slovak"), "sk", "helix84", NULL}, {N_("Slovak"), "sk", "Richard Golier", NULL}, {N_("Slovenian"), "sl", "Matjaz Horvat", NULL}, + {N_("Serbian"), "sr", "Danilo Šegan", "dsegan@gmx.net"}, + {N_("Serbian"), "sr", "Aleksandar Urosevic", "urke@users.sourceforge.net"}, {N_("Swedish"), "sv", "Tore Lundqvist", NULL}, {N_("Swedish"), "sv", "Christian Rose", NULL}, {N_("Turkish"), "tr", "Ahmet Alp BALKAN", NULL}, @@ -285,6 +292,7 @@ about = NULL; } +#if 0 /* This function puts the version number onto the pixmap we use in the 'about' * screen in Pidgin. */ static void @@ -322,6 +330,7 @@ width, height); g_object_unref(G_OBJECT(pixmap)); } +#endif void pidgin_dialogs_about() { @@ -385,6 +394,9 @@ str = g_string_sized_new(4096); g_string_append_printf(str, + "<CENTER><FONT SIZE=\"4\"><B>%s %s</B></FONT></CENTER><BR><BR>", PIDGIN_NAME, VERSION); + + g_string_append_printf(str, _("%s is a graphical modular messaging client based on " "libpurple which is capable of connecting to " "AIM, MSN, Yahoo!, XMPP, ICQ, IRC, SILC, SIP/SIMPLE, "
--- a/pidgin/gtkdialogs.h Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtkdialogs.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,7 +1,8 @@ /** * @defgroup pidgin Pidgin (GTK+ User Interface) - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkdnd-hints.c Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtkdnd-hints.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /* * @file gtkdnd-hints.c GTK+ Drag-and-Drop arrow hints * @ingroup pidgin - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkdnd-hints.h Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtkdnd-hints.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gtkdnd-hints.h GTK+ Drag-and-Drop arrow hints * @ingroup pidgin - * - * Pidgin is the legal property of its developers, whose names are too numerous + */ + +/* Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this * source distribution. *
--- a/pidgin/gtkdocklet.c Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtkdocklet.c Mon Oct 01 17:49:01 2007 +0000 @@ -532,7 +532,7 @@ g_signal_connect(G_OBJECT(menuitem), "toggled", G_CALLBACK(docklet_toggle_mute), NULL); gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); - menuitem = gtk_check_menu_item_new_with_label(_("Blink on new message")); + menuitem = gtk_check_menu_item_new_with_label(_("Blink on New Message")); gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuitem), purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/docklet/blink")); g_signal_connect(G_OBJECT(menuitem), "toggled", G_CALLBACK(docklet_toggle_blink), NULL); gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
--- a/pidgin/gtkeventloop.c Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtkeventloop.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gtk_eventloop.c Purple Event Loop API (gtk implementation) * @ingroup pidgin - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkeventloop.h Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtkeventloop.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gtkeventloop.h Pidgin GTK+ Event Loop Implementation * @ingroup pidgin - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkft.c Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtkft.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gtkft.c GTK+ File Transfer UI * @ingroup pidgin - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkft.h Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtkft.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gtkft.h GTK+ File Transfer UI * @ingroup pidgin - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkgaim-compat.h Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtkgaim-compat.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,7 +1,8 @@ /** * @file gtkgaim-compat.h Gtk Gaim Compat macros - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkidle.h Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtkidle.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gtkidle.h GTK+ Idle API * @ingroup pidgin - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkimhtml.c Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtkimhtml.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /* * @file gtkimhtml.c GTK+ IMHtml * @ingroup pidgin - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkimhtml.h Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtkimhtml.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gtkimhtml.h GTK+ IM/HTML rendering component * @ingroup pidgin - * - * Pidgin is the legal property of its developers, whose names are too numerous + */ + +/* Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this * source distribution. *
--- a/pidgin/gtkimhtmltoolbar.c Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtkimhtmltoolbar.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /* * @file gtkimhtmltoolbar.c GTK+ IMHtml Toolbar * @ingroup pidgin - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this @@ -739,11 +740,11 @@ while (it != NULL) { it_tmp = it; - gtk_box_pack_start(GTK_BOX(line), it->button, TRUE, TRUE, 0); + gtk_box_pack_start(GTK_BOX(line), it->button, FALSE, FALSE, 0); gtk_widget_show(it->button); line_width += it->width; if (line_width >= max_line_width) { - gtk_box_pack_start(GTK_BOX(smiley_table), line, FALSE, TRUE, 0); + gtk_box_pack_start(GTK_BOX(smiley_table), line, FALSE, FALSE, 0); line = gtk_hbox_new(FALSE, 0); line_width = 0; col = 0; @@ -776,6 +777,9 @@ /* show everything */ gtk_window_set_title(GTK_WINDOW(dialog), _("Smile!")); gtk_widget_show_all(dialog); +#ifdef _WIN32 + winpidgin_ensure_onscreen(dialog); +#endif toolbar->smiley_dialog = dialog; @@ -1162,6 +1166,7 @@ GtkWidget *label; GtkWidget *insert_button; GtkWidget *font_button; + GtkWidget *smiley_button; GtkWidget *font_menu; GtkWidget *insert_menu; GtkWidget *menuitem; @@ -1263,12 +1268,6 @@ insert_menu = gtk_menu_new(); g_object_set_data(G_OBJECT(toolbar), "insert_menu", insert_menu); - menuitem = gtk_menu_item_new_with_mnemonic(_("_Smiley")); - g_signal_connect_swapped(G_OBJECT(menuitem), "activate", G_CALLBACK(gtk_button_clicked), toolbar->smiley); - gtk_menu_shell_append(GTK_MENU_SHELL(insert_menu), menuitem); - g_signal_connect(G_OBJECT(toolbar->smiley), "notify::sensitive", - G_CALLBACK(button_sensitiveness_changed), menuitem); - menuitem = gtk_menu_item_new_with_mnemonic(_("_Image")); g_signal_connect_swapped(G_OBJECT(menuitem), "activate", G_CALLBACK(gtk_button_clicked), toolbar->image); gtk_menu_shell_append(GTK_MENU_SHELL(insert_menu), menuitem); @@ -1290,6 +1289,24 @@ g_signal_connect(G_OBJECT(insert_button), "activate", G_CALLBACK(pidgin_menu_clicked), insert_menu); g_signal_connect(G_OBJECT(insert_menu), "deactivate", G_CALLBACK(pidgin_menu_deactivate), insert_button); toolbar->sml = NULL; + + /* Sep */ + sep = gtk_vseparator_new(); + gtk_box_pack_start(GTK_BOX(box), sep, FALSE, FALSE, 0); + gtk_widget_show_all(sep); + + /* Smiley */ + smiley_button = gtk_button_new(); + gtk_button_set_relief(GTK_BUTTON(smiley_button), GTK_RELIEF_NONE); + bbox = gtk_hbox_new(FALSE, 3); + gtk_container_add(GTK_CONTAINER(smiley_button), bbox); + image = gtk_image_new_from_stock(PIDGIN_STOCK_TOOLBAR_SMILEY, gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL)); + gtk_box_pack_start(GTK_BOX(bbox), image, FALSE, FALSE, 0); + label = gtk_label_new_with_mnemonic(_("_Smiley")); + gtk_box_pack_start(GTK_BOX(bbox), label, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(box), smiley_button, FALSE, FALSE, 0); + g_signal_connect_swapped(G_OBJECT(smiley_button), "clicked", G_CALLBACK(gtk_button_clicked), toolbar->smiley); + gtk_widget_show_all(smiley_button); gtk_box_pack_start(GTK_BOX(hbox), box, FALSE, FALSE, 0); g_object_set_data(G_OBJECT(hbox), "lean-view", box);
--- a/pidgin/gtklog.c Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtklog.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gtklog.c GTK+ Log viewer * @ingroup pidgin - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtklog.h Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtklog.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gtklog.h GTK+ Log viewer * @ingroup pidgin - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkmain.c Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtkmain.c Mon Oct 01 17:49:01 2007 +0000 @@ -394,6 +394,9 @@ " -n, --nologin don't automatically login\n" " -l, --login[=NAME] automatically login (optional argument NAME specifies\n" " account(s) to use, separated by commas)\n" +#ifndef WIN32 + " --display=DISPLAY X display to use\n" +#endif " -v, --version display the current version and exit\n"), PIDGIN_NAME, VERSION, name); } @@ -481,6 +484,7 @@ {"nologin", no_argument, NULL, 'n'}, {"session", required_argument, NULL, 's'}, {"version", no_argument, NULL, 'v'}, + {"display", required_argument, NULL, 'D'}, {0, 0, 0, 0} }; @@ -626,6 +630,9 @@ case 'm': /* do not ensure single instance. */ opt_si = FALSE; break; + case 'D': /* --display */ + /* handled by gtk_init_check below */ + break; case '?': /* show terse help */ default: show_usage(argv[0], TRUE);
--- a/pidgin/gtkmenutray.h Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtkmenutray.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gtkmenutray.h GTK+ Tray menu item * @ingroup pidgin - * - * Pidgin is the legal property of its developers, whose names are too numerous + */ + +/* Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this * source distribution. *
--- a/pidgin/gtknickcolors.h Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtknickcolors.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gtknickcolors.h GTK+ Conversation API * @ingroup pidgin - * - * pidgin + */ + +/* pidgin * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this * source distribution.
--- a/pidgin/gtknotify.c Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtknotify.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gtknotify.c GTK+ Notification API * @ingroup pidgin - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this @@ -412,32 +413,50 @@ * count > 0 mean non-detailed. */ static void * -pidgin_notify_add_mail(GtkTreeStore *treemodel, PurpleAccount *account, char *notification, const char *url, int count) +pidgin_notify_add_mail(GtkTreeStore *treemodel, PurpleAccount *account, char *notification, const char *url, int count, gboolean clear) { PidginNotifyMailData *data = NULL; GtkTreeIter iter; GdkPixbuf *icon; gboolean new_n = TRUE; - icon = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_MEDIUM); - - if (count > 0) { + if (count > 0 || clear) { /* Allow only one non-detailed email notification for each account */ if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(treemodel), &iter)) { + gboolean advanced; do { + advanced = FALSE; gtk_tree_model_get(GTK_TREE_MODEL(treemodel), &iter, PIDGIN_MAIL_DATA, &data, -1); - if (data->account == account && data->count > 0) { - new_n = FALSE; - g_free(data->url); - data->url = NULL; - mail_dialog->total_count -= data->count; - break; + if (data->account == account) { + if (clear) { +#if GTK_CHECK_VERSION(2,2,0) + advanced = gtk_tree_store_remove(treemodel, &iter); +#else + gtk_tree_store_remove(treemodel, &iter); + advanced = (iter.stamp == 0) ? FALSE : TRUE; +#endif + purple_notify_close(PURPLE_NOTIFY_EMAILS, data); + /* We're completely done if we've processed all entries */ + if (!advanced) + return NULL; + } else if (data->count > 0) { + new_n = FALSE; + g_free(data->url); + data->url = NULL; + mail_dialog->total_count -= data->count; + break; + } } - } while (gtk_tree_model_iter_next(GTK_TREE_MODEL(treemodel), &iter)); + } while (advanced || gtk_tree_model_iter_next(GTK_TREE_MODEL(treemodel), &iter)); } } + if (clear) + return NULL; + + icon = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_MEDIUM); + if (new_n) { data = g_new0(PidginNotifyMailData, 1); gtk_tree_store_append(treemodel, &iter, NULL); @@ -471,9 +490,13 @@ PurpleAccount *account; PidginNotifyMailData *data = NULL; + /* Don't bother updating if there aren't new emails and we don't have any displayed currently */ + if (count == 0 && mail_dialog == NULL) + return NULL; + account = purple_connection_get_account(gc); dialog = pidgin_get_mail_dialog(); /* This creates mail_dialog if necessary */ - + mail_dialog->total_count += count; if (detailed) { while (count--) { @@ -511,19 +534,33 @@ g_free(from_text); g_free(subject_text); - data = pidgin_notify_add_mail(mail_dialog->treemodel, account, notification, urls ? *urls : NULL, 0); + data = pidgin_notify_add_mail(mail_dialog->treemodel, account, notification, urls ? *urls : NULL, 0, FALSE); g_free(notification); if (urls != NULL) urls++; } } else { - notification = g_strdup_printf(ngettext("%s has %d new message.", - "%s has %d new messages.", - (int)count), - *tos, (int)count); - data = pidgin_notify_add_mail(mail_dialog->treemodel, account, notification, urls ? *urls : NULL, count); - g_free(notification); + if (count > 0) { + notification = g_strdup_printf(ngettext("%s has %d new message.", + "%s has %d new messages.", + (int)count), + *tos, (int)count); + data = pidgin_notify_add_mail(mail_dialog->treemodel, account, notification, urls ? *urls : NULL, count, FALSE); + g_free(notification); + } else { + GtkTreeIter iter; + + /* Clear out all mails for the account */ + pidgin_notify_add_mail(mail_dialog->treemodel, account, NULL, NULL, 0, TRUE); + + if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(mail_dialog->treemodel), &iter)) { + /* There is no API to clear the headline specifically */ + /* This will trigger reset_mail_dialog() */ + pidgin_blist_set_headline(NULL, NULL, NULL, NULL, NULL); + return NULL; + } + } } if (!GTK_WIDGET_VISIBLE(dialog)) { @@ -535,7 +572,7 @@ mail_dialog->in_use = TRUE; /* So that _set_headline doesn't accidentally remove the notifications when replacing an old notification. */ - pidgin_blist_set_headline(label_text, + pidgin_blist_set_headline(label_text, pixbuf, G_CALLBACK(gtk_widget_show_all), dialog, (GDestroyNotify)reset_mail_dialog); mail_dialog->in_use = FALSE; @@ -660,30 +697,30 @@ GtkTreeIter iter; GdkPixbuf *pixbuf; guint col_num; - guint i; - guint j; + GList *row, *column; + guint n; gtk_list_store_clear(data->model); pixbuf = pidgin_create_prpl_icon(purple_connection_get_account(gc), 0.5); /* +1 is for the automagically created Status column. */ - col_num = purple_notify_searchresults_get_columns_count(results) + 1; + col_num = g_list_length(results->columns) + 1; - for (i = 0; i < purple_notify_searchresults_get_rows_count(results); i++) { - GList *row = purple_notify_searchresults_row_get(results, i); + for (row = results->rows; row != NULL; row = row->next) { gtk_list_store_append(model, &iter); gtk_list_store_set(model, &iter, 0, pixbuf, -1); - for (j = 1; j < col_num; j++) { + n = 1; + for (column = row->data; column != NULL; column = column->next) { GValue v; - char *data = g_list_nth_data(row, j - 1); v.g_type = 0; g_value_init(&v, G_TYPE_STRING); - g_value_set_string(&v, data); - gtk_list_store_set_value(model, &iter, j, &v); + g_value_set_string(&v, column->data); + gtk_list_store_set_value(model, &iter, n, &v); + n++; } } @@ -703,6 +740,7 @@ GtkListStore *model; GtkCellRenderer *renderer; guint col_num; + GList *column; guint i; GtkWidget *vbox; @@ -750,7 +788,7 @@ g_free(label_text); /* +1 is for the automagically created Status column. */ - col_num = purple_notify_searchresults_get_columns_count(results) + 1; + col_num = g_list_length(results->columns) + 1; /* Setup the list model */ col_types = g_new0(GType, col_num); @@ -785,12 +823,13 @@ gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(treeview), -1, "", renderer, "pixbuf", 0, NULL); - for (i = 1; i < col_num; i++) { + i = 1; + for (column = results->columns; column != NULL; column = column->next) { renderer = gtk_cell_renderer_text_new(); gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(treeview), -1, - purple_notify_searchresults_column_get_title(results, i-1), - renderer, "text", i, NULL); + column->data, renderer, "text", i, NULL); + i++; } for (i = 0; i < g_list_length(results->buttons); i++) {
--- a/pidgin/gtknotify.h Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtknotify.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gtknotify.h GTK+ Notification API * @ingroup pidgin - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkplugin.c Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtkplugin.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gtkplugin.c GTK+ Plugins support * @ingroup pidgin - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkplugin.h Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtkplugin.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gtkplugin.h GTK+ Plugin API * @ingroup pidgin - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkpluginpref.c Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtkpluginpref.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gtkpluginpref.c GTK+ Plugin preferences * @ingroup pidgin - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkpluginpref.h Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtkpluginpref.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gtkpluginpref.h GTK+ Plugin Preferences * @ingroup pidgin - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkpounce.c Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtkpounce.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gtkpounce.c GTK+ Buddy Pounce API * @ingroup pidgin - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this @@ -305,6 +306,13 @@ if (*command == '\0') command = NULL; if (*sound == '\0') sound = NULL; + /* If the pounce has already been triggered, let's pretend it is a new one */ + if (dialog->pounce != NULL + && g_list_find(purple_pounces_get_all(), dialog->pounce) == NULL) { + purple_debug_info("gtkpounce", "Saving pounce that no longer exists; creating new pounce.\n"); + dialog->pounce = NULL; + } + if (dialog->pounce == NULL) { dialog->pounce = purple_pounce_new(PIDGIN_UI, dialog->account,
--- a/pidgin/gtkpounce.h Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtkpounce.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gtkpounce.h GTK+ Buddy Pounce API * @ingroup pidgin - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkprefs.c Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtkprefs.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gtkprefs.c GTK+ Preferences * @ingroup pidgin - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this @@ -993,6 +994,8 @@ pidgin_prefs_checkbox(_("Show _formatting on incoming messages"), PIDGIN_PREFS_ROOT "/conversations/show_incoming_formatting", vbox); + pidgin_prefs_checkbox(_("Close IMs immediately when the tab is closed"), + PIDGIN_PREFS_ROOT "/conversations/im/close_immediately", vbox); iconpref1 = pidgin_prefs_checkbox(_("Show _detailed information"), PIDGIN_PREFS_ROOT "/conversations/im/show_buddy_icons", vbox);
--- a/pidgin/gtkprefs.h Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtkprefs.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gtkprefs.h GTK+ Preferences * @ingroup pidgin - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkprivacy.c Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtkprivacy.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gtkprivacy.c GTK+ Privacy UI * @ingroup pidgin - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkprivacy.h Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtkprivacy.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gtkprivacy.h GTK+ Privacy UI * @ingroup pidgin - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkrequest.c Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtkrequest.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gtkrequest.c GTK+ Request API * @ingroup pidgin - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this @@ -998,7 +999,6 @@ /* Create the tree view */ treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); - gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(treeview), TRUE); gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(treeview), FALSE); sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
--- a/pidgin/gtkrequest.h Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtkrequest.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gtkrequest.h GTK+ Request API * @ingroup pidgin - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkroomlist.c Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtkroomlist.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gtkroomlist.c GTK+ Room List UI * @ingroup pidgin - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkroomlist.h Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtkroomlist.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gtkroomlist.h GTK+ Room List UI * @ingroup pidgin - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtksavedstatuses.c Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtksavedstatuses.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gtksavedstatus.c GTK+ Saved Status Editor UI * @ingroup pidgin - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this @@ -1410,7 +1411,7 @@ -1); type = purple_account_get_status_type(dialog->account, id); if (purple_status_type_get_attr(type, "message") != NULL) - message = gtk_imhtml_get_text(GTK_IMHTML(dialog->message), NULL, NULL); + message = gtk_imhtml_get_markup(GTK_IMHTML(dialog->message)); name = purple_status_type_get_name(type); status_editor = dialog->status_editor;
--- a/pidgin/gtksavedstatuses.h Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtksavedstatuses.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gtksavedstatuses.h GTK+ Saved Status Editor UI * @ingroup pidgin - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkscrollbook.c Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtkscrollbook.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /* * @file gtkscrollbook.c GTK+ Scrolling notebook widget * @ingroup pidgin - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkscrollbook.h Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtkscrollbook.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /* * @file gtkscrollbook GTK+ Scrolling notebook Widget * @ingroup pidgin - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtksession.c Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtksession.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /* * @file gtksession.c X Windows session management API * @ingroup pidgin - * - * Pidgin is the legal property of its developers, whose names are too numerous + */ + +/* Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this * source distribution. * @@ -35,6 +36,7 @@ #include <gdk/gdkx.h> #include <unistd.h> #include <fcntl.h> +#include <gdk/gdk.h> #define ERROR_LENGTH 512 @@ -140,7 +142,7 @@ /* my magic utility function */ static gchar **session_make_command(gchar *client_id, gchar *config_dir) { - gint i = 2; + gint i = 4; gint j = 0; gchar **ret; @@ -160,6 +162,9 @@ ret[j++] = g_strdup(config_dir); } + ret[j++] = g_strdup("--display"); + ret[j++] = g_strdup((gchar *)gdk_display_get_name(gdk_display_get_default())); + ret[j++] = NULL; return ret;
--- a/pidgin/gtksession.h Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtksession.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gtksession.h X Windows session management API * @ingroup pidgin - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtksound.c Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtksound.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /* * @file gtksound.c GTK+ Sound * @ingroup pidgin - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtksound.h Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtksound.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gtksound.h GTK+ Sound API * @ingroup pidgin - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkstatusbox.c Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtkstatusbox.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /* * @file gtkstatusbox.c GTK+ Status Selection Widget * @ingroup pidgin - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkstatusbox.h Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtkstatusbox.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /* * @file gtkstatusbox.c GTK+ Status Selection Widget * @ingroup pidgin - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkthemes.h Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtkthemes.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gtkthemes.h GTK+ Smiley Theme API * @ingroup pidgin - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkutils.c Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtkutils.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gtkutils.c GTK+ utility functions * @ingroup pidgin - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkutils.h Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtkutils.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file gtkutils.h GTK+ utility functions * @ingroup pidgin - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkwhiteboard.h Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/gtkwhiteboard.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,7 +1,8 @@ /** * @file gtkwhiteboard.h The PidginWhiteboard frontend object - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/pidgin.h Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/pidgin.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file pidgin.h UI definitions and includes * @ingroup pidgin - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/pidginstock.c Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/pidginstock.c Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file pidginstock.c GTK+ Stock resources * @ingroup pidgin - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/pidginstock.h Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/pidginstock.h Mon Oct 01 17:49:01 2007 +0000 @@ -1,8 +1,9 @@ /** * @file pidginstock.h GTK+ Stock resources * @ingroup pidgin - * - * pidgin + */ + +/* pidgin * * Pidgin is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/pixmaps/emblems/16/Makefile.am Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/pixmaps/emblems/16/Makefile.am Mon Oct 01 17:49:01 2007 +0000 @@ -12,6 +12,7 @@ hiptop.png \ male.png \ mobile.png \ + music.png \ not-authorized.png \ operator.png \ qq-member.png \
--- a/pidgin/pixmaps/emblems/16/scalable/Makefile.am Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/pixmaps/emblems/16/scalable/Makefile.am Mon Oct 01 17:49:01 2007 +0000 @@ -7,6 +7,7 @@ game.svg \ male.svg \ mobile.svg \ + music.svg \ not-authorized.svg \ qq-member.svg \ secure.svg \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pidgin/pixmaps/emblems/16/scalable/music.svg Mon Oct 01 17:49:01 2007 +0000 @@ -0,0 +1,187 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://web.resource.org/cc/" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="16" + height="16" + id="svg2" + sodipodi:version="0.32" + inkscape:version="0.45" + sodipodi:modified="true" + version="1.0"> + <defs + id="defs4"> + <linearGradient + inkscape:collect="always" + id="linearGradient3185"> + <stop + style="stop-color:#4e9a06;stop-opacity:1;" + offset="0" + id="stop3187" /> + <stop + style="stop-color:#4e9a06;stop-opacity:0" + offset="1" + id="stop3189" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + id="linearGradient3177"> + <stop + style="stop-color:#4e9a06;stop-opacity:1;" + offset="0" + id="stop3179" /> + <stop + style="stop-color:#4e9a06;stop-opacity:0;" + offset="1" + id="stop3181" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + id="linearGradient3153"> + <stop + style="stop-color:#eeeeec;stop-opacity:1;" + offset="0" + id="stop3155" /> + <stop + style="stop-color:#eeeeec;stop-opacity:0;" + offset="1" + id="stop3157" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3153" + id="linearGradient3159" + x1="2.5409546" + y1="10.048674" + x2="10.378205" + y2="15.928688" + gradientUnits="userSpaceOnUse" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3177" + id="radialGradient3183" + cx="5.2116022" + cy="8.4051199" + fx="5.2116022" + fy="8.4051199" + r="2.9404981" + gradientTransform="matrix(2.6050387,0,0,2.2888674,-8.415579,-10.767812)" + gradientUnits="userSpaceOnUse" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3185" + id="radialGradient3191" + cx="5.1978397" + cy="8.4135866" + fx="5.1978397" + fy="8.4135866" + r="3.1428281" + gradientTransform="matrix(2.8202152,0,0,2.4999643,-9.461187,-12.455954)" + gradientUnits="userSpaceOnUse" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + gridtolerance="10000" + guidetolerance="10" + objecttolerance="10" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="22.4" + inkscape:cx="19.784002" + inkscape:cy="11.848" + inkscape:document-units="px" + inkscape:current-layer="layer1" + width="16px" + height="16px" + showgrid="true" + inkscape:window-width="1440" + inkscape:window-height="847" + inkscape:window-x="0" + inkscape:window-y="22" /> + <metadata + id="metadata7"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1"> + <path + sodipodi:type="arc" + style="opacity:1;fill:#555753;fill-opacity:1;stroke:#222728;stroke-width:1.14297926;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="path2160" + sodipodi:cx="6.4712896" + sodipodi:cy="14.484771" + sodipodi:rx="3.5986683" + sodipodi:ry="2.1781414" + d="M 10.069958 14.484771 A 3.5986683 2.1781414 0 1 1 2.8726213,14.484771 A 3.5986683 2.1781414 0 1 1 10.069958 14.484771 z" + transform="matrix(0.8336417,0,0,0.918214,4.1052631,-0.8001194)" /> + <rect + style="opacity:1;fill:#222728;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect3143" + width="1" + height="12" + x="12" + y="1" + rx="0.18940361" + ry="0.20662212" /> + <path + style="fill:#222728;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1" + d="M 12.006464,3.0203051 L 11.981638,1 C 13.945163,1 17.837365,1.1548232 14.996311,7.9684328 C 15.596089,2.2547574 13.743811,3.0203051 12.006464,3.0203051 z " + id="rect3146" + sodipodi:nodetypes="cccc" /> + <path + sodipodi:type="arc" + style="opacity:1;fill:#555753;fill-opacity:1;stroke:url(#linearGradient3159);stroke-width:1.97969818;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="path3151" + sodipodi:cx="6.4712896" + sodipodi:cy="14.484771" + sodipodi:rx="3.5986683" + sodipodi:ry="2.1781414" + d="M 10.069958 14.484771 A 3.5986683 2.1781414 0 1 1 2.8726213,14.484771 A 3.5986683 2.1781414 0 1 1 10.069958 14.484771 z" + transform="matrix(0.5557611,0,0,0.4591071,5.903509,5.8499391)" /> + <path + sodipodi:type="arc" + style="opacity:1;fill:none;fill-opacity:1;stroke:url(#radialGradient3191);stroke-width:0.98568761;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="path3173" + sodipodi:cx="8.0970039" + sodipodi:cy="11.122857" + sodipodi:rx="4.3089318" + sodipodi:ry="3.5513175" + d="M 3.9729753,12.152015 A 4.3089318,3.5513175 0 0 1 9.0871283,7.6665672" + transform="matrix(1.0443424,0,0,0.9855497,-0.4560443,3.7870959e-2)" + sodipodi:start="2.8475788" + sodipodi:end="4.9442449" + sodipodi:open="true" /> + <path + sodipodi:type="arc" + style="opacity:1;fill:none;fill-opacity:1;stroke:url(#radialGradient3183);stroke-width:0.58102763;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="path3175" + sodipodi:cx="8.0970039" + sodipodi:cy="11.122857" + sodipodi:rx="4.3089318" + sodipodi:ry="3.5513175" + d="M 3.9729753,12.152015 A 4.3089318,3.5513175 0 0 1 9.0871283,7.6665672" + transform="matrix(1.6981233,0,0,1.7443645,-5.9310642,-8.697544)" + sodipodi:start="2.8475788" + sodipodi:end="4.9442449" + sodipodi:open="true" /> + </g> +</svg>
--- a/pidgin/pixmaps/emotes/default/24/default.theme.in Mon Oct 01 17:02:03 2007 +0000 +++ b/pidgin/pixmaps/emotes/default/24/default.theme.in Mon Oct 01 17:49:01 2007 +0000 @@ -23,7 +23,7 @@ foot-in-mouth.png :-! shout.png >:o >:O ! skywalker.png C:-) c:-) C:) c:) -! monkey.png :-(|) :(|) +! monkey.png :-(|) :(|) 8-|) ! cyclops.png O-) o-) # Following AIM 6.1 @@ -249,7 +249,7 @@ sick.png :-! kissed.png *KISSED* stop.png *STOP* -kiss.png :-* +kiss.png :-{} :-* kissing.png *KISSING* embarrassed.png :-[ devil.png ]:-> @@ -262,7 +262,6 @@ shout.png >:o >:O beer.png *DRINK* smile-big.png :-D :D -moneymouth.png :-$ glasses-cool.png 8-) in-love.png *IN\ LOVE* ! skywalker.png C:-) c:-) C:) c:)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pidgin/pixmaps/protocols/22/scalable/myspace.svg Mon Oct 01 17:49:01 2007 +0000 @@ -0,0 +1,114 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://web.resource.org/cc/" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="24" + height="24" + id="svg2160" + sodipodi:version="0.32" + inkscape:version="0.45" + sodipodi:docname="myspace48.svg" + sodipodi:docbase="/home/hbons/Desktop" + inkscape:output_extension="org.inkscape.output.svg.inkscape" + sodipodi:modified="true" + version="1.0"> + <defs + id="defs2162"> + <linearGradient + inkscape:collect="always" + id="linearGradient3147"> + <stop + style="stop-color:#eeeeec;stop-opacity:1;" + offset="0" + id="stop3149" /> + <stop + style="stop-color:#eeeeec;stop-opacity:0;" + offset="1" + id="stop3151" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + id="linearGradient3172"> + <stop + style="stop-color:#eeeeec;stop-opacity:1;" + offset="0" + id="stop3174" /> + <stop + style="stop-color:#eeeeec;stop-opacity:0;" + offset="1" + id="stop3176" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3172" + id="linearGradient3178" + x1="10.549266" + y1="5.125" + x2="52.810349" + y2="49.864979" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3147" + id="linearGradient3153" + x1="6.0203052" + y1="1.0398448" + x2="26.101271" + y2="25.83909" + gradientUnits="userSpaceOnUse" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="9.8994949" + inkscape:cx="31.349135" + inkscape:cy="11.3794" + inkscape:current-layer="layer1" + showgrid="true" + inkscape:grid-bbox="true" + inkscape:document-units="px" + inkscape:window-width="1440" + inkscape:window-height="847" + inkscape:window-x="3" + inkscape:window-y="25" + width="24px" + height="24px" /> + <metadata + id="metadata2165"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + id="layer1" + inkscape:label="Layer 1" + inkscape:groupmode="layer"> + <path + style="opacity:1;fill:#babdb6;fill-opacity:1;stroke:#888a85;stroke-width:1.00000012;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 17 1.5 C 15.068 1.5 13.5 3.0680001 13.5 5 C 13.5 6.932 15.068 8.5 17 8.5 C 18.932 8.5 20.499999 6.932 20.5 5 C 20.5 3.068 18.931999 1.4999999 17 1.5 z M 10.5 2.5 C 8.8439999 2.5 7.5000001 3.8439999 7.5 5.5 C 7.5 7.1559999 8.8439997 8.4999996 10.5 8.5 C 9.395701 8.5527352 8.4448563 9.5454035 7.875 10.4375 C 7.830859 8.7148111 7.161553 7.5791344 5.6875 7.5 C 6.7035586 7.4052513 7.5 6.5406823 7.5 5.5 C 7.5 4.396 6.604 3.5 5.5 3.5 C 4.396 3.5 3.4999999 4.396 3.5 5.5 C 3.5 6.5828941 4.3626534 7.4666427 5.4375 7.5 C 4.352857 7.6401732 3.5000005 8.6243123 3.5 9.875 L 3.5 14.53125 L 7.5625 14.53125 L 7.5625 18.53125 L 12.5 18.53125 L 12.5 22.5 L 21.5 22.5 C 21.499867 19.408873 21.5 16.303843 21.5 13.21875 C 21.5 10.634939 19.434134 8.53125 16.875 8.53125 C 15.587036 8.5312503 14.40291 9.424387 13.5625 10.28125 C 13.046577 9.1148819 11.916283 8.5 10.59375 8.5 C 12.205095 8.4489386 13.5 7.1236737 13.5 5.5 C 13.5 3.8440001 12.156 2.5 10.5 2.5 z "