Sat, 06 Feb 2010 05:15:35 +0000
propagate from branch 'im.pidgin.pidgin' (head fa3096fc03d96aab042c6f0c6d678564ba5aba7e)
to branch 'im.pidgin.cpw.qulogic.msnp16' (head 75d293894d857681ce55f1cb7fa973165a497cb9)
--- a/COPYRIGHT Thu Feb 04 20:57:01 2010 +0000 +++ b/COPYRIGHT Sat Feb 06 05:15:35 2010 +0000 @@ -147,6 +147,7 @@ Marc Etcheverry David Everly Larry Ewing +Fartash Faghri Gábor Farkas Jesse Farmer Gavan Fantom (gavan) @@ -154,6 +155,7 @@ David Fiander Rob Flynn <gaim@robflynn.com> Rob Foehl (rwf) +Chris Foote Alan Ford Nathan Fredrickson Chris J. Friesen @@ -377,6 +379,7 @@ R. Ramkumar Mart Raudsepp Etan Reisner +Luoh Ren-Shan Kristian Rietveld Pekka Riikonen Tim Ringenbach @@ -388,6 +391,7 @@ Luciano Miguel Ferreira Rocha Andrew Rodland Miguel Rodríguez (migrax) +Adi Roiban Martin Rosinski Bob Rossi Jason Roth
--- a/ChangeLog Thu Feb 04 20:57:01 2010 +0000 +++ b/ChangeLog Sat Feb 06 05:15:35 2010 +0000 @@ -1,6 +1,69 @@ Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul -version 2.6.5 (??/??/20??): +version 2.6.6 (??/??/20??): + libpurple: + * Fix 'make check' on OS X. (David Fang) + * Fix a quirk in purple_markup_html_to_xhtml that caused some messages + to be improperly converted to XHTML. + * Set "controlling-mode" correctly when initializing a media session. + Fixes receiving voice calls from Psi. + + General: + * Correctly disable all missing dependencies when using the + --disable-missing-dependencies option. (Gabriel Schulhof) + + Gadu-Gadu: + * Fix display of avatars after a server-side change. (Krzysztof + Klinikowski) + + AIM: + * Allow setting and displaying icons between 1x1 and 100x100 pixels. + Previously only icons between 48x48 and 50x50 were allowed. + + MSN: + * File transfer requests will no longer cause a crash if you delete the + file before the other side accepts. + * Received files will no longer hold an extra lock after completion, + meaning they can be moved or deleted without complaints from your OS. + * Buddies who sign in from a second location will no longer cause an + unnecessary chat window to open. + * Support setting an animated GIF as a buddy icon. + + XMPP: + * Added support for the SCRAM-SHA-1 SASL mechanism. This is only + available when built without Cyrus SASL support. + * When getting info on a domain-only (server) JID, show uptime + (when given by the result of the "last query") and don't show status as + offline. + * Wrap XHTML messages in <p>, as described in XEP-0071, for compatibility + with some clients. + * Don't do an SRV lookup for a STUN server associated with the account + if one is already set globally in prefs. + * Don't send custom smileys larger than the recommended maximum object size + specified in the BoB XEP. This prevents a client from being + disconnected by servers that dislike overly-large stanzas. + + Yahoo: + * Don't send <span> and </span> tags. (Fartash Faghri) + + Pidgin: + * Correctly size conversation and status box entries when the + interior-focus style property is diabled. (Gabriel Schulhof) + * Correctly handle a multiline text field being required in a + request form. (Thanks to Florian Zeitz for finding this problem) + * Search friends by email-addresses in the buddy list. (Luoh Ren-Shan) + + Finch: + * Rebindable 'move-first' and 'move-last' actions for tree widgets. So + it is possible to jump to the first or last entry in the buddy list + (and other such lists) by pressing home or end key (defaults) + respectively. + +version 2.6.5 (01/08/2010): + libpurple: + * TLS certificates are actually stored to the local cache once again + (accepting a name mismatch on a certificate should now be remembered) + General: * Build-time fixes for Solaris. (Paul Townsend) @@ -9,17 +72,10 @@ Chinese characters (broken in 2.6.4) MSN: - * File transfer requests will no longer cause a crash if you delete the file - before the other side accepts. - * Recieved files will no longer hold an extra lock after completion, meaning - they can be moved or deleted without complaints from your OS. + * Fix an issue allowing a remote user to download arbitrary files from + a libpurple client. (CVE-2010-0013) XMPP: - * Added support for the SCRAM-SHA-1 SASL mechanism. This is only - available when built without Cyrus SASL support. - * When getting info on a domain-only (server) JID, show uptime - (when given by the result of the "last query") and don't show status as - offline. * Do not crash when attempting to register for a new account on Windows. * Fix file transfer with clients that do not support Entity Capabilities (e.g. Spark)
--- a/ChangeLog.API Thu Feb 04 20:57:01 2010 +0000 +++ b/ChangeLog.API Sat Feb 06 05:15:35 2010 +0000 @@ -1,6 +1,22 @@ Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul -version 2.6.5 (??/??/20??): +version 2.6.6 (??/??/2010): + libpurple: + Changed: + * purple_xfer_cancel_local is now called instead of + purple_xfer_request_denied if an error is found when selecting + a file to send. Request denied is still used when a receive + request is not allowed. + Perl: + Changed: + * Corrected the package names for the PurpleProxyType and + PurpleLogReadFlags enums to have the correct number of colons + (from Purple::ProxyType::::<type> to Purple::ProxyType::<type> + and Purple::Log:ReadFlags::::<type> to + Purple::Log::ReadFlags::<type>) (Chris Foote) + +version 2.6.5 (01/08/2010): + No changes version 2.6.4 (11/29/2009): No changes
--- a/ChangeLog.win32 Thu Feb 04 20:57:01 2010 +0000 +++ b/ChangeLog.win32 Sat Feb 06 05:15:35 2010 +0000 @@ -1,6 +1,10 @@ -version 2.6.5 (??/??/20??): + +version 2.6.6 (??/??/2010): * Installer translations for: Norwegian nynorsk +version 2.6.5 (01/08/2010): + * No changes + version 2.6.4 (11/29/2009): * Register URL handlers for everything that Windows knows about. Still use the HTTP "open" handler for security reasons.
--- a/NEWS Thu Feb 04 20:57:01 2010 +0000 +++ b/NEWS Sat Feb 06 05:15:35 2010 +0000 @@ -2,7 +2,12 @@ Our development blog is available at: http://planet.pidgin.im -2.6.5 (??/??/20??): +2.6.6 (??/??/2010): + +2.6.5 (01/08/2010): + Paul: This release fixes a pretty serious bug in the MSN code, so we're + releasing this build a little earlier than planned with only major + bugs fixed. See the ChangeLog for details. Enjoy! 2.6.4 (11/29/2009): John: It's release time again. Lots of bug fixes this time around, as
--- a/configure.ac Thu Feb 04 20:57:01 2010 +0000 +++ b/configure.ac Sat Feb 06 05:15:35 2010 +0000 @@ -46,7 +46,7 @@ m4_define([purple_lt_current], [6]) m4_define([purple_major_version], [2]) m4_define([purple_minor_version], [6]) -m4_define([purple_micro_version], [5]) +m4_define([purple_micro_version], [6]) m4_define([purple_version_suffix], [devel]) m4_define([purple_version], [purple_major_version.purple_minor_version.purple_micro_version]) @@ -55,7 +55,7 @@ m4_define([gnt_lt_current], [6]) m4_define([gnt_major_version], [2]) m4_define([gnt_minor_version], [6]) -m4_define([gnt_micro_version], [5]) +m4_define([gnt_micro_version], [6]) m4_define([gnt_version_suffix], [devel]) m4_define([gnt_version], [gnt_major_version.gnt_minor_version.gnt_micro_version]) @@ -144,7 +144,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 ga gl gu he hi hu hy id it ja ka km kn ko ku lo lt mk mn ms_MY my_MM nb ne nl nn oc pa pl pt_BR pt ps ro ru si sk sl sq sr sr@latin sv sw ta te th tr uk ur 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 ga gl gu he hi hu hy id it ja ka km kn ko ku lo lt mk mn mr ms_MY my_MM nb ne nl nn oc pa pl pt_BR pt ps ro ru si sk sl sq sr sr@latin sv sw ta te th tr uk ur 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 @@ -426,6 +426,7 @@ X11_LIBS="$x_libpath_add" X11_CFLAGS="$x_incpath_add" else + with_x="no" if test "x$force_deps" = "xyes" ; then AC_MSG_ERROR([ X11 development headers not found. @@ -528,6 +529,7 @@ if test "x$enable_startup_notification" = "xyes"; then PKG_CHECK_MODULES(STARTUP_NOTIFICATION, [libstartup-notification-1.0 >= 0.5], , [ AC_MSG_RESULT(no) + enable_startup_notification="no" if test "x$force_deps" = "xyes" ; then AC_MSG_ERROR([ Startup notification development headers not found. @@ -548,6 +550,7 @@ if test "x$enable_gtkspell" = "xyes" ; then PKG_CHECK_MODULES(GTKSPELL, gtkspell-2.0 >= 2.0.2, , [ AC_MSG_RESULT(no) + enable_gtkspell="no" if test "x$force_deps" = "xyes" ; then AC_MSG_ERROR([ GtkSpell development headers not found. @@ -598,6 +601,7 @@ if test "x$enable_cap" = "xyes"; then PKG_CHECK_MODULES(SQLITE3, sqlite3 >= 3.3,,[ AC_MSG_RESULT(no) + enable_cap="no" if test "x$force_deps" = "xyes" ; then AC_MSG_ERROR([ sqlite3 development headers not found. @@ -746,6 +750,7 @@ [], [$GSTREAMER_LIBS]) ], [ AC_MSG_RESULT(no) + enable_gst="no" if test "x$force_deps" = "xyes" ; then AC_MSG_ERROR([ GStreamer development headers not found. @@ -812,6 +817,10 @@ fi AM_CONDITIONAL(USE_VV, test "x$enable_gstreamer" != "xno" -a "x$enable_gstinterfaces" != "xno" -a "x$enable_farsight" != "xno") +dnl ####################################################################### +dnl # Check for Internationalized Domain Name support +dnl ####################################################################### + AC_ARG_ENABLE(idn, [AC_HELP_STRING([--disable-idn], [compile without IDN support])], [enable_idn="$enableval" force_idn=$enableval], [enable_idn="yes" force_idn=no]) @@ -822,6 +831,7 @@ AC_SUBST(IDN_LIBS) ], [ AC_MSG_RESULT(no) + enable_idn="no" if test "x$force_deps" = "xyes" ; then AC_MSG_ERROR([ GNU Libidn development headers not found. @@ -894,11 +904,14 @@ AC_CHECK_LIB(avahi-client, avahi_client_new, [avahilibs=yes], [avahilibs=no], $AVAHI_LIBS) fi -if test "x$enable_avahi" = "xyes" -a "x$force_deps" = "xyes" -a \( "x$avahiincludes" = "xno" -o "x$avahilibs" = "xno" \); then - AC_MSG_ERROR([ +if test "x$enable_avahi" = "xyes" -a \( "x$avahiincludes" = "xno" -o "x$avahilibs" = "xno" \); then + enable_avahi="no" + if test "x$force_deps" = "xyes"; then + AC_MSG_ERROR([ avahi development headers not found. Use --disable-avahi if you do not need avahi (Bonjour) support. ]) + fi fi AC_SUBST(AVAHI_CFLAGS) AC_SUBST(AVAHI_LIBS)
--- a/doc/finch.1.in Thu Feb 04 20:57:01 2010 +0000 +++ b/doc/finch.1.in Sat Feb 06 05:15:35 2010 +0000 @@ -366,6 +366,10 @@ .br backspace = move-parent .br +home = move-first +.br +end = move-last +.br # Following is the default binding for the context-menu .br menu = context-menu
--- a/finch/gntidle.c Thu Feb 04 20:57:01 2010 +0000 +++ b/finch/gntidle.c Sat Feb 06 05:15:35 2010 +0000 @@ -21,6 +21,8 @@ * */ +#include <internal.h> + #include "finch.h" #include "gntidle.h" #include "gntwm.h"
--- a/finch/gntrequest.c Thu Feb 04 20:57:01 2010 +0000 +++ b/finch/gntrequest.c Sat Feb 06 05:15:35 2010 +0000 @@ -23,6 +23,8 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ +#include <internal.h> + #include <gnt.h> #include <gntbox.h> #include <gntbutton.h> @@ -35,7 +37,6 @@ #include <gnttree.h> #include "finch.h" -#include <internal.h> #include "gntrequest.h" #include "debug.h" #include "util.h"
--- a/finch/gntstatus.c Thu Feb 04 20:57:01 2010 +0000 +++ b/finch/gntstatus.c Sat Feb 06 05:15:35 2010 +0000 @@ -23,6 +23,8 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ +#include <internal.h> + #include <gnt.h> #include <gntbox.h> #include <gntbutton.h> @@ -34,7 +36,6 @@ #include <gntutils.h> #include "finch.h" -#include <internal.h> #include <notify.h> #include <request.h>
--- a/finch/libgnt/gntinternal.h Thu Feb 04 20:57:01 2010 +0000 +++ b/finch/libgnt/gntinternal.h Sat Feb 06 05:15:35 2010 +0000 @@ -32,6 +32,14 @@ # define gnt_warning g_warning #endif +#ifndef G_GNUC_NULL_TERMINATED +# if defined(__GNUC__) && __GNUC__ >= 4 +# define G_GNUC_NULL_TERMINATED __attribute__((__sentinel__)) +# else +# define G_GNUC_NULL_TERMINATED +# endif +#endif + extern int gnt_need_conversation_to_locale; extern const char *C_(const char *x);
--- a/finch/libgnt/gntline.c Thu Feb 04 20:57:01 2010 +0000 +++ b/finch/libgnt/gntline.c Sat Feb 06 05:15:35 2010 +0000 @@ -20,6 +20,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ +#include "gntinternal.h" #include "gntline.h" enum
--- a/finch/libgnt/gntmenuitem.c Thu Feb 04 20:57:01 2010 +0000 +++ b/finch/libgnt/gntmenuitem.c Sat Feb 06 05:15:35 2010 +0000 @@ -20,6 +20,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ +#include "gntinternal.h" #include "gntmenu.h" #include "gntmenuitem.h"
--- a/finch/libgnt/gntmenuitemcheck.c Thu Feb 04 20:57:01 2010 +0000 +++ b/finch/libgnt/gntmenuitemcheck.c Sat Feb 06 05:15:35 2010 +0000 @@ -20,6 +20,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ +#include "gntinternal.h" #include "gntmenuitemcheck.h" static GntMenuItemClass *parent_class = NULL;
--- a/finch/libgnt/gntprogressbar.c Thu Feb 04 20:57:01 2010 +0000 +++ b/finch/libgnt/gntprogressbar.c Sat Feb 06 05:15:35 2010 +0000 @@ -20,6 +20,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA **/ +#include "gntinternal.h" #include "gntprogressbar.h" #include "gntutils.h"
--- a/finch/libgnt/gntslider.c Thu Feb 04 20:57:01 2010 +0000 +++ b/finch/libgnt/gntslider.c Sat Feb 06 05:15:35 2010 +0000 @@ -20,6 +20,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ +#include "gntinternal.h" #include "gntcolors.h" #include "gntkeys.h" #include "gntslider.h"
--- a/finch/libgnt/gnttree.c Thu Feb 04 20:57:01 2010 +0000 +++ b/finch/libgnt/gnttree.c Sat Feb 06 05:15:35 2010 +0000 @@ -957,6 +957,45 @@ return TRUE; } +static gboolean +move_first_action(GntBindable *bind, GList *null) +{ + GntTree *tree = GNT_TREE(bind); + GntTreeRow *row = tree->root; + GntTreeRow *old = tree->current; + if (row && !row_matches_search(row)) + row = get_next(row); + if (row) { + tree->current = row; + redraw_tree(tree); + if (old != tree->current) + tree_selection_changed(tree, old, tree->current); + } + + return TRUE; +} + +static gboolean +move_last_action(GntBindable *bind, GList *null) +{ + GntTree *tree = GNT_TREE(bind); + GntTreeRow *old = tree->current; + GntTreeRow *row = tree->bottom; + GntTreeRow *next; + + while ((next = get_next(row))) + row = next; + + if (row) { + tree->current = row; + redraw_tree(tree); + if (old != tree->current) + tree_selection_changed(tree, old, tree->current); + } + + return TRUE; +} + static void gnt_tree_set_property(GObject *obj, guint prop_id, const GValue *value, GParamSpec *spec) @@ -1076,6 +1115,10 @@ "/", NULL); gnt_bindable_class_register_action(bindable, "end-search", end_search_action, "\033", NULL); + gnt_bindable_class_register_action(bindable, "move-first", move_first_action, + GNT_KEY_HOME, NULL); + gnt_bindable_class_register_action(bindable, "move-last", move_last_action, + GNT_KEY_END, NULL); gnt_style_read_actions(G_OBJECT_CLASS_TYPE(klass), bindable); GNTDEBUG;
--- a/finch/libgnt/gntutils.c Thu Feb 04 20:57:01 2010 +0000 +++ b/finch/libgnt/gntutils.c Sat Feb 06 05:15:35 2010 +0000 @@ -373,7 +373,6 @@ xmlFreeDoc(doc); xmlFreeParserCtxt(ctxt); - xmlCleanupParser(); va_end(list); g_free(data); #endif @@ -470,7 +469,6 @@ ret = TRUE; } xmlFreeParserCtxt(ctxt); - xmlCleanupParser(); return ret; #endif }
--- a/finch/libgnt/gntwidget.c Thu Feb 04 20:57:01 2010 +0000 +++ b/finch/libgnt/gntwidget.c Sat Feb 06 05:15:35 2010 +0000 @@ -22,6 +22,7 @@ /* Stuff brutally ripped from Gflib */ +#include "gntinternal.h" #include "gntwidget.h" #include "gntstyle.h" #include "gntmarshal.h"
--- a/finch/libgnt/gntwindow.c Thu Feb 04 20:57:01 2010 +0000 +++ b/finch/libgnt/gntwindow.c Sat Feb 06 05:15:35 2010 +0000 @@ -20,6 +20,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ +#include "gntinternal.h" #include "gntstyle.h" #include "gntwindow.h"
--- a/finch/libgnt/gntwm.c Thu Feb 04 20:57:01 2010 +0000 +++ b/finch/libgnt/gntwm.c Sat Feb 06 05:15:35 2010 +0000 @@ -889,6 +889,13 @@ all = g_list_delete_link(all, list); wm->cws->list = all; gnt_ws_draw_taskbar(wm->cws, FALSE); + if (wm->cws->ordered) { + GntWidget *w = wm->cws->ordered->data; + GntNode *node = g_hash_table_lookup(wm->nodes, w); + top_panel(node->panel); + update_panels(); + doupdate(); + } } static gboolean @@ -1106,12 +1113,20 @@ refresh_screen(GntBindable *bindable, GList *null) { GntWM *wm = GNT_WM(bindable); + GList *iter; endwin(); refresh(); g_hash_table_foreach(wm->nodes, (GHFunc)refresh_node, GINT_TO_POINTER(TRUE)); g_signal_emit(wm, signals[SIG_TERMINAL_REFRESH], 0); + + for (iter = g_list_last(wm->cws->ordered); iter; iter = iter->prev) { + GntWidget *w = iter->data; + GntNode *node = g_hash_table_lookup(wm->nodes, w); + top_panel(node->panel); + } + gnt_ws_draw_taskbar(wm->cws, TRUE); update_screen(wm); curs_set(0); /* endwin resets the cursor to normal */
--- a/finch/libgnt/wms/irssi.c Thu Feb 04 20:57:01 2010 +0000 +++ b/finch/libgnt/wms/irssi.c Sat Feb 06 05:15:35 2010 +0000 @@ -33,6 +33,8 @@ #include <string.h> #include <sys/types.h> +#include "gntinternal.h" + #include "gnt.h" #include "gntbox.h" #include "gntmenu.h" @@ -205,11 +207,15 @@ update_conv_window_title(GntNode *node) { char title[256]; + int x, y; snprintf(title, sizeof(title), "%d: %s", GPOINTER_TO_INT(g_object_get_data(G_OBJECT(node->me), "irssi-index")) + 1, GNT_BOX(node->me)->title); + + getyx(node->window, y, x); wbkgdset(node->window, '\0' | COLOR_PAIR(gnt_widget_has_focus(node->me) ? GNT_COLOR_TITLE : GNT_COLOR_TITLE_D)); mvwaddstr(node->window, 0, 0, title); + wmove(node->window, y, x); if (!gnt_is_refugee()) { update_panels(); doupdate(); @@ -294,10 +300,15 @@ name = gnt_widget_get_name(widget); if (name && strstr(name, "conversation-window")) { + int cx, cy, cw, ch; + gnt_widget_get_position(widget, &cx, &cy); + gnt_widget_get_size(widget, &cw, &ch); find_window_position(irssi, widget, &hor, &vert); get_xywh_for_frame(irssi, hor, vert, &x, &y, &w, &h); - gnt_wm_move_window(GNT_WM(irssi), widget, x, y); - gnt_wm_resize_window(GNT_WM(irssi), widget, w, h); + if (x != cx || y != cy) + gnt_wm_move_window(GNT_WM(irssi), widget, x, y); + if (w != cw || h != ch) + gnt_wm_resize_window(GNT_WM(irssi), widget, w, h); } }
--- a/libpurple/account.c Thu Feb 04 20:57:01 2010 +0000 +++ b/libpurple/account.c Sat Feb 06 05:15:35 2010 +0000 @@ -1341,7 +1341,8 @@ handles = g_list_remove(handles, info); - info->auth_cb(info->userdata); + if (info->auth_cb != NULL) + info->auth_cb(info->userdata); purple_signal_emit(purple_accounts_get_handle(), "account-authorization-granted", info->account, info->user); @@ -1356,7 +1357,8 @@ handles = g_list_remove(handles, info); - info->deny_cb(info->userdata); + if (info->deny_cb != NULL) + info->deny_cb(info->userdata); purple_signal_emit(purple_accounts_get_handle(), "account-authorization-denied", info->account, info->user); @@ -1383,10 +1385,12 @@ "account-authorization-requested", account, remote_user)); if (plugin_return > 0) { - auth_cb(user_data); + if (auth_cb != NULL) + auth_cb(user_data); return NULL; } else if (plugin_return < 0) { - deny_cb(user_data); + if (deny_cb != NULL) + deny_cb(user_data); return NULL; } @@ -2311,7 +2315,7 @@ gc = purple_account_get_connection(account); if (gc != NULL) - prpl = purple_connection_get_prpl(gc); + prpl = purple_connection_get_prpl(gc); if (prpl != NULL) prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); @@ -2328,7 +2332,7 @@ PurplePlugin *prpl = NULL; if (gc != NULL) - prpl = purple_connection_get_prpl(gc); + prpl = purple_connection_get_prpl(gc); if (prpl != NULL) prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); @@ -2367,7 +2371,7 @@ PurplePlugin *prpl = NULL; if (gc != NULL) - prpl = purple_connection_get_prpl(gc); + prpl = purple_connection_get_prpl(gc); if (prpl != NULL) prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); @@ -2384,7 +2388,7 @@ PurplePlugin *prpl = NULL; if (gc != NULL) - prpl = purple_connection_get_prpl(gc); + prpl = purple_connection_get_prpl(gc); if (prpl != NULL) prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); @@ -2412,7 +2416,7 @@ PurplePlugin *prpl = NULL; if (gc != NULL) - prpl = purple_connection_get_prpl(gc); + prpl = purple_connection_get_prpl(gc); if (prpl != NULL) prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); @@ -2432,7 +2436,7 @@ purple_account_set_password(account, new_pw); if (gc != NULL) - prpl = purple_connection_get_prpl(gc); + prpl = purple_connection_get_prpl(gc); if (prpl != NULL) prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
--- a/libpurple/buddyicon.c Thu Feb 04 20:57:01 2010 +0000 +++ b/libpurple/buddyicon.c Sat Feb 06 05:15:35 2010 +0000 @@ -716,9 +716,8 @@ if (read_icon_file(path, &data, &len)) { g_free(path); - img = purple_buddy_icon_data_new(data, len, account_icon_file); - g_hash_table_insert(pointer_icon_cache, account, img); - return img; + img = purple_buddy_icons_set_account_icon(account, data, len); + return purple_imgstore_ref(img); } g_free(path); @@ -841,9 +840,8 @@ if (read_icon_file(path, &data, &len)) { g_free(path); - img = purple_buddy_icon_data_new(data, len, custom_icon_file); - g_hash_table_insert(pointer_icon_cache, node, img); - return img; + img = purple_buddy_icons_node_set_custom_icon(node, data, len); + return purple_imgstore_ref(img); } g_free(path); @@ -1302,6 +1300,9 @@ g_hash_table_destroy(pointer_icon_cache); g_free(old_icons_dir); g_free(cache_dir); + + cache_dir = NULL; + old_icons_dir = NULL; } void purple_buddy_icon_get_scale_size(PurpleBuddyIconSpec *spec, int *width, int *height)
--- a/libpurple/certificate.c Thu Feb 04 20:57:01 2010 +0000 +++ b/libpurple/certificate.c Sat Feb 06 05:15:35 2010 +0000 @@ -1431,9 +1431,8 @@ tls_peers = purple_certificate_find_pool(x509_tls_cached.scheme_name, "tls_peers"); if (tls_peers) { - if (!purple_certificate_pool_contains(tls_peers, vrq->subject_name) && - !purple_certificate_pool_store(tls_peers,vrq->subject_name, - peer_crt)) { + if (!purple_certificate_pool_store(tls_peers,vrq->subject_name, + peer_crt)) { purple_debug_error("certificate/x509/tls_cached", "FAILED to cache peer certificate\n"); }
--- a/libpurple/conversation.h Thu Feb 04 20:57:01 2010 +0000 +++ b/libpurple/conversation.h Sat Feb 06 05:15:35 2010 +0000 @@ -368,7 +368,8 @@ * @param type The type of conversation. * @param account The account opening the conversation window on the purple * user's end. - * @param name The name of the conversation. + * @param name The name of the conversation. For PURPLE_CONV_TYPE_IM, + * this is the name of the buddy. * * @return The new conversation. */
--- a/libpurple/dbus-server.c Thu Feb 04 20:57:01 2010 +0000 +++ b/libpurple/dbus-server.c Sat Feb 06 05:15:35 2010 +0000 @@ -601,7 +601,6 @@ { static DBusObjectPathVTable vtable = {NULL, &purple_dbus_dispatch, NULL, NULL, NULL, NULL}; DBusError error; - int result; dbus_error_init(&error); purple_dbus_connection = dbus_bus_get(DBUS_BUS_STARTER, &error); @@ -625,16 +624,15 @@ return; } - dbus_request_name_reply = - result = dbus_bus_request_name(purple_dbus_connection, + dbus_request_name_reply = dbus_bus_request_name(purple_dbus_connection, DBUS_SERVICE_PURPLE, 0, &error); if (dbus_error_is_set(&error)) { dbus_connection_unref(purple_dbus_connection); - dbus_error_free(&error); purple_dbus_connection = NULL; init_error = g_strdup_printf(N_("Failed to get serv name: %s"), error.name); + dbus_error_free(&error); return; }
--- a/libpurple/dnssrv.c Thu Feb 04 20:57:01 2010 +0000 +++ b/libpurple/dnssrv.c Sat Feb 06 05:15:35 2010 +0000 @@ -366,7 +366,7 @@ cp += 6; GETSHORT(dlen,cp); - if (query.type == T_SRV) { + if (type == T_SRV) { GETSHORT(pref,cp); GETSHORT(weight,cp); @@ -386,7 +386,7 @@ srvres->weight = weight; ret = g_list_prepend(ret, srvres); - } else if (query.type == T_TXT) { + } else if (type == T_TXT) { txtres = g_new0(PurpleTxtResponse, 1); txtres->content = g_strndup((gchar*)(++cp), dlen-1); ret = g_list_append(ret, txtres);
--- a/libpurple/ft.c Thu Feb 04 20:57:01 2010 +0000 +++ b/libpurple/ft.c Sat Feb 06 05:15:35 2010 +0000 @@ -69,6 +69,30 @@ g_free(priv); } +static const gchar * +purple_xfer_status_type_to_string(PurpleXferStatusType type) +{ + static const struct { + PurpleXferStatusType type; + const char *name; + } type_names[] = { + { PURPLE_XFER_STATUS_UNKNOWN, "unknown" }, + { PURPLE_XFER_STATUS_NOT_STARTED, "not started" }, + { PURPLE_XFER_STATUS_ACCEPTED, "accepted" }, + { PURPLE_XFER_STATUS_STARTED, "started" }, + { PURPLE_XFER_STATUS_DONE, "done" }, + { PURPLE_XFER_STATUS_CANCEL_LOCAL, "cancelled locally" }, + { PURPLE_XFER_STATUS_CANCEL_REMOTE, "cancelled remotely" } + }; + int i; + + for (i = 0; i < G_N_ELEMENTS(type_names); ++i) + if (type_names[i].type == type) + return type_names[i].name; + + return "invalid state"; +} + GList * purple_xfers_get_all() { @@ -109,6 +133,10 @@ ui_ops->new_xfer(xfer); xfers = g_list_prepend(xfers, xfer); + + if (purple_debug_is_verbose()) + purple_debug_info("xfer", "new %p [%d]\n", xfer, xfer->ref); + return xfer; } @@ -119,6 +147,9 @@ g_return_if_fail(xfer != NULL); + if (purple_debug_is_verbose()) + purple_debug_info("xfer", "destroyed %p [%d]\n", xfer, xfer->ref); + /* Close the file browser, if it's open */ purple_request_close_with_handle(xfer); @@ -148,6 +179,9 @@ g_return_if_fail(xfer != NULL); xfer->ref++; + + if (purple_debug_is_verbose()) + purple_debug_info("xfer", "ref'd %p [%d]\n", xfer, xfer->ref); } void @@ -158,6 +192,9 @@ xfer->ref--; + if (purple_debug_is_verbose()) + purple_debug_info("xfer", "unref'd %p [%d]\n", xfer, xfer->ref); + if (xfer->ref == 0) purple_xfer_destroy(xfer); } @@ -167,6 +204,11 @@ { g_return_if_fail(xfer != NULL); + if (purple_debug_is_verbose()) + purple_debug_info("xfer", "Changing status of xfer %p from %s to %s\n", + xfer, purple_xfer_status_type_to_string(xfer->status), + purple_xfer_status_type_to_string(status)); + if (xfer->status == status) return; @@ -268,14 +310,16 @@ purple_xfer_choose_file_ok_cb(void *user_data, const char *filename) { PurpleXfer *xfer; + PurpleXferType type; struct stat st; gchar *dir; xfer = (PurpleXfer *)user_data; + type = purple_xfer_get_type(xfer); if (g_stat(filename, &st) != 0) { /* File not found. */ - if (purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE) { + if (type == PURPLE_XFER_RECEIVE) { #ifndef _WIN32 int mode = W_OK; #else @@ -297,29 +341,26 @@ } else { purple_xfer_show_file_error(xfer, filename); - purple_xfer_request_denied(xfer); + purple_xfer_cancel_local(xfer); } } - else if ((purple_xfer_get_type(xfer) == PURPLE_XFER_SEND) && - (st.st_size == 0)) { + else if ((type == PURPLE_XFER_SEND) && (st.st_size == 0)) { purple_notify_error(NULL, NULL, _("Cannot send a file of 0 bytes."), NULL); - purple_xfer_request_denied(xfer); + purple_xfer_cancel_local(xfer); } - else if ((purple_xfer_get_type(xfer) == PURPLE_XFER_SEND) && - S_ISDIR(st.st_mode)) { + else if ((type == PURPLE_XFER_SEND) && S_ISDIR(st.st_mode)) { /* * XXX - Sending a directory should be valid for some protocols. */ purple_notify_error(NULL, NULL, _("Cannot send a directory."), NULL); - purple_xfer_request_denied(xfer); + purple_xfer_cancel_local(xfer); } - else if ((purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE) && - S_ISDIR(st.st_mode)) { + else if ((type == PURPLE_XFER_RECEIVE) && S_ISDIR(st.st_mode)) { char *msg, *utf8; utf8 = g_filename_to_utf8(filename, -1, NULL, NULL, NULL); msg = g_strdup_printf( @@ -329,6 +370,23 @@ g_free(msg); purple_xfer_request_denied(xfer); } + else if (type == PURPLE_XFER_SEND) { +#ifndef _WIN32 + int mode = R_OK; +#else + int mode = F_OK; +#endif + + if (g_access(filename, mode) == 0) { + purple_xfer_request_accepted(xfer, filename); + } else { + purple_xfer_ref(xfer); + purple_notify_message( + NULL, PURPLE_NOTIFY_MSG_ERROR, NULL, + _("File is not readable."), NULL, + (PurpleNotifyCloseCallback)purple_xfer_choose_file, xfer); + } + } else { purple_xfer_request_accepted(xfer, filename); } @@ -342,7 +400,11 @@ PurpleXfer *xfer = (PurpleXfer *)user_data; purple_xfer_set_status(xfer, PURPLE_XFER_STATUS_CANCEL_LOCAL); - purple_xfer_request_denied(xfer); + if (purple_xfer_get_type(xfer) == PURPLE_XFER_SEND) + purple_xfer_cancel_local(xfer); + else + purple_xfer_request_denied(xfer); + purple_xfer_unref(xfer); } static int @@ -506,6 +568,8 @@ type = purple_xfer_get_type(xfer); account = purple_xfer_get_account(xfer); + purple_debug_misc("xfer", "request accepted for %p\n", xfer); + if (!filename && type == PURPLE_XFER_RECEIVE) { xfer->status = PURPLE_XFER_STATUS_ACCEPTED; xfer->ops.init(xfer); @@ -583,6 +647,8 @@ { g_return_if_fail(xfer != NULL); + purple_debug_misc("xfer", "xfer %p denied\n", xfer); + if (xfer->ops.request_denied != NULL) xfer->ops.request_denied(xfer); @@ -1024,17 +1090,22 @@ if (ui_ops && ui_ops->ui_read) { gssize tmp = ui_ops->ui_read(xfer, &buffer, s); if (tmp == 0) { + PurpleXferPrivData *priv = g_hash_table_lookup(xfers_data, xfer); + /* - * UI isn't ready to send data. It will call - * purple_xfer_ui_ready when ready, which sets back up this - * watcher. + * The UI claimed it was ready, but didn't have any data for + * us... It will call purple_xfer_ui_ready when ready, which + * sets back up this watcher. */ if (xfer->watcher != 0) { purple_input_remove(xfer->watcher); xfer->watcher = 0; } - return; + /* Need to indicate the prpl is still ready... */ + priv->ready |= PURPLE_XFER_READY_PRPL; + + g_return_if_reached(); } else if (tmp < 0) { purple_debug_error("filetransfer", "Unable to read whole buffer.\n"); purple_xfer_cancel_local(xfer); @@ -1111,8 +1182,12 @@ purple_input_remove(xfer->watcher); xfer->watcher = 0; + + purple_debug_misc("xfer", "prpl is ready on ft %p, waiting for UI\n", xfer); return; } + + priv->ready = PURPLE_XFER_READY_NONE; } do_transfer(xfer); @@ -1173,8 +1248,12 @@ priv = g_hash_table_lookup(xfers_data, xfer); priv->ready |= PURPLE_XFER_READY_UI; - if (0 == (priv->ready & PURPLE_XFER_READY_PRPL)) + if (0 == (priv->ready & PURPLE_XFER_READY_PRPL)) { + purple_debug_misc("xfer", "UI is ready on ft %p, waiting for prpl\n", xfer); return; + } + + purple_debug_misc("xfer", "UI (and prpl) ready on ft %p, so proceeding\n", xfer); type = purple_xfer_get_type(xfer); if (type == PURPLE_XFER_SEND) @@ -1201,8 +1280,12 @@ priv->ready |= PURPLE_XFER_READY_PRPL; /* I don't think fwrite/fread are ever *not* ready */ - if (xfer->dest_fp == NULL && 0 == (priv->ready & PURPLE_XFER_READY_UI)) + if (xfer->dest_fp == NULL && 0 == (priv->ready & PURPLE_XFER_READY_UI)) { + purple_debug_misc("xfer", "prpl is ready on ft %p, waiting for UI\n", xfer); return; + } + + purple_debug_misc("xfer", "Prpl (and UI) ready on ft %p, so proceeding\n", xfer); priv->ready = PURPLE_XFER_READY_NONE;
--- a/libpurple/media.c Thu Feb 04 20:57:01 2010 +0000 +++ b/libpurple/media.c Sat Feb 06 05:15:35 2010 +0000 @@ -2754,15 +2754,21 @@ FsStream *fsstream = NULL; const gchar *stun_ip = purple_network_get_stun_ip(); const gchar *turn_ip = purple_network_get_turn_ip(); - - if (stun_ip || turn_ip) { - guint new_num_params = + guint new_num_params = + !stun_ip && !turn_ip ? num_params + 1 : (stun_ip && is_nice) && turn_ip ? - num_params + 2 : num_params + 1; - guint next_param_index = num_params; - GParameter *param = g_new0(GParameter, new_num_params); - memcpy(param, params, sizeof(GParameter) * num_params); - + num_params + 3 : num_params + 2; + guint next_param_index = num_params; + GParameter *param = g_new0(GParameter, new_num_params); + memcpy(param, params, sizeof(GParameter) * num_params); + + /* set controlling mode according to direction */ + param[next_param_index].name = "controlling-mode"; + g_value_init(¶m[next_param_index].value, G_TYPE_BOOLEAN); + g_value_set_boolean(¶m[next_param_index].value, initiator); + next_param_index++; + + if (stun_ip || turn_ip) { if (stun_ip) { purple_debug_info("media", "setting property stun-ip on new stream: %s\n", stun_ip); @@ -2813,20 +2819,14 @@ return FALSE; } } - - fsstream = fs_session_new_stream(session->session, + } + + fsstream = fs_session_new_stream(session->session, participant, initiator == TRUE ? type_direction : (type_direction & FS_DIRECTION_RECV), transmitter, new_num_params, param, &err); - g_free(param); - } else { - fsstream = fs_session_new_stream(session->session, - participant, initiator == TRUE ? - type_direction : (type_direction & - FS_DIRECTION_RECV), transmitter, - num_params, params, &err); - } + g_free(param); if (fsstream == NULL) { purple_debug_error("media",
--- a/libpurple/media.h Thu Feb 04 20:57:01 2010 +0000 +++ b/libpurple/media.h Sat Feb 06 05:15:35 2010 +0000 @@ -75,7 +75,7 @@ PURPLE_MEDIA_CAPS_VIDEO_SINGLE_DIRECTION = 1 << 3, PURPLE_MEDIA_CAPS_AUDIO_VIDEO = 1 << 4, PURPLE_MEDIA_CAPS_MODIFY_SESSION = 1 << 5, - PURPLE_MEDIA_CAPS_CHANGE_DIRECTION = 1 << 6, + PURPLE_MEDIA_CAPS_CHANGE_DIRECTION = 1 << 6 } PurpleMediaCaps; /** Media session types */ @@ -93,7 +93,7 @@ typedef enum { PURPLE_MEDIA_STATE_NEW = 0, PURPLE_MEDIA_STATE_CONNECTED, - PURPLE_MEDIA_STATE_END, + PURPLE_MEDIA_STATE_END } PurpleMediaState; /** Media info types */ @@ -106,7 +106,7 @@ PURPLE_MEDIA_INFO_PAUSE, PURPLE_MEDIA_INFO_UNPAUSE, PURPLE_MEDIA_INFO_HOLD, - PURPLE_MEDIA_INFO_UNHOLD, + PURPLE_MEDIA_INFO_UNHOLD } PurpleMediaInfoType; typedef enum { @@ -114,18 +114,18 @@ PURPLE_MEDIA_CANDIDATE_TYPE_SRFLX, PURPLE_MEDIA_CANDIDATE_TYPE_PRFLX, PURPLE_MEDIA_CANDIDATE_TYPE_RELAY, - PURPLE_MEDIA_CANDIDATE_TYPE_MULTICAST, + PURPLE_MEDIA_CANDIDATE_TYPE_MULTICAST } PurpleMediaCandidateType; typedef enum { PURPLE_MEDIA_COMPONENT_NONE = 0, PURPLE_MEDIA_COMPONENT_RTP = 1, - PURPLE_MEDIA_COMPONENT_RTCP = 2, + PURPLE_MEDIA_COMPONENT_RTCP = 2 } PurpleMediaComponentType; typedef enum { PURPLE_MEDIA_NETWORK_PROTOCOL_UDP, - PURPLE_MEDIA_NETWORK_PROTOCOL_TCP, + PURPLE_MEDIA_NETWORK_PROTOCOL_TCP } PurpleMediaNetworkProtocol; #include "signals.h"
--- a/libpurple/network.h Thu Feb 04 20:57:01 2010 +0000 +++ b/libpurple/network.h Sat Feb 06 05:15:35 2010 +0000 @@ -252,7 +252,7 @@ void purple_network_set_turn_server(const gchar *turn_server); /** - * Get the IP address of the STUN server as a string representation + * Get the IP address of the TURN server as a string representation * * @return the IP address * @since 2.6.0
--- a/libpurple/plugins/perl/common/Log.xs Thu Feb 04 20:57:01 2010 +0000 +++ b/libpurple/plugins/perl/common/Log.xs Sat Feb 06 05:15:35 2010 +0000 @@ -6,7 +6,7 @@ BOOT: { HV *type_stash = gv_stashpv("Purple::Log::Type", 1); - HV *flags_stash = gv_stashpv("Purple::Log:ReadFlags::", 1); + HV *flags_stash = gv_stashpv("Purple::Log::ReadFlags", 1); static const constiv *civ, type_const_iv[] = { #define const_iv(name) {#name, (IV)PURPLE_LOG_##name}
--- a/libpurple/plugins/perl/common/Proxy.xs Thu Feb 04 20:57:01 2010 +0000 +++ b/libpurple/plugins/perl/common/Proxy.xs Sat Feb 06 05:15:35 2010 +0000 @@ -5,7 +5,7 @@ BOOT: { - HV *stash = gv_stashpv("Purple::ProxyType::", 1); + HV *stash = gv_stashpv("Purple::ProxyType", 1); static const constiv *civ, const_iv[] = { #define const_iv(name) {#name, (IV)PURPLE_PROXY_##name}
--- a/libpurple/plugins/signals-test.c Thu Feb 04 20:57:01 2010 +0000 +++ b/libpurple/plugins/signals-test.c Sat Feb 06 05:15:35 2010 +0000 @@ -547,6 +547,26 @@ purple_debug_misc("signals test", "quitting ()\n"); } +static void +printhash(gpointer key, gpointer value, gpointer data) +{ + char *a = (char *)key; + char *b = (char *)value; + GString *str = (GString *)data; + g_string_append_printf(str, " [%s] = [%s]\n", a, b ? b : "(null)"); +} + +static gboolean +uri_handler(const char *proto, const char *cmd, GHashTable *params) +{ + GString *str = g_string_new("\n{\n"); + g_hash_table_foreach(params, printhash, str); + g_string_append_c(str, '}'); + purple_debug_misc("signals test", "uri handler (%s, %s, %s)\n", proto, cmd, str->str); + g_string_free(str, TRUE); + return FALSE; +} + /************************************************************************** * File transfer signal callbacks **************************************************************************/ @@ -820,6 +840,8 @@ /* Core signals */ purple_signal_connect(core_handle, "quitting", plugin, PURPLE_CALLBACK(quitting_cb), NULL); + purple_signal_connect(core_handle, "uri-handler", + plugin, PURPLE_CALLBACK(uri_handler), NULL); /* File transfer signals */ purple_signal_connect(ft_handle, "file-recv-accept",
--- a/libpurple/prefs.h Thu Feb 04 20:57:01 2010 +0000 +++ b/libpurple/prefs.h Sat Feb 06 05:15:35 2010 +0000 @@ -185,7 +185,16 @@ * * @param name The name of the pref * @param value The value to set + * + * @deprecated We're not really sure what purpose this function serves, so it + * will be removed in 3.0.0. Preferences values set using this + * function aren't serialized to prefs.xml, which could be + * misleading. There is also no purple_prefs_get_generic, which + * means that if you can't really get the value (other in a + * connected callback). If you think you have a use for this then + * please let us know. */ +/* TODO: When this is removed, also remove struct purple_pref->value.generic */ void purple_prefs_set_generic(const char *name, gpointer value); /**
--- a/libpurple/protocols/bonjour/bonjour.c Thu Feb 04 20:57:01 2010 +0000 +++ b/libpurple/protocols/bonjour/bonjour.c Sat Feb 06 05:15:35 2010 +0000 @@ -392,11 +392,8 @@ purple_notify_user_info_add_pair(user_info, _("XMPP Account"), bb->jid); } -static void -bonjour_group_buddy(PurpleConnection *connection, const char *who, const char *old_group, const char *new_group) -{ +static void bonjour_do_group_change(PurpleBuddy *buddy, const char *new_group) { PurpleBlistNodeFlags oldflags; - PurpleBuddy *buddy = purple_find_buddy(connection->account, who); if (buddy == NULL) return; @@ -404,13 +401,38 @@ oldflags = purple_blist_node_get_flags((PurpleBlistNode *)buddy); /* If we're moving them out of the bonjour group, make them persistent */ - if (strcmp(new_group, BONJOUR_GROUP_NAME) == 0) + if (purple_strequal(new_group, BONJOUR_GROUP_NAME)) purple_blist_node_set_flags((PurpleBlistNode *)buddy, oldflags | PURPLE_BLIST_NODE_FLAG_NO_SAVE); else purple_blist_node_set_flags((PurpleBlistNode *)buddy, oldflags ^ PURPLE_BLIST_NODE_FLAG_NO_SAVE); } +static void +bonjour_group_buddy(PurpleConnection *connection, const char *who, const char *old_group, const char *new_group) +{ + PurpleBuddy *buddy = purple_find_buddy(connection->account, who); + + bonjour_do_group_change(buddy, new_group); + +} + +static void +bonjour_rename_group(PurpleConnection *connection, const char *old_name, PurpleGroup *group, GList *moved_buddies) +{ + GList *cur; + const char *new_group; + PurpleBuddy *buddy; + + new_group = purple_group_get_name(group); + + for (cur = moved_buddies; cur; cur = cur->next) { + buddy = cur->data; + bonjour_do_group_change(buddy, new_group); + } + +} + static gboolean bonjour_can_receive_file(PurpleConnection *connection, const char *who) { @@ -478,7 +500,7 @@ NULL, /* get_cb_away */ NULL, /* alias_buddy */ bonjour_group_buddy, /* group_buddy */ - NULL, /* rename_group */ + bonjour_rename_group, /* rename_group */ NULL, /* buddy_free */ bonjour_convo_closed, /* convo_closed */ NULL, /* normalize */
--- a/libpurple/protocols/gg/gg.c Thu Feb 04 20:57:01 2010 +0000 +++ b/libpurple/protocols/gg/gg.c Sat Feb 06 05:15:35 2010 +0000 @@ -947,7 +947,7 @@ if (xmlnode_avatar == NULL) goto out; - xmlnode_bigavatar = xmlnode_get_child(xmlnode_avatar, "bigAvatar"); + xmlnode_bigavatar = xmlnode_get_child(xmlnode_avatar, "originBigAvatar"); if (xmlnode_bigavatar == NULL) goto out;
--- a/libpurple/protocols/irc/msgs.c Thu Feb 04 20:57:01 2010 +0000 +++ b/libpurple/protocols/irc/msgs.c Sat Feb 06 05:15:35 2010 +0000 @@ -1069,7 +1069,7 @@ nick = irc_mask_nick(from); if (!purple_utf8_strcasecmp(nick, purple_connection_get_display_name(gc))) { - char *escaped = g_markup_escape_text(args[1], -1); + char *escaped = args[1] ? g_markup_escape_text(args[1], -1) : NULL; msg = g_strdup_printf(_("You have parted the channel%s%s"), (args[1] && *args[1]) ? ": " : "", (escaped && *escaped) ? escaped : "");
--- a/libpurple/protocols/jabber/auth.c Thu Feb 04 20:57:01 2010 +0000 +++ b/libpurple/protocols/jabber/auth.c Sat Feb 06 05:15:35 2010 +0000 @@ -485,9 +485,12 @@ xmlnode *stanza = NULL; JabberSaslState state = js->auth_mech->handle_failure(js, packet, &stanza, &msg); - if (state != JABBER_SASL_STATE_FAIL && stanza) { - jabber_send(js, stanza); - xmlnode_free(stanza); + if (state != JABBER_SASL_STATE_FAIL) { + if (stanza) { + jabber_send(js, stanza); + xmlnode_free(stanza); + } + return; } }
--- a/libpurple/protocols/jabber/buddy.c Thu Feb 04 20:57:01 2010 +0000 +++ b/libpurple/protocols/jabber/buddy.c Sat Feb 06 05:15:35 2010 +0000 @@ -823,7 +823,8 @@ const gchar *title = NULL; if (is_domain) { title = _("Uptime"); - message = g_strdup_printf(_("%s"), last); + message = last; + last = NULL; } else { title = _("Logged Off"); message = g_strdup_printf(_("%s ago"), last);
--- a/libpurple/protocols/jabber/data.h Thu Feb 04 20:57:01 2010 +0000 +++ b/libpurple/protocols/jabber/data.h Sat Feb 06 05:15:35 2010 +0000 @@ -26,6 +26,8 @@ #include <glib.h> +#define JABBER_DATA_MAX_SIZE 8192 + typedef struct { char *cid; char *type;
--- a/libpurple/protocols/jabber/disco.c Thu Feb 04 20:57:01 2010 +0000 +++ b/libpurple/protocols/jabber/disco.c Sat Feb 06 05:15:35 2010 +0000 @@ -22,6 +22,7 @@ */ #include "internal.h" +#include "network.h" #include "prefs.h" #include "debug.h" #include "request.h" @@ -534,8 +535,12 @@ js->googletalk = TRUE; /* autodiscover stun and relays */ - jabber_google_send_jingle_info(js); - } else { + if (purple_network_get_stun_ip() == NULL || + purple_strequal(purple_network_get_stun_ip(), "")) { + jabber_google_send_jingle_info(js); + } + } else if (purple_network_get_stun_ip() == NULL || + purple_strequal(purple_network_get_stun_ip(), "")) { js->srv_query_data = purple_srv_resolve("stun", "udp", js->user->domain, jabber_disco_stun_srv_resolve_cb, js);
--- a/libpurple/protocols/jabber/jabber.c Thu Feb 04 20:57:01 2010 +0000 +++ b/libpurple/protocols/jabber/jabber.c Sat Feb 06 05:15:35 2010 +0000 @@ -356,11 +356,20 @@ } if (ret < 0 && errno != EAGAIN) { - gchar *tmp = g_strdup_printf(_("Lost connection with server: %s"), - g_strerror(errno)); - purple_connection_error_reason(js->gc, - PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); - g_free(tmp); + PurpleAccount *account = purple_connection_get_account(js->gc); + /* + * The server may have closed the socket (on a stream error), so if + * we're disconnecting, don't generate (possibly another) error that + * (for some UIs) would mask the first. + */ + if (!account->disconnecting) { + gchar *tmp = g_strdup_printf(_("Lost connection with server: %s"), + g_strerror(errno)); + purple_connection_error_reason(js->gc, + PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); + g_free(tmp); + } + success = FALSE; } else if (ret < len) { if (ret < 0) @@ -418,13 +427,12 @@ g_free(text); } - /* If we've got a security layer, we need to encode the data, - * splitting it on the maximum buffer length negotiated */ - purple_signal_emit(purple_connection_get_prpl(js->gc), "jabber-sending-text", js->gc, &data); if (data == NULL) return; + /* If we've got a security layer, we need to encode the data, + * splitting it on the maximum buffer length negotiated */ #ifdef HAVE_CYRUS_SASL if (js->sasl_maxbuf>0) { int pos = 0; @@ -639,10 +647,11 @@ js->srv_query_data = NULL; if (responses == NULL) { + purple_debug_warning("jabber", "Unable to find alternative XMPP connection " + "methods after failing to connect directly.\n"); purple_connection_error_reason(js->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, - _("Unable to find alternative XMPP connection " - "methods after failing to connect directly.")); + _("Unable to connect")); return; } @@ -677,14 +686,14 @@ jabber_login_callback(gpointer data, gint source, const gchar *error) { PurpleConnection *gc = data; - JabberStream *js = gc->proto_data; + JabberStream *js = purple_connection_get_protocol_data(gc); if (source < 0) { if (js->srv_rec != NULL) { - purple_debug_error("jabber", "Unable to connect to server: %s. Trying next SRV record.\n", error); + purple_debug_error("jabber", "Unable to connect to server: %s. Trying next SRV record or connecting directly.\n", error); try_srv_connect(js); } else { - purple_debug_info("jabber","Couldn't connect directly to %s. Trying to find alternative connection methods, like BOSH.\n", js->user->domain); + purple_debug_info("jabber","Couldn't connect directly to %s. Trying to find alternative connection methods, like BOSH.\n", js->user->domain); js->srv_query_data = purple_txt_resolve("_xmppconnect", js->user->domain, txt_resolved_cb, js); } @@ -1434,30 +1443,21 @@ */ void jabber_close(PurpleConnection *gc) { - JabberStream *js = gc->proto_data; + JabberStream *js = purple_connection_get_protocol_data(gc); /* Close all of the open Jingle sessions on this stream */ jingle_terminate_sessions(js); - /* Don't perform any actions on the ssl connection - * if we were forcibly disconnected because it will crash - * on some SSL backends. - */ - if (!gc->disconnect_timeout) { - if (js->bosh) - jabber_bosh_connection_close(js->bosh); - else if ((js->gsc && js->gsc->fd > 0) || js->fd > 0) - jabber_send_raw(js, "</stream:stream>", -1); - } + if (js->bosh) + jabber_bosh_connection_close(js->bosh); + else if ((js->gsc && js->gsc->fd > 0) || js->fd > 0) + jabber_send_raw(js, "</stream:stream>", -1); if (js->srv_query_data) purple_srv_cancel(js->srv_query_data); if(js->gsc) { -#ifdef HAVE_OPENSSL - if (!gc->disconnect_timeout) -#endif - purple_ssl_close(js->gsc); + purple_ssl_close(js->gsc); } else if (js->fd > 0) { if(js->gc->inpa) purple_input_remove(js->gc->inpa);
--- a/libpurple/protocols/jabber/libxmpp.c Thu Feb 04 20:57:01 2010 +0000 +++ b/libpurple/protocols/jabber/libxmpp.c Sat Feb 06 05:15:35 2010 +0000 @@ -431,7 +431,7 @@ jabber_data_init(); jabber_bosh_init(); - #warning implement adding and retrieving own features via IPC API + /* TODO: Implement adding and retrieving own features via IPC API */ jabber_ibb_init(); jabber_si_init();
--- a/libpurple/protocols/jabber/message.c Thu Feb 04 20:57:01 2010 +0000 +++ b/libpurple/protocols/jabber/message.c Sat Feb 06 05:15:35 2010 +0000 @@ -862,6 +862,7 @@ for (; smileys ; smileys = g_list_delete_link(smileys, smileys)) { PurpleSmiley *smiley = (PurpleSmiley *) smileys->data; + const gchar *shortcut = purple_smiley_get_shortcut(smiley); const gssize len = strlen(shortcut); @@ -983,36 +984,52 @@ if (found_smileys) { gchar *smileyfied_xhtml = NULL; const GList *iterator; - + GList *valid_smileys = NULL; + gboolean has_too_large_smiley = FALSE; + for (iterator = found_smileys; iterator ; iterator = g_list_next(iterator)) { - const PurpleSmiley *smiley = - (PurpleSmiley *) iterator->data; + PurpleSmiley *smiley = (PurpleSmiley *) iterator->data; const gchar *shortcut = purple_smiley_get_shortcut(smiley); const JabberData *data = jabber_data_find_local_by_alt(shortcut); + PurpleStoredImage *image = purple_smiley_get_stored_image(smiley); - /* the object has not been sent before */ - if (!data) { - PurpleStoredImage *image = - purple_smiley_get_stored_image(smiley); - const gchar *ext = purple_imgstore_get_extension(image); - JabberStream *js = jm->js; + if (purple_imgstore_get_size(image) <= JABBER_DATA_MAX_SIZE) { + /* the object has not been sent before */ + if (!data) { + const gchar *ext = purple_imgstore_get_extension(image); + JabberStream *js = jm->js; - JabberData *new_data = - jabber_data_create_from_data(purple_imgstore_get_data(image), - purple_imgstore_get_size(image), - jabber_message_get_mimetype_from_ext(ext), js); - purple_debug_info("jabber", - "cache local smiley alt = %s, cid = %s\n", - shortcut, jabber_data_get_cid(new_data)); - jabber_data_associate_local(new_data, shortcut); - } + JabberData *new_data = + jabber_data_create_from_data(purple_imgstore_get_data(image), + purple_imgstore_get_size(image), + jabber_message_get_mimetype_from_ext(ext), js); + purple_debug_info("jabber", + "cache local smiley alt = %s, cid = %s\n", + shortcut, jabber_data_get_cid(new_data)); + jabber_data_associate_local(new_data, shortcut); + } + valid_smileys = g_list_append(valid_smileys, smiley); + } else { + has_too_large_smiley = TRUE; + purple_debug_warning("jabber", "Refusing to send smiley %s " + "(too large, max is %d)\n", + purple_smiley_get_shortcut(smiley), + JABBER_DATA_MAX_SIZE); + } + } + + if (has_too_large_smiley) { + purple_conversation_write(conv, NULL, + _("A custom smiley in the message is too large to send."), + PURPLE_MESSAGE_ERROR, time(NULL)); } smileyfied_xhtml = - jabber_message_get_smileyfied_xhtml(xhtml, found_smileys); + jabber_message_get_smileyfied_xhtml(xhtml, valid_smileys); g_list_free(found_smileys); + g_list_free(valid_smileys); return smileyfied_xhtml; } @@ -1193,6 +1210,7 @@ tmp = purple_utf8_strip_unprintables(msg); purple_markup_html_to_xhtml(tmp, &xhtml, &jm->body); g_free(tmp); + tmp = jabber_message_smileyfy_xhtml(jm, xhtml); if (tmp) { g_free(xhtml); @@ -1206,7 +1224,8 @@ if (!jbr || !jbr->caps.info || jabber_resource_has_capability(jbr, NS_XHTML_IM)) { if (!jabber_xhtml_plain_equal(xhtml, jm->body)) - jm->xhtml = g_strdup_printf("<html xmlns='" NS_XHTML_IM "'><body xmlns='" NS_XHTML "'>%s</body></html>", xhtml); + /* Wrap the message in <p/> for great interoperability justice. */ + jm->xhtml = g_strdup_printf("<html xmlns='" NS_XHTML_IM "'><body xmlns='" NS_XHTML "'><p>%s</p></body></html>", xhtml); } g_free(xhtml); @@ -1249,7 +1268,8 @@ } if (chat->xhtml && !jabber_xhtml_plain_equal(xhtml, jm->body)) - jm->xhtml = g_strdup_printf("<html xmlns='" NS_XHTML_IM "'><body xmlns='" NS_XHTML "'>%s</body></html>", xhtml); + /* Wrap the message in <p/> for greater interoperability justice. */ + jm->xhtml = g_strdup_printf("<html xmlns='" NS_XHTML_IM "'><body xmlns='" NS_XHTML "'><p>%s</p></body></html>", xhtml); g_free(xhtml);
--- a/libpurple/protocols/jabber/presence.c Thu Feb 04 20:57:01 2010 +0000 +++ b/libpurple/protocols/jabber/presence.c Sat Feb 06 05:15:35 2010 +0000 @@ -790,8 +790,9 @@ g_free(room_jid); } - jabber_buddy_track_resource(jb, jid->resource, priority, state, + jbr = jabber_buddy_track_resource(jb, jid->resource, priority, state, status); + jbr->commands_fetched = TRUE; jabber_chat_track_handle(chat, jid->resource, real_jid, affiliation, role);
--- a/libpurple/protocols/jabber/roster.c Thu Feb 04 20:57:01 2010 +0000 +++ b/libpurple/protocols/jabber/roster.c Sat Feb 06 05:15:35 2010 +0000 @@ -193,7 +193,9 @@ JabberIqType type, const char *id, xmlnode *query) { xmlnode *item, *group; +#if 0 const char *ver; +#endif if (!jabber_is_own_account(js, from)) { purple_debug_warning("jabber", "Received bogon roster push from %s\n", @@ -266,11 +268,13 @@ } } +#if 0 ver = xmlnode_get_attrib(query, "ver"); if (ver) { PurpleAccount *account = purple_connection_get_account(js->gc); purple_account_set_string(account, "roster_ver", ver); } +#endif js->currently_parsing_roster_push = FALSE; }
--- a/libpurple/protocols/msn/contact.c Thu Feb 04 20:57:01 2010 +0000 +++ b/libpurple/protocols/msn/contact.c Sat Feb 06 05:15:35 2010 +0000 @@ -406,8 +406,8 @@ msn_user_set_network(user, nid); msn_user_set_invite_message(user, invite); - if (member_id) { - user->membership_id[list] = atoi(member_id); + if (list == MSN_LIST_PL && member_id) { + user->member_id_on_pending_list = atoi(member_id); } msn_got_lst_user(session, user, 1 << list, NULL); @@ -1567,11 +1567,11 @@ if (user && user->networkid != MSN_NETWORK_PASSPORT) member = g_strdup_printf(MSN_MEMBER_MEMBERSHIPID_XML, "EmailMember", "Email", - user->membership_id[MSN_LIST_PL]); + user->member_id_on_pending_list); else member = g_strdup_printf(MSN_MEMBER_MEMBERSHIPID_XML, "PassportMember", "Passport", - user->membership_id[MSN_LIST_PL]); + user->member_id_on_pending_list); } else { /* list == MSN_LIST_AL || list == MSN_LIST_BL */ partner_scenario = MSN_PS_BLOCK_UNBLOCK;
--- a/libpurple/protocols/msn/msn.c Thu Feb 04 20:57:01 2010 +0000 +++ b/libpurple/protocols/msn/msn.c Sat Feb 06 05:15:35 2010 +0000 @@ -345,17 +345,23 @@ msn_show_set_friendly_name(PurplePluginAction *action) { PurpleConnection *gc; + PurpleAccount *account; + char *tmp; gc = (PurpleConnection *) action->context; - - purple_request_input(gc, NULL, _("Set your friendly name."), + account = purple_connection_get_account(gc); + + tmp = g_strdup_printf(_("Set friendly name for %s."), + purple_account_get_username(account)); + purple_request_input(gc, _("Set your friendly name."), tmp, _("This is the name that other MSN buddies will " "see you as."), purple_connection_get_display_name(gc), FALSE, FALSE, NULL, _("OK"), G_CALLBACK(msn_act_id), _("Cancel"), NULL, - purple_connection_get_account(gc), NULL, NULL, + account, NULL, NULL, gc); + g_free(tmp); } typedef struct MsnLocationData { @@ -1655,6 +1661,8 @@ { const char *bname; MsnAddReqData *data; + MsnSession *session; + MsnUser *user; bname = purple_buddy_get_name(buddy); @@ -1676,12 +1684,18 @@ data->buddy = buddy; data->group = group; - purple_request_input(gc, NULL, _("Authorization Request Message:"), - NULL, _("Please authorize me!"), TRUE, FALSE, NULL, - _("_OK"), G_CALLBACK(finish_auth_request), - _("_Cancel"), G_CALLBACK(cancel_auth_request), - purple_connection_get_account(gc), bname, NULL, - data); + session = purple_connection_get_protocol_data(gc); + user = msn_userlist_find_user(session->userlist, bname); + if (user && user->authorized) { + finish_auth_request(data, NULL); + } else { + purple_request_input(gc, NULL, _("Authorization Request Message:"), + NULL, _("Please authorize me!"), TRUE, FALSE, NULL, + _("_OK"), G_CALLBACK(finish_auth_request), + _("_Cancel"), G_CALLBACK(cancel_auth_request), + purple_connection_get_account(gc), bname, NULL, + data); + } } static void @@ -2771,7 +2785,7 @@ OPT_PROTO_MAIL_CHECK, NULL, /* user_splits */ NULL, /* protocol_options */ - {"png", 0, 0, 96, 96, 0, PURPLE_ICON_SCALE_SEND}, /* icon_spec */ + {"png,gif", 0, 0, 96, 96, 0, PURPLE_ICON_SCALE_SEND}, /* icon_spec */ msn_list_icon, /* list_icon */ msn_list_emblems, /* list_emblems */ msn_status_text, /* status_text */
--- a/libpurple/protocols/msn/notification.c Thu Feb 04 20:57:01 2010 +0000 +++ b/libpurple/protocols/msn/notification.c Sat Feb 06 05:15:35 2010 +0000 @@ -1173,7 +1173,7 @@ msn_user_set_object(user, msnobj); - user->mobile = (clientid & MSN_CLIENT_CAP_MSNMOBILE) || (user->phone.mobile && user->phone.mobile[0] == '+'); + user->mobile = (clientid & MSN_CLIENT_CAP_MSNMOBILE) || (user->extinfo && user->extinfo->phone_mobile && user->extinfo->phone_mobile[0] == '+'); msn_user_set_clientid(user, clientid); msn_user_set_extcaps(user, extcaps); msn_user_set_network(user, networkid); @@ -1354,7 +1354,8 @@ extcaps = strtoul(extcap_str+1, NULL, 10); else extcaps = 0; - user->mobile = (clientid & MSN_CLIENT_CAP_MSNMOBILE) || (user->phone.mobile && user->phone.mobile[0] == '+'); + + user->mobile = (clientid & MSN_CLIENT_CAP_MSNMOBILE) || (user->extinfo && user->extinfo->phone_mobile && user->extinfo->phone_mobile[0] == '+'); msn_user_set_clientid(user, clientid); msn_user_set_extcaps(user, extcaps); @@ -1709,6 +1710,63 @@ } } +static void parse_currentmedia(MsnUser *user, const char *cmedia) +{ + char **cmedia_array; + int strings = 0; + + if (!cmedia || cmedia[0] == '\0') { + purple_debug_info("msn", "No currentmedia string\n"); + return; + } + + purple_debug_info("msn", "Parsing currentmedia string: \"%s\"\n", cmedia); + + cmedia_array = g_strsplit(cmedia, "\\0", 0); + + /* + * 0: Application + * 1: 'Music'/'Games'/'Office' + * 2: '1' if enabled, '0' if not + * 3: Format (eg. {0} by {1}) + * 4: Title + * If 'Music': + * 5: Artist + * 6: Album + * 7: ? + */ +#if GLIB_CHECK_VERSION(2,6,0) + strings = g_strv_length(cmedia_array); +#else + while (cmedia_array[++strings] != NULL); +#endif + + if (strings >= 4 && !strcmp(cmedia_array[2], "1")) { + if (user->extinfo == NULL) + user->extinfo = g_new0(MsnUserExtendedInfo, 1); + else { + g_free(user->extinfo->media_album); + g_free(user->extinfo->media_artist); + g_free(user->extinfo->media_title); + } + + if (!strcmp(cmedia_array[1], "Music")) + user->extinfo->media_type = CURRENT_MEDIA_MUSIC; + else if (!strcmp(cmedia_array[1], "Games")) + user->extinfo->media_type = CURRENT_MEDIA_GAMES; + else if (!strcmp(cmedia_array[1], "Office")) + user->extinfo->media_type = CURRENT_MEDIA_OFFICE; + else + user->extinfo->media_type = CURRENT_MEDIA_UNKNOWN; + + user->extinfo->media_title = g_strdup(cmedia_array[strings == 4 ? 3 : 4]); + user->extinfo->media_artist = strings > 5 ? g_strdup(cmedia_array[5]) : NULL; + user->extinfo->media_album = strings > 6 ? g_strdup(cmedia_array[6]) : NULL; + } + + g_strfreev(cmedia_array); +} + /* * Get the UBX's PSM info * Post it to the User status @@ -1724,7 +1782,6 @@ const char *passport; xmlnode *payloadNode; char *psm_str, *str; - CurrentMedia media = {CURRENT_MEDIA_UNKNOWN, NULL, NULL, NULL}; session = cmdproc->session; account = session->account; @@ -1742,13 +1799,22 @@ return; } + /* Free any existing media info for this user */ + if (user->extinfo) { + g_free(user->extinfo->media_album); + g_free(user->extinfo->media_artist); + g_free(user->extinfo->media_title); + user->extinfo->media_album = NULL; + user->extinfo->media_artist = NULL; + user->extinfo->media_title = NULL; + } + if (len != 0) { payloadNode = xmlnode_from_str(payload, len); if (!payloadNode) { purple_debug_error("msn", "UBX XML parse Error!\n"); msn_user_set_statusline(user, NULL); - msn_user_set_currentmedia(user, NULL); msn_user_update(user); return; @@ -1759,13 +1825,7 @@ g_free(psm_str); str = msn_get_currentmedia(payloadNode); - if (msn_parse_currentmedia(str, &media)) - msn_user_set_currentmedia(user, &media); - else - msn_user_set_currentmedia(user, NULL); - g_free(media.title); - g_free(media.album); - g_free(media.artist); + parse_currentmedia(user, str); g_free(str); parse_user_endpoints(user, payloadNode); @@ -1774,7 +1834,6 @@ } else { msn_user_set_statusline(user, NULL); - msn_user_set_currentmedia(user, NULL); } msn_user_update(user);
--- a/libpurple/protocols/msn/slp.c Thu Feb 04 20:57:01 2010 +0000 +++ b/libpurple/protocols/msn/slp.c Sat Feb 06 05:15:35 2010 +0000 @@ -276,6 +276,38 @@ msn_slplink_queue_slpmsg(slplink, slpmsg); } +/* XXX: this could be improved if we tracked custom smileys + * per-protocol, per-account, per-session or (ideally) per-conversation + */ +static PurpleStoredImage * +find_valid_emoticon(PurpleAccount *account, const char *path) +{ + GList *smileys; + + if (!purple_account_get_bool(account, "custom_smileys", TRUE)) + return NULL; + + smileys = purple_smileys_get_all(); + + for (; smileys; smileys = g_list_delete_link(smileys, smileys)) { + PurpleSmiley *smiley; + PurpleStoredImage *img; + + smiley = smileys->data; + img = purple_smiley_get_stored_image(smiley); + + if (purple_strequal(path, purple_imgstore_get_filename(img))) { + g_list_free(smileys); + return img; + } + + purple_imgstore_unref(img); + } + + purple_debug_error("msn", "Received illegal request for file %s\n", path); + return NULL; +} + #define MAX_FILE_NAME_LEN 0x226 static void @@ -293,7 +325,7 @@ MsnSlpMessage *slpmsg; MsnObject *obj; char *msnobj_data; - PurpleStoredImage *img; + PurpleStoredImage *img = NULL; int type; /* Send Ok */ @@ -311,51 +343,38 @@ obj = msn_object_new_from_string(msnobj_data); type = msn_object_get_type(obj); g_free(msnobj_data); - - if ((type != MSN_OBJECT_USERTILE) && (type != MSN_OBJECT_EMOTICON)) - { - purple_debug_error("msn", "Wrong object?\n"); - msn_object_destroy(obj); - g_return_if_reached(); - } - if (type == MSN_OBJECT_EMOTICON) { - char *path; - path = g_build_filename(purple_smileys_get_storing_dir(), - obj->location, NULL); - img = purple_imgstore_new_from_file(path); - g_free(path); - } else { + img = find_valid_emoticon(slplink->session->account, obj->location); + } else if (type == MSN_OBJECT_USERTILE) { img = msn_object_get_image(obj); if (img) purple_imgstore_ref(img); } msn_object_destroy(obj); - if (img == NULL) - { - purple_debug_error("msn", "Wrong object.\n"); - g_return_if_reached(); - } + if (img != NULL) { + /* DATA PREP */ + slpmsg = msn_slpmsg_new(slplink); + slpmsg->slpcall = slpcall; + slpmsg->session_id = slpcall->session_id; + msn_slpmsg_set_body(slpmsg, NULL, 4); + slpmsg->info = "SLP DATA PREP"; + msn_slplink_queue_slpmsg(slplink, slpmsg); - /* DATA PREP */ - slpmsg = msn_slpmsg_new(slplink); - slpmsg->slpcall = slpcall; - slpmsg->session_id = slpcall->session_id; - msn_slpmsg_set_body(slpmsg, NULL, 4); - slpmsg->info = "SLP DATA PREP"; - msn_slplink_queue_slpmsg(slplink, slpmsg); + /* DATA */ + slpmsg = msn_slpmsg_new(slplink); + slpmsg->slpcall = slpcall; + slpmsg->flags = 0x20; + slpmsg->info = "SLP DATA"; + msn_slpmsg_set_image(slpmsg, img); + msn_slplink_queue_slpmsg(slplink, slpmsg); + purple_imgstore_unref(img); - /* DATA */ - slpmsg = msn_slpmsg_new(slplink); - slpmsg->slpcall = slpcall; - slpmsg->flags = 0x20; - slpmsg->info = "SLP DATA"; - msn_slpmsg_set_image(slpmsg, img); - msn_slplink_queue_slpmsg(slplink, slpmsg); - purple_imgstore_unref(img); + accepted = TRUE; - accepted = TRUE; + } else { + purple_debug_error("msn", "Wrong object.\n"); + } } else if (!strcmp(euf_guid, MSN_FT_GUID))
--- a/libpurple/protocols/msn/slplink.c Thu Feb 04 20:57:01 2010 +0000 +++ b/libpurple/protocols/msn/slplink.c Sat Feb 06 05:15:35 2010 +0000 @@ -669,9 +669,8 @@ #define MAX_FILE_NAME_LEN 0x226 static gchar * -gen_context(const char *file_name, const char *file_path) +gen_context(PurpleXfer *xfer, const char *file_name, const char *file_path) { - struct stat st; gsize size = 0; MsnContextHeader header; gchar *u8 = NULL; @@ -683,8 +682,7 @@ glong uni_len = 0; gsize len; - if (g_stat(file_path, &st) == 0) - size = st.st_size; + size = purple_xfer_get_size(xfer); if(!file_name) { gchar *basename = g_path_get_basename(file_path); @@ -761,7 +759,7 @@ xfer->data = slpcall; - context = gen_context(fn, fp); + context = gen_context(xfer, fn, fp); msn_slpcall_invite(slpcall, MSN_FT_GUID, 2, context);
--- a/libpurple/protocols/msn/state.c Thu Feb 04 20:57:01 2010 +0000 +++ b/libpurple/protocols/msn/state.c Sat Feb 06 05:15:35 2010 +0000 @@ -89,78 +89,6 @@ return result; } -/* parse CurrentMedia string */ -gboolean -msn_parse_currentmedia(const char *cmedia, CurrentMedia *media) -{ - char **cmedia_array; - int strings = 0; - gboolean parsed = FALSE; - - if ((cmedia == NULL) || (*cmedia == '\0')) { - purple_debug_info("msn", "No currentmedia string\n"); - return FALSE; - } - - purple_debug_info("msn", "Parsing currentmedia string: \"%s\"\n", cmedia); - - cmedia_array = g_strsplit(cmedia, "\\0", 0); - - /* - * 0: Application - * 1: 'Music'/'Games'/'Office' - * 2: '1' if enabled, '0' if not - * 3: Format (eg. {0} by {1}) - * 4: Title - * If 'Music': - * 5: Artist - * 6: Album - * 7: ? - */ -#if GLIB_CHECK_VERSION(2,6,0) - strings = g_strv_length(cmedia_array); -#else - while (cmedia_array[++strings] != NULL); -#endif - - if (strings >= 4 && !strcmp(cmedia_array[2], "1")) { - parsed = TRUE; - - if (!strcmp(cmedia_array[1], "Music")) - media->type = CURRENT_MEDIA_MUSIC; - else if (!strcmp(cmedia_array[1], "Games")) - media->type = CURRENT_MEDIA_GAMES; - else if (!strcmp(cmedia_array[1], "Office")) - media->type = CURRENT_MEDIA_OFFICE; - else - media->type = CURRENT_MEDIA_UNKNOWN; - - g_free(media->title); - if (strings == 4) { - media->title = g_strdup(cmedia_array[3]); - } else { - media->title = g_strdup(cmedia_array[4]); - } - - g_free(media->artist); - if (strings > 5) - media->artist = g_strdup(cmedia_array[5]); - else - media->artist = NULL; - - g_free(media->album); - if (strings > 6) - media->album = g_strdup(cmedia_array[6]); - else - media->album = NULL; - - } - - g_strfreev(cmedia_array); - - return parsed; -} - /* get the CurrentMedia info from the XML node */ char * msn_get_currentmedia(xmlnode *payloadNode)
--- a/libpurple/protocols/msn/state.h Thu Feb 04 20:57:01 2010 +0000 +++ b/libpurple/protocols/msn/state.h Sat Feb 06 05:15:35 2010 +0000 @@ -61,9 +61,6 @@ void msn_set_psm(MsnSession *session); -/* Parse CurrentMedia string */ -gboolean msn_parse_currentmedia(const char *cmedia, CurrentMedia *media); - /* Get the CurrentMedia info from the XML node */ char * msn_get_currentmedia(xmlnode *payloadNode);
--- a/libpurple/protocols/msn/user.c Thu Feb 04 20:57:01 2010 +0000 +++ b/libpurple/protocols/msn/user.c Sat Feb 06 05:15:35 2010 +0000 @@ -75,12 +75,15 @@ g_free(user->passport); g_free(user->friendly_name); g_free(user->uid); - g_free(user->phone.home); - g_free(user->phone.work); - g_free(user->phone.mobile); - g_free(user->media.artist); - g_free(user->media.title); - g_free(user->media.album); + if (user->extinfo) { + g_free(user->extinfo->media_album); + g_free(user->extinfo->media_artist); + g_free(user->extinfo->media_title); + g_free(user->extinfo->phone_home); + g_free(user->extinfo->phone_mobile); + g_free(user->extinfo->phone_work); + g_free(user->extinfo); + } g_free(user->statusline); g_free(user->invite_message); @@ -115,24 +118,24 @@ purple_prpl_got_user_status_deactive(account, user->passport, "mobile"); } - if (!offline && user->media.type != CURRENT_MEDIA_UNKNOWN) { - if (user->media.type == CURRENT_MEDIA_MUSIC) { + if (!offline && user->extinfo && user->extinfo->media_type != CURRENT_MEDIA_UNKNOWN) { + if (user->extinfo->media_type == CURRENT_MEDIA_MUSIC) { purple_prpl_got_user_status(account, user->passport, "tune", - PURPLE_TUNE_ARTIST, user->media.artist, - PURPLE_TUNE_ALBUM, user->media.album, - PURPLE_TUNE_TITLE, user->media.title, + PURPLE_TUNE_ARTIST, user->extinfo->media_artist, + PURPLE_TUNE_ALBUM, user->extinfo->media_album, + PURPLE_TUNE_TITLE, user->extinfo->media_title, NULL); - } else if (user->media.type == CURRENT_MEDIA_GAMES) { + } else if (user->extinfo->media_type == CURRENT_MEDIA_GAMES) { purple_prpl_got_user_status(account, user->passport, "tune", - "game", user->media.title, + "game", user->extinfo->media_title, NULL); - } else if (user->media.type == CURRENT_MEDIA_OFFICE) { + } else if (user->extinfo->media_type == CURRENT_MEDIA_OFFICE) { purple_prpl_got_user_status(account, user->passport, "tune", - "office", user->media.title, + "office", user->extinfo->media_title, NULL); } else { purple_debug_warning("msn", "Got CurrentMedia with unknown type %d.\n", - user->media.type); + user->extinfo->media_type); } } else { purple_prpl_got_user_status_deactive(account, user->passport, "tune"); @@ -216,21 +219,6 @@ } void -msn_user_set_currentmedia(MsnUser *user, const CurrentMedia *media) -{ - g_return_if_fail(user != NULL); - - g_free(user->media.title); - g_free(user->media.album); - g_free(user->media.artist); - - user->media.type = media ? media->type : CURRENT_MEDIA_UNKNOWN; - user->media.title = media ? g_strdup(media->title) : NULL; - user->media.artist = media ? g_strdup(media->artist) : NULL; - user->media.album = media ? g_strdup(media->album) : NULL; -} - -void msn_user_set_uid(MsnUser *user, const char *uid) { g_return_if_fail(user != NULL); @@ -415,8 +403,15 @@ { g_return_if_fail(user != NULL); - g_free(user->phone.home); - user->phone.home = g_strdup(number); + if (!number && !user->extinfo) + return; + + if (user->extinfo) + g_free(user->extinfo->phone_home); + else + user->extinfo = g_new0(MsnUserExtendedInfo, 1); + + user->extinfo->phone_home = g_strdup(number); } void @@ -424,8 +419,15 @@ { g_return_if_fail(user != NULL); - g_free(user->phone.work); - user->phone.work = g_strdup(number); + if (!number && !user->extinfo) + return; + + if (user->extinfo) + g_free(user->extinfo->phone_work); + else + user->extinfo = g_new0(MsnUserExtendedInfo, 1); + + user->extinfo->phone_work = g_strdup(number); } void @@ -433,8 +435,15 @@ { g_return_if_fail(user != NULL); - g_free(user->phone.mobile); - user->phone.mobile = g_strdup(number); + if (!number && !user->extinfo) + return; + + if (user->extinfo) + g_free(user->extinfo->phone_mobile); + else + user->extinfo = g_new0(MsnUserExtendedInfo, 1); + + user->extinfo->phone_mobile = g_strdup(number); } void @@ -517,7 +526,7 @@ { g_return_val_if_fail(user != NULL, NULL); - return user->phone.home; + return user->extinfo ? user->extinfo->phone_home : NULL; } const char * @@ -525,7 +534,7 @@ { g_return_val_if_fail(user != NULL, NULL); - return user->phone.work; + return user->extinfo ? user->extinfo->phone_work : NULL; } const char * @@ -533,7 +542,7 @@ { g_return_val_if_fail(user != NULL, NULL); - return user->phone.mobile; + return user->extinfo ? user->extinfo->phone_mobile : NULL; } guint
--- a/libpurple/protocols/msn/user.h Thu Feb 04 20:57:01 2010 +0000 +++ b/libpurple/protocols/msn/user.h Sat Feb 06 05:15:35 2010 +0000 @@ -53,13 +53,25 @@ CURRENT_MEDIA_OFFICE } CurrentMediaType; -typedef struct _CurrentMedia +/** + * Contains optional info about a user that is fairly uncommon. We + * put this info in in a separate struct to save memory because we + * allocate an MsnUser struct for each buddy, but we generally only + * need this information for a small percentage of our buddies + * (usually less than 1%). Putting it in a separate struct saves + * makes MsnUser smaller by the size of a few pointers. + */ +typedef struct _MsnUserExtendedInfo { - CurrentMediaType type; /**< Type. */ - char *title; /**< Title. */ - char *artist; /**< Artist. */ - char *album; /**< Album. */ -} CurrentMedia; + CurrentMediaType media_type; /**< Type of the user's current media. */ + char *media_title; /**< Title of the user's current media. */ + char *media_artist; /**< Artist of the user's current media. */ + char *media_album; /**< Album of the user's current media. */ + + char *phone_home; /**< E.T. uses this. */ + char *phone_work; /**< Work phone number. */ + char *phone_mobile; /**< Mobile phone number. */ +} MsnUserExtendedInfo; /** * A user. @@ -71,22 +83,15 @@ char *passport; /**< The passport account. */ char *friendly_name; /**< The friendly name. */ - char * uid; /*< User Id */ - GHashTable *endpoints; /*< Endpoint-specific data */ + char *uid; /*< User ID */ + GHashTable *endpoints; /*< Endpoint-specific data */ const char *status; /**< The state of the user. */ char *statusline; /**< The state of the user. */ - CurrentMedia media; /**< Current media of the user. */ gboolean idle; /**< The idle state of the user. */ - struct - { - char *home; /**< Home phone number. */ - char *work; /**< Work phone number. */ - char *mobile; /**< Mobile phone number. */ - - } phone; + MsnUserExtendedInfo *extinfo; /**< Extended info for the user. */ gboolean authorized; /**< Authorized to add this user. */ gboolean mobile; /**< Signed up with MSN Mobile. */ @@ -105,8 +110,11 @@ int list_op; /**< Which lists the user is in */ - guint membership_id[5]; /**< The membershipId sent by the contacts server, - indexed by the list it belongs to */ + /** + * The membershipId for this buddy on our pending list. Sent by + * the contact's server + */ + guint member_id_on_pending_list; char *invite_message; /**< Invite message of user request */ }; @@ -165,14 +173,6 @@ */ void msn_user_set_statusline(MsnUser *user, const char *statusline); - /** - * Sets the current media of user. - * - * @param user The user. - * @param cmedia Current media. - */ -void msn_user_set_currentmedia(MsnUser *user, const CurrentMedia *cmedia); - /** * Sets the new state of user. *
--- a/libpurple/protocols/msn/userlist.c Thu Feb 04 20:57:01 2010 +0000 +++ b/libpurple/protocols/msn/userlist.c Sat Feb 06 05:15:35 2010 +0000 @@ -119,26 +119,16 @@ if (group_id == NULL) return FALSE; - if (g_list_find_custom(user->group_ids, group_id, (GCompareFunc)strcmp)) - return TRUE; - - return FALSE; + return (g_list_find_custom(user->group_ids, group_id, (GCompareFunc)strcmp)) != NULL; } gboolean msn_userlist_user_is_in_list(MsnUser *user, MsnListId list_id) { - int list_op; - if (user == NULL) return FALSE; - list_op = 1 << list_id; - - if (user->list_op & list_op) - return TRUE; - else - return FALSE; + return (user->list_op & (1 << list_id)); } /************************************************************************** @@ -210,6 +200,7 @@ if (list_op & MSN_LIST_PL_OP) { + user->authorized = TRUE; got_new_entry(gc, passport, store, message); } } @@ -343,14 +334,10 @@ for (l = userlist->users; l != NULL; l = l->next) { MsnUser *user = (MsnUser *)l->data; + const char *user_number = msn_user_get_mobile_phone(user); - if (user->phone.mobile == NULL) { - continue; - } - - if (!g_ascii_strcasecmp(number, user->phone.mobile)) { + if (user_number && !g_ascii_strcasecmp(number, user_number)) return user; - } } return NULL;
--- a/libpurple/protocols/msn/userlist.h Thu Feb 04 20:57:01 2010 +0000 +++ b/libpurple/protocols/msn/userlist.h Sat Feb 06 05:15:35 2010 +0000 @@ -31,12 +31,11 @@ typedef enum { - MSN_LIST_FL, - MSN_LIST_AL, - MSN_LIST_BL, - MSN_LIST_RL, - MSN_LIST_PL - + MSN_LIST_FL, /**< Forward list */ + MSN_LIST_AL, /**< Allow list */ + MSN_LIST_BL, /**< Block list */ + MSN_LIST_RL, /**< Reverse list */ + MSN_LIST_PL /**< Pending list */ } MsnListId;
--- a/libpurple/protocols/mxit/splashscreen.c Thu Feb 04 20:57:01 2010 +0000 +++ b/libpurple/protocols/mxit/splashscreen.c Sat Feb 06 05:15:35 2010 +0000 @@ -24,7 +24,6 @@ */ #include "internal.h" -#include <glib/gstdio.h> #include "purple.h" #include "imgstore.h"
--- a/libpurple/protocols/myspace/myspace.c Thu Feb 04 20:57:01 2010 +0000 +++ b/libpurple/protocols/myspace/myspace.c Sat Feb 06 05:15:35 2010 +0000 @@ -251,7 +251,6 @@ MsimMessage *msg; const gchar *from_username; - g_return_val_if_fail(MSIM_SESSION_VALID(session), FALSE); g_return_val_if_fail(who != NULL, FALSE); g_return_val_if_fail(text != NULL, FALSE); @@ -344,8 +343,6 @@ { guint rid; - g_return_val_if_fail(MSIM_SESSION_VALID(session), -1); - rid = session->next_rid++; g_hash_table_insert(session->user_lookup_cb, GUINT_TO_POINTER(rid), cb); @@ -394,8 +391,6 @@ gc = purple_account_get_connection(account); session = (MsimSession *)gc->proto_data; - g_return_val_if_fail(MSIM_SESSION_VALID(session), NULL); - display_name = headline = NULL; /* Retrieve display name and/or headline, depending on user preference. */ @@ -442,11 +437,9 @@ MsimSession *session; PurpleAccount *account = purple_buddy_get_account(buddy); PurpleConnection *gc = purple_account_get_connection(account); - + session = (MsimSession *)gc->proto_data; - g_return_if_fail(MSIM_SESSION_VALID(session)); - /* TODO: if (full), do something different? */ /* TODO: request information? have to figure out how to do @@ -694,7 +687,6 @@ gsize nc_len; gboolean ret; - g_return_val_if_fail(MSIM_SESSION_VALID(session), FALSE); g_return_val_if_fail(msg != NULL, FALSE); g_return_val_if_fail(msim_msg_get_binary(msg, "nc", &nc, &nc_len), FALSE); @@ -783,7 +775,6 @@ static gboolean msim_is_username_set(MsimSession *session, MsimMessage *msg) { - g_return_val_if_fail(MSIM_SESSION_VALID(session), FALSE); g_return_val_if_fail(msg != NULL, FALSE); g_return_val_if_fail(session->gc != NULL, FALSE); @@ -842,8 +833,6 @@ session = (MsimSession *)data; - g_return_val_if_fail(MSIM_SESSION_VALID(session), FALSE); - delta = time(NULL) - session->last_comm; /* purple_debug_info("msim", "msim_check_alive: delta=%d\n", delta); */ @@ -970,11 +959,6 @@ session = (MsimSession *)data; - if (!MSIM_SESSION_VALID(session)) { - purple_debug_info("msim", "msim_check_inbox: session invalid, stopping the mail check.\n"); - return FALSE; - } - purple_debug_info("msim", "msim_check_inbox: checking mail\n"); g_return_val_if_fail(msim_send(session, "persist", MSIM_TYPE_INTEGER, 1, @@ -1215,8 +1199,6 @@ { MsimMessage *body; - g_return_val_if_fail(MSIM_SESSION_VALID(session), FALSE); - /* Set display name to username (otherwise will show email address) */ purple_connection_set_display_name(session->gc, session->username); @@ -1382,7 +1364,6 @@ gchar *username; gchar *unrecognized_msg; - g_return_val_if_fail(MSIM_SESSION_VALID(session), FALSE); g_return_val_if_fail(msg != NULL, FALSE); /* Helpfully looked up by msim_incoming_resolve() for us. */ @@ -1577,7 +1558,6 @@ gchar *msg_text, *username; gboolean rc; - g_return_val_if_fail(MSIM_SESSION_VALID(session), FALSE); g_return_val_if_fail(msg != NULL, FALSE); msg_text = msim_msg_get_string(msg, "msg"); @@ -1797,7 +1777,6 @@ gpointer data; guint rid, cmd, dsn, lid; - g_return_val_if_fail(MSIM_SESSION_VALID(session), FALSE); g_return_val_if_fail(msg != NULL, FALSE); msim_store_user_info(session, msg, NULL); @@ -1848,7 +1827,6 @@ gchar *errmsg, *full_errmsg; guint err; - g_return_val_if_fail(MSIM_SESSION_VALID(session), FALSE); g_return_val_if_fail(msg != NULL, FALSE); err = msim_msg_get_integer(msg, "err"); @@ -1962,7 +1940,6 @@ gchar *username; MsimMessage *msg, *body; - g_return_if_fail(MSIM_SESSION_VALID(session)); g_return_if_fail(userinfo != NULL); body = msim_msg_get_dictionary(userinfo, "body"); @@ -1998,7 +1975,6 @@ static gboolean msim_preprocess_incoming(MsimSession *session, MsimMessage *msg) { - g_return_val_if_fail(MSIM_SESSION_VALID(session), FALSE); g_return_val_if_fail(msg != NULL, FALSE); if (msim_msg_get(msg, "bm") && msim_msg_get(msg, "f")) { @@ -2071,7 +2047,6 @@ } g_return_if_fail(cond == PURPLE_INPUT_READ); - g_return_if_fail(MSIM_SESSION_VALID(session)); /* Mark down that we got data, so we don't timeout. */ session->last_comm = time(NULL); @@ -2264,6 +2239,13 @@ } } +static void +msim_buddy_free(PurpleBuddy *buddy) +{ + msim_user_free(purple_buddy_get_protocol_data(buddy)); + purple_buddy_set_protocol_data(buddy, NULL); +} + /** * Close the connection. * @@ -2272,22 +2254,30 @@ static void msim_close(PurpleConnection *gc) { + GSList *buddies; MsimSession *session; if (gc == NULL) { return; } + /* + * Free our protocol-specific buddy data. It almost seems like libpurple + * should call our buddy_free prpl callback so that we don't need to do + * this... but it doesn't, so we do. + */ + buddies = purple_find_buddies(purple_connection_get_account(gc), NULL); + while (buddies != NULL) { + msim_buddy_free(buddies->data); + buddies = g_slist_delete_link(buddies, buddies); + } + session = (MsimSession *)gc->proto_data; if (session == NULL) return; gc->proto_data = NULL; - if (!MSIM_SESSION_VALID(session)) { - return; - } - if (session->gc->inpa) { purple_input_remove(session->gc->inpa); } @@ -2329,8 +2319,6 @@ session = (MsimSession *)gc->proto_data; - g_return_val_if_fail(MSIM_SESSION_VALID(session), -1); - message_msim = html_to_msim_markup(session, message); if (msim_send_bm(session, who, message_msim, MSIM_BM_ACTION_OR_IM_DELAYABLE)) { @@ -2371,8 +2359,6 @@ session = (MsimSession *)gc->proto_data; - g_return_val_if_fail(MSIM_SESSION_VALID(session), 0); - switch (state) { case PURPLE_TYPING: typing_str = "%typing%"; @@ -2402,8 +2388,6 @@ PurpleNotifyUserInfo *user_info; MsimUser *user; - g_return_if_fail(MSIM_SESSION_VALID(session)); - /* Get user{name,id} from msim_get_info, passed as an MsimMessage for orthogonality. */ msg = (MsimMessage *)data; @@ -2439,16 +2423,8 @@ purple_notify_user_info_destroy(user_info); - if (user->temporary_user) { - g_free(user->client_info); - g_free(user->gender); - g_free(user->location); - g_free(user->headline); - g_free(user->display_name); - g_free(user->username); - g_free(user->image_url); - g_free(user); - } + if (user->temporary_user) + msim_user_free(user); g_free(username); } @@ -2469,8 +2445,6 @@ session = (MsimSession *)gc->proto_data; - g_return_if_fail(MSIM_SESSION_VALID(session)); - /* Obtain uid of buddy. */ user = msim_find_user(session, username); @@ -2504,7 +2478,6 @@ static void msim_set_status_code(MsimSession *session, guint status_code, gchar *statstring) { - g_return_if_fail(MSIM_SESSION_VALID(session)); g_return_if_fail(statstring != NULL); purple_debug_info("msim", "msim_set_status_code: going to set status to code=%d,str=%s\n", @@ -2537,8 +2510,6 @@ session = (MsimSession *)account->gc->proto_data; - g_return_if_fail(MSIM_SESSION_VALID(session)); - type = purple_status_get_type(status); pres = purple_status_get_presence(status); @@ -2602,8 +2573,6 @@ session = (MsimSession *)gc->proto_data; - g_return_if_fail(MSIM_SESSION_VALID(session)); - status = purple_account_get_active_status(session->account); if (time == 0) { @@ -2742,13 +2711,6 @@ msim_update_blocklist_for_buddy(session, name, TRUE, FALSE); } -static void -msim_buddy_free(PurpleBuddy *buddy) -{ - msim_user_free(purple_buddy_get_protocol_data(buddy)); - purple_buddy_set_protocol_data(buddy, NULL); -} - /** * Remove a buddy from the user's buddy list. */ @@ -3001,8 +2963,6 @@ session = (MsimSession *)gc->proto_data; - g_return_val_if_fail(MSIM_SESSION_VALID(session), -1); - /* Loop until all data is sent, or a failure occurs. */ total_bytes_sent = 0; do { @@ -3037,7 +2997,6 @@ { size_t len; - g_return_val_if_fail(MSIM_SESSION_VALID(session), FALSE); g_return_val_if_fail(msg != NULL, FALSE); purple_debug_info("msim", "msim_send_raw: writing <%s>\n", msg);
--- a/libpurple/protocols/myspace/session.c Thu Feb 04 20:57:01 2010 +0000 +++ b/libpurple/protocols/myspace/session.c Sat Feb 06 05:15:35 2010 +0000 @@ -76,8 +76,6 @@ void msim_session_destroy(MsimSession *session) { - g_return_if_fail(MSIM_SESSION_VALID(session)); - session->magic = -1; g_free(session->rxbuf);
--- a/libpurple/protocols/myspace/session.h Thu Feb 04 20:57:01 2010 +0000 +++ b/libpurple/protocols/myspace/session.h Sat Feb 06 05:15:35 2010 +0000 @@ -54,9 +54,6 @@ guint inbox_handle; /**< The handle for the mail check timer */ } 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);
--- a/libpurple/protocols/myspace/user.c Thu Feb 04 20:57:01 2010 +0000 +++ b/libpurple/protocols/myspace/user.c Sat Feb 06 05:15:35 2010 +0000 @@ -70,6 +70,9 @@ if (!user) return; + if (user->url_data != NULL) + purple_util_fetch_url_cancel(user->url_data); + g_free(user->client_info); g_free(user->gender); g_free(user->location); @@ -89,16 +92,13 @@ 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, TRUE); - - return user; + return msim_get_user_from_buddy(buddy, TRUE); } /** @@ -212,6 +212,8 @@ const char *name = purple_buddy_get_name(user->buddy); PurpleAccount *account; + user->url_data = NULL; + purple_debug_info("msim_downloaded_buddy_icon", "Downloaded %" G_GSIZE_FORMAT " bytes\n", len); @@ -350,14 +352,6 @@ return; } - if (user->temporary_user) { - /* This user will be destroyed soon; don't try to look up its image or avatar, - * since that won't return immediately and we will end up accessing freed data. - */ - g_free(value_str); - return; - } - g_free(user->image_url); user->image_url = value_str; @@ -375,7 +369,9 @@ /* 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); + if (user->url_data != NULL) + purple_util_fetch_url_cancel(user->url_data); + user->url_data = 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 */ @@ -418,7 +414,6 @@ 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"); @@ -570,7 +565,6 @@ 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);*/ @@ -630,8 +624,6 @@ purple_debug_info("msim","username_is_set made\n"); - g_return_if_fail(MSIM_SESSION_VALID(session)); - cmd = msim_msg_get_integer(userinfo, "cmd"); dsn = msim_msg_get_integer(userinfo, "dsn"); uid = msim_msg_get_integer(userinfo, "uid"); @@ -711,7 +703,6 @@ MsimMessage *body; guint rid; - g_return_if_fail(MSIM_SESSION_VALID(session)); g_return_if_fail(username != NULL); g_return_if_fail(cb != NULL); @@ -758,9 +749,6 @@ session = (MsimSession *)gc->proto_data; - g_return_if_fail(MSIM_SESSION_VALID(session)); - - user_msg = msim_msg_new( "user", MSIM_TYPE_STRING, g_strdup(msim_username_to_set), NULL); @@ -787,7 +775,6 @@ purple_debug_info("msim_username_is_available_cb", "Look up username callback made\n"); msg = (MsimMessage *)data; - g_return_if_fail(MSIM_SESSION_VALID(session)); g_return_if_fail(msg != NULL); username = msim_msg_get_string(msg, "user"); @@ -855,8 +842,6 @@ session = (MsimSession *)gc->proto_data; - g_return_if_fail(MSIM_SESSION_VALID(session)); - purple_debug_info("msim_check_username_availability_cb", "Checking username: %s\n", username_to_check); user_msg = msim_msg_new(
--- a/libpurple/protocols/myspace/user.h Thu Feb 04 20:57:01 2010 +0000 +++ b/libpurple/protocols/myspace/user.h Sat Feb 06 05:15:35 2010 +0000 @@ -40,6 +40,7 @@ gchar *image_url; guint last_image_updated; gboolean temporary_user; + PurpleUtilFetchUrlData *url_data; } MsimUser; /* Callback function pointer type for when a user's information is received,
--- a/libpurple/protocols/oscar/clientlogin.c Thu Feb 04 20:57:01 2010 +0000 +++ b/libpurple/protocols/oscar/clientlogin.c Sat Feb 06 05:15:35 2010 +0000 @@ -62,6 +62,26 @@ DEFAULT_CLIENT_KEY); } +static gchar *generate_error_message(xmlnode *resp, const char *url) +{ + xmlnode *text; + gchar *err = NULL; + gchar *details = NULL; + + if (resp && (text = xmlnode_get_child(resp, "statusText"))) { + details = xmlnode_get_data(text); + } + + if (details && *details) { + err = g_strdup_printf(_("Received unexpected response from %s: %s"), url, details); + } else { + err = g_strdup_printf(_("Received unexpected response from %s"), url); + } + + g_free(details); + return err; +} + /** * @return A null-terminated base64 encoded version of the HMAC * calculated using the given key and data. @@ -121,7 +141,7 @@ purple_debug_error("oscar", "startOSCARSession could not parse " "response as XML: %s\n", response); /* Note to translators: %s in this string is a URL */ - msg = g_strdup_printf(_("Received unexpected response from %s"), + msg = generate_error_message(response_node, URL_START_OSCAR_SESSION); purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg); @@ -144,7 +164,7 @@ char *msg; purple_debug_error("oscar", "startOSCARSession response was " "missing statusCode: %s\n", response); - msg = g_strdup_printf(_("Received unexpected response from %s"), + msg = generate_error_message(response_node, URL_START_OSCAR_SESSION); purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg); @@ -169,7 +189,7 @@ "longer.")); else { char *msg; - msg = g_strdup_printf(_("Received unexpected response from %s"), + msg = generate_error_message(response_node, URL_START_OSCAR_SESSION); purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, msg); @@ -190,7 +210,7 @@ char *msg; purple_debug_error("oscar", "startOSCARSession response was missing " "something: %s\n", response); - msg = g_strdup_printf(_("Received unexpected response from %s"), + msg = generate_error_message(response_node, URL_START_OSCAR_SESSION); purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg); @@ -213,7 +233,7 @@ char *msg; purple_debug_error("oscar", "startOSCARSession response was missing " "something: %s\n", response); - msg = g_strdup_printf(_("Received unexpected response from %s"), + msg = generate_error_message(response_node, URL_START_OSCAR_SESSION); purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg); @@ -340,7 +360,7 @@ char *msg; purple_debug_error("oscar", "clientLogin could not parse " "response as XML: %s\n", response); - msg = g_strdup_printf(_("Received unexpected response from %s"), + msg = generate_error_message(response_node, URL_CLIENT_LOGIN); purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg); @@ -364,7 +384,7 @@ char *msg; purple_debug_error("oscar", "clientLogin response was " "missing statusCode: %s\n", response); - msg = g_strdup_printf(_("Received unexpected response from %s"), + msg = generate_error_message(response_node, URL_CLIENT_LOGIN); purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg); @@ -399,7 +419,7 @@ _("AOL does not allow your screen name to authenticate here")); } else { char *msg; - msg = g_strdup_printf(_("Received unexpected response from %s"), + msg = generate_error_message(response_node, URL_CLIENT_LOGIN); purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, msg); @@ -418,7 +438,7 @@ char *msg; purple_debug_error("oscar", "clientLogin response was missing " "something: %s\n", response); - msg = g_strdup_printf(_("Received unexpected response from %s"), + msg = generate_error_message(response_node, URL_CLIENT_LOGIN); purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg); @@ -436,7 +456,7 @@ char *msg; purple_debug_error("oscar", "clientLogin response was missing " "something: %s\n", response); - msg = g_strdup_printf(_("Received unexpected response from %s"), + msg = generate_error_message(response_node, URL_CLIENT_LOGIN); purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
--- a/libpurple/protocols/oscar/family_oservice.c Thu Feb 04 20:57:01 2010 +0000 +++ b/libpurple/protocols/oscar/family_oservice.c Sat Feb 06 05:15:35 2010 +0000 @@ -27,6 +27,24 @@ #include "cipher.h" +/* + * Each time we make a FLAP connection to an oscar server the server gives + * us a list of rate classes. Each rate class has different properties for + * how frequently we can send SNACs in that rate class before we become + * throttled or disconnected. + * + * The server also gives us a list of every available SNAC and tells us which + * rate class it's in. There are a lot of different SNACs, so this list can be + * fairly large. One important characteristic of these rate classes is that + * currently (and since at least 2004) most SNACs are in the same rate class. + * + * One optimization we can do to save memory is to only keep track of SNACs + * that are in classes other than this default rate class. So if we try to + * look up a SNAC and it's not in our hash table then we can assume that it's + * in the default rate class. + */ +#define OSCAR_DEFAULT_RATECLASS 1 + /* Subtype 0x0002 - Client Online */ void aim_srv_clientready(OscarData *od, FlapConnection *conn) @@ -323,7 +341,7 @@ struct timeval now; gettimeofday(&now, NULL); - rateclass = g_new0(struct rateclass, 1); + rateclass = g_new(struct rateclass, 1); rateclass->classid = byte_stream_get16(bs); rateclass->windowsize = byte_stream_get32(bs); @@ -333,34 +351,21 @@ rateclass->disconnect = byte_stream_get32(bs); rateclass->current = byte_stream_get32(bs); rateclass->max = byte_stream_get32(bs); - - /* - * The server will send an extra five bytes of parameters - * depending on the version we advertised in 1/17. If we - * didn't send 1/17 (evil!), then this will crash and you - * die, as it will default to the old version but we have - * the new version hardcoded here. - */ - if (mod->version >= 3) - { - rateclass->delta = byte_stream_get32(bs); + if (mod->version >= 3) { + delta = byte_stream_get32(bs); rateclass->dropping_snacs = byte_stream_get8(bs); - - delta = rateclass->delta; - - rateclass->last.tv_sec = now.tv_sec - delta / 1000; - delta %= 1000; - rateclass->last.tv_usec = now.tv_usec - delta * 1000; - } - else - { - rateclass->delta = rateclass->dropping_snacs = 0; - rateclass->last.tv_sec = now.tv_sec; - rateclass->last.tv_usec = now.tv_usec; + } else { + delta = 0; + rateclass->dropping_snacs = 0; } - rateclass->members = g_hash_table_new(g_direct_hash, g_direct_equal); + rateclass->last.tv_sec = now.tv_sec - delta / 1000; + rateclass->last.tv_usec = now.tv_usec - (delta % 1000) * 1000; + conn->rateclasses = g_slist_prepend(conn->rateclasses, rateclass); + + if (rateclass->classid == OSCAR_DEFAULT_RATECLASS) + conn->default_rateclass = rateclass; } conn->rateclasses = g_slist_reverse(conn->rateclasses); @@ -376,6 +381,15 @@ classid = byte_stream_get16(bs); count = byte_stream_get16(bs); + if (classid == OSCAR_DEFAULT_RATECLASS) { + /* + * Don't bother adding these SNACs to the hash table. See the + * comment for OSCAR_DEFAULT_RATECLASS at the top of this file. + */ + byte_stream_advance(bs, 4 * count); + continue; + } + rateclass = rateclass_find(conn->rateclasses, classid); for (j = 0; j < count; j++) @@ -386,9 +400,9 @@ subtype = byte_stream_get16(bs); if (rateclass != NULL) - g_hash_table_insert(rateclass->members, + g_hash_table_insert(conn->rateclass_members, GUINT_TO_POINTER((group << 16) + subtype), - GUINT_TO_POINTER(TRUE)); + rateclass); } } @@ -462,12 +476,17 @@ static int ratechange(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { - int ret = 0; - aim_rxcallback_t userfunc; guint16 code, classid; struct rateclass *rateclass; guint32 delta; struct timeval now; + static const char *codes[5] = { + "invalid", + "change", + "warning", + "limit", + "limit cleared", + }; gettimeofday(&now, NULL); code = byte_stream_get16(bs); @@ -485,32 +504,32 @@ rateclass->disconnect = byte_stream_get32(bs); rateclass->current = byte_stream_get32(bs); rateclass->max = byte_stream_get32(bs); - - if (mod->version >= 3) - { - rateclass->delta = byte_stream_get32(bs); + if (mod->version >= 3) { + delta = byte_stream_get32(bs); rateclass->dropping_snacs = byte_stream_get8(bs); - - delta = rateclass->delta; - - rateclass->last.tv_sec = now.tv_sec - delta / 1000; - delta %= 1000; - rateclass->last.tv_usec = now.tv_usec - delta * 1000; - } - else - { - rateclass->delta = rateclass->dropping_snacs = 0; - rateclass->last.tv_sec = now.tv_sec; - rateclass->last.tv_usec = now.tv_usec; + } else { + delta = 0; + rateclass->dropping_snacs = 0; } - if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) { - /* Can't pass in guint8 via ... varargs, so we use an unsigned int */ - unsigned int dropping_snacs = rateclass->dropping_snacs; - ret = userfunc(od, conn, frame, code, classid, rateclass->windowsize, rateclass->clear, rateclass->alert, rateclass->limit, rateclass->disconnect, rateclass->current, rateclass->max, rateclass->delta, dropping_snacs); + rateclass->last.tv_sec = now.tv_sec - delta / 1000; + rateclass->last.tv_usec = now.tv_usec - (delta % 1000) * 1000; + + purple_debug_misc("oscar", "rate %s (param ID 0x%04hx): curavg = %u, " + "maxavg = %u, alert at %u, clear warning at %u, limit at %u, " + "disconnect at %u, delta is %u, dropping is %u (window size = %u)\n", + (code < 5) ? codes[code] : codes[0], rateclass->classid, + rateclass->current, rateclass->max, rateclass->alert, + rateclass->clear, rateclass->limit, rateclass->disconnect, + delta, rateclass->dropping_snacs, rateclass->windowsize); + + if (code == AIM_RATE_CODE_LIMIT) { + purple_debug_warning("oscar", _("The last action you attempted " + "could not be performed because you are over the rate " + "limit. Please wait 10 seconds and try again.\n")); } - return ret; + return 1; } /*
--- a/libpurple/protocols/oscar/flap_connection.c Thu Feb 04 20:57:01 2010 +0000 +++ b/libpurple/protocols/oscar/flap_connection.c Sat Feb 06 05:15:35 2010 +0000 @@ -106,21 +106,15 @@ static struct rateclass * flap_connection_get_rateclass(FlapConnection *conn, guint16 family, guint16 subtype) { - GSList *tmp1; gconstpointer key; + gpointer rateclass; key = GUINT_TO_POINTER((family << 16) + subtype); - - for (tmp1 = conn->rateclasses; tmp1 != NULL; tmp1 = tmp1->next) - { - struct rateclass *rateclass; - rateclass = tmp1->data; + rateclass = g_hash_table_lookup(conn->rateclass_members, key); + if (rateclass != NULL) + return rateclass; - if (g_hash_table_lookup(rateclass->members, key)) - return rateclass; - } - - return NULL; + return conn->default_rateclass; } /* @@ -133,10 +127,10 @@ unsigned long timediff; /* In milliseconds */ guint32 current; + /* This formula is documented at http://dev.aol.com/aim/oscar/#RATELIMIT */ timediff = (now->tv_sec - rateclass->last.tv_sec) * 1000 + (now->tv_usec - rateclass->last.tv_usec) / 1000; current = ((rateclass->current * (rateclass->windowsize - 1)) + timediff) / rateclass->windowsize; - /* This formula is taken from http://dev.aol.com/aim/oscar/#RATELIMIT */ return MIN(current, rateclass->max); } @@ -258,14 +252,6 @@ rateclass->last.tv_sec = now.tv_sec; rateclass->last.tv_usec = now.tv_usec; } - } else { - /* - * It's normal for SNACs 0x0001/0x0006 and 0x0001/0x0017 to be - * sent before we receive rate info from the server, so don't - * bother warning about them. - */ - if (family != 0x0001 || (subtype != 0x0006 && subtype != 0x0017)) - purple_debug_warning("oscar", "No rate class found for family 0x%04hx subtype 0x%04hx\n", family, subtype); } if (enqueue) @@ -354,6 +340,7 @@ conn->fd = -1; conn->subtype = -1; conn->type = type; + conn->rateclass_members = g_hash_table_new(g_direct_hash, g_direct_equal); od->oscar_connections = g_slist_prepend(od->oscar_connections, conn); @@ -421,13 +408,6 @@ conn->buffer_outgoing = NULL; } -static void -flap_connection_destroy_rateclass(struct rateclass *rateclass) -{ - g_hash_table_destroy(rateclass->members); - g_free(rateclass); -} - /** * Free a FlapFrame * @@ -515,10 +495,12 @@ g_slist_free(conn->groups); while (conn->rateclasses != NULL) { - flap_connection_destroy_rateclass(conn->rateclasses->data); + g_free(conn->rateclasses->data); conn->rateclasses = g_slist_delete_link(conn->rateclasses, conn->rateclasses); } + g_hash_table_destroy(conn->rateclass_members); + if (conn->queued_snacs) { while (!g_queue_is_empty(conn->queued_snacs)) {
--- a/libpurple/protocols/oscar/libaim.c Thu Feb 04 20:57:01 2010 +0000 +++ b/libpurple/protocols/oscar/libaim.c Sat Feb 06 05:15:35 2010 +0000 @@ -32,8 +32,7 @@ NULL, /* user_splits */ NULL, /* protocol_options */ /* The mimimum icon size below is not needed in AIM 6.0 */ - {"gif,jpeg,bmp,ico", 48, 48, 50, 50, 7168, - PURPLE_ICON_SCALE_SEND | PURPLE_ICON_SCALE_DISPLAY}, /* icon_spec */ + {"gif,jpeg,bmp,ico", 0, 0, 100, 100, 7168, PURPLE_ICON_SCALE_DISPLAY}, /* icon_spec */ oscar_list_icon_aim, /* list_icon */ oscar_list_emblem, /* list_emblems */ oscar_status_text, /* status_text */
--- a/libpurple/protocols/oscar/oscar.c Thu Feb 04 20:57:01 2010 +0000 +++ b/libpurple/protocols/oscar/oscar.c Sat Feb 06 05:15:35 2010 +0000 @@ -190,7 +190,6 @@ static int purple_icon_parseicon (OscarData *, FlapConnection *, FlapFrame *, ...); static int oscar_icon_req (OscarData *, FlapConnection *, FlapFrame *, ...); static int purple_parse_msgack (OscarData *, FlapConnection *, FlapFrame *, ...); -static int purple_parse_ratechange (OscarData *, FlapConnection *, FlapFrame *, ...); static int purple_parse_evilnotify (OscarData *, FlapConnection *, FlapFrame *, ...); static int purple_parse_searcherror(OscarData *, FlapConnection *, FlapFrame *, ...); static int purple_parse_searchreply(OscarData *, FlapConnection *, FlapFrame *, ...); @@ -378,12 +377,12 @@ } static gchar * -oscar_utf8_try_convert(PurpleAccount *account, const gchar *msg) +oscar_utf8_try_convert(PurpleAccount *account, OscarData *od, const gchar *msg) { const char *charset = NULL; char *ret = NULL; - if(oscar_util_valid_name_icq(purple_account_get_username(account))) + if (od->icq) charset = purple_account_get_string(account, "encoding", NULL); if(charset && *charset) @@ -798,24 +797,24 @@ } static void -oscar_user_info_convert_and_add_pair(PurpleAccount *account, PurpleNotifyUserInfo *user_info, +oscar_user_info_convert_and_add_pair(PurpleAccount *account, OscarData *od, PurpleNotifyUserInfo *user_info, const char *name, const char *value) { gchar *utf8; - if (value && value[0] && (utf8 = oscar_utf8_try_convert(account, value))) { + if (value && value[0] && (utf8 = oscar_utf8_try_convert(account, od, value))) { purple_notify_user_info_add_pair(user_info, name, utf8); g_free(utf8); } } static void -oscar_user_info_convert_and_add(PurpleAccount *account, PurpleNotifyUserInfo *user_info, +oscar_user_info_convert_and_add(PurpleAccount *account, OscarData *od, PurpleNotifyUserInfo *user_info, const char *name, const char *value) { gchar *utf8; - if (value && value[0] && (utf8 = oscar_utf8_try_convert(account, value))) { + if (value && value[0] && (utf8 = oscar_utf8_try_convert(account, od, value))) { purple_notify_user_info_add_pair(user_info, name, utf8); g_free(utf8); } @@ -1022,7 +1021,7 @@ char *tmp2 = g_markup_escape_text(tmp, strlen(tmp)); g_free(tmp); - oscar_user_info_convert_and_add_pair(account, user_info, _("Buddy Comment"), tmp2); + oscar_user_info_convert_and_add_pair(account, od, user_info, _("Buddy Comment"), tmp2); g_free(tmp2); } } @@ -1526,7 +1525,6 @@ oscar_data_addhandler(od, SNAC_FAMILY_OSERVICE, 0x000f, purple_selfinfo, 0); oscar_data_addhandler(od, SNAC_FAMILY_OSERVICE, 0x001f, purple_memrequest, 0); oscar_data_addhandler(od, SNAC_FAMILY_OSERVICE, 0x0021, oscar_icon_req,0); - oscar_data_addhandler(od, SNAC_FAMILY_OSERVICE, SNAC_SUBTYPE_OSERVICE_RATECHANGE, purple_parse_ratechange, 0); oscar_data_addhandler(od, SNAC_FAMILY_OSERVICE, SNAC_SUBTYPE_OSERVICE_REDIRECT, purple_handle_redirect, 0); oscar_data_addhandler(od, SNAC_FAMILY_OSERVICE, SNAC_SUBTYPE_OSERVICE_MOTD, purple_parse_motd, 0); oscar_data_addhandler(od, SNAC_FAMILY_OSERVICE, SNAC_SUBTYPE_OSERVICE_EVIL, purple_parse_evilnotify, 0); @@ -2450,7 +2448,7 @@ * Note: There *may* be some clients which send messages as HTML formatted - * they need to be special-cased somehow. */ - if (oscar_util_valid_name_icq(purple_account_get_username(account)) && oscar_util_valid_name_icq(userinfo->bn)) { + if (od->icq && oscar_util_valid_name_icq(userinfo->bn)) { /* being recevied by ICQ from ICQ - escape HTML so it is displayed as sent */ gchar *tmp2 = g_markup_escape_text(tmp, -1); g_free(tmp); @@ -3838,56 +3836,6 @@ return 1; } -static int purple_parse_ratechange(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { - static const char *codes[5] = { - "invalid", - "change", - "warning", - "limit", - "limit cleared", - }; - va_list ap; - guint16 code, rateclass; - guint32 windowsize, clear, alert, limit, disconnect, currentavg, maxavg, delta; - guint8 dropping_snacs; - - va_start(ap, fr); - code = (guint16)va_arg(ap, unsigned int); - rateclass= (guint16)va_arg(ap, unsigned int); - windowsize = va_arg(ap, guint32); - clear = va_arg(ap, guint32); - alert = va_arg(ap, guint32); - limit = va_arg(ap, guint32); - disconnect = va_arg(ap, guint32); - currentavg = va_arg(ap, guint32); - maxavg = va_arg(ap, guint32); - delta = va_arg(ap, guint32); - dropping_snacs = (guint8)va_arg(ap, unsigned int); - va_end(ap); - - purple_debug_misc("oscar", - "rate %s (param ID 0x%04hx): curavg = %u, maxavg = %u, alert at %u, " - "clear warning at %u, limit at %u, disconnect at %u, delta is %u, dropping is %u (window size = %u)\n", - (code < 5) ? codes[code] : codes[0], - rateclass, - currentavg, maxavg, - alert, clear, - limit, disconnect, - delta, - dropping_snacs, - windowsize - ); - - if (code == AIM_RATE_CODE_LIMIT) - { - purple_debug_warning("oscar", _("The last action you attempted could not be " - "performed because you are over the rate limit. " - "Please wait 10 seconds and try again.\n")); - } - - return 1; -} - static int purple_parse_evilnotify(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { #ifdef CRAZY_WARNING va_list ap; @@ -4173,7 +4121,7 @@ bi = NULL; purple_notify_user_info_add_pair(user_info, _("UIN"), who); - oscar_user_info_convert_and_add(account, user_info, _("Nick"), info->nick); + oscar_user_info_convert_and_add(account, od, user_info, _("Nick"), info->nick); if ((bi != NULL) && (bi->ipaddr != 0)) { char *tstr = g_strdup_printf("%hhu.%hhu.%hhu.%hhu", (bi->ipaddr & 0xff000000) >> 24, @@ -4183,9 +4131,9 @@ purple_notify_user_info_add_pair(user_info, _("IP Address"), tstr); g_free(tstr); } - oscar_user_info_convert_and_add(account, user_info, _("First Name"), info->first); - oscar_user_info_convert_and_add(account, user_info, _("Last Name"), info->last); - if (info->email && info->email[0] && (utf8 = oscar_utf8_try_convert(account, info->email))) { + oscar_user_info_convert_and_add(account, od, user_info, _("First Name"), info->first); + oscar_user_info_convert_and_add(account, od, user_info, _("Last Name"), info->last); + if (info->email && info->email[0] && (utf8 = oscar_utf8_try_convert(account, od, info->email))) { buf = g_strdup_printf("<a href=\"mailto:%s\">%s</a>", utf8, utf8); purple_notify_user_info_add_pair(user_info, _("Email Address"), buf); g_free(buf); @@ -4194,7 +4142,7 @@ if (info->numaddresses && info->email2) { int i; for (i = 0; i < info->numaddresses; i++) { - if (info->email2[i] && info->email2[i][0] && (utf8 = oscar_utf8_try_convert(account, info->email2[i]))) { + if (info->email2[i] && info->email2[i][0] && (utf8 = oscar_utf8_try_convert(account, od, info->email2[i]))) { buf = g_strdup_printf("<a href=\"mailto:%s\">%s</a>", utf8, utf8); purple_notify_user_info_add_pair(user_info, _("Email Address"), buf); g_free(buf); @@ -4202,7 +4150,7 @@ } } } - oscar_user_info_convert_and_add(account, user_info, _("Mobile Phone"), info->mobile); + oscar_user_info_convert_and_add(account, od, user_info, _("Mobile Phone"), info->mobile); if (info->gender != 0) purple_notify_user_info_add_pair(user_info, _("Gender"), (info->gender == 1 ? _("Female") : _("Male"))); @@ -4222,14 +4170,14 @@ * feel free to remove it. --rlaager */ mktime(tm); - oscar_user_info_convert_and_add(account, user_info, _("Birthday"), purple_date_format_short(tm)); + oscar_user_info_convert_and_add(account, od, user_info, _("Birthday"), purple_date_format_short(tm)); } if ((info->age > 0) && (info->age < 255)) { char age[5]; snprintf(age, sizeof(age), "%hhd", info->age); purple_notify_user_info_add_pair(user_info, _("Age"), age); } - if (info->personalwebpage && info->personalwebpage[0] && (utf8 = oscar_utf8_try_convert(account, info->personalwebpage))) { + if (info->personalwebpage && info->personalwebpage[0] && (utf8 = oscar_utf8_try_convert(account, od, info->personalwebpage))) { buf = g_strdup_printf("<a href=\"%s\">%s</a>", utf8, utf8); purple_notify_user_info_add_pair(user_info, _("Personal Web Page"), buf); g_free(buf); @@ -4239,33 +4187,33 @@ if (buddy != NULL) oscar_user_info_append_status(gc, user_info, buddy, /* aim_userinfo_t */ NULL, /* strip_html_tags */ FALSE); - oscar_user_info_convert_and_add(account, user_info, _("Additional Information"), info->info); + oscar_user_info_convert_and_add(account, od, user_info, _("Additional Information"), info->info); purple_notify_user_info_add_section_break(user_info); if ((info->homeaddr && (info->homeaddr[0])) || (info->homecity && info->homecity[0]) || (info->homestate && info->homestate[0]) || (info->homezip && info->homezip[0])) { purple_notify_user_info_add_section_header(user_info, _("Home Address")); - oscar_user_info_convert_and_add(account, user_info, _("Address"), info->homeaddr); - oscar_user_info_convert_and_add(account, user_info, _("City"), info->homecity); - oscar_user_info_convert_and_add(account, user_info, _("State"), info->homestate); - oscar_user_info_convert_and_add(account, user_info, _("Zip Code"), info->homezip); + oscar_user_info_convert_and_add(account, od, user_info, _("Address"), info->homeaddr); + oscar_user_info_convert_and_add(account, od, user_info, _("City"), info->homecity); + oscar_user_info_convert_and_add(account, od, user_info, _("State"), info->homestate); + oscar_user_info_convert_and_add(account, od, user_info, _("Zip Code"), info->homezip); } if ((info->workaddr && info->workaddr[0]) || (info->workcity && info->workcity[0]) || (info->workstate && info->workstate[0]) || (info->workzip && info->workzip[0])) { purple_notify_user_info_add_section_header(user_info, _("Work Address")); - oscar_user_info_convert_and_add(account, user_info, _("Address"), info->workaddr); - oscar_user_info_convert_and_add(account, user_info, _("City"), info->workcity); - oscar_user_info_convert_and_add(account, user_info, _("State"), info->workstate); - oscar_user_info_convert_and_add(account, user_info, _("Zip Code"), info->workzip); + oscar_user_info_convert_and_add(account, od, user_info, _("Address"), info->workaddr); + oscar_user_info_convert_and_add(account, od, user_info, _("City"), info->workcity); + oscar_user_info_convert_and_add(account, od, user_info, _("State"), info->workstate); + oscar_user_info_convert_and_add(account, od, user_info, _("Zip Code"), info->workzip); } if ((info->workcompany && info->workcompany[0]) || (info->workdivision && info->workdivision[0]) || (info->workposition && info->workposition[0]) || (info->workwebpage && info->workwebpage[0])) { purple_notify_user_info_add_section_header(user_info, _("Work Information")); - oscar_user_info_convert_and_add(account, user_info, _("Company"), info->workcompany); - oscar_user_info_convert_and_add(account, user_info, _("Division"), info->workdivision); - oscar_user_info_convert_and_add(account, user_info, _("Position"), info->workposition); - - if (info->workwebpage && info->workwebpage[0] && (utf8 = oscar_utf8_try_convert(account, info->workwebpage))) { + oscar_user_info_convert_and_add(account, od, user_info, _("Company"), info->workcompany); + oscar_user_info_convert_and_add(account, od, user_info, _("Division"), info->workdivision); + oscar_user_info_convert_and_add(account, od, user_info, _("Position"), info->workposition); + + if (info->workwebpage && info->workwebpage[0] && (utf8 = oscar_utf8_try_convert(account, od, info->workwebpage))) { char *webpage = g_strdup_printf("<a href=\"%s\">%s</a>", utf8, utf8); purple_notify_user_info_add_pair(user_info, _("Web Page"), webpage); g_free(webpage); @@ -4296,7 +4244,7 @@ info = va_arg(ap, struct aim_icq_info *); va_end(ap); - if (info->uin && info->nick && info->nick[0] && (utf8 = oscar_utf8_try_convert(account, info->nick))) { + if (info->uin && info->nick && info->nick[0] && (utf8 = oscar_utf8_try_convert(account, od, info->nick))) { g_snprintf(who, sizeof(who), "%u", info->uin); serv_got_alias(gc, who, utf8); if ((b = purple_find_buddy(account, who))) { @@ -4751,7 +4699,7 @@ /* Messaging an SMS (mobile) user */ tmp2 = purple_markup_strip_html(tmp1); is_html = FALSE; - } else if (oscar_util_valid_name_icq(purple_account_get_username(account))) { + } else if (od->icq) { if (oscar_util_valid_name_icq(name)) { /* From ICQ to ICQ */ tmp2 = purple_markup_strip_html(tmp1); @@ -5047,6 +4995,9 @@ void oscar_set_status(PurpleAccount *account, PurpleStatus *status) { + PurpleConnection *pc; + OscarData *od; + purple_debug_info("oscar", "Set status to %s\n", purple_status_get_name(status)); if (!purple_status_is_active(status)) @@ -5055,11 +5006,14 @@ if (!purple_account_is_connected(account)) return; + pc = purple_account_get_connection(account); + od = purple_connection_get_protocol_data(pc); + /* Set the AIM-style away message for both AIM and ICQ accounts */ oscar_set_info_and_status(account, FALSE, NULL, TRUE, status); /* Set the ICQ status for ICQ accounts only */ - if (oscar_util_valid_name_icq(purple_account_get_username(account))) + if (od->icq) oscar_set_status_icq(account); } @@ -5404,7 +5358,7 @@ if (g_utf8_validate(gname, -1, NULL)) gname_utf8 = g_strdup(gname); else - gname_utf8 = oscar_utf8_try_convert(account, gname); + gname_utf8 = oscar_utf8_try_convert(account, od, gname); } else gname_utf8 = NULL; @@ -5419,7 +5373,7 @@ if (g_utf8_validate(alias, -1, NULL)) alias_utf8 = g_strdup(alias); else - alias_utf8 = oscar_utf8_try_convert(account, alias); + alias_utf8 = oscar_utf8_try_convert(account, od, alias); g_free(alias); } else alias_utf8 = NULL; @@ -5468,7 +5422,7 @@ if (g_utf8_validate(gname, -1, NULL)) gname_utf8 = g_strdup(gname); else - gname_utf8 = oscar_utf8_try_convert(account, gname); + gname_utf8 = oscar_utf8_try_convert(account, od, gname); } else gname_utf8 = NULL; @@ -5636,7 +5590,7 @@ return 1; gname = aim_ssi_itemlist_findparentname(od->ssi.local, name); - gname_utf8 = gname ? oscar_utf8_try_convert(account, gname) : NULL; + gname_utf8 = gname ? oscar_utf8_try_convert(account, od, gname) : NULL; alias = aim_ssi_getalias(od->ssi.local, gname, name); if (alias != NULL) @@ -5644,7 +5598,7 @@ if (g_utf8_validate(alias, -1, NULL)) alias_utf8 = g_strdup(alias); else - alias_utf8 = oscar_utf8_try_convert(account, alias); + alias_utf8 = oscar_utf8_try_convert(account, od, alias); } else alias_utf8 = NULL; @@ -6417,7 +6371,7 @@ data = g_new(struct name_data, 1); comment = aim_ssi_getcomment(od->ssi.local, purple_group_get_name(g), name); - comment_utf8 = comment ? oscar_utf8_try_convert(account, comment) : NULL; + comment_utf8 = comment ? oscar_utf8_try_convert(account, od, comment) : NULL; data->gc = gc; data->name = g_strdup(name);
--- a/libpurple/protocols/oscar/oscar.h Thu Feb 04 20:57:01 2010 +0000 +++ b/libpurple/protocols/oscar/oscar.h Sat Feb 06 05:15:35 2010 +0000 @@ -445,6 +445,8 @@ guint16 seqnum_in; /**< The sequence number of most recently received packet. */ GSList *groups; GSList *rateclasses; /* Contains nodes of struct rateclass. */ + struct rateclass *default_rateclass; + GHashTable *rateclass_members; /* Key is family and subtype, value is pointer to the rateclass struct to use. */ GQueue *queued_snacs; /**< Contains QueuedSnacs. */ GQueue *queued_lowpriority_snacs; /**< Contains QueuedSnacs to send only once queued_snacs is empty */ @@ -1685,9 +1687,7 @@ guint32 disconnect; guint32 current; guint32 max; - guint32 delta; guint8 dropping_snacs; - GHashTable *members; /* Key is family and subtype, value is TRUE. */ struct timeval last; /**< The time when we last sent a SNAC of this rate class. */ };
--- a/libpurple/protocols/qq/Makefile.am Thu Feb 04 20:57:01 2010 +0000 +++ b/libpurple/protocols/qq/Makefile.am Sat Feb 06 05:15:35 2010 +0000 @@ -65,12 +65,19 @@ else st = +noinst_LTLIBRARIES = pkg_LTLIBRARIES = libqq.la libqq_la_SOURCES = $(QQSOURCES) libqq_la_LIBADD = $(GLIB_LIBS) endif +# For 'make check' +noinst_LTLIBRARIES += libqq_tmp.la +libqq_tmp_la_SOURCES = $(libqq_la_SOURCES) +libqq_tmp_la_LIBADD = $(libqq_la_LIBADD) + + # QQ_BUDDY_ICON_DIR is the path where a bunch of stock icons can be # places for users to choose from when setting their buddy icon. We # don't distribute those icons ourselves because of possibly copyright
--- a/libpurple/protocols/yahoo/util.c Thu Feb 04 20:57:01 2010 +0000 +++ b/libpurple/protocols/yahoo/util.c Sat Feb 06 05:15:35 2010 +0000 @@ -884,6 +884,8 @@ } g_free(etag); } + } else if (g_str_equal(tag_name, "span") || g_str_equal(tag_name, "/span")) { + /* Do nothing */ } else { /* We don't know what the tag is. Send it unmodified. */ g_string_append(dest, tag);
--- a/libpurple/purple-uninstalled.pc.in Thu Feb 04 20:57:01 2010 +0000 +++ b/libpurple/purple-uninstalled.pc.in Sat Feb 06 05:15:35 2010 +0000 @@ -6,9 +6,12 @@ datadir=@datadir@ sysconfdir=@sysconfdir@ +abs_srcdir=@abs_srcdir@ +abs_builddir=@abs_builddir@ + Name: libpurple Description: libpurple is a GLib-based instant messenger library. Version: @VERSION@ Requires: glib-2.0 -Cflags: -I${pcfiledir} -Libs: ${pcfiledir}/libpurple.la +Cflags: -I${abs_srcdir} -I${abs_builddir} +Libs: ${abs_builddir}/libpurple.la
--- a/libpurple/tests/Makefile.am Thu Feb 04 20:57:01 2010 +0000 +++ b/libpurple/tests/Makefile.am Sat Feb 06 05:15:35 2010 +0000 @@ -28,7 +28,7 @@ check_libpurple_LDADD=\ $(top_builddir)/libpurple/protocols/jabber/libjabber.la \ - $(top_builddir)/libpurple/protocols/qq/libqq.la \ + $(top_builddir)/libpurple/protocols/qq/libqq_tmp.la \ $(top_builddir)/libpurple/protocols/yahoo/libymsg.la \ $(top_builddir)/libpurple/libpurple.la \ @CHECK_LIBS@ \
--- a/libpurple/tests/test_util.c Thu Feb 04 20:57:01 2010 +0000 +++ b/libpurple/tests/test_util.c Sat Feb 06 05:15:35 2010 +0000 @@ -113,6 +113,11 @@ purple_markup_html_to_xhtml("<a>", &xhtml, &plaintext); assert_string_equal_free("<a href=\"\"></a>", xhtml); assert_string_equal_free("", plaintext); + + + purple_markup_html_to_xhtml("<FONT>x</FONT>", &xhtml, &plaintext); + assert_string_equal_free("x", xhtml); + assert_string_equal_free("x", plaintext); } END_TEST
--- a/libpurple/util.c Thu Feb 04 20:57:01 2010 +0000 +++ b/libpurple/util.c Sat Feb 06 05:15:35 2010 +0000 @@ -1519,7 +1519,7 @@ if(tag) { while(tags) { struct purple_parse_tag *pt = tags->data; - if(xhtml) + if(xhtml && !pt->ignore) g_string_append_printf(xhtml, "</%s>", pt->dest_tag); if(plain && purple_strequal(pt->src_tag, "a")) { /* if this is a link, we have to add the url to the plaintext, too */
--- a/pidgin/gtkaccount.c Thu Feb 04 20:57:01 2010 +0000 +++ b/pidgin/gtkaccount.c Sat Feb 06 05:15:35 2010 +0000 @@ -381,6 +381,7 @@ static void update_editable(PurpleConnection *gc, AccountPrefsDialog *dialog) { + GtkStyle *style; gboolean set; GList *l; @@ -392,10 +393,21 @@ set = !(purple_account_is_connected(dialog->account) || purple_account_is_connecting(dialog->account)); gtk_widget_set_sensitive(dialog->protocol_menu, set); - gtk_widget_set_sensitive(dialog->username_entry, set); - - for (l = dialog->user_split_entries ; l != NULL ; l = l->next) - gtk_widget_set_sensitive((GtkWidget *)l->data, set); + gtk_editable_set_editable(GTK_EDITABLE(dialog->username_entry), set); + style = set ? NULL : gtk_widget_get_style(dialog->username_entry); + gtk_widget_modify_base(dialog->username_entry, GTK_STATE_NORMAL, + style ? &style->base[GTK_STATE_INSENSITIVE] : NULL); + + for (l = dialog->user_split_entries ; l != NULL ; l = l->next) { + if (GTK_IS_EDITABLE(l->data)) { + gtk_editable_set_editable(GTK_EDITABLE(l->data), set); + style = set ? NULL : gtk_widget_get_style(GTK_WIDGET(l->data)); + gtk_widget_modify_base(GTK_WIDGET(l->data), GTK_STATE_NORMAL, + style ? &style->base[GTK_STATE_INSENSITIVE] : NULL); + } else { + gtk_widget_set_sensitive(GTK_WIDGET(l->data), set); + } + } } static void
--- a/pidgin/gtkblist-theme-loader.c Thu Feb 04 20:57:01 2010 +0000 +++ b/pidgin/gtkblist-theme-loader.c Sat Feb 06 05:15:35 2010 +0000 @@ -58,6 +58,20 @@ return pidgin_theme_font_new(font, &color); } +static GdkColor * +parse_color(xmlnode *node, const char *tag) +{ + const char *temp = xmlnode_get_attrib(node, tag); + GdkColor color; + + if (temp && gdk_color_parse(temp, &color)) { + gdk_colormap_alloc_color(gdk_colormap_get_system(), &color, FALSE, TRUE); + return gdk_color_copy(&color); + } else { + return NULL; + } +} + static PurpleTheme * pidgin_blist_loader_build(const gchar *dir) { @@ -65,7 +79,7 @@ gchar *filename_full, *data = NULL; const gchar *temp, *name; gboolean success = TRUE; - GdkColor bgcolor, expanded_bgcolor, collapsed_bgcolor, contact_color; + GdkColor *bgcolor, *expanded_bgcolor, *collapsed_bgcolor, *contact_color; PidginThemeFont *expanded, *collapsed, *contact, *online, *away, *offline, *idle, *message, *message_nick_said, *status; PidginBlistLayout layout; PidginBlistTheme *theme; @@ -119,14 +133,10 @@ purple_debug_warning("gtkblist-theme-loader", "Missing attribute or problem with the root element\n"); if (success) { - if ((success = (sub_node = xmlnode_get_child(root_node, "blist")) != NULL)) { - - if ((temp = xmlnode_get_attrib(sub_node, "color")) != NULL && gdk_color_parse(temp, &bgcolor)) - gdk_colormap_alloc_color(gdk_colormap_get_system(), &bgcolor, FALSE, TRUE); - else - memset(&bgcolor, 0, sizeof(GdkColor)); - - } else purple_debug_warning("gtkblist-theme-loader", "Missing or problem with tags: <blist>.\n"); + if ((success = (sub_node = xmlnode_get_child(root_node, "blist")) != NULL)) + bgcolor = parse_color(sub_node, "color"); + else + purple_debug_warning("gtkblist-theme-loader", "Missing or problem with tags: <blist>.\n"); } /* <groups> */ @@ -134,26 +144,17 @@ if ((success = (sub_node = xmlnode_get_child(root_node, "groups")) != NULL && (sub_sub_node = xmlnode_get_child(sub_node, "expanded")) != NULL)) { expanded = pidgin_theme_font_parse(sub_sub_node); - - if ((temp = xmlnode_get_attrib(sub_sub_node, "background")) != NULL && gdk_color_parse(temp, &expanded_bgcolor)) - gdk_colormap_alloc_color(gdk_colormap_get_system(), &expanded_bgcolor, FALSE, TRUE); - else - memset(&expanded_bgcolor, 0, sizeof(GdkColor)); - - } else purple_debug_warning("gtkblist-theme-loader", "Missing or problem with tags: <groups> <expanded>.\n"); + expanded_bgcolor = parse_color(sub_sub_node, "background"); + } else + purple_debug_warning("gtkblist-theme-loader", "Missing or problem with tags: <groups> <expanded>.\n"); } if (success) { if ((success = sub_node != NULL && (sub_sub_node = xmlnode_get_child(sub_node, "collapsed")) != NULL)) { - collapsed = pidgin_theme_font_parse(sub_sub_node); - - if ((temp = xmlnode_get_attrib(sub_sub_node, "background")) != NULL && gdk_color_parse(temp, &collapsed_bgcolor)) - gdk_colormap_alloc_color(gdk_colormap_get_system(), &collapsed_bgcolor, FALSE, TRUE); - else - memset(&collapsed_bgcolor, 0, sizeof(GdkColor)); - - } else purple_debug_warning("gtkblist-theme-loader", "Missing or problem with tags: <groups> <collapsed>.\n"); + collapsed_bgcolor = parse_color(sub_sub_node, "background"); + } else + purple_debug_warning("gtkblist-theme-loader", "Missing or problem with tags: <groups> <collapsed>.\n"); } /* <buddys> */ @@ -172,13 +173,10 @@ } if (success) { - if ((success = (sub_node != NULL && (sub_sub_node = xmlnode_get_child(sub_node, "background")) != NULL))) { - if(gdk_color_parse(xmlnode_get_attrib(sub_sub_node, "color"), &contact_color)) - gdk_colormap_alloc_color(gdk_colormap_get_system(), &contact_color, FALSE, TRUE); - else - memset(&contact_color, 0, sizeof(GdkColor)); - - } else purple_debug_warning("gtkblist-theme-loader", "Missing or problem with tags: <buddys> <background>.\n"); + if ((success = (sub_node != NULL && (sub_sub_node = xmlnode_get_child(sub_node, "background")) != NULL))) + contact_color = parse_color(sub_sub_node, "color"); + else + purple_debug_warning("gtkblist-theme-loader", "Missing or problem with tags: <buddys> <background>.\n"); } for (i = 0; success && lookups[i].tag; i++) { @@ -201,13 +199,13 @@ "image", xmlnode_get_attrib(root_node, "image"), "directory", dir, "description", data, - "background-color", &bgcolor, + "background-color", bgcolor, "layout", &layout, - "expanded-color", &expanded_bgcolor, + "expanded-color", expanded_bgcolor, "expanded-text", expanded, - "collapsed-color", &collapsed_bgcolor, + "collapsed-color", collapsed_bgcolor, "collapsed-text", collapsed, - "contact-color", &contact_color, + "contact-color", contact_color, "contact", contact, "online", online, "away", away, @@ -235,6 +233,15 @@ theme = NULL; } + if (bgcolor) + gdk_color_free(bgcolor); + if (expanded_bgcolor) + gdk_color_free(expanded_bgcolor); + if (collapsed_bgcolor) + gdk_color_free(collapsed_bgcolor); + if (contact_color) + gdk_color_free(contact_color); + return PURPLE_THEME(theme); }
--- a/pidgin/gtkblist-theme.c Thu Feb 04 20:57:01 2010 +0000 +++ b/pidgin/gtkblist-theme.c Sat Feb 06 05:15:35 2010 +0000 @@ -133,7 +133,7 @@ copy->font = g_strdup(pair->font); strncpy(copy->color, pair->color, sizeof(copy->color) - 1); if (pair->gdkcolor) - copy->gdkcolor = gdk_color_copy(pair->gdkcolor); + copy->gdkcolor = pair->gdkcolor ? gdk_color_copy(pair->gdkcolor) : NULL; return copy; } @@ -704,7 +704,7 @@ if (priv->bgcolor) gdk_color_free(priv->bgcolor); - priv->bgcolor = gdk_color_copy(color); + priv->bgcolor = color ? gdk_color_copy(color) : NULL; } void @@ -743,7 +743,7 @@ if (priv->expanded_color) gdk_color_free(priv->expanded_color); - priv->expanded_color = gdk_color_copy(color); + priv->expanded_color = color ? gdk_color_copy(color) : NULL; } void @@ -770,7 +770,7 @@ if (priv->collapsed_color) gdk_color_free(priv->collapsed_color); - priv->collapsed_color = gdk_color_copy(color); + priv->collapsed_color = color ? gdk_color_copy(color) : NULL; } void @@ -797,7 +797,7 @@ if (priv->contact_color) gdk_color_free(priv->contact_color); - priv->contact_color = gdk_color_copy(color); + priv->contact_color = color ? gdk_color_copy(color) : NULL; } void
--- a/pidgin/gtkblist.c Thu Feb 04 20:57:01 2010 +0000 +++ b/pidgin/gtkblist.c Sat Feb 06 05:15:35 2010 +0000 @@ -470,6 +470,9 @@ case PURPLE_BLIST_GROUP_NODE: text = purple_group_get_name(PURPLE_GROUP(node)); break; + case PURPLE_BLIST_CHAT_NODE: + text = purple_chat_get_name(PURPLE_CHAT(node)); + break; default: g_return_if_reached(); } @@ -5613,6 +5616,51 @@ } +static gboolean +pidgin_blist_search_equal_func(GtkTreeModel *model, gint column, + const gchar *key, GtkTreeIter *iter, gpointer data) +{ + PurpleBlistNode *node = NULL; + gboolean res = TRUE; + const char *compare = NULL; + + if (!pidgin_tree_view_search_equal_func(model, column, key, iter, data)) + return FALSE; + + /* If the search string does not match the displayed label, then look + * at the alternate labels for the nodes and search in them. Currently, + * alternate labels that make sense are usernames/email addresses for + * buddies (but only for the ones who don't have a local alias). + */ + + gtk_tree_model_get(model, iter, NODE_COLUMN, &node, -1); + if (!node) + return TRUE; + + compare = NULL; + if (PURPLE_BLIST_NODE_IS_CONTACT(node)) { + PurpleBuddy *b = purple_contact_get_priority_buddy(PURPLE_CONTACT(node)); + if (!purple_buddy_get_local_buddy_alias(b)) + compare = purple_buddy_get_name(b); + } else if (PURPLE_BLIST_NODE_IS_BUDDY(node)) { + if (!purple_buddy_get_local_buddy_alias(PURPLE_BUDDY(node))) + compare = purple_buddy_get_name(PURPLE_BUDDY(node)); + } + + if (compare) { + char *tmp, *enteredstring; + tmp = g_utf8_normalize(key, -1, G_NORMALIZE_DEFAULT); + enteredstring = g_utf8_casefold(tmp, -1); + g_free(tmp); + + if (purple_str_has_prefix(compare, enteredstring)) + res = FALSE; + g_free(enteredstring); + } + + return res; +} + static void pidgin_blist_show(PurpleBuddyList *list) { PidginBuddyListPrivate *priv; @@ -5849,7 +5897,8 @@ /* Enable CTRL+F searching */ gtk_tree_view_set_search_column(GTK_TREE_VIEW(gtkblist->treeview), NAME_COLUMN); - gtk_tree_view_set_search_equal_func(GTK_TREE_VIEW(gtkblist->treeview), pidgin_tree_view_search_equal_func, NULL, NULL); + gtk_tree_view_set_search_equal_func(GTK_TREE_VIEW(gtkblist->treeview), + pidgin_blist_search_equal_func, NULL, NULL); gtk_box_pack_start(GTK_BOX(gtkblist->vbox), sw, TRUE, TRUE, 0); gtk_container_add(GTK_CONTAINER(sw), gtkblist->treeview);
--- a/pidgin/gtkconv.c Thu Feb 04 20:57:01 2010 +0000 +++ b/pidgin/gtkconv.c Sat Feb 06 05:15:35 2010 +0000 @@ -497,17 +497,15 @@ prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); if ((prpl_info != NULL) && (prpl_info->options & OPT_PROTO_SLASH_COMMANDS_NATIVE)) { - char *firstspace; - char *slash; - - firstspace = strchr(cmdline, ' '); - if (firstspace != NULL) { - slash = strrchr(firstspace, '/'); - } else { - slash = strchr(cmdline, '/'); - } - - if (slash == NULL) { + char *spaceslash; + + /* If the first word in the entered text has a '/' in it, then the user + * probably didn't mean it as a command. So send the text as message. */ + spaceslash = cmdline; + while (*spaceslash && *spaceslash != ' ' && *spaceslash != '/') + spaceslash++; + + if (*spaceslash != '/') { purple_conversation_write(conv, "", _("Unknown command."), PURPLE_MESSAGE_NO_LOG, time(NULL)); retval = TRUE; } @@ -4652,6 +4650,8 @@ int max_height = total_height / 2; int min_lines = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/minimum_entry_lines"); int min_height; + gboolean interior_focus; + int focus_width; pad_top = gtk_text_view_get_pixels_above_lines(GTK_TEXT_VIEW(gtkconv->entry)); pad_bottom = gtk_text_view_get_pixels_below_lines(GTK_TEXT_VIEW(gtkconv->entry)); @@ -4678,6 +4678,13 @@ min_height = min_lines * (oneline.height + MAX(pad_inside, pad_top + pad_bottom)); height = CLAMP(height, MIN(min_height, max_height), max_height); + gtk_widget_style_get(gtkconv->entry, + "interior-focus", &interior_focus, + "focus-line-width", &focus_width, + NULL); + if (!interior_focus) + height += 2 * focus_width; + diff = height - gtkconv->entry->allocation.height; if (ABS(diff) < oneline.height / 2) return FALSE; @@ -5493,10 +5500,12 @@ } /* Somebody wants to keep this conversation around, so don't time it out */ - timer = GPOINTER_TO_INT(purple_conversation_get_data(conv, "close-timer")); - if (timer) { - purple_timeout_remove(timer); - purple_conversation_set_data(conv, "close-timer", GINT_TO_POINTER(0)); + if (conv) { + timer = GPOINTER_TO_INT(purple_conversation_get_data(conv, "close-timer")); + if (timer) { + purple_timeout_remove(timer); + purple_conversation_set_data(conv, "close-timer", GINT_TO_POINTER(0)); + } } } @@ -7622,16 +7631,24 @@ } } +struct _status_timeout_user { + gchar *name; + PurpleAccount *account; +}; + static gboolean -update_buddy_status_timeout(PurpleBuddy *buddy) +update_buddy_status_timeout(struct _status_timeout_user *user) { /* To remove the signing-on/off door icon */ PurpleConversation *conv; - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, buddy->name, buddy->account); + conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, user->name, user->account); if (conv) pidgin_conv_update_fields(conv, PIDGIN_CONV_TAB_ICON); + g_free(user->name); + g_free(user); + return FALSE; } @@ -7640,6 +7657,7 @@ { PidginConversation *gtkconv; PurpleConversation *conv; + struct _status_timeout_user *user; gtkconv = get_gtkconv_with_contact(purple_buddy_get_contact(buddy)); if (gtkconv) @@ -7652,8 +7670,12 @@ pidgin_conv_update_fields(conv, PIDGIN_CONV_MENU); } + user = g_malloc(sizeof(struct _status_timeout_user)); + user->name = g_strdup(buddy->name); + user->account = buddy->account; + /* In case a conversation is started after the buddy has signed-on/off */ - purple_timeout_add_seconds(11, (GSourceFunc)update_buddy_status_timeout, buddy); + purple_timeout_add_seconds(11, (GSourceFunc)update_buddy_status_timeout, user); } static void @@ -9484,6 +9506,24 @@ return FALSE; } +static gboolean +gtkconv_tab_set_tip(GtkWidget *widget, GdkEventCrossing *event, PidginConversation *gtkconv) +{ +#if GTK_CHECK_VERSION(2, 12, 0) +#define gtk_tooltips_set_tip(tips, w, l, p) gtk_widget_set_tooltip_text(w, l) +#endif + PangoLayout *layout; + + layout = gtk_label_get_layout(GTK_LABEL(gtkconv->tab_label)); + gtk_tooltips_set_tip(gtkconv->tooltips, widget, + pango_layout_is_ellipsized(layout) ? gtk_label_get_text(GTK_LABEL(gtkconv->tab_label)) : NULL, + NULL); + return FALSE; +#if GTK_CHECK_VERSION(2, 12, 0) +#undef gtk_tooltips_set_tip +#endif +} + void pidgin_conv_window_add_gtkconv(PidginWindow *win, PidginConversation *gtkconv) { @@ -9642,6 +9682,8 @@ gtk_event_box_set_visible_window(GTK_EVENT_BOX(ebox), FALSE); #endif gtk_container_add(GTK_CONTAINER(ebox), gtkconv->tabby); + g_signal_connect(G_OBJECT(ebox), "enter-notify-event", + G_CALLBACK(gtkconv_tab_set_tip), gtkconv); if (gtkconv->tab_label->parent == NULL) { /* Pack if it's a new widget */
--- a/pidgin/gtkdebug.c Thu Feb 04 20:57:01 2010 +0000 +++ b/pidgin/gtkdebug.c Sat Feb 06 05:15:35 2010 +0000 @@ -766,11 +766,12 @@ gtk_toolbar_insert_space(GTK_TOOLBAR(toolbar), -1); /* regex toggle button */ + image = gtk_image_new_from_stock(GTK_STOCK_FIND, GTK_ICON_SIZE_MENU); win->filter = gtk_toolbar_append_element(GTK_TOOLBAR(toolbar), GTK_TOOLBAR_CHILD_TOGGLEBUTTON, NULL, _("Filter"), _("Filter"), - NULL, NULL, + NULL, image, G_CALLBACK(regex_filter_toggled_cb), win); /* we purposely disable the toggle button here in case
--- a/pidgin/gtkdialogs.c Thu Feb 04 20:57:01 2010 +0000 +++ b/pidgin/gtkdialogs.c Sat Feb 06 05:15:35 2010 +0000 @@ -197,11 +197,11 @@ {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_("Mongolian"), "mn", "gooyo", NULL}, + {N_("Marathi"), "mr", "Sandeep Shedmake", "sandeep.shedmake@gmail.com"}, {N_("Malay"), "ms_MY", "Muhammad Najmi bin Ahmad Zabidi", "najmi.zabidi@gmail.com"}, {N_("Bokmål Norwegian"), "nb", "Hans Fredrik Nordhaug", "hans@nordhaug.priv.no"}, {N_("Nepali"), "ne", "Shyam Krishna Bal", "shyamkrishna_bal@yahoo.com"}, @@ -276,8 +276,9 @@ {N_("Georgian"), "ka", "Temuri Doghonadze", NULL}, {N_("Korean"), "ko", "Sang-hyun S, A Ho-seok Lee", NULL}, {N_("Korean"), "ko", "Kyeong-uk Son", NULL}, + {N_("Lithuanian"), "lt", "Laurynas Biveinis", "laurynas.biveinis@gmail.com"}, + {N_("Lithuanian"), "lt", "Gediminas Čičinskas", NULL}, {N_("Lithuanian"), "lt", "Andrius Štikonas", NULL}, - {N_("Lithuanian"), "lt", "Gediminas Čičinskas", NULL}, {N_("Macedonian"), "mk", "Tomislav Markovski", NULL}, {N_("Bokmål Norwegian"), "nb", "Hallvard Glad", "hallvard.glad@gmail.com"}, {N_("Bokmål Norwegian"), "nb", "Petter Johan Olsen", NULL},
--- a/pidgin/gtkft.c Thu Feb 04 20:57:01 2010 +0000 +++ b/pidgin/gtkft.c Sat Feb 06 05:15:35 2010 +0000 @@ -730,6 +730,7 @@ GtkWidget *sw; GtkWidget *button; GtkWidget *expander; + GtkWidget *alignment; GtkWidget *table; GtkWidget *checkbox; @@ -787,9 +788,15 @@ gtk_widget_set_sensitive(expander, FALSE); + /* Small indent make table fall under GtkExpander's label */ + alignment = gtk_alignment_new(1, 0, 1, 1); + gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 0, 0, 20, 0); + gtk_container_add(GTK_CONTAINER(expander), alignment); + gtk_widget_show(alignment); + /* The table of information. */ table = make_info_table(dialog); - gtk_container_add(GTK_CONTAINER(expander), table); + gtk_container_add(GTK_CONTAINER(alignment), table); gtk_widget_show(table); /* Open button */
--- a/pidgin/gtkimhtml.c Thu Feb 04 20:57:01 2010 +0000 +++ b/pidgin/gtkimhtml.c Sat Feb 06 05:15:35 2010 +0000 @@ -549,6 +549,7 @@ imhtml->tip_timer = 0; imhtml->tip_window = gtk_window_new (GTK_WINDOW_POPUP); gtk_widget_set_app_paintable (imhtml->tip_window, TRUE); + gtk_window_set_title(GTK_WINDOW(imhtml->tip_window), "GtkIMHtml"); gtk_window_set_resizable (GTK_WINDOW (imhtml->tip_window), FALSE); gtk_widget_set_name (imhtml->tip_window, "gtk-tooltips"); #if GTK_CHECK_VERSION(2,10,0) @@ -4933,7 +4934,9 @@ mark = gtk_text_buffer_get_insert(imhtml->text_buffer); gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, mark); + gtk_text_buffer_begin_user_action(imhtml->text_buffer); gtk_imhtml_insert_smiley_at_iter(imhtml, sml, smiley, &iter); + gtk_text_buffer_end_user_action(imhtml->text_buffer); } static gboolean
--- a/pidgin/gtklog.c Thu Feb 04 20:57:01 2010 +0000 +++ b/pidgin/gtklog.c Sat Feb 06 05:15:35 2010 +0000 @@ -423,6 +423,7 @@ { PidginLogViewer *viewer = data; gtk_imhtml_search_find(GTK_IMHTML(viewer->imhtml), viewer->search); + g_object_steal_data(G_OBJECT(viewer->entry), "search-find-cb"); return FALSE; } @@ -475,8 +476,11 @@ g_free(read); if (viewer->search != NULL) { + guint source; gtk_imhtml_search_clear(GTK_IMHTML(viewer->imhtml)); - g_idle_add(search_find_cb, viewer); + source = g_idle_add(search_find_cb, viewer); + g_object_set_data_full(G_OBJECT(viewer->entry), "search-find-cb", + GINT_TO_POINTER(source), (GDestroyNotify)g_source_remove); } pidgin_clear_cursor(viewer->window);
--- a/pidgin/gtkprefs.c Thu Feb 04 20:57:01 2010 +0000 +++ b/pidgin/gtkprefs.c Sat Feb 06 05:15:35 2010 +0000 @@ -70,27 +70,33 @@ gchar *original_name; }; -static int sound_row_sel = 0; -static GtkWidget *prefsnotebook; - +/* Main dialog */ +static GtkWidget *prefs = NULL; + +/* Notebook */ +static GtkWidget *prefsnotebook = NULL; +static int notebook_page = 0; + +/* Conversations page */ +static GtkWidget *sample_imhtml = NULL; + +/* Themes page */ +static GtkWidget *prefs_sound_themes_combo_box; +static GtkWidget *prefs_blist_themes_combo_box; +static GtkWidget *prefs_status_themes_combo_box; +static GtkWidget *prefs_smiley_themes_combo_box; + +/* Sound theme specific */ static GtkWidget *sound_entry = NULL; - -static GtkWidget *prefs = NULL; -static GtkWidget *debugbutton = NULL; -static int notebook_page = 0; - +static int sound_row_sel = 0; +static gboolean prefs_sound_themes_loading; + +/* These exist outside the lifetime of the prefs dialog */ static GtkListStore *prefs_sound_themes; static GtkListStore *prefs_blist_themes; static GtkListStore *prefs_status_icon_themes; static GtkListStore *prefs_smiley_themes; -static GtkWidget *prefs_sound_themes_combo_box; -static GtkWidget *prefs_blist_themes_combo_box; -static GtkWidget *prefs_status_themes_combo_box; -static GtkWidget *prefs_smiley_themes_combo_box; - -static gboolean prefs_sound_themes_loading; - /* * PROTOTYPES */ @@ -334,10 +340,21 @@ /* Unregister callbacks. */ purple_prefs_disconnect_by_handle(prefs); - prefs = NULL; + /* NULL-ify globals */ sound_entry = NULL; - debugbutton = NULL; + sound_row_sel = 0; + prefs_sound_themes_loading = FALSE; + + prefs_sound_themes_combo_box = NULL; + prefs_blist_themes_combo_box = NULL; + prefs_status_themes_combo_box = NULL; + prefs_smiley_themes_combo_box = NULL; + + sample_imhtml = NULL; + notebook_page = 0; + prefsnotebook = NULL; + prefs = NULL; } static gchar * @@ -949,6 +966,7 @@ gtk_tree_model_get(GTK_TREE_MODEL(prefs_smiley_themes), &new_iter, 2, &new_theme, -1); purple_prefs_set_string(PIDGIN_PREFS_ROOT "/smileys/theme", new_theme); + pidgin_themes_smiley_themeize(sample_imhtml); g_free(new_theme); } @@ -1537,7 +1555,7 @@ G_CALLBACK(formatting_toggle_cb), toolbar); g_signal_connect_after(G_OBJECT(imhtml), "format_function_clear", G_CALLBACK(formatting_clear_cb), NULL); - + sample_imhtml = imhtml; gtk_widget_show(ret); @@ -2842,7 +2860,7 @@ purple_prefs_add_string(PIDGIN_PREFS_ROOT "/smileys/theme", "Default"); /* Smiley Callbacks */ - purple_prefs_connect_callback(prefs, PIDGIN_PREFS_ROOT "/smileys/theme", + purple_prefs_connect_callback(&prefs, PIDGIN_PREFS_ROOT "/smileys/theme", smiley_theme_pref_cb, NULL); pidgin_prefs_update_old();
--- a/pidgin/gtkrequest.c Thu Feb 04 20:57:01 2010 +0000 +++ b/pidgin/gtkrequest.c Sat Feb 06 05:15:35 2010 +0000 @@ -719,9 +719,25 @@ { PurpleRequestFieldGroup *group; PidginRequestData *req_data; - const char *text = gtk_entry_get_text(GTK_ENTRY(entry)); + + if (purple_request_field_string_is_multiline(field)) + { + char *text; + GtkTextIter start_iter, end_iter; + + gtk_text_buffer_get_start_iter(GTK_TEXT_BUFFER(entry), &start_iter); + gtk_text_buffer_get_end_iter(GTK_TEXT_BUFFER(entry), &end_iter); - purple_request_field_string_set_value(field, (*text == '\0' ? NULL : text)); + text = gtk_text_buffer_get_text(GTK_TEXT_BUFFER(entry), &start_iter, &end_iter, FALSE); + purple_request_field_string_set_value(field, (!text || !*text) ? NULL : text); + g_free(text); + } + else + { + const char *text = NULL; + text = gtk_entry_get_text(GTK_ENTRY(entry)); + purple_request_field_string_set_value(field, (*text == '\0') ? NULL : text); + } group = purple_request_field_get_group(field); req_data = (PidginRequestData *)group->fields_list->ui_data; @@ -824,6 +840,13 @@ g_signal_connect(G_OBJECT(textview), "focus-out-event", G_CALLBACK(field_string_focus_out_cb), field); + + if (purple_request_field_is_required(field)) + { + GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview)); + g_signal_connect(G_OBJECT(buffer), "changed", + G_CALLBACK(req_entry_field_changed_cb), field); + } } else {
--- a/pidgin/gtkstatusbox.c Thu Feb 04 20:57:01 2010 +0000 +++ b/pidgin/gtkstatusbox.c Sat Feb 06 05:15:35 2010 +0000 @@ -2541,6 +2541,8 @@ GdkRectangle oneline; int height; int pad_top, pad_inside, pad_bottom; + gboolean interior_focus; + int focus_width; if (!status_box->imhtml_visible) { @@ -2591,6 +2593,13 @@ height += (pad_top + pad_bottom) * lines; height += (pad_inside) * (display_lines - lines); + gtk_widget_style_get(status_box->imhtml, + "interior-focus", &interior_focus, + "focus-line-width", &focus_width, + NULL); + if (!interior_focus) + height += 2 * focus_width; + gtk_widget_set_size_request(status_box->vbox, -1, height + PIDGIN_HIG_BOX_SPACE); } @@ -2621,6 +2630,7 @@ gpointer data; GList *accounts = NULL, *node; int active; + gboolean wastyping = FALSE; if (!gtk_tree_model_get_iter (GTK_TREE_MODEL(status_box->dropdown_store), &iter, path)) @@ -2633,7 +2643,7 @@ TYPE_COLUMN, &type, DATA_COLUMN, &data, -1); - if (status_box->typing != 0) + if ((wastyping = (status_box->typing != 0))) purple_timeout_remove(status_box->typing); status_box->typing = 0; @@ -2657,14 +2667,18 @@ pidgin_status_editor_show(FALSE, purple_savedstatus_is_transient(saved_status) ? saved_status : NULL); - status_menu_refresh_iter(status_box, FALSE); + status_menu_refresh_iter(status_box, wastyping); + if (wastyping) + pidgin_status_box_refresh(status_box); return; } if (type == PIDGIN_STATUS_BOX_TYPE_SAVED) { pidgin_status_window_show(); - status_menu_refresh_iter(status_box, FALSE); + status_menu_refresh_iter(status_box, wastyping); + if (wastyping) + pidgin_status_box_refresh(status_box); return; } }
--- a/pidgin/gtkthemes.c Thu Feb 04 20:57:01 2010 +0000 +++ b/pidgin/gtkthemes.c Sat Feb 06 05:15:35 2010 +0000 @@ -263,7 +263,14 @@ if (buf[0] == '#' || buf[0] == '\0') continue; - + else { + int len = strlen(buf); + while (len && (buf[len - 1] == '\r' || buf[len - 1] == '\n')) + buf[--len] = '\0'; + if (len == 0) + continue; + } + i = buf; while (isspace(*i)) i++; @@ -280,25 +287,17 @@ list->smileys = g_slist_reverse(list->smileys); list = child; } else if (!g_ascii_strncasecmp(i, "Name=", strlen("Name="))) { - int len; g_free(theme->name); theme->name = g_strdup(i + strlen("Name=")); - len = strlen(theme->name); - theme->name[len-1] = 0; - if(len > 2 && theme->name[len-2] == '\r') - theme->name[len-2] = 0; } else if (!g_ascii_strncasecmp(i, "Description=", strlen("Description="))) { g_free(theme->desc); theme->desc = g_strdup(i + strlen("Description=")); - theme->desc[strlen(theme->desc)-1] = 0; } else if (!g_ascii_strncasecmp(i, "Icon=", strlen("Icon="))) { g_free(theme->icon); theme->icon = g_build_filename(dirname, i + strlen("Icon="), NULL); - theme->icon[strlen(theme->icon)-1] = 0; } else if (!g_ascii_strncasecmp(i, "Author=", strlen("Author="))) { g_free(theme->author); theme->author = g_strdup(i + strlen("Author=")); - theme->author[strlen(theme->author)-1] = 0; } else if (load && list) { gboolean hidden = FALSE; char *sfile = NULL; @@ -310,8 +309,8 @@ while (*i) { char l[64]; int li = 0; - while (!isspace(*i) && li < sizeof(l) - 1) { - if (*i == '\\' && *(i+1) != '\0' && *(i+1) != '\n' && *(i+1) != '\r') + while (*i && !isspace(*i) && li < sizeof(l) - 1) { + if (*i == '\\' && *(i+1) != '\0') i++; l[li++] = *(i++); }
--- a/pidgin/gtkutils.c Thu Feb 04 20:57:01 2010 +0000 +++ b/pidgin/gtkutils.c Sat Feb 06 05:15:35 2010 +0000 @@ -1586,8 +1586,8 @@ _("You have dragged an image"), _("You can send this image as a file transfer, " "embed it into this message, or use it as the buddy icon for this user."), - DND_FILE_TRANSFER, "OK", (GCallback)dnd_image_ok_callback, - "Cancel", (GCallback)dnd_image_cancel_callback, + DND_FILE_TRANSFER, _("OK"), (GCallback)dnd_image_ok_callback, + _("Cancel"), (GCallback)dnd_image_cancel_callback, account, who, NULL, data, _("Set as buddy icon"), DND_BUDDY_ICON, @@ -1606,8 +1606,8 @@ (ft ? _("You can send this image as a file transfer, or use it as the buddy icon for this user.") : _("You can insert this image into this message, or use it as the buddy icon for this user")), (ft ? DND_FILE_TRANSFER : DND_IM_IMAGE), - "OK", (GCallback)dnd_image_ok_callback, - "Cancel", (GCallback)dnd_image_cancel_callback, + _("OK"), (GCallback)dnd_image_ok_callback, + _("Cancel"), (GCallback)dnd_image_cancel_callback, account, who, NULL, data, _("Set as buddy icon"), DND_BUDDY_ICON, @@ -2723,6 +2723,7 @@ g_object_unref(G_OBJECT(pixbuf)); if (!success) { purple_debug_error("buddyicon", "Could not convert icon to usable format.\n"); + g_free(filename); return NULL; }
--- a/pidgin/pidgin-uninstalled.pc.in Thu Feb 04 20:57:01 2010 +0000 +++ b/pidgin/pidgin-uninstalled.pc.in Sat Feb 06 05:15:35 2010 +0000 @@ -6,8 +6,11 @@ datadir=@datadir@ sysconfdir=@sysconfdir@ +abs_srcdir=@abs_srcdir@ +abs_builddir=@abs_builddir@ + Name: Pidgin Description: Pidgin is a GTK2-based instant messenger application. Version: @VERSION@ Requires: gtk+-2.0 purple -Cflags: -I${pcfiledir} +Cflags: -I${abs_srcdir}
--- a/pidgin/plugins/timestamp.c Thu Feb 04 20:57:01 2010 +0000 +++ b/pidgin/plugins/timestamp.c Sat Feb 06 05:15:35 2010 +0000 @@ -49,25 +49,33 @@ const char *mdate; int y, height; GdkRectangle rect; + gboolean scrolled = FALSE; + GtkTextTag *tag; /* display timestamp */ mdate = purple_utf8_strftime(then == 0 ? "%H:%M" : "\n%H:%M", localtime(&now)); gtk_text_buffer_get_end_iter(buffer, &iter); - if (gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(buffer), "TIMESTAMP") == NULL) - gtk_text_buffer_create_tag(buffer, "TIMESTAMP", + /* is the view already scrolled? */ + gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect); + gtk_text_view_get_line_yrange(GTK_TEXT_VIEW(imhtml), &iter, &y, &height); + if (((y + height) - (rect.y + rect.height)) > height) + scrolled = TRUE; + + if ((tag = gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(buffer), "TIMESTAMP")) == NULL) + tag = gtk_text_buffer_create_tag(buffer, "TIMESTAMP", "foreground", "#888888", "justification", GTK_JUSTIFY_CENTER, "weight", PANGO_WEIGHT_BOLD, NULL); - gtk_text_buffer_insert_with_tags_by_name(buffer, &iter, mdate, - strlen(mdate), "TIMESTAMP", NULL); + gtk_text_buffer_insert_with_tags(buffer, &iter, mdate, + strlen(mdate), tag, NULL); /* scroll view if necessary */ gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect); gtk_text_view_get_line_yrange( GTK_TEXT_VIEW(imhtml), &iter, &y, &height); - if (((y + height) - (rect.y + rect.height)) > height && + if (!scrolled && ((y + height) - (rect.y + rect.height)) > height && gtk_text_buffer_get_char_count(buffer)) { gboolean smooth = purple_prefs_get_bool( PIDGIN_PREFS_ROOT "/conversations/use_smooth_scrolling");
--- a/pidgin/win32/nsis/translations/polish.nsh Thu Feb 04 20:57:01 2010 +0000 +++ b/pidgin/win32/nsis/translations/polish.nsh Sat Feb 06 05:15:35 2010 +0000 @@ -4,33 +4,82 @@ ;; Polish language strings for the Windows Pidgin NSIS installer. ;; Windows Code page: 1250 ;; -;; Author: Jan Eldenmalm <jan.eldenmalm@amazingports.com> -;; Version 2 -;; +;; Version 3 +;; Note: If translating this file, replace '!insertmacro PIDGIN_MACRO_DEFAULT_STRING' +;; with '!define'.