# HG changeset patch # User Sadrul Habib Chowdhury # Date 1269564231 0 # Node ID 2bdbf3fbd894bb15c9ca77fbc72380478dda830b # Parent c316749944c1d7397de36700501240096be35211# Parent 72fd8c6144a2d3e3ea369d27363ffb2b19ba8166 propagate from branch 'im.pidgin.pidgin' (head 25f95fb2f47b70980b79422c9a02be98eed376f7) to branch 'im.pidgin.cpw.qulogic.msnp16' (head 2047e8ca11ef3f4bd140cd8ab1bb4067eb531716) diff -r c316749944c1 -r 2bdbf3fbd894 COPYRIGHT --- a/COPYRIGHT Sat Mar 13 08:18:25 2010 +0000 +++ b/COPYRIGHT Fri Mar 26 00:43:51 2010 +0000 @@ -383,6 +383,7 @@ Mart Raudsepp Etan Reisner Luoh Ren-Shan +Daniele Ricci Kristian Rietveld Pekka Riikonen Tim Ringenbach diff -r c316749944c1 -r 2bdbf3fbd894 ChangeLog --- a/ChangeLog Sat Mar 13 08:18:25 2010 +0000 +++ b/ChangeLog Fri Mar 26 00:43:51 2010 +0000 @@ -4,6 +4,8 @@ General: * Changed GTK+ minimum version requirement to 2.10.0. * Changed GLib minimum version requirement to 2.12.0. + * Using the --disable-nls argument to configre now works properly. You + will no longer be forced to have intltool to configure and build. Pidgin: * Moved the "Debugging Information" section of the About box to a @@ -20,6 +22,14 @@ * The Recent Log Activity sort method for the Buddy List now distinguishes between no activity and a small amount of activity in the distant past. (Greg McNew) + * Added a menu set mood globally for all mood-supporting accounts + (currently XMPP and ICQ). + * Use standard (but small) GTK+ buttons instead of custom "X" symbol. + * Default binding of Ctrl+Shift+v to 'Paste as Plain Text' in + conversation windows. This can be changed in .gtkrc-2.0. For example, + Ctrl+v can be bound to 'Paste as Plain Text' by default. + * Plugins can now handle markup in buddy names by attaching to the signal + "drawing-buddy". (Daniele Ricci, Andrea Piccinelli) Bonjour: * Added support for IPv6. (Thanks to T_X for testing) @@ -30,13 +40,31 @@ * Minimum requirement for external libgadu is now also 1.9.0-rc2. ICQ: - * X-Status (Custom ICQ status icon) support (Andrew Ivanov, Tomáš Kebert, - Yuriy Yevgrafov, and trac users bob007, salieff, and nops) + * X-Status (Custom ICQ status icon) support. Since most of the icons + available reflect moods, this is labeled "Set Mood" on the Accounts->ICQ + Account menu. (Andrew Ivanov, Tomáš Kebert, Yuriy Yevgrafov, and trac + users bob007, salieff, and nops) + * Allow setting and displaying icons between 1x1 and 100x100 pixels. + Previously only icons between 48x48 and 52x64 were allowed. + + MSN: + * Support for version 9 of the MSN protocol has been removed. This + version is no longer supported on the servers. XMPP: * Direct messages to a specific resource only upon receipt of a message with content (as opposed to a typing notification, etc). (Thanks to rjoly for testing) + * When sending data using in-band-bytestreams, interpret the block-size + attribute as the size of the BASE64-encoded representation of the data. + * Validate the hash on incoming BoB data objects (for custom smileys etc.), + cache based per JID when the CID is not a valid hash (as specified by the + BoB XEP). + + Yahoo: + * Attempt to better handle transparent proxies interfering with HTTP-based + login. + * Fix handling of P2P packets, thus fixing the loss of some messages. version 2.6.6 (02/18/2010): libpurple: diff -r c316749944c1 -r 2bdbf3fbd894 ChangeLog.API --- a/ChangeLog.API Sat Mar 13 08:18:25 2010 +0000 +++ b/ChangeLog.API Fri Mar 26 00:43:51 2010 +0000 @@ -23,6 +23,7 @@ * ui-caps-changed media manager signal * sent-attention conversation signal * got-attention conversation signal + * PurpleMood struct in status.h Pidgin: Added: @@ -30,6 +31,8 @@ * pidgin_dialogs_developers (should not be used by anything but Pidgin) * pidgin_dialogs_translators (should not be used by anything but Pidgin) * gtk_imhtmltoolbar_switch_active_conversation + * 'paste' signal for GtkIMHtml (more in gtkimhtml-signals.dox) + * 'drawing-buddy' signal for gtkblist (more in gtkblist-signals.dox) version 2.6.6 (02/18/2010): libpurple: diff -r c316749944c1 -r 2bdbf3fbd894 ChangeLog.win32 --- a/ChangeLog.win32 Sat Mar 13 08:18:25 2010 +0000 +++ b/ChangeLog.win32 Fri Mar 26 00:43:51 2010 +0000 @@ -1,13 +1,15 @@ version 2.7.0 (??/??/????): - * Minimum required GTK+ version increased to 2.14.0 + * Updated GTK+ to 2.16.6 * Private GTK+ Runtime now used (GTK+ Installer no longer supported) + * Minimum required GTK+ version increased to 2.14.7 * Win9x no longer supported. * Crash Report files (pidgin.RPT) are now generated in the ~/.purple directory instead of the installation directory. * NSS SSL Library upgraded to 3.12.5 (thanks to Berke Viktor) * GtkSpell upgraded to 2.0.16, changing the spellchecking backend to - enchant. This means that myspell, hunspell (OpenOffice) and existing - aspell dictionaries can be used. + enchant. This means that myspell and hunspell (OpenOffice) + dictionaries can be used (previous versions' aspell dictionaries + will not work). version 2.6.6 (02/18/2010): * Installer translations for: Norwegian nynorsk diff -r c316749944c1 -r 2bdbf3fbd894 Makefile.am --- a/Makefile.am Sat Mar 13 08:18:25 2010 +0000 +++ b/Makefile.am Fri Mar 26 00:43:51 2010 +0000 @@ -71,22 +71,24 @@ gpg --verify pidgin-$(PACKAGE_VERSION).tar.gz.asc pidgin-$(PACKAGE_VERSION).tar.gz gpg --verify pidgin-$(PACKAGE_VERSION).tar.bz2.asc pidgin-$(PACKAGE_VERSION).tar.bz2 +if INSTALL_I18N +PO_DIR=po +DESKTOP_FILE=pidgin.desktop + if ENABLE_GTK appsdir = $(datadir)/applications apps_in_files = pidgin.desktop.in apps_DATA = $(apps_in_files:.desktop.in=.desktop) @INTLTOOL_DESKTOP_RULE@ GTK_DIR=pidgin -endif +endif #ENABLE_GTK + +endif #INSTALL_I18N if ENABLE_GNT GNT_DIR=finch endif -if INSTALL_I18N -PO_DIR=po -endif - # This is phony, so that we always try to rebuild it. If it succeeds # in calculating changes, it produces its target; otherwise, its # target does not exist. @@ -146,5 +148,5 @@ distuninstallcheck_listfiles = \ find . -type f -print | grep -v perl | grep -v Purple.3pm -DISTCLEANFILES= pidgin.desktop libpurple/gconf/purple.schemas intltool-extract \ +DISTCLEANFILES= $(DESKTOP_FILE) libpurple/gconf/purple.schemas intltool-extract \ intltool-merge intltool-update diff -r c316749944c1 -r 2bdbf3fbd894 Makefile.mingw --- a/Makefile.mingw Sat Mar 13 08:18:25 2010 +0000 +++ b/Makefile.mingw Fri Mar 26 00:43:51 2010 +0000 @@ -31,7 +31,7 @@ exit; \ }' VERSION) -GTK_INSTALL_VERSION = 2.14.7.0 +GTK_INSTALL_VERSION = 2.16.6.0 STRIPPED_RELEASE_DIR = $(PIDGIN_TREE_TOP)/pidgin-$(PIDGIN_VERSION)-win32bin DEBUG_SYMBOLS_DIR = $(PIDGIN_TREE_TOP)/pidgin-$(PIDGIN_VERSION)-dbgsym @@ -47,13 +47,15 @@ k5sprt32.dll \ krb5_32.dll \ libenchant.dll \ + libenchant_ispell.dll \ + libenchant_myspell.dll \ libgtkspell-0.dll \ libmeanwhile-1.dll \ libnspr4.dll \ libplc4.dll \ libplds4.dll \ libsasl.dll \ - libxml2.dll \ + libxml2-2.dll \ nss3.dll \ nssckbi.dll \ nssutil3.dll \ @@ -94,7 +96,7 @@ cp $(GTKSPELL_TOP)/bin/libgtkspell-0.dll $(PIDGIN_INSTALL_DIR)/spellcheck cp $(ENCHANT_TOP)/bin/libenchant.dll $(PIDGIN_INSTALL_DIR)/spellcheck cp -R $(ENCHANT_TOP)/lib $(PIDGIN_INSTALL_DIR)/spellcheck - cp $(WIN32_DEV_TOP)/pidgin-inst-deps-20100223/exchndl.dll $(PIDGIN_INSTALL_DIR) + cp $(WIN32_DEV_TOP)/pidgin-inst-deps-20100315/exchndl.dll $(PIDGIN_INSTALL_DIR) pidgin/win32/nsis/gtk-runtime-$(GTK_BUNDLE_VERSION).zip: pidgin/win32/nsis/generate_gtk_zip.sh `pwd` @@ -150,7 +152,7 @@ installers: installer installer_offline debug_symbols_zip installer_zip Doxyfile.mingw: Doxyfile.in - sed -e "s/@PACKAGE@/pidgin/" -e "s/@VERSION@/$(PIDGIN_VERSION)/" -e "s/@top_srcdir@/$(PIDGIN_TREE_TOP)/g" -e "s/@enable_dot@/NO/" Doxyfile.in > Doxyfile.mingw + sed -e "s/@PACKAGE@/pidgin/" -e "s/@VERSION@/$(PIDGIN_VERSION)/" -e "s/@top_srcdir@/$(PIDGIN_TREE_TOP)/g" -e "s/@enable_dot@/NO/" $< > $@ docs: Doxyfile.mingw @echo "Running doxygen..." diff -r c316749944c1 -r 2bdbf3fbd894 configure.ac --- a/configure.ac Sat Mar 13 08:18:25 2010 +0000 +++ b/configure.ac Fri Mar 26 00:43:51 2010 +0000 @@ -112,61 +112,8 @@ AC_PROG_LIBTOOL LIBTOOL="$LIBTOOL --silent" AC_PROG_INSTALL -AC_PROG_INTLTOOL PKG_PROG_PKG_CONFIG AC_FUNC_ALLOCA -GETTEXT_PACKAGE=pidgin -AC_SUBST(GETTEXT_PACKAGE) - - -# before gettexting, in case iconv matters -case "$host_os" in -darwin*) - AC_CHECK_LIB(resolv, res_query) - - AC_CHECK_HEADER(CoreFoundation/CoreFoundation.h, [ - AC_CHECK_HEADER(IOKit/IOKitLib.h, [ - AC_DEFINE(HAVE_IOKIT, 1, [Define if we have IOKit]) - LIBS="$LIBS -framework IOKit -framework CoreFoundation" - ], []) - ], []) - - AC_MSG_CHECKING([for fink]) - if test -d /sw; then - AC_MSG_RESULT([found, adding /sw to search paths]) - CPPFLAGS="$CPPFLAGS -I/sw/include" - LDFLAGS="$LDFLAGS -L/sw/lib" - else - AC_MSG_RESULT([not found]) - fi - ;; -*) - ;; -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 mr ms_MY my_MM nb ne nl nn oc or 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 -dnl AM_GLIB_GNU_GETTEXT found it. - -if test x$MSGFMT = xno -o x$MSGFMT$GMSGFMT$INTLTOOL_MSGFMT = x -then - AC_MSG_ERROR([ - -The msgfmt command is required to build libpurple. If it is installed -on your system, ensure that it is in your path. If it is not, install -GNU gettext to continue. - -If you have msgfmt installed, but for some reason this error message -is still displayed, you have encountered what appears to be a bug in -third-party configure macros. Try setting the MSGFMT environment -variable to the absolute path to your msgfmt binary and trying -configure again, like this: - -MSGFMT=/path/to/msgfmt ./configure ... -]) -fi dnl Checks for header files. AC_HEADER_STDC @@ -306,6 +253,67 @@ ]) dnl ####################################################################### +dnl # Disable creation and installation of translation files +dnl ####################################################################### +AC_ARG_ENABLE(nls, AC_HELP_STRING([--disable-nls], [disable installation of translation files]), enable_i18n="$enableval", enable_i18n=yes) + +if test x$enable_i18n = xyes; then + AC_PROG_INTLTOOL + GETTEXT_PACKAGE=pidgin + AC_SUBST(GETTEXT_PACKAGE) + + + # before gettexting, in case iconv matters + case "$host_os" in + darwin*) + AC_CHECK_LIB(resolv, res_query) + + AC_CHECK_HEADER(CoreFoundation/CoreFoundation.h, [ + AC_CHECK_HEADER(IOKit/IOKitLib.h, [ + AC_DEFINE(HAVE_IOKIT, 1, [Define if we have IOKit]) + LIBS="$LIBS -framework IOKit -framework CoreFoundation" + ], []) + ], []) + + AC_MSG_CHECKING([for fink]) + if test -d /sw; then + AC_MSG_RESULT([found, adding /sw to search paths]) + CPPFLAGS="$CPPFLAGS -I/sw/include" + LDFLAGS="$LDFLAGS -L/sw/lib" + else + AC_MSG_RESULT([not found]) + fi + ;; + *) + ;; + 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 mr ms_MY my_MM nb ne nl nn oc or 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 + dnl AM_GLIB_GNU_GETTEXT found it. + + if test x$MSGFMT = xno -o x$MSGFMT$GMSGFMT$INTLTOOL_MSGFMT = x + then + AC_MSG_ERROR([ + +The msgfmt command is required to build libpurple. If it is installed +on your system, ensure that it is in your path. If it is not, install +GNU gettext to continue. + +If you have msgfmt installed, but for some reason this error message +is still displayed, you have encountered what appears to be a bug in +third-party configure macros. Try setting the MSGFMT environment +variable to the absolute path to your msgfmt binary and trying +configure again, like this: + +MSGFMT=/path/to/msgfmt ./configure ... + ]) + fi +fi #enable_i18n + +dnl ####################################################################### dnl # Check for GLib 2.12 (required) dnl ####################################################################### PKG_CHECK_MODULES(GLIB, [glib-2.0 >= 2.12.0 gobject-2.0 gmodule-2.0 gthread-2.0], , [ @@ -2443,11 +2451,6 @@ AM_CONDITIONAL(INSTALL_PIXMAPS, test "x$enable_pixmaps" = "xyes") -dnl ####################################################################### -dnl # Disable installation of translation files -dnl ####################################################################### -AC_ARG_ENABLE(nls, AC_HELP_STRING([--disable-nls], [disable installation of translation files]), enable_i18n="$enableval", enable_i18n=yes) - AM_CONDITIONAL(INSTALL_I18N, test "x$enable_i18n" = "xyes") dnl ####################################################################### @@ -2642,7 +2645,13 @@ if test "x$enable_pixmaps" = "xno" ; then echo echo Warning: You have disabled the installation of pixmap data, but Pidgin - echo still requires installed pixmaps. Be sure you know what you\'re doing. + echo still requires installed pixmaps. Be sure you know what you are doing. +fi +if test "x$enable_i18n" = "xno" ; then + echo + echo Warning: You have disabled the building and intallation of translation + echo data. This will prevent building pidgin.desktop and the GConf schemas. + echo Be sure you know what you are doing. fi echo echo configure complete, now type \'make\' diff -r c316749944c1 -r 2bdbf3fbd894 doc/gtkblist-signals.dox --- a/doc/gtkblist-signals.dox Sat Mar 13 08:18:25 2010 +0000 +++ b/doc/gtkblist-signals.dox Fri Mar 26 00:43:51 2010 +0000 @@ -5,6 +5,7 @@ @signal gtkblist-unhiding @signal gtkblist-created @signal drawing-tooltip + @signal drawing-buddy @endsignals @see gtkblist.h @@ -53,5 +54,17 @@ @param full Whether we're doing a full tooltip for the priority buddy or a compact tooltip for a non-priority buddy. @endsignaldef + + @signaldef drawing-buddy + @signalproto +char *(*drawing-buddy)(PurpleBuddy *buddy); + @endsignalproto + @signaldesc + Emitted to allow plugins to handle markup within a buddy's name or to + override the default of no formatting for names shown in the buddy list. + @param buddy A pointer to the PurpleBuddy that will be displayed. + @return The text to display (must be allocated), or @c NULL if no + changes to the default behavior are desired. + @endsignaldef */ // vim: syntax=c.doxygen tw=75 et diff -r c316749944c1 -r 2bdbf3fbd894 doc/gtkimhtml-signals.dox --- a/doc/gtkimhtml-signals.dox Sat Mar 13 08:18:25 2010 +0000 +++ b/doc/gtkimhtml-signals.dox Fri Mar 26 00:43:51 2010 +0000 @@ -6,6 +6,7 @@ @signal format_function_clear @signal format_function_toggle @signal format_function_update + @signal paste @endsignals @see gtkimhtml.h @@ -57,6 +58,17 @@ @signaldesc Emitted when the cursor has moved and formatting has changed @param imhtml The GtkIMHtml emitting the signal. @param data User defined data. + + @signaldef paste + @signalproto +void (*paste) (GtkIMHtml *imhtml, char *format) + @endsignalproto + @signaldef Emitted when paste from the clipboard is requested. + @param imhtml The GtkIMHtml emitting the signal. + @param format If 'text', then the formatting of the clipboard content + will be removed before pasting. If empty or 'html', then + the formatting will not be removed. Any other value for + this parameter is ignored and nothing is pasted. @endsignaldef */ // vim: syntax=c.doxygen tw=75 et diff -r c316749944c1 -r 2bdbf3fbd894 doc/gtkrc-2.0 --- a/doc/gtkrc-2.0 Sat Mar 13 08:18:25 2010 +0000 +++ b/doc/gtkrc-2.0 Fri Mar 26 00:43:51 2010 +0000 @@ -81,6 +81,12 @@ bind "F2" { "format_toggle" (2) } # Ctrl-alt-shift-f3 toggles underline bind "F3" { "format_toggle" (4) } + +# Ctrl-v to paste as plain text + bind "v" { "paste" ("text") } + +# Ctrl-Shift-v for normal 'Paste' + bind "v" { "paste" ("html") } } widget "*pidgin_conv_entry" binding "my-bindings" diff -r c316749944c1 -r 2bdbf3fbd894 finch/libgnt/gntbox.c --- a/finch/libgnt/gntbox.c Sat Mar 13 08:18:25 2010 +0000 +++ b/finch/libgnt/gntbox.c Fri Mar 26 00:43:51 2010 +0000 @@ -27,6 +27,9 @@ #include +#define PROP_LAST_RESIZE_S "last-resize" +#define PROP_SIZE_QUEUED_S "size-queued" + enum { PROP_0, @@ -194,7 +197,7 @@ GntBox *box = GNT_BOX(widget); GList *iter; int maxw = 0, maxh = 0; - + g_list_foreach(box->list, (GFunc)gnt_widget_size_request, NULL); for (iter = box->list; iter; iter = iter->next) @@ -398,6 +401,7 @@ GList *iter; GntBox *box = GNT_BOX(widget); int wchange, hchange; + GntWidget *child, *last; if (!box->list) return TRUE; @@ -406,67 +410,59 @@ hchange = widget->priv.height - height; if (wchange == 0 && hchange == 0) - return TRUE; /* Quit playing games */ + return TRUE; /* Quit playing games with my size */ - /* XXX: Right now, I am trying to just apply all the changes to - * just one widget. It should be possible to distribute the - * changes to all the widgets in the box. */ - for (iter = box->list; iter; iter = iter->next) - { + child = NULL; + last = g_object_get_data(G_OBJECT(box), PROP_LAST_RESIZE_S); + + /* First, make sure all the widgets will fit into the box after resizing. */ + for (iter = box->list; iter; iter = iter->next) { GntWidget *wid = iter->data; int w, h; gnt_widget_get_size(wid, &w, &h); - if (gnt_widget_confirm_size(wid, w - wchange, h - hchange)) - { - GList *i; - - for (i = box->list; i; i = i->next) - { - int tw, th; - if (i == iter) continue; - gnt_widget_get_size(GNT_WIDGET(i->data), &tw, &th); - if (box->vertical) - { - if (!gnt_widget_confirm_size(i->data, tw - wchange, th)) { - /* If we are decreasing the size and the widget is going - * to be too large to fit into the box, then do not allow - * resizing. */ - if (wchange > 0 && tw >= widget->priv.width) - return FALSE; - } - } - else - { - if (!gnt_widget_confirm_size(i->data, tw, th - hchange)) { - if (hchange > 0 && th >= widget->priv.height) - return FALSE; - return FALSE; - } - } - } -#if 0 - gnt_widget_set_size(wid, w - wchange, h - hchange); - if (box->vertical) - hchange = 0; - else - wchange = 0; - - for (i = box->list; i; i = i->next) - { - int tw, th; - if (i == iter) continue; - gnt_widget_get_size(GNT_WIDGET(i->data), &tw, &th); - gnt_widget_set_size(i->data, tw - wchange, th - hchange); - } -#endif - g_object_set_data(G_OBJECT(box), "size-queued", wid); - return TRUE; + if (wid != last && !child && gnt_widget_confirm_size(wid, w - wchange, h - hchange)) { + child = wid; + break; } } - return FALSE; + if (!child && (child = last)) { + int w, h; + gnt_widget_get_size(child, &w, &h); + if (!gnt_widget_confirm_size(child, w - wchange, h - hchange)) + child = NULL; + } + + g_object_set_data(G_OBJECT(box), PROP_SIZE_QUEUED_S, child); + + if (child) { + for (iter = box->list; iter; iter = iter->next) { + GntWidget *wid = iter->data; + int w, h; + + gnt_widget_get_size(wid, &w, &h); + if (box->vertical) { + /* For a vertical box, if we are changing the width, make sure the widgets + * in the box will fit after resizing the width. */ + if (wchange > 0 && + w >= child->priv.width && + !gnt_widget_confirm_size(wid, w - wchange, h)) + return FALSE; + } else { + /* If we are changing the height, make sure the widgets in the box fit after + * the resize. */ + if (hchange > 0 && + h >= child->priv.height && + !gnt_widget_confirm_size(wid, w, h - hchange)) + return FALSE; + } + + } + } + + return (child != NULL); } static void @@ -477,16 +473,16 @@ GntBox *box = GNT_BOX(widget); GntWidget *wid; int tw, th; - + wchange = widget->priv.width - oldw; hchange = widget->priv.height - oldh; - - wid = g_object_get_data(G_OBJECT(box), "size-queued"); - if (wid) - { + + wid = g_object_get_data(G_OBJECT(box), PROP_SIZE_QUEUED_S); + if (wid) { gnt_widget_get_size(wid, &tw, &th); gnt_widget_set_size(wid, tw + wchange, th + hchange); - g_object_set_data(G_OBJECT(box), "size-queued", NULL); + g_object_set_data(G_OBJECT(box), PROP_SIZE_QUEUED_S, NULL); + g_object_set_data(G_OBJECT(box), PROP_LAST_RESIZE_S, wid); } if (box->vertical) diff -r c316749944c1 -r 2bdbf3fbd894 libpurple/gconf/Makefile.am --- a/libpurple/gconf/Makefile.am Sat Mar 13 08:18:25 2010 +0000 +++ b/libpurple/gconf/Makefile.am Fri Mar 26 00:43:51 2010 +0000 @@ -2,14 +2,17 @@ EXTRA_DIST = purple.schemas.in +if GCONF_SCHEMAS_INSTALL + +if INSTALL_I18N schema_in_files = purple.schemas.in schema_DATA = $(schema_in_files:.schemas.in=.schemas) @INTLTOOL_SCHEMAS_RULE@ +endif #INSTALL_I18N -if GCONF_SCHEMAS_INSTALL install-data-local: GCONF_CONFIG_SOURCE=$(GCONF_SCHEMA_CONFIG_SOURCE) $(GCONFTOOL) --makefile-install-rule $(schema_DATA) 2>&1 | \ grep -v "^WARNING: failed to install schema" | grep -v "^Attached schema" 1>&2 else install-data-local: -endif +endif #GCONF_SCHEMAS_INSTALL diff -r c316749944c1 -r 2bdbf3fbd894 libpurple/plugins/perl/common/Makefile.mingw --- a/libpurple/plugins/perl/common/Makefile.mingw Sat Mar 13 08:18:25 2010 +0000 +++ b/libpurple/plugins/perl/common/Makefile.mingw Fri Mar 26 00:43:51 2010 +0000 @@ -13,7 +13,6 @@ TARGET = Purple AUTOSPLIT = lib/auto/Purple/autosplit.ix -EXTUTILS ?= C:/perl/lib/ExtUtils PERL_PLUGIN_TOP := .. ## diff -r c316749944c1 -r 2bdbf3fbd894 libpurple/protocols/jabber/auth.c --- a/libpurple/protocols/jabber/auth.c Sat Mar 13 08:18:25 2010 +0000 +++ b/libpurple/protocols/jabber/auth.c Fri Mar 26 00:43:51 2010 +0000 @@ -287,7 +287,7 @@ x = xmlnode_new_child(query, "digest"); s = g_strdup_printf("%s%s", js->stream_id, pw); - hash = jabber_calculate_data_sha1sum(s, strlen(s)); + hash = jabber_calculate_data_hash(s, strlen(s), "sha1"); xmlnode_insert_data(x, hash, -1); g_free(hash); g_free(s); diff -r c316749944c1 -r 2bdbf3fbd894 libpurple/protocols/jabber/buddy.c --- a/libpurple/protocols/jabber/buddy.c Sat Mar 13 08:18:25 2010 +0000 +++ b/libpurple/protocols/jabber/buddy.c Fri Mar 26 00:43:51 2010 +0000 @@ -516,7 +516,8 @@ binval = xmlnode_new_child(photo, "BINVAL"); enc = purple_base64_encode(avatar_data, avatar_len); - js->avatar_hash = jabber_calculate_data_sha1sum(avatar_data, avatar_len); + js->avatar_hash = + jabber_calculate_data_hash(avatar_data, avatar_len, "sha1"); xmlnode_insert_data(binval, enc, -1); g_free(enc); @@ -936,7 +937,7 @@ g_free(bintext); if (data) { - vcard_hash = jabber_calculate_data_sha1sum(data, size); + vcard_hash = jabber_calculate_data_hash(data, size, "sha1"); g_free(data); } } @@ -1185,7 +1186,7 @@ purple_notify_user_info_add_pair(user_info, (photo ? _("Photo") : _("Logo")), img_text); - hash = jabber_calculate_data_sha1sum(data, size); + hash = jabber_calculate_data_hash(data, size, "sha1"); purple_buddy_icons_set_for_user(account, bare_jid, data, size, hash); g_free(hash); g_free(img_text); diff -r c316749944c1 -r 2bdbf3fbd894 libpurple/protocols/jabber/caps.c --- a/libpurple/protocols/jabber/caps.c Sat Mar 13 08:18:25 2010 +0000 +++ b/libpurple/protocols/jabber/caps.c Fri Mar 26 00:43:51 2010 +0000 @@ -845,19 +845,18 @@ return fields; } -static GString* -jabber_caps_verification_append(GString *verification, const gchar *str) +static void +append_escaped_string(PurpleCipherContext *context, const gchar *str) { char *tmp = g_markup_escape_text(str, -1); - verification = g_string_append(verification, tmp); + purple_cipher_context_append(context, (const guchar *)tmp, strlen(tmp)); g_free(tmp); - return g_string_append_c(verification, '<'); + purple_cipher_context_append(context, (const guchar *)"<", 1); } gchar *jabber_caps_calculate_hash(JabberCapsClientInfo *info, const char *hash) { GList *node; - GString *verification; PurpleCipherContext *context; guint8 checksum[20]; gsize checksum_size = 20; @@ -871,24 +870,26 @@ info->features = g_list_sort(info->features, (GCompareFunc)strcmp); info->forms = g_list_sort(info->forms, jabber_xdata_compare); - verification = g_string_new(""); - - /* concat identities to the verification string */ + /* Add identities to the hash data */ for (node = info->identities; node; node = node->next) { JabberIdentity *id = (JabberIdentity*)node->data; char *category = g_markup_escape_text(id->category, -1); char *type = g_markup_escape_text(id->type, -1); char *lang = NULL; char *name = NULL; + char *tmp; if (id->lang) lang = g_markup_escape_text(id->lang, -1); if (id->name) name = g_markup_escape_text(id->name, -1); - g_string_append_printf(verification, "%s/%s/%s/%s<", category, - type, lang ? lang : "", name ? name : ""); + tmp = g_strconcat(category, "/", type, "/", lang ? lang : "", + "/", name ? name : "", "<", NULL); + purple_cipher_context_append(context, (const guchar *)tmp, strlen(tmp)); + + g_free(tmp); g_free(category); g_free(type); g_free(lang); @@ -897,7 +898,7 @@ /* concat features to the verification string */ for (node = info->features; node; node = node->next) { - verification = jabber_caps_verification_append(verification, node->data); + append_escaped_string(context, node->data); } /* concat x-data forms to the verification string */ @@ -907,19 +908,19 @@ GList *fields = jabber_caps_xdata_get_fields(data); /* append FORM_TYPE's field value to the verification string */ - verification = jabber_caps_verification_append(verification, formtype); + append_escaped_string(context, formtype); g_free(formtype); while (fields) { GList *value; JabberDataFormField *field = (JabberDataFormField*)fields->data; - if (strcmp(field->var, "FORM_TYPE")) { + if (!g_str_equal(field->var, "FORM_TYPE")) { /* Append the "var" attribute */ - verification = jabber_caps_verification_append(verification, field->var); + append_escaped_string(context, field->var); /* Append elements' cdata */ - for(value = field->values; value; value = value->next) { - verification = jabber_caps_verification_append(verification, value->data); + for (value = field->values; value; value = value->next) { + append_escaped_string(context, value->data); g_free(value->data); } } @@ -932,12 +933,9 @@ } /* generate hash */ - purple_cipher_context_append(context, (guchar*)verification->str, verification->len); - - success = purple_cipher_context_digest(context, verification->len, + success = purple_cipher_context_digest(context, checksum_size, checksum, &checksum_size); - g_string_free(verification, TRUE); purple_cipher_context_destroy(context); return (success ? purple_base64_encode(checksum, checksum_size) : NULL); diff -r c316749944c1 -r 2bdbf3fbd894 libpurple/protocols/jabber/data.c --- a/libpurple/protocols/jabber/data.c Sat Mar 13 08:18:25 2010 +0000 +++ b/libpurple/protocols/jabber/data.c Fri Mar 26 00:43:51 2010 +0000 @@ -39,7 +39,7 @@ JabberStream *js) { JabberData *data = g_new0(JabberData, 1); - gchar *checksum = jabber_calculate_data_sha1sum(rawdata, size); + gchar *checksum = jabber_calculate_data_hash(rawdata, size, "sha1"); gchar cid[256]; g_snprintf(cid, sizeof(cid), "sha1+%s@bob.xmpp.org", checksum); @@ -54,6 +54,17 @@ return data; } +static void +jabber_data_delete(gpointer cbdata) +{ + JabberData *data = cbdata; + g_free(data->cid); + g_free(data->type); + g_free(data->data); + g_free(data); +} + + JabberData * jabber_data_create_from_xml(xmlnode *tag) { @@ -99,17 +110,6 @@ return data; } - -static void -jabber_data_delete(gpointer cbdata) -{ - JabberData *data = cbdata; - g_free(data->cid); - g_free(data->type); - g_free(data->data); - g_free(data); -} - const char * jabber_data_get_cid(const JabberData *data) { @@ -165,7 +165,7 @@ return img; } -xmlnode * +static xmlnode * jabber_data_get_xml_request(const gchar *cid) { xmlnode *tag = xmlnode_new("data"); @@ -176,6 +176,118 @@ return tag; } +static gboolean +jabber_data_has_valid_hash(const JabberData *data) +{ + const gchar *cid = jabber_data_get_cid(data); + gchar **cid_parts = g_strsplit(cid, "@", -1); + gchar **iter; + int num_parts = 0; + + purple_debug_info("jabber", "validating BoB hash %s\n", cid); + + for (iter = cid_parts; *iter != NULL ; iter++) { + num_parts++; + } + + if (num_parts == 2 && purple_strequal(cid_parts[1], "bob.xmpp.org")) { + gchar **sub_parts = g_strsplit(cid_parts[0], "+", -1); + + num_parts = 0; + for (iter = sub_parts ; *iter != NULL ; iter++) { + num_parts++; + } + + if (num_parts == 2) { + const gchar *hash_algo = sub_parts[0]; + const gchar *hash_value = sub_parts[1]; + gchar *digest = + jabber_calculate_data_hash(jabber_data_get_data(data), + jabber_data_get_size(data), hash_algo); + + if (digest) { + gboolean result = purple_strequal(digest, hash_value); + + purple_debug_info("jabber", "BoB expecting hash: %s\n", digest); + + if (!result) { + purple_debug_error("jabber", "invalid BoB hash\n"); + } + g_free(digest); + return result; + } else { + purple_debug_info("jabber", "unknown BoB hash algo\n"); + return FALSE; + } + } else { + return FALSE; + } + } else { + return FALSE; + } +} + + +typedef struct { + gpointer userdata; + gchar *alt; + gboolean ephemeral; + JabberDataRequestCallback *cb; +} JabberDataRequestData; + +static void +jabber_data_request_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, xmlnode *packet, gpointer data) +{ + JabberDataRequestData *request_data = (JabberDataRequestData *) data; + gpointer userdata = request_data->userdata; + gchar *alt = request_data->alt; + gboolean ephemeral = request_data->ephemeral; + JabberDataRequestCallback *cb = request_data->cb; + + xmlnode *data_element = xmlnode_get_child(packet, "data"); + xmlnode *item_not_found = xmlnode_get_child(packet, "item-not-found"); + + /* did we get a data element as result? */ + if (data_element && type == JABBER_IQ_RESULT) { + JabberData *data = jabber_data_create_from_xml(data_element); + + if (!ephemeral) { + jabber_data_associate_remote(js, from, data); + } + cb(data, alt, userdata); + } else if (item_not_found) { + purple_debug_info("jabber", + "Responder didn't recognize requested data\n"); + cb(NULL, alt, userdata); + } else { + purple_debug_error("jabber", "Unknown response to data request\n"); + cb(NULL, alt, userdata); + } + + g_free(request_data); +} + +void +jabber_data_request(JabberStream *js, const gchar *cid, const gchar *who, + gchar *alt, gboolean ephemeral, JabberDataRequestCallback cb, + gpointer userdata) +{ + JabberIq *request = jabber_iq_new(js, JABBER_IQ_GET); + xmlnode *data_request = jabber_data_get_xml_request(cid); + JabberDataRequestData *data = g_new0(JabberDataRequestData, 1); + + data->userdata = userdata; + data->alt = alt; + data->ephemeral = ephemeral; + data->cb = cb; + + xmlnode_set_attrib(request->node, "to", who); + jabber_iq_set_callback(request, jabber_data_request_cb, data); + xmlnode_insert_child(request->node, data_request); + jabber_iq_send(request); +} + const JabberData * jabber_data_find_local_by_alt(const gchar *alt) { @@ -191,11 +303,23 @@ } const JabberData * -jabber_data_find_remote_by_cid(const gchar *cid) +jabber_data_find_remote_by_cid(JabberStream *js, const gchar *who, + const gchar *cid) { + const JabberData *data = g_hash_table_lookup(remote_data_by_cid, cid); purple_debug_info("jabber", "lookup remote smiley with cid = %s\n", cid); - return g_hash_table_lookup(remote_data_by_cid, cid); + if (data == NULL) { + gchar *jid_cid = + g_strdup_printf("%s@%s/%s%s%s", js->user->node, js->user->domain, + js->user->resource, who, cid); + purple_debug_info("jabber", + "didn't find BoB object by pure CID, try including JIDs: %s\n", + jid_cid); + data = g_hash_table_lookup(remote_data_by_cid, jid_cid); + g_free(jid_cid); + } + return data; } void @@ -209,12 +333,21 @@ } void -jabber_data_associate_remote(JabberData *data) +jabber_data_associate_remote(JabberStream *js, const gchar *who, JabberData *data) { - purple_debug_info("jabber", "associating remote smiley, cid = %s\n", - jabber_data_get_cid(data)); - g_hash_table_insert(remote_data_by_cid, g_strdup(jabber_data_get_cid(data)), - data); + gchar *cid; + + if (jabber_data_has_valid_hash(data)) { + cid = g_strdup(jabber_data_get_cid(data)); + } else { + cid = g_strdup_printf("%s@%s/%s%s%s", js->user->node, js->user->domain, + js->user->resource, who, jabber_data_get_cid(data)); + } + + purple_debug_info("jabber", "associating remote BoB object with cid = %s\n", + cid); + + g_hash_table_insert(remote_data_by_cid, cid, data); } void diff -r c316749944c1 -r 2bdbf3fbd894 libpurple/protocols/jabber/data.h --- a/libpurple/protocols/jabber/data.h Sat Mar 13 08:18:25 2010 +0000 +++ b/libpurple/protocols/jabber/data.h Fri Mar 26 00:43:51 2010 +0000 @@ -28,6 +28,7 @@ #define JABBER_DATA_MAX_SIZE 8192 + typedef struct { char *cid; char *type; @@ -35,6 +36,10 @@ gpointer data; } JabberData; +typedef void (JabberDataRequestCallback)(JabberData *data, gchar *alt, + gpointer userdata); + + /* creates a JabberData instance from raw data */ JabberData *jabber_data_create_from_data(gconstpointer data, gsize size, const char *type, JabberStream *js); @@ -55,18 +60,20 @@ /* returns an XHTML-IM "img" tag given a data instance */ xmlnode *jabber_data_get_xhtml_im(const JabberData *data, const gchar *alt); -/* returns a data request element (to be included in an iq stanza) for requesting - data */ -xmlnode *jabber_data_get_xml_request(const gchar *cid); +void jabber_data_request(JabberStream *js, const gchar *cid, const gchar *who, + gchar *alt, gboolean ephemeral, JabberDataRequestCallback cb, + gpointer userdata); /* lookup functions */ const JabberData *jabber_data_find_local_by_alt(const gchar *alt); const JabberData *jabber_data_find_local_by_cid(const gchar *cid); -const JabberData *jabber_data_find_remote_by_cid(const gchar *cid); +const JabberData *jabber_data_find_remote_by_cid(JabberStream *js, + const gchar *who, const gchar *cid); /* store data objects */ void jabber_data_associate_local(JabberData *data, const gchar *alt); -void jabber_data_associate_remote(JabberData *data); +void jabber_data_associate_remote(JabberStream *js, const gchar *who, + JabberData *data); /* handles iq requests */ void jabber_data_parse(JabberStream *js, const char *who, JabberIqType type, diff -r c316749944c1 -r 2bdbf3fbd894 libpurple/protocols/jabber/ibb.c --- a/libpurple/protocols/jabber/ibb.c Sat Mar 13 08:18:25 2010 +0000 +++ b/libpurple/protocols/jabber/ibb.c Fri Mar 26 00:43:51 2010 +0000 @@ -157,6 +157,12 @@ } } +gsize +jabber_ibb_session_get_max_data_size(const JabberIBBSession *sess) +{ + return (gsize) floor((sess->block_size - 2) * (float) 3 / 4); +} + gpointer jabber_ibb_session_get_user_data(JabberIBBSession *sess) { @@ -321,7 +327,7 @@ if (state != JABBER_IBB_SESSION_OPENED) { purple_debug_error("jabber", "trying to send data on a non-open IBB session\n"); - } else if (size > jabber_ibb_session_get_block_size(sess)) { + } else if (size > jabber_ibb_session_get_max_data_size(sess)) { purple_debug_error("jabber", "trying to send a too large packet in the IBB session\n"); } else { @@ -416,6 +422,10 @@ purple_debug_info("jabber", "got %" G_GSIZE_FORMAT " bytes of data on IBB stream\n", size); + /* we accept other clients to send up to block-size + of _unencoded_ data, since there's been some confusions + regarding the interpretation of this attribute + (including previous versions of libpurple) */ if (size > jabber_ibb_session_get_block_size(sess)) { purple_debug_error("jabber", "IBB: received a too large packet\n"); diff -r c316749944c1 -r 2bdbf3fbd894 libpurple/protocols/jabber/ibb.h --- a/libpurple/protocols/jabber/ibb.h Sat Mar 13 08:18:25 2010 +0000 +++ b/libpurple/protocols/jabber/ibb.h Fri Mar 26 00:43:51 2010 +0000 @@ -107,6 +107,10 @@ gsize jabber_ibb_session_get_block_size(const JabberIBBSession *sess); void jabber_ibb_session_set_block_size(JabberIBBSession *sess, gsize size); +/* get maximum size data block to send (in bytes) + (before encoded to BASE64) */ +gsize jabber_ibb_session_get_max_data_size(const JabberIBBSession *sess); + gpointer jabber_ibb_session_get_user_data(JabberIBBSession *sess); /* handle incoming packet */ diff -r c316749944c1 -r 2bdbf3fbd894 libpurple/protocols/jabber/jabber.c --- a/libpurple/protocols/jabber/jabber.c Sat Mar 13 08:18:25 2010 +0000 +++ b/libpurple/protocols/jabber/jabber.c Fri Mar 26 00:43:51 2010 +0000 @@ -86,6 +86,11 @@ { char *open_stream; + if (js->stream_id) { + g_free(js->stream_id); + js->stream_id = NULL; + } + open_stream = g_strdup_printf("gc), "jabber-receiving-xmlnode", js->gc, packet); @@ -269,6 +275,7 @@ if(NULL == *packet) return; + name = (*packet)->name; xmlns = xmlnode_get_namespace(*packet); if(!strcmp((*packet)->name, "iq")) { @@ -277,30 +284,30 @@ jabber_presence_parse(js, *packet); } else if(!strcmp((*packet)->name, "message")) { jabber_message_parse(js, *packet); - } else if(!strcmp((*packet)->name, "stream:features")) { - jabber_stream_features_parse(js, *packet); - } else if (!strcmp((*packet)->name, "features") && xmlns && - !strcmp(xmlns, NS_XMPP_STREAMS)) { - jabber_stream_features_parse(js, *packet); - } else if(!strcmp((*packet)->name, "stream:error") || - (!strcmp((*packet)->name, "error") && xmlns && - !strcmp(xmlns, NS_XMPP_STREAMS))) - { - jabber_stream_handle_error(js, *packet); - } else if(!strcmp((*packet)->name, "challenge")) { - if(js->state == JABBER_STREAM_AUTHENTICATING) - jabber_auth_handle_challenge(js, *packet); - } else if(!strcmp((*packet)->name, "success")) { - if(js->state == JABBER_STREAM_AUTHENTICATING) - jabber_auth_handle_success(js, *packet); - } else if(!strcmp((*packet)->name, "failure")) { - if(js->state == JABBER_STREAM_AUTHENTICATING) - jabber_auth_handle_failure(js, *packet); - } else if(!strcmp((*packet)->name, "proceed")) { - if (js->state == JABBER_STREAM_INITIALIZING_ENCRYPTION && !js->gsc) - tls_init(js); - else - purple_debug_warning("jabber", "Ignoring spurious \n"); + } else if (purple_strequal(xmlns, NS_XMPP_STREAMS)) { + if (g_str_equal(name, "features")) + jabber_stream_features_parse(js, *packet); + else if (g_str_equal(name, "error")) + jabber_stream_handle_error(js, *packet); + } else if (purple_strequal(xmlns, NS_XMPP_SASL)) { + if (js->state != JABBER_STREAM_AUTHENTICATING) + purple_debug_warning("jabber", "Ignoring spurious SASL stanza %s\n", name); + else { + if (g_str_equal(name, "challenge")) + jabber_auth_handle_challenge(js, *packet); + else if (g_str_equal(name, "success")) + jabber_auth_handle_success(js, *packet); + else if (g_str_equal(name, "failure")) + jabber_auth_handle_failure(js, *packet); + } + } else if (purple_strequal(xmlns, NS_XMPP_TLS)) { + if (js->state != JABBER_STREAM_INITIALIZING_ENCRYPTION || js->gsc) + purple_debug_warning("jabber", "Ignoring spurious %s\n", name); + else { + if (g_str_equal(name, "proceed")) + tls_init(js); + /* TODO: Handle , I guess? */ + } } else { purple_debug_warning("jabber", "Unknown packet: %s\n", (*packet)->name); } @@ -973,8 +980,8 @@ image = purple_buddy_icons_find_account_icon(account); if (image != NULL) { js->initial_avatar_hash = - jabber_calculate_data_sha1sum(purple_imgstore_get_data(image), - purple_imgstore_get_size(image)); + jabber_calculate_data_hash(purple_imgstore_get_data(image), + purple_imgstore_get_size(image), "sha1"); purple_imgstore_unref(image); } diff -r c316749944c1 -r 2bdbf3fbd894 libpurple/protocols/jabber/jabber.h --- a/libpurple/protocols/jabber/jabber.h Sat Mar 13 08:18:25 2010 +0000 +++ b/libpurple/protocols/jabber/jabber.h Fri Mar 26 00:43:51 2010 +0000 @@ -112,6 +112,13 @@ JabberSaslMech *auth_mech; gpointer auth_mech_data; + + /** + * The header from the opening tag. This being NULL is treated + * as a special condition in the parsing code (signifying the next + * stanza started is an opening stream tag), and its being missing on + * the stream header is treated as a fatal error. + */ char *stream_id; JabberStreamState state; diff -r c316749944c1 -r 2bdbf3fbd894 libpurple/protocols/jabber/jutil.c --- a/libpurple/protocols/jabber/jutil.c Sat Mar 13 08:18:25 2010 +0000 +++ b/libpurple/protocols/jabber/jutil.c Fri Mar 26 00:43:51 2010 +0000 @@ -728,17 +728,17 @@ return NULL; } -/* The same as purple_util_get_image_checksum, but guaranteed to remain SHA1 */ char * -jabber_calculate_data_sha1sum(gconstpointer data, size_t len) +jabber_calculate_data_hash(gconstpointer data, size_t len, + const gchar *hash_algo) { PurpleCipherContext *context; - static gchar digest[41]; + static gchar digest[129]; /* 512 bits hex + \0 */ - context = purple_cipher_context_new_by_name("sha1", NULL); + context = purple_cipher_context_new_by_name(hash_algo, NULL); if (context == NULL) { - purple_debug_error("jabber", "Could not find sha1 cipher\n"); + purple_debug_error("jabber", "Could not find %s cipher\n", hash_algo); g_return_val_if_reached(NULL); } @@ -746,7 +746,8 @@ purple_cipher_context_append(context, data, len); if (!purple_cipher_context_digest_to_str(context, sizeof(digest), digest, NULL)) { - purple_debug_error("jabber", "Failed to get SHA-1 digest.\n"); + purple_debug_error("jabber", "Failed to get digest for %s cipher.\n", + hash_algo); g_return_val_if_reached(NULL); } purple_cipher_context_destroy(context); diff -r c316749944c1 -r 2bdbf3fbd894 libpurple/protocols/jabber/jutil.h --- a/libpurple/protocols/jabber/jutil.h Sat Mar 13 08:18:25 2010 +0000 +++ b/libpurple/protocols/jabber/jutil.h Fri Mar 26 00:43:51 2010 +0000 @@ -85,5 +85,6 @@ /* show attr (presence stanza) -> state */ JabberBuddyState jabber_buddy_show_get_state(const char *id); -char *jabber_calculate_data_sha1sum(gconstpointer data, size_t len); +char *jabber_calculate_data_hash(gconstpointer data, size_t len, + const gchar *hash_algo); #endif /* PURPLE_JABBER_JUTIL_H_ */ diff -r c316749944c1 -r 2bdbf3fbd894 libpurple/protocols/jabber/libxmpp.c --- a/libpurple/protocols/jabber/libxmpp.c Sat Mar 13 08:18:25 2010 +0000 +++ b/libpurple/protocols/jabber/libxmpp.c Fri Mar 26 00:43:51 2010 +0000 @@ -257,7 +257,7 @@ purple_account_user_split_set_reverse(split, FALSE); prpl_info.user_splits = g_list_append(prpl_info.user_splits, split); - split = purple_account_user_split_new(_("Resource"), NULL, '/'); + split = purple_account_user_split_new(_("Resource"), "", '/'); purple_account_user_split_set_reverse(split, FALSE); prpl_info.user_splits = g_list_append(prpl_info.user_splits, split); diff -r c316749944c1 -r 2bdbf3fbd894 libpurple/protocols/jabber/message.c --- a/libpurple/protocols/jabber/message.c Sat Mar 13 08:18:25 2010 +0000 +++ b/libpurple/protocols/jabber/message.c Fri Mar 26 00:43:51 2010 +0000 @@ -462,82 +462,43 @@ } static void -jabber_message_add_remote_smileys(const xmlnode *message) +jabber_message_add_remote_smileys(JabberStream *js, const gchar *who, + const xmlnode *message) { xmlnode *data_tag; for (data_tag = xmlnode_get_child_with_namespace(message, "data", NS_BOB) ; data_tag ; data_tag = xmlnode_get_next_twin(data_tag)) { const gchar *cid = xmlnode_get_attrib(data_tag, "cid"); - const JabberData *data = jabber_data_find_remote_by_cid(cid); + const JabberData *data = jabber_data_find_remote_by_cid(js, who, cid); if (!data && cid != NULL) { /* we haven't cached this already, let's add it */ JabberData *new_data = jabber_data_create_from_xml(data_tag); - jabber_data_associate_remote(new_data); + + if (new_data) { + jabber_data_associate_remote(js, who, new_data); + } } } } -/* used in the function below to supply a conversation and shortcut for a - smiley */ -typedef struct { - PurpleConversation *conv; - gchar *alt; -} JabberDataRef; - static void -jabber_message_get_data_cb(JabberStream *js, const char *from, - JabberIqType type, const char *id, - xmlnode *packet, gpointer data) +jabber_message_request_data_cb(JabberData *data, gchar *alt, + gpointer userdata) { - JabberDataRef *ref = (JabberDataRef *) data; - PurpleConversation *conv = ref->conv; - const gchar *alt = ref->alt; - xmlnode *data_element = xmlnode_get_child(packet, "data"); - xmlnode *item_not_found = xmlnode_get_child(packet, "item-not-found"); - - /* did we get a data element as result? */ - if (data_element && type == JABBER_IQ_RESULT) { - JabberData *data = jabber_data_create_from_xml(data_element); + PurpleConversation *conv = (PurpleConversation *) userdata; - if (data) { - jabber_data_associate_remote(data); - purple_conv_custom_smiley_write(conv, alt, - jabber_data_get_data(data), - jabber_data_get_size(data)); - purple_conv_custom_smiley_close(conv, alt); - } - - } else if (item_not_found) { - purple_debug_info("jabber", - "Responder didn't recognize requested data\n"); - } else { - purple_debug_error("jabber", "Unknown response to data request\n"); + if (data) { + purple_conv_custom_smiley_write(conv, alt, + jabber_data_get_data(data), + jabber_data_get_size(data)); + purple_conv_custom_smiley_close(conv, alt); } - g_free(ref->alt); - g_free(ref); -} -static void -jabber_message_send_data_request(JabberStream *js, PurpleConversation *conv, - const gchar *cid, const gchar *who, - const gchar *alt) -{ - JabberIq *request = jabber_iq_new(js, JABBER_IQ_GET); - JabberDataRef *ref = g_new0(JabberDataRef, 1); - xmlnode *data_request = jabber_data_get_xml_request(cid); - - xmlnode_set_attrib(request->node, "to", who); - ref->conv = conv; - ref->alt = g_strdup(alt); - jabber_iq_set_callback(request, jabber_message_get_data_cb, ref); - xmlnode_insert_child(request->node, data_request); - - jabber_iq_send(request); + g_free(alt); } - void jabber_message_parse(JabberStream *js, xmlnode *packet) { JabberMessage *jm; @@ -674,7 +635,7 @@ } /* process any newly provided smileys */ - jabber_message_add_remote_smileys(packet); + jabber_message_add_remote_smileys(js, to, packet); } /* reformat xhtml so that img tags with a "cid:" src gets @@ -693,14 +654,14 @@ for (; conv && smiley_refs ; smiley_refs = g_list_delete_link(smiley_refs, smiley_refs)) { JabberSmileyRef *ref = (JabberSmileyRef *) smiley_refs->data; const gchar *cid = ref->cid; - const gchar *alt = ref->alt; + gchar *alt = g_strdup(ref->alt); purple_debug_info("jabber", "about to add custom smiley %s to the conv\n", alt); if (purple_conv_custom_smiley_add(conv, alt, "cid", cid, TRUE)) { const JabberData *data = - jabber_data_find_remote_by_cid(cid); + jabber_data_find_remote_by_cid(js, from, cid); /* if data is already known, we write it immediatly */ if (data) { purple_debug_info("jabber", @@ -713,8 +674,8 @@ /* we need to request the smiley (data) */ purple_debug_info("jabber", "data is unknown, need to request it\n"); - jabber_message_send_data_request(js, conv, cid, from, - alt); + jabber_data_request(js, cid, from, alt, FALSE, + jabber_message_request_data_cb, conv); } } g_free(ref->cid); diff -r c316749944c1 -r 2bdbf3fbd894 libpurple/protocols/jabber/namespaces.h --- a/libpurple/protocols/jabber/namespaces.h Sat Mar 13 08:18:25 2010 +0000 +++ b/libpurple/protocols/jabber/namespaces.h Fri Mar 26 00:43:51 2010 +0000 @@ -30,6 +30,7 @@ #define NS_XMPP_SESSION "urn:ietf:params:xml:ns:xmpp-session" #define NS_XMPP_STANZAS "urn:ietf:params:xml:ns:xmpp-stanzas" #define NS_XMPP_STREAMS "http://etherx.jabber.org/streams" +#define NS_XMPP_TLS "urn:ietf:params:xml:ns:xmpp-tls" /* XEP-0012 Last Activity (and XEP-0256 Last Activity in Presence) */ #define NS_LAST_ACTIVITY "jabber:iq:last" diff -r c316749944c1 -r 2bdbf3fbd894 libpurple/protocols/jabber/parser.c --- a/libpurple/protocols/jabber/parser.c Sat Mar 13 08:18:25 2010 +0000 +++ b/libpurple/protocols/jabber/parser.c Fri Mar 26 00:43:51 2010 +0000 @@ -43,10 +43,25 @@ if(!element_name) { return; - } else if(!xmlStrcmp(element_name, (xmlChar*) "stream")) { + } else if (js->stream_id == NULL) { + /* Sanity checking! */ + if (0 != xmlStrcmp(element_name, (xmlChar *) "stream") || + 0 != xmlStrcmp(namespace, (xmlChar *) NS_XMPP_STREAMS)) { + /* We were expecting a opening stanza, but + * didn't get it. Bad! + */ + purple_debug_error("jabber", "Expecting stream header, got %s with " + "xmlns %s\n", element_name, namespace); + purple_connection_error_reason(js->gc, + PURPLE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE, + _("XMPP stream header missing")); + return; + } + js->protocol_version.major = 0; js->protocol_version.minor = 9; - for(i=0; i < nb_attributes * 5; i += 5) { + + for (i = 0; i < nb_attributes * 5; i += 5) { int attrib_len = attributes[i+4] - attributes[i+3]; char *attrib = g_strndup((gchar *)attributes[i+3], attrib_len); @@ -56,11 +71,14 @@ js->protocol_version.major = atoi(attrib); js->protocol_version.minor = dot ? atoi(dot + 1) : 0; - if (js->protocol_version.major > 1) + if (js->protocol_version.major > 1) { /* TODO: Send error */ purple_connection_error_reason(js->gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE, _("XMPP Version Mismatch")); + g_free(attrib); + return; + } if (js->protocol_version.major == 0 && js->protocol_version.minor != 9) { purple_debug_warning("jabber", "Treating version %s as 0.9 for backward " @@ -74,6 +92,11 @@ g_free(attrib); } } + + if (js->stream_id == NULL) + purple_connection_error_reason(js->gc, + PURPLE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE, + _("XMPP stream missing ID")); } else { if(js->current) diff -r c316749944c1 -r 2bdbf3fbd894 libpurple/protocols/jabber/presence.c --- a/libpurple/protocols/jabber/presence.c Sat Mar 13 08:18:25 2010 +0000 +++ b/libpurple/protocols/jabber/presence.c Fri Mar 26 00:43:51 2010 +0000 @@ -457,7 +457,7 @@ data = purple_base64_decode(text, &size); if (data) { - gchar *hash = jabber_calculate_data_sha1sum(data, size); + gchar *hash = jabber_calculate_data_hash(data, size, "sha1"); purple_buddy_icons_set_for_user(js->gc->account, from, data, size, hash); g_free(hash); @@ -538,7 +538,7 @@ g_free(userdata); } -gboolean +static gboolean handle_presence_chat(JabberStream *js, JabberPresence *presence, xmlnode *packet) { static int i = 1; @@ -670,7 +670,7 @@ if (chat->muc) { if (g_slist_find(presence->chat_info.codes, GINT_TO_POINTER(110))) is_our_resource = TRUE; - + if (g_slist_find(presence->chat_info.codes, GINT_TO_POINTER(301))) { /* XXX: We got banned. YAY! (No GIR, that's bad) */ } @@ -744,15 +744,15 @@ g_free(reason); } - + if (g_slist_find(presence->chat_info.codes, GINT_TO_POINTER(321))) { /* XXX: removed due to an affiliation change */ } - + if (g_slist_find(presence->chat_info.codes, GINT_TO_POINTER(322))) { /* XXX: removed because room is now members-only */ } - + if (g_slist_find(presence->chat_info.codes, GINT_TO_POINTER(332))) { /* XXX: removed due to system shutdown */ } @@ -792,7 +792,7 @@ return TRUE; } -gboolean +static gboolean handle_presence_contact(JabberStream *js, JabberPresence *presence) { JabberBuddyResource *jbr; @@ -996,7 +996,7 @@ JabberPresenceHandler *pih; if (child->type != XMLNODE_TYPE_TAG) continue; - + key = g_strdup_printf("%s %s", child->name, xmlnode_get_namespace(child)); pih = g_hash_table_lookup(presence_handlers, key); g_free(key); @@ -1052,11 +1052,15 @@ } out: + while (presence.chat_info.codes) + presence.chat_info.codes = + g_slist_delete_link(presence.chat_info.codes, + presence.chat_info.codes); + + g_free(presence.status); + g_free(presence.vcard_avatar_hash); g_free(presence.nickname); - g_free(presence.status); jabber_id_free(presence.jid_from); - g_free(presence.nickname); - g_free(presence.vcard_avatar_hash); } void jabber_presence_subscription_set(JabberStream *js, const char *who, const char *type) diff -r c316749944c1 -r 2bdbf3fbd894 libpurple/protocols/jabber/si.c --- a/libpurple/protocols/jabber/si.c Sat Mar 13 08:18:25 2010 +0000 +++ b/libpurple/protocols/jabber/si.c Fri Mar 26 00:43:51 2010 +0000 @@ -289,7 +289,7 @@ jsx->js->user->node, jsx->js->user->domain, jsx->js->user->resource); /* Per XEP-0065, the 'host' must be SHA1(SID + from JID + to JID) */ - hash = jabber_calculate_data_sha1sum(dstaddr, strlen(dstaddr)); + hash = jabber_calculate_data_hash(dstaddr, strlen(dstaddr), "sha1"); jsx->connect_data = purple_proxy_connect_socks5(NULL, jsx->gpi, hash, 0, @@ -474,7 +474,7 @@ jsx->js->user->resource, xfer->who); /* Per XEP-0065, the 'host' must be SHA1(SID + from JID + to JID) */ - hash = jabber_calculate_data_sha1sum(dstaddr, strlen(dstaddr)); + hash = jabber_calculate_data_hash(dstaddr, strlen(dstaddr), "sha1"); if(strncmp(hash, jsx->rxqueue + 5, 40) || jsx->rxqueue[45] != 0x00 || jsx->rxqueue[46] != 0x00) { @@ -1075,6 +1075,9 @@ jabber_si_xfer_ibb_error_cb); jsx->ibb_session = sess; + /* we handle up to block-size bytes of decoded data, to handle + clients interpreting the block-size attribute as that + (see also remark in ibb.c) */ jsx->ibb_buffer = purple_circ_buffer_new(jabber_ibb_session_get_block_size(sess)); @@ -1103,8 +1106,8 @@ { JabberSIXfer *jsx = (JabberSIXfer *) xfer->data; JabberIBBSession *sess = jsx->ibb_session; - gsize packet_size = len < jabber_ibb_session_get_block_size(sess) ? - len : jabber_ibb_session_get_block_size(sess); + gsize packet_size = len < jabber_ibb_session_get_max_data_size(sess) ? + len : jabber_ibb_session_get_max_data_size(sess); jabber_ibb_session_send_data(sess, buffer, packet_size); @@ -1170,7 +1173,7 @@ purple_xfer_set_write_fnc(xfer, jabber_si_xfer_ibb_write); jsx->ibb_buffer = - purple_circ_buffer_new(jabber_ibb_session_get_block_size(jsx->ibb_session)); + purple_circ_buffer_new(jabber_ibb_session_get_max_data_size(jsx->ibb_session)); /* open the IBB session */ jabber_ibb_session_open(jsx->ibb_session); diff -r c316749944c1 -r 2bdbf3fbd894 libpurple/protocols/jabber/useravatar.c --- a/libpurple/protocols/jabber/useravatar.c Sat Mar 13 08:18:25 2010 +0000 +++ b/libpurple/protocols/jabber/useravatar.c Fri Mar 26 00:43:51 2010 +0000 @@ -149,8 +149,9 @@ char *lengthstring, *widthstring, *heightstring; /* compute the sha1 hash */ - char *hash = jabber_calculate_data_sha1sum(purple_imgstore_get_data(img), - purple_imgstore_get_size(img)); + char *hash = jabber_calculate_data_hash(purple_imgstore_get_data(img), + purple_imgstore_get_size(img), + "sha1"); char *base64avatar = purple_base64_encode(purple_imgstore_get_data(img), purple_imgstore_get_size(img)); diff -r c316749944c1 -r 2bdbf3fbd894 libpurple/protocols/msn/README --- a/libpurple/protocols/msn/README Sat Mar 13 08:18:25 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,55 +0,0 @@ -MSNP14 Implementation -by Ma Yuan - -1. Introduction -------------- - -MSNP14 Protocol, proposed by Windows Live Messenger, is new, and there is no available implementation except the official one on Windows Platform. - -It has introduced many new features attractable to many users, such as: -* Offline Instant Message - You can send the offline Message to the offline User, - The message will be posted to that user the next time when he is online. - -* Communicate with Yahoo User - U can chat with the Yahoo User in MSN, That's Fantastic! Till now , - you can send text/Nudge to Yahoo User. - -* Windows Live ID authentition - WLM use the Window Live ID Authentication process,Known as Passport 3.0, - The procedure is totally different to the previous Passport 2.0 - -* Video/Audio Conversation - U can communicate with other's via Video/Audio. -(Though very interesting, not implemented in this version) - -2.New Features Added ------------------ - -Till now, This project has implemented the following Feature: -* Windows Live ID authentication. - -* Offline Instant Message -Now can send and receive the Offline Instant Message to MSN user and Yahoo User. - -*contact management -Can add/delete Contact -Can add/delete Group - -* Communicate with Yahoo User -Can send/receive Message/Nudge to Yahoo User. - -*. Changes to made to fit MSNP14 Protocol - -3. Reference -------------- - -The very useful sites of MSN Protocol: -MSNpiki site: -reverse engineer of MSN Protocol.up to dated. -http://msnpiki.msnfanatic.com/index.php/MSN_Protocol_Version_13 - -hypothetic site: -old MSN Protocol Introduction,but very useful for basic idea of MSN protocol -http://www.hypothetic.org/docs/msn/index.php - diff -r c316749944c1 -r 2bdbf3fbd894 libpurple/protocols/oscar/family_locate.c --- a/libpurple/protocols/oscar/family_locate.c Sat Mar 13 08:18:25 2010 +0000 +++ b/libpurple/protocols/oscar/family_locate.c Fri Mar 26 00:43:51 2010 +0000 @@ -577,10 +577,10 @@ return NULL; } -guint32 +guint64 aim_locate_getcaps(OscarData *od, ByteStream *bs, int len) { - guint32 flags = 0; + guint64 flags = 0; int offset; for (offset = 0; byte_stream_empty(bs) && (offset < len); offset += 0x10) { @@ -637,10 +637,10 @@ return result; } -guint32 +guint64 aim_locate_getcaps_short(OscarData *od, ByteStream *bs, int len) { - guint32 flags = 0; + guint64 flags = 0; int offset; for (offset = 0; byte_stream_empty(bs) && (offset < len); offset += 0x02) { @@ -667,7 +667,7 @@ } int -byte_stream_putcaps(ByteStream *bs, guint32 caps) +byte_stream_putcaps(ByteStream *bs, guint64 caps) { int i; @@ -1400,7 +1400,7 @@ * Subtype 0x0004 - Set your client's capabilities. */ int -aim_locate_setcaps(OscarData *od, guint32 caps) +aim_locate_setcaps(OscarData *od, guint64 caps) { FlapConnection *conn; PurpleAccount *account = purple_connection_get_account(od->gc); diff -r c316749944c1 -r 2bdbf3fbd894 libpurple/protocols/oscar/libaim.c --- a/libpurple/protocols/oscar/libaim.c Sat Mar 13 08:18:25 2010 +0000 +++ b/libpurple/protocols/oscar/libaim.c Fri Mar 26 00:43:51 2010 +0000 @@ -31,7 +31,6 @@ OPT_PROTO_MAIL_CHECK | OPT_PROTO_IM_IMAGE, NULL, /* user_splits */ NULL, /* protocol_options */ - /* The mimimum icon size below is not needed in AIM 6.0 */ {"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 */ diff -r c316749944c1 -r 2bdbf3fbd894 libpurple/protocols/oscar/libicq.c --- a/libpurple/protocols/oscar/libicq.c Sat Mar 13 08:18:25 2010 +0000 +++ b/libpurple/protocols/oscar/libicq.c Fri Mar 26 00:43:51 2010 +0000 @@ -41,8 +41,7 @@ OPT_PROTO_MAIL_CHECK | OPT_PROTO_IM_IMAGE, NULL, /* user_splits */ NULL, /* protocol_options */ - {"gif,jpeg,bmp,ico", 48, 48, 52, 64, 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_icq, /* list_icon */ oscar_list_emblem, /* list_emblems */ oscar_status_text, /* status_text */ diff -r c316749944c1 -r 2bdbf3fbd894 libpurple/protocols/oscar/msgcookie.c --- a/libpurple/protocols/oscar/msgcookie.c Sat Mar 13 08:18:25 2010 +0000 +++ b/libpurple/protocols/oscar/msgcookie.c Fri Mar 26 00:43:51 2010 +0000 @@ -179,7 +179,7 @@ } /* XXX I hate switch */ -int aim_msgcookie_gettype(int type) +int aim_msgcookie_gettype(guint64 type) { /* XXX: hokey-assed. needs fixed. */ switch(type) { diff -r c316749944c1 -r 2bdbf3fbd894 libpurple/protocols/oscar/oscar.c --- a/libpurple/protocols/oscar/oscar.c Sat Mar 13 08:18:25 2010 +0000 +++ b/libpurple/protocols/oscar/oscar.c Fri Mar 26 00:43:51 2010 +0000 @@ -71,9 +71,18 @@ #define OSCAR_CONNECT_STEPS 6 -static OscarCapability purple_caps = (OSCAR_CAPABILITY_CHAT | OSCAR_CAPABILITY_BUDDYICON | OSCAR_CAPABILITY_DIRECTIM | - OSCAR_CAPABILITY_SENDFILE | OSCAR_CAPABILITY_UNICODE | OSCAR_CAPABILITY_INTEROPERATE | - OSCAR_CAPABILITY_SHORTCAPS | OSCAR_CAPABILITY_TYPING | OSCAR_CAPABILITY_ICQSERVERRELAY | OSCAR_CAPABILITY_NEWCAPS | OSCAR_CAPABILITY_XTRAZ); +static guint64 purple_caps = + OSCAR_CAPABILITY_CHAT + | OSCAR_CAPABILITY_BUDDYICON + | OSCAR_CAPABILITY_DIRECTIM + | OSCAR_CAPABILITY_SENDFILE + | OSCAR_CAPABILITY_UNICODE + | OSCAR_CAPABILITY_INTEROPERATE + | OSCAR_CAPABILITY_SHORTCAPS + | OSCAR_CAPABILITY_TYPING + | OSCAR_CAPABILITY_ICQSERVERRELAY + | OSCAR_CAPABILITY_NEWCAPS + | OSCAR_CAPABILITY_XTRAZ; static guint8 features_aim[] = {0x01, 0x01, 0x01, 0x02}; static guint8 features_icq[] = {0x01, 0x06}; @@ -471,7 +480,7 @@ charsetstr1 = "UTF-8"; charsetstr2 = purple_account_get_string(account, "encoding", OSCAR_DEFAULT_CUSTOM_ENCODING); } - + purple_debug_info("oscar", "Parsing IM part, charset=0x%04hx, charsubset=0x%04hx, datalen=%" G_GSIZE_FORMAT ", choice1=%s, choice2=%s, choice3=%s\n", charset, charsubset, datalen, charsetstr1, charsetstr2, (charsetstr3 ? charsetstr3 : "")); @@ -673,7 +682,7 @@ return g_string_free(cpy, FALSE); } -static gchar *oscar_caps_to_string(OscarCapability caps) +static gchar *oscar_caps_to_string(guint64 caps) { GString *str; const gchar *tmp; @@ -2594,7 +2603,6 @@ PurpleAccount *account; PurpleMessageFlags flags = 0; char *message = NULL; - char *rtfmsg = NULL; g_return_val_if_fail(od != NULL, 0); g_return_val_if_fail(od->gc != NULL, 0); @@ -2606,8 +2614,9 @@ if (args == NULL) return 0; - purple_debug_misc("oscar", "Incoming rendezvous message of type %u, " - "user %s, status %hu\n", args->type, userinfo->bn, args->status); + purple_debug_misc("oscar", "Incoming rendezvous message of type %" + G_GUINT64_FORMAT ", user %s, status %hu\n", + args->type, userinfo->bn, args->status); if (args->msg != NULL) { @@ -2624,20 +2633,6 @@ } } - if (args->info.rtfmsg.rtfmsg != NULL) - { - if (args->encoding != NULL) - { - char *encoding = NULL; - encoding = oscar_encoding_extract(args->encoding); - rtfmsg = oscar_encoding_to_utf8(account, encoding, args->info.rtfmsg.rtfmsg, - strlen(args->info.rtfmsg.rtfmsg)); - g_free(encoding); - } else { - if (g_utf8_validate(args->info.rtfmsg.rtfmsg, strlen(args->info.rtfmsg.rtfmsg), NULL)) - rtfmsg = g_strdup(args->info.rtfmsg.rtfmsg); - } - } if (args->type & OSCAR_CAPABILITY_CHAT) { char *encoding, *utf8name, *tmp; @@ -2725,30 +2720,35 @@ { purple_debug_info("oscar", "Got an ICQ Server Relay message of " "type %d\n", args->info.rtfmsg.msgtype); - purple_debug_info("oscar", "Sending X-Status Reply\n"); - - if(args->info.rtfmsg.msgtype == 26) - icq_relay_xstatus(od, userinfo->bn, args->cookie); - - if(args->info.rtfmsg.msgtype == 1) + + if (args->info.rtfmsg.msgtype == 1) { - if(rtfmsg) + if (args->info.rtfmsg.rtfmsg != NULL) { - serv_got_im(gc, userinfo->bn, rtfmsg, flags, - time(NULL)); + char *rtfmsg = NULL; + if (args->encoding != NULL) { + char *encoding = oscar_encoding_extract(args->encoding); + rtfmsg = oscar_encoding_to_utf8(account, encoding, + args->info.rtfmsg.rtfmsg, strlen(args->info.rtfmsg.rtfmsg)); + g_free(encoding); + } else { + if (g_utf8_validate(args->info.rtfmsg.rtfmsg, strlen(args->info.rtfmsg.rtfmsg), NULL)) + rtfmsg = g_strdup(args->info.rtfmsg.rtfmsg); + } + if (rtfmsg) { + serv_got_im(gc, userinfo->bn, rtfmsg, flags, time(NULL)); + g_free(rtfmsg); + } } - else - { - serv_got_im(gc, userinfo->bn, - args->info.rtfmsg.rtfmsg, flags, - time(NULL)); - } - } + } else if (args->info.rtfmsg.msgtype == 26) + purple_debug_info("oscar", "Sending X-Status Reply\n"); + icq_relay_xstatus(od, userinfo->bn, args->cookie); + } else { - purple_debug_error("oscar", "Unknown request class %hu\n", - args->type); + purple_debug_error("oscar", "Unknown request class %" + G_GUINT64_FORMAT "\n", args->type); } g_free(message); @@ -3331,9 +3331,9 @@ /* Split at (carriage return/newline)'s, then rejoin later with BRs between. */ statusmsg = oscar_icqstatus(state); splitmsg = g_strsplit(msg, "\r\n", 0); - + user_info = purple_notify_user_info_new(); - + purple_notify_user_info_add_pair(user_info, _("UIN"), who); purple_notify_user_info_add_pair(user_info, _("Status"), statusmsg); purple_notify_user_info_add_section_break(user_info); @@ -4758,8 +4758,8 @@ img = purple_buddy_icons_find_account_icon(account); if (img) { gconstpointer data = purple_imgstore_get_data(img); - args.iconlen = purple_imgstore_get_size(img); - args.iconsum = aimutil_iconsum(data, args.iconlen); + args.iconlen = purple_imgstore_get_size(img); + args.iconsum = aimutil_iconsum(data, args.iconlen); args.iconstamp = purple_buddy_icons_get_account_icon_timestamp(account); if ((args.iconlen != bi->ico_me_len) || (args.iconsum != bi->ico_me_csum) || (args.iconstamp != bi->ico_me_time)) { @@ -5368,7 +5368,7 @@ { /* If not in server list then prune from local list */ GSList *cur, *next; GSList *buddies = purple_find_buddies(account, NULL); - + /* Buddies */ cur = NULL; @@ -5807,28 +5807,34 @@ return 1; } -static int purple_ssi_authrequest(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { +static int purple_ssi_authrequest(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) +{ PurpleConnection *gc = od->gc; va_list ap; - char *bn; - char *msg; + const char *bn; + const char *msg; PurpleAccount *account = purple_connection_get_account(gc); - gchar *reason = NULL; struct name_data *data; PurpleBuddy *buddy; va_start(ap, fr); - bn = va_arg(ap, char *); - msg = va_arg(ap, char *); + bn = va_arg(ap, const char *); + msg = va_arg(ap, const char *); va_end(ap); purple_debug_info("oscar", - "ssi: received authorization request from %s\n", bn); + "ssi: received authorization request from %s\n", bn); buddy = purple_find_buddy(account, bn); - if (msg != NULL) - reason = purple_plugin_oscar_decode_im_part(account, bn, AIM_CHARSET_LATIN_1, 0x0000, msg, strlen(msg)); + if (!msg) { + purple_debug_warning("oscar", "Received auth request from %s with " + "empty message\n", bn); + } else if (!g_utf8_validate(msg, -1, NULL)) { + purple_debug_warning("oscar", "Received auth request from %s with " + "invalid UTF-8 message\n", bn); + msg = NULL; + } data = g_new(struct name_data, 1); data->gc = gc; @@ -5837,9 +5843,8 @@ purple_account_request_authorization(account, bn, NULL, (buddy ? purple_buddy_get_alias_only(buddy) : NULL), - reason, buddy != NULL, purple_auth_grant, + msg, buddy != NULL, purple_auth_grant, purple_auth_dontgrant_msgprompt, data); - g_free(reason); return 1; } @@ -6389,7 +6394,7 @@ purple_value_new(PURPLE_TYPE_STRING), NULL); status_types = g_list_prepend(status_types, type); - + type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE, OSCAR_STATUS_ID_EVIL, _("Evil"), TRUE, is_icq, FALSE, @@ -6651,23 +6656,22 @@ * window. Let the user know that we canceled the Direct IM. */ conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, name); purple_conversation_write(conv, NULL, _("You closed the connection."), - PURPLE_MESSAGE_SYSTEM, time(NULL)); - } -} - -static void oscar_get_icqxstatusmsg (PurpleBlistNode *node, gpointer ignore) + PURPLE_MESSAGE_SYSTEM, time(NULL)); + } +} + +static void oscar_get_icqxstatusmsg(PurpleBlistNode *node, gpointer ignore) { PurpleBuddy *buddy; PurpleConnection *gc; PurpleAccount *account; - - + g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); buddy = (PurpleBuddy *)node; gc = purple_account_get_connection(buddy->account); account = purple_connection_get_account(gc); - purple_debug_info("oscar", "Manual X-Status Get From %s to %s:\n", purple_buddy_get_name(buddy), account->username); + purple_debug_info("oscar", "Manual X-Status Get From %s to %s:\n", purple_buddy_get_name(buddy), account->username); icq_im_xstatus_request(gc->proto_data, purple_buddy_get_name(buddy)); } diff -r c316749944c1 -r 2bdbf3fbd894 libpurple/protocols/oscar/oscar.h --- a/libpurple/protocols/oscar/oscar.h Sat Mar 13 08:18:25 2010 +0000 +++ b/libpurple/protocols/oscar/oscar.h Fri Mar 26 00:43:51 2010 +0000 @@ -344,44 +344,39 @@ OSCAR_DISCONNECT_RETRYING /* peer connections only */ } OscarDisconnectReason; -typedef enum -{ - OSCAR_CAPABILITY_BUDDYICON = 0x00000001, - OSCAR_CAPABILITY_TALK = 0x00000002, - OSCAR_CAPABILITY_DIRECTIM = 0x00000004, - OSCAR_CAPABILITY_CHAT = 0x00000008, - OSCAR_CAPABILITY_GETFILE = 0x00000010, - OSCAR_CAPABILITY_SENDFILE = 0x00000020, - OSCAR_CAPABILITY_GAMES = 0x00000040, - OSCAR_CAPABILITY_ADDINS = 0x00000080, - OSCAR_CAPABILITY_SENDBUDDYLIST = 0x00000100, - OSCAR_CAPABILITY_GAMES2 = 0x00000200, - OSCAR_CAPABILITY_ICQ_DIRECT = 0x00000400, - OSCAR_CAPABILITY_APINFO = 0x00000800, - OSCAR_CAPABILITY_ICQRTF = 0x00001000, - OSCAR_CAPABILITY_EMPTY = 0x00002000, - OSCAR_CAPABILITY_ICQSERVERRELAY = 0x00004000, - OSCAR_CAPABILITY_UNICODEOLD = 0x00008000, - OSCAR_CAPABILITY_TRILLIANCRYPT = 0x00010000, - OSCAR_CAPABILITY_UNICODE = 0x00020000, - OSCAR_CAPABILITY_INTEROPERATE = 0x00040000, - OSCAR_CAPABILITY_SHORTCAPS = 0x00080000, - OSCAR_CAPABILITY_HIPTOP = 0x00100000, - OSCAR_CAPABILITY_SECUREIM = 0x00200000, - OSCAR_CAPABILITY_SMS = 0x00400000, - OSCAR_CAPABILITY_VIDEO = 0x00800000, - OSCAR_CAPABILITY_ICHATAV = 0x01000000, - OSCAR_CAPABILITY_LIVEVIDEO = 0x02000000, - OSCAR_CAPABILITY_CAMERA = 0x04000000, - OSCAR_CAPABILITY_ICHAT_SCREENSHARE = 0x08000000, - OSCAR_CAPABILITY_TYPING = 0x10000000, - OSCAR_CAPABILITY_NEWCAPS = 0x20000000, - OSCAR_CAPABILITY_XTRAZ = 0x40000000, - OSCAR_CAPABILITY_GENERICUNKNOWN = 0x80000000, -#warning Fix OSCAR_CAPABILITY_LAST situation - // TODO: We're out of bits. Rework things that depend on this or remove some capability. (Or, ensure this is a 64-bit type.) - OSCAR_CAPABILITY_LAST = 0x100000000 -} OscarCapability; +#define OSCAR_CAPABILITY_BUDDYICON 0x0000000000000001 +#define OSCAR_CAPABILITY_TALK 0x0000000000000002 +#define OSCAR_CAPABILITY_DIRECTIM 0x0000000000000004 +#define OSCAR_CAPABILITY_CHAT 0x0000000000000008 +#define OSCAR_CAPABILITY_GETFILE 0x0000000000000010 +#define OSCAR_CAPABILITY_SENDFILE 0x0000000000000020 +#define OSCAR_CAPABILITY_GAMES 0x0000000000000040 +#define OSCAR_CAPABILITY_ADDINS 0x0000000000000080 +#define OSCAR_CAPABILITY_SENDBUDDYLIST 0x0000000000000100 +#define OSCAR_CAPABILITY_GAMES2 0x0000000000000200 +#define OSCAR_CAPABILITY_ICQ_DIRECT 0x0000000000000400 +#define OSCAR_CAPABILITY_APINFO 0x0000000000000800 +#define OSCAR_CAPABILITY_ICQRTF 0x0000000000001000 +#define OSCAR_CAPABILITY_EMPTY 0x0000000000002000 +#define OSCAR_CAPABILITY_ICQSERVERRELAY 0x0000000000004000 +#define OSCAR_CAPABILITY_UNICODEOLD 0x0000000000008000 +#define OSCAR_CAPABILITY_TRILLIANCRYPT 0x0000000000010000 +#define OSCAR_CAPABILITY_UNICODE 0x0000000000020000 +#define OSCAR_CAPABILITY_INTEROPERATE 0x0000000000040000 +#define OSCAR_CAPABILITY_SHORTCAPS 0x0000000000080000 +#define OSCAR_CAPABILITY_HIPTOP 0x0000000000100000 +#define OSCAR_CAPABILITY_SECUREIM 0x0000000000200000 +#define OSCAR_CAPABILITY_SMS 0x0000000000400000 +#define OSCAR_CAPABILITY_VIDEO 0x0000000000800000 +#define OSCAR_CAPABILITY_ICHATAV 0x0000000001000000 +#define OSCAR_CAPABILITY_LIVEVIDEO 0x0000000002000000 +#define OSCAR_CAPABILITY_CAMERA 0x0000000004000000 +#define OSCAR_CAPABILITY_ICHAT_SCREENSHARE 0x0000000008000000 +#define OSCAR_CAPABILITY_TYPING 0x0000000010000000 +#define OSCAR_CAPABILITY_NEWCAPS 0x0000000020000000 +#define OSCAR_CAPABILITY_XTRAZ 0x0000000040000000 +#define OSCAR_CAPABILITY_GENERICUNKNOWN 0x0000000080000000 +#define OSCAR_CAPABILITY_LAST 0x0000000100000000 /* * Byte Stream type. Sort of. @@ -949,7 +944,7 @@ { guint16 status; guchar cookie[8]; - int type; /* One of the OSCAR_CAPABILITY_ constants */ + guint64 type; /* One of the OSCAR_CAPABILITY_ constants */ const char *proxyip; const char *clientip; const char *verifiedip; @@ -1077,7 +1072,7 @@ guint32 membersince; /* time_t */ guint32 onlinesince; /* time_t */ guint32 sessionlen; /* in seconds */ - guint32 capabilities; + guint64 capabilities; struct { guint32 status; guint32 ipaddr; @@ -1142,7 +1137,7 @@ void aim_locate_dorequest(OscarData *od); /* 0x0002 */ int aim_locate_reqrights(OscarData *od); -/* 0x0004 */ int aim_locate_setcaps(OscarData *od, guint32 caps); +/* 0x0004 */ int aim_locate_setcaps(OscarData *od, guint64 caps); /* 0x0004 */ int aim_locate_setprofile(OscarData *od, const char *profile_encoding, const gchar *profile, const int profile_len, const char *awaymsg_encoding, const gchar *awaymsg, const int awaymsg_len); /* 0x0005 */ int aim_locate_getinfo(OscarData *od, const char *, guint16); /* 0x0009 */ int aim_locate_setdirinfo(OscarData *od, const char *first, const char *middle, const char *last, const char *maiden, const char *nickname, const char *street, const char *city, const char *state, const char *zip, int country, guint16 privacy); @@ -1150,8 +1145,8 @@ /* 0x000f */ int aim_locate_setinterests(OscarData *od, const char *interest1, const char *interest2, const char *interest3, const char *interest4, const char *interest5, guint16 privacy); /* 0x0015 */ int aim_locate_getinfoshort(OscarData *od, const char *bn, guint32 flags); -guint32 aim_locate_getcaps(OscarData *od, ByteStream *bs, int len); -guint32 aim_locate_getcaps_short(OscarData *od, ByteStream *bs, int len); +guint64 aim_locate_getcaps(OscarData *od, ByteStream *bs, int len); +guint64 aim_locate_getcaps_short(OscarData *od, ByteStream *bs, int len); void aim_info_free(aim_userinfo_t *); int aim_info_extract(OscarData *od, ByteStream *bs, aim_userinfo_t *); int aim_putuserinfo(ByteStream *bs, aim_userinfo_t *info); @@ -1487,7 +1482,7 @@ int aim_tlvlist_add_16(GSList **list, const guint16 type, const guint16 value); int aim_tlvlist_add_32(GSList **list, const guint16 type, const guint32 value); int aim_tlvlist_add_str(GSList **list, const guint16 type, const char *value); -int aim_tlvlist_add_caps(GSList **list, const guint16 type, const guint32 caps, const char *mood); +int aim_tlvlist_add_caps(GSList **list, const guint16 type, const guint64 caps, const char *mood); int aim_tlvlist_add_userinfo(GSList **list, guint16 type, aim_userinfo_t *userinfo); int aim_tlvlist_add_chatroom(GSList **list, guint16 type, guint16 exchange, const char *roomname, guint16 instance); int aim_tlvlist_add_frozentlvlist(GSList **list, guint16 type, GSList **tl); @@ -1650,7 +1645,7 @@ int byte_stream_putstr(ByteStream *bs, const char *str); int byte_stream_putbs(ByteStream *bs, ByteStream *srcbs, int len); int byte_stream_putuid(ByteStream *bs, OscarData *od); -int byte_stream_putcaps(ByteStream *bs, guint32 caps); +int byte_stream_putcaps(ByteStream *bs, guint64 caps); /** * Inserts a BART asset block into the given byte stream. The flags @@ -1710,7 +1705,7 @@ IcbmCookie *aim_mkcookie(guint8 *, int, void *); IcbmCookie *aim_checkcookie(OscarData *, const unsigned char *, const int); int aim_freecookie(OscarData *od, IcbmCookie *cookie); -int aim_msgcookie_gettype(int type); +int aim_msgcookie_gettype(guint64 type); int aim_cookie_free(OscarData *od, IcbmCookie *cookie); int aim_chat_readroominfo(ByteStream *bs, struct aim_chat_roominfo *outinfo); diff -r c316749944c1 -r 2bdbf3fbd894 libpurple/protocols/oscar/peer.c --- a/libpurple/protocols/oscar/peer.c Sat Mar 13 08:18:25 2010 +0000 +++ b/libpurple/protocols/oscar/peer.c Fri Mar 26 00:43:51 2010 +0000 @@ -69,7 +69,7 @@ #endif PeerConnection * -peer_connection_find_by_type(OscarData *od, const char *bn, OscarCapability type) +peer_connection_find_by_type(OscarData *od, const char *bn, guint64 type) { GSList *cur; PeerConnection *conn; @@ -104,7 +104,7 @@ } PeerConnection * -peer_connection_new(OscarData *od, OscarCapability type, const char *bn) +peer_connection_new(OscarData *od, guint64 type, const char *bn) { PeerConnection *conn; PurpleAccount *account; @@ -897,7 +897,7 @@ * Initiate a peer connection with someone. */ void -peer_connection_propose(OscarData *od, OscarCapability type, const char *bn) +peer_connection_propose(OscarData *od, guint64 type, const char *bn) { PeerConnection *conn; diff -r c316749944c1 -r 2bdbf3fbd894 libpurple/protocols/oscar/peer.h --- a/libpurple/protocols/oscar/peer.h Sat Mar 13 08:18:25 2010 +0000 +++ b/libpurple/protocols/oscar/peer.h Fri Mar 26 00:43:51 2010 +0000 @@ -136,7 +136,7 @@ struct _PeerConnection { OscarData *od; - OscarCapability type; + guint64 type; char *bn; guchar magic[4]; guchar cookie[8]; @@ -228,11 +228,11 @@ * @param type The type of the peer connection. One of * OSCAR_CAPABILITY_DIRECTIM or OSCAR_CAPABILITY_SENDFILE. */ -PeerConnection *peer_connection_new(OscarData *od, OscarCapability type, const char *bn); +PeerConnection *peer_connection_new(OscarData *od, guint64 type, const char *bn); void peer_connection_destroy(PeerConnection *conn, OscarDisconnectReason reason, const gchar *error_message); void peer_connection_schedule_destroy(PeerConnection *conn, OscarDisconnectReason reason, const gchar *error_message); -PeerConnection *peer_connection_find_by_type(OscarData *od, const char *bn, OscarCapability type); +PeerConnection *peer_connection_find_by_type(OscarData *od, const char *bn, guint64 type); PeerConnection *peer_connection_find_by_cookie(OscarData *od, const char *bn, const guchar *cookie); void peer_connection_listen_cb(gpointer data, gint source, PurpleInputCondition cond); @@ -241,7 +241,7 @@ void peer_connection_trynext(PeerConnection *conn); void peer_connection_finalize_connection(PeerConnection *conn); -void peer_connection_propose(OscarData *od, OscarCapability type, const char *bn); +void peer_connection_propose(OscarData *od, guint64 type, const char *bn); void peer_connection_got_proposition(OscarData *od, const gchar *bn, const gchar *message, IcbmArgsCh2 *args); /* diff -r c316749944c1 -r 2bdbf3fbd894 libpurple/protocols/oscar/tlv.c --- a/libpurple/protocols/oscar/tlv.c Sat Mar 13 08:18:25 2010 +0000 +++ b/libpurple/protocols/oscar/tlv.c Fri Mar 26 00:43:51 2010 +0000 @@ -407,7 +407,7 @@ * @param caps Bitfield of capability flags to send * @return The size of the value added. */ -int aim_tlvlist_add_caps(GSList **list, const guint16 type, const guint32 caps, const char *mood) +int aim_tlvlist_add_caps(GSList **list, const guint16 type, const guint64 caps, const char *mood) { guint8 buf[256]; /* TODO: Don't use a fixed length buffer */ ByteStream bs; diff -r c316749944c1 -r 2bdbf3fbd894 libpurple/protocols/yahoo/libymsg.c --- a/libpurple/protocols/yahoo/libymsg.c Sat Mar 13 08:18:25 2010 +0000 +++ b/libpurple/protocols/yahoo/libymsg.c Fri Mar 26 00:43:51 2010 +0000 @@ -1854,6 +1854,7 @@ return; } else if (len > 0 && ret_data && *ret_data) { + PurpleAccount *account = purple_connection_get_account(gc); gchar **split_data = g_strsplit(ret_data, "\r\n", -1); int totalelements = 0; int response_no = -1; @@ -1861,11 +1862,13 @@ totalelements = g_strv_length(split_data); - if(totalelements == 1) + if(totalelements == 1) { /* Received an error code */ response_no = strtol(split_data[0], NULL, 10); - else if(totalelements >= 2) { + } else if(totalelements == 2 || totalelements == 3 ) { /* received valid data */ response_no = strtol(split_data[0], NULL, 10); token = g_strdup(split_data[1] + strlen("ymsgr=")); + } else { /* It looks like a transparent proxy has returned a document we don't want */ + response_no = -1; } g_strfreev(split_data); @@ -1884,8 +1887,8 @@ case 1212: /* Password incorrect */ /* Set password to NULL. Avoids account locking. Brings dialog to enter password if clicked on Re-enable account */ - if (!purple_account_get_remember_password(purple_connection_get_account(gc))) - purple_account_set_password(purple_connection_get_account(gc), NULL); + if (!purple_account_get_remember_password(account)) + purple_account_set_password(account, NULL); error_reason = g_strdup(_("Incorrect password")); error = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED; break; @@ -1927,7 +1930,6 @@ else { /* OK to login, correct information provided */ PurpleUtilFetchUrlData *url_data = NULL; - PurpleAccount *account = purple_connection_get_account(gc); char *url = NULL; gboolean yahoojp = yahoo_is_japan(account); gboolean proxy_ssl = purple_account_get_bool(account, "proxy_ssl", FALSE); @@ -2731,8 +2733,9 @@ PurpleAccount *account; YahooFriend *f; - /* if status is not 1 ie YAHOO_STATUS_BRB, the packet bounced back, so contains our own ip */ - if(!(pkt->status == YAHOO_STATUS_BRB)) + /* if status is not YAHOO_STATUS_BRB or YAHOO_STATUS_P2P, the packet bounced back, + * so it contains our own ip */ + if(pkt->status != YAHOO_STATUS_BRB && pkt->status != YAHOO_STATUS_P2P) return ; while (l) { diff -r c316749944c1 -r 2bdbf3fbd894 libpurple/protocols/yahoo/libymsg.h --- a/libpurple/protocols/yahoo/libymsg.h Sat Mar 13 08:18:25 2010 +0000 +++ b/libpurple/protocols/yahoo/libymsg.h Fri Mar 26 00:43:51 2010 +0000 @@ -90,8 +90,8 @@ #define YAHOO_CLIENT_VERSION_ID "4194239" #define YAHOO_CLIENT_VERSION "9.0.0.2162" -#define YAHOOJP_CLIENT_VERSION_ID "4194239" -#define YAHOOJP_CLIENT_VERSION "9.0.0.2162" +#define YAHOOJP_CLIENT_VERSION_ID "4186047" +#define YAHOOJP_CLIENT_VERSION "9.0.0.1727" #define YAHOO_CLIENT_USERAGENT "Mozilla/5.0" @@ -119,6 +119,7 @@ YAHOO_STATUS_ONVACATION, YAHOO_STATUS_OUTTOLUNCH, YAHOO_STATUS_STEPPEDOUT, + YAHOO_STATUS_P2P = 11, YAHOO_STATUS_INVISIBLE = 12, YAHOO_STATUS_CUSTOM = 99, YAHOO_STATUS_IDLE = 999, diff -r c316749944c1 -r 2bdbf3fbd894 libpurple/win32/global.mak --- a/libpurple/win32/global.mak Sat Mar 13 08:18:25 2010 +0000 +++ b/libpurple/win32/global.mak Fri Mar 26 00:43:51 2010 +0000 @@ -105,7 +105,7 @@ GMSGFMT ?= $(WIN32_DEV_TOP)/gettext-0.17/bin/msgfmt MAKENSIS ?= makensis.exe MAKENSISOPT ?= / -PERL ?= /cygdrive/c/perl/bin/perl +PERL ?= perl WINDRES ?= windres STRIP ?= strip diff -r c316749944c1 -r 2bdbf3fbd894 libpurple/win32/rules.mak --- a/libpurple/win32/rules.mak Sat Mar 13 08:18:25 2010 +0000 +++ b/libpurple/win32/rules.mak Fri Mar 26 00:43:51 2010 +0000 @@ -4,7 +4,7 @@ $(CC) $(CFLAGS) $(DEFINES) $(INCLUDE_PATHS) -o $@ -c $< %.c: %.xs - $(PERL) $(EXTUTILS)/xsubpp -typemap $(EXTUTILS)/typemap -typemap $(PURPLE_PERL_TOP)/common/typemap $< > $@ + $(PERL) -MExtUtils::ParseXS -e 'ExtUtils::ParseXS::process_file(filename => "$<", output => "$@", typemap => "$(PURPLE_PERL_TOP)/common/typemap");' %.o: %.rc $(WINDRES) -I$(PURPLE_TOP) -i $< -o $@ diff -r c316749944c1 -r 2bdbf3fbd894 pidgin/gtkblist.c --- a/pidgin/gtkblist.c Sat Mar 13 08:18:25 2010 +0000 +++ b/pidgin/gtkblist.c Fri Mar 26 00:43:51 2010 +0000 @@ -70,8 +70,6 @@ #include #include -#define HEADLINE_CLOSE_SIZE 11 - typedef struct { PurpleAccount *account; @@ -120,7 +118,6 @@ PidginMiniDialog *signed_on_elsewhere; PidginBlistTheme *current_theme; - } PidginBuddyListPrivate; #define PIDGIN_BUDDY_LIST_GET_PRIVATE(list) \ @@ -3384,6 +3381,266 @@ !purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/debug/enabled")); } +static char *get_mood_icon_path(const char *mood) +{ + char *path; + + if (!strcmp(mood, "busy")) { + path = g_build_filename(DATADIR, "pixmaps", "pidgin", + "status", "16", "busy.png", NULL); + } else if (!strcmp(mood, "hiptop")) { + path = g_build_filename(DATADIR, "pixmaps", "pidgin", + "emblems", "16", "hiptop.png", NULL); + } else { + char *filename = g_strdup_printf("%s.png", mood); + path = g_build_filename(DATADIR, "pixmaps", "pidgin", + "emotes", "small", filename, NULL); + g_free(filename); + } + return path; +} + +static void +update_status_with_mood(PurpleAccount *account, const gchar *mood, + const gchar *text) +{ + if (mood && *mood) { + if (text) { + purple_account_set_status(account, "mood", TRUE, + PURPLE_MOOD_NAME, mood, + PURPLE_MOOD_COMMENT, text, + NULL); + } else { + purple_account_set_status(account, "mood", TRUE, + PURPLE_MOOD_NAME, mood, + NULL); + } + } else { + purple_account_set_status(account, "mood", FALSE, NULL); + } +} + +static void +edit_mood_cb(PurpleConnection *gc, PurpleRequestFields *fields) +{ + PurpleRequestField *mood_field; + GList *l; + + mood_field = purple_request_fields_get_field(fields, "mood"); + l = purple_request_field_list_get_selected(mood_field); + + if (l) { + const char *mood = purple_request_field_list_get_data(mood_field, l->data); + + if (gc) { + const char *text; + PurpleAccount *account = purple_connection_get_account(gc); + + if (gc->flags & PURPLE_CONNECTION_SUPPORT_MOOD_MESSAGES) { + PurpleRequestField *text_field; + text_field = purple_request_fields_get_field(fields, "text"); + text = purple_request_field_string_get_value(text_field); + } else { + text = NULL; + } + + update_status_with_mood(account, mood, text); + } else { + GList *accounts = purple_accounts_get_all_active(); + + for (; accounts ; accounts = g_list_delete_link(accounts, accounts)) { + PurpleAccount *account = (PurpleAccount *) accounts->data; + PurpleConnection *gc = purple_account_get_connection(account); + + if (gc->flags & PURPLE_CONNECTION_SUPPORT_MOODS) { + update_status_with_mood(account, mood, NULL); + } + } + } + } +} + +static void +global_moods_for_each(gpointer key, gpointer value, gpointer user_data) +{ + GList **out_moods = (GList **) user_data; + PurpleMood *mood = (PurpleMood *) value; + + *out_moods = g_list_append(*out_moods, mood); +} + +static PurpleMood * +get_global_moods(void) +{ + GHashTable *global_moods = + g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL); + GHashTable *mood_counts = + g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL); + GList *accounts = purple_accounts_get_all_active(); + PurpleMood *result = NULL; + GList *out_moods = NULL; + int i = 0; + int num_accounts = 0; + + for (; accounts ; accounts = g_list_delete_link(accounts, accounts)) { + PurpleAccount *account = (PurpleAccount *) accounts->data; + PurpleConnection *gc = purple_account_get_connection(account); + + if (gc->flags & PURPLE_CONNECTION_SUPPORT_MOODS) { + PurplePluginProtocolInfo *prpl_info = + PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); + PurpleMood *mood = NULL; + + /* PURPLE_CONNECTION_SUPPORT_MOODS would not be set if the prpl doesn't + * have get_moods, so using PURPLE_PROTOCOL_PLUGIN_HAS_FUNC isn't necessary + * here */ + for (mood = prpl_info->get_moods(account) ; + mood->mood != NULL ; mood++) { + int mood_count = + GPOINTER_TO_INT(g_hash_table_lookup(mood_counts, mood->mood)); + + if (!g_hash_table_lookup(global_moods, mood->mood)) { + g_hash_table_insert(global_moods, (gpointer)mood->mood, mood); + } + g_hash_table_insert(mood_counts, (gpointer)mood->mood, + GINT_TO_POINTER(mood_count + 1)); + } + + num_accounts++; + } + } + + g_hash_table_foreach(global_moods, global_moods_for_each, &out_moods); + result = g_new0(PurpleMood, g_hash_table_size(global_moods) + 1); + + while (out_moods) { + PurpleMood *mood = (PurpleMood *) out_moods->data; + int in_num_accounts = + GPOINTER_TO_INT(g_hash_table_lookup(mood_counts, mood->mood)); + + if (in_num_accounts == num_accounts) { + /* mood is present in all accounts supporting moods */ + result[i].mood = mood->mood; + result[i].description = mood->description; + i++; + } + out_moods = g_list_delete_link(out_moods, out_moods); + } + + g_hash_table_destroy(global_moods); + g_hash_table_destroy(mood_counts); + + return result; +} + +/* get current set mood for all mood-supporting accounts, or NULL if not set + or not set to the same on all */ +static const gchar * +get_global_mood_status(void) +{ + GList *accounts = purple_accounts_get_all_active(); + const gchar *found_mood = NULL; + + for (; accounts ; accounts = g_list_delete_link(accounts, accounts)) { + PurpleAccount *account = (PurpleAccount *) accounts->data; + + if (purple_account_get_connection(account)->flags & + PURPLE_CONNECTION_SUPPORT_MOODS) { + PurplePresence *presence = purple_account_get_presence(account); + PurpleStatus *status = purple_presence_get_status(presence, "mood"); + const gchar *curr_mood = purple_status_get_attr_string(status, PURPLE_MOOD_NAME); + + if (found_mood != NULL && !purple_strequal(curr_mood, found_mood)) { + /* found a different mood */ + found_mood = NULL; + break; + } else { + found_mood = curr_mood; + } + } + } + + return found_mood; +} + +static void +set_mood_cb(GtkWidget *widget, PurpleAccount *account) +{ + const char *current_mood; + PurpleRequestFields *fields; + PurpleRequestFieldGroup *g; + PurpleRequestField *f; + PurpleConnection *gc = NULL; + PurplePluginProtocolInfo *prpl_info = NULL; + PurpleMood *mood; + PurpleMood *global_moods = get_global_moods(); + + if (account) { + PurplePresence *presence = purple_account_get_presence(account); + PurpleStatus *status = purple_presence_get_status(presence, "mood"); + gc = purple_account_get_connection(account); + g_return_if_fail(gc->prpl != NULL); + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); + current_mood = purple_status_get_attr_string(status, PURPLE_MOOD_NAME); + } else { + current_mood = get_global_mood_status(); + } + + fields = purple_request_fields_new(); + g = purple_request_field_group_new(NULL); + f = purple_request_field_list_new("mood", _("Please select your mood from the list")); + + purple_request_field_list_add(f, _("None"), ""); + if (current_mood == NULL) + purple_request_field_list_add_selected(f, _("None")); + + /* TODO: rlaager wants this sorted. */ + /* The connection is checked for PURPLE_CONNECTION_SUPPORT_MOODS flag before + * this function is called for a non-null account. So using + * PURPLE_PROTOCOL_PLUGIN_HAS_FUNC isn't necessary here */ + for (mood = account ? prpl_info->get_moods(account) : global_moods; + mood->mood != NULL ; mood++) { + char *path; + + if (mood->mood == NULL || mood->description == NULL) + continue; + + path = get_mood_icon_path(mood->mood); + purple_request_field_list_add_icon(f, _(mood->description), + path, (gpointer)mood->mood); + g_free(path); + + if (current_mood && !strcmp(current_mood, mood->mood)) + purple_request_field_list_add_selected(f, _(mood->description)); + } + purple_request_field_group_add_field(g, f); + + purple_request_fields_add_group(fields, g); + + /* if the connection allows setting a mood message */ + if (gc && (gc->flags & PURPLE_CONNECTION_SUPPORT_MOOD_MESSAGES)) { + g = purple_request_field_group_new(NULL); + f = purple_request_field_string_new("text", + _("Message (optional)"), NULL, FALSE); + purple_request_field_group_add_field(g, f); + purple_request_fields_add_group(fields, g); + } + + purple_request_fields(gc, _("Edit User Mood"), _("Edit User Mood"), + NULL, fields, + _("OK"), G_CALLBACK(edit_mood_cb), + _("Cancel"), NULL, + gc ? purple_connection_get_account(gc) : NULL, + NULL, NULL, gc); + + g_free(global_moods); +} + +static void +set_mood_show(void) +{ + set_mood_cb(NULL, NULL); +} /*************************************************** * Crap * @@ -3423,6 +3680,7 @@ { N_("/Tools/Plu_gins"), "U", pidgin_plugin_dialog_show, 2, "", PIDGIN_STOCK_TOOLBAR_PLUGINS }, { N_("/Tools/Pr_eferences"), "P", pidgin_prefs_show, 0, "", GTK_STOCK_PREFERENCES }, { N_("/Tools/Pr_ivacy"), NULL, pidgin_privacy_dialog_show, 0, "", NULL }, + { N_("/Tools/Set _Mood"), "M", set_mood_show, 0, "", NULL }, { "/Tools/sep2", NULL, NULL, 0, "", NULL }, { N_("/Tools/_File Transfers"), "T", pidgin_xfer_dialog_show, 0, "", PIDGIN_STOCK_TOOLBAR_TRANSFER }, { N_("/Tools/R_oom List"), NULL, pidgin_roomlist_dialog_show, 0, "", NULL }, @@ -3754,25 +4012,6 @@ return pb; } -static char *get_mood_icon_path(const char *mood) -{ - char *path; - - if (!strcmp(mood, "busy")) { - path = g_build_filename(DATADIR, "pixmaps", "pidgin", - "status", "16", "busy.png", NULL); - } else if (!strcmp(mood, "hiptop")) { - path = g_build_filename(DATADIR, "pixmaps", "pidgin", - "emblems", "16", "hiptop.png", NULL); - } else { - char *filename = g_strdup_printf("%s.png", mood); - path = g_build_filename(DATADIR, "pixmaps", "pidgin", - "emotes", "small", filename, NULL); - g_free(filename); - } - return path; -} - GdkPixbuf * pidgin_blist_get_emblem(PurpleBlistNode *node) { @@ -4044,7 +4283,12 @@ else name = purple_buddy_get_alias(b); - nametext = g_markup_escape_text(name, strlen(name)); + /* Raise a contact pre-draw signal here. THe callback will return an + * escaped version of the name. */ + nametext = purple_signal_emit_return_1(pidgin_blist_get_handle(), "drawing-buddy", b); + + if(!nametext) + nametext = g_markup_escape_text(name, strlen(name)); presence = purple_buddy_get_presence(b); @@ -4754,58 +4998,16 @@ } static gboolean -headline_hover_close(int x, int y) -{ - GtkWidget *w = gtkblist->headline_hbox; - if (x <= w->allocation.width && x >= w->allocation.width - HEADLINE_CLOSE_SIZE && - y >= 0 && y <= HEADLINE_CLOSE_SIZE) - return TRUE; - return FALSE; -} - -static gboolean headline_box_enter_cb(GtkWidget *widget, GdkEventCrossing *event, PidginBuddyList *gtkblist) { gdk_window_set_cursor(widget->window, gtkblist->hand_cursor); - - if (gtkblist->headline_close) { - gdk_draw_pixbuf(widget->window, NULL, gtkblist->headline_close, - 0, 0, - widget->allocation.width - 2 - HEADLINE_CLOSE_SIZE, 2, - HEADLINE_CLOSE_SIZE, HEADLINE_CLOSE_SIZE, - GDK_RGB_DITHER_NONE, 0, 0); - gtk_paint_focus(widget->style, widget->window, GTK_STATE_PRELIGHT, - NULL, widget, NULL, - widget->allocation.width - HEADLINE_CLOSE_SIZE - 3, 1, - HEADLINE_CLOSE_SIZE + 2, HEADLINE_CLOSE_SIZE + 2); - } - return FALSE; } -#if 0 -static gboolean -headline_box_motion_cb(GtkWidget *widget, GdkEventMotion *event, PidginBuddyList *gtkblist) -{ - purple_debug_fatal("motion", "%d %d\n", (int)event->x, (int)event->y); - if (headline_hover_close((int)event->x, (int)event->y)) - gtk_paint_focus(widget->style, widget->window, GTK_STATE_PRELIGHT, - NULL, widget, NULL, - widget->allocation.width - HEADLINE_CLOSE_SIZE - 3, 1, - HEADLINE_CLOSE_SIZE + 2, HEADLINE_CLOSE_SIZE + 2); - return FALSE; -} -#endif - static gboolean headline_box_leave_cb(GtkWidget *widget, GdkEventCrossing *event, PidginBuddyList *gtkblist) { gdk_window_set_cursor(widget->window, gtkblist->arrow_cursor); - if (gtkblist->headline_close) { - GdkRectangle rect = {widget->allocation.width - 3 - HEADLINE_CLOSE_SIZE, 1, - HEADLINE_CLOSE_SIZE + 2, HEADLINE_CLOSE_SIZE + 2}; - gdk_window_invalidate_rect(widget->window, &rect, TRUE); - } return FALSE; } @@ -4828,10 +5030,17 @@ } static gboolean +headline_close_press_cb(GtkButton *button, PidginBuddyList *gtkblist) +{ + gtk_widget_hide(gtkblist->headline_hbox); + return FALSE; +} + +static gboolean headline_box_press_cb(GtkWidget *widget, GdkEventButton *event, PidginBuddyList *gtkblist) { gtk_widget_hide(gtkblist->headline_hbox); - if (gtkblist->headline_callback && !headline_hover_close((int)event->x, (int)event->y)) + if (gtkblist->headline_callback) g_idle_add(headline_click_callback, NULL); else { if (gtkblist->headline_destroy) @@ -5583,6 +5792,7 @@ GtkWidget *sw; GtkWidget *sep; GtkWidget *label; + GtkWidget *close; char *pretty, *tmp; const char *theme_name; GtkAccelGroup *accel_group; @@ -5716,16 +5926,18 @@ gtkblist->hand_cursor = gdk_cursor_new (GDK_HAND2); gtkblist->arrow_cursor = gdk_cursor_new (GDK_LEFT_PTR); + /* Close button. */ + close = gtk_image_new_from_stock(GTK_STOCK_CLOSE, GTK_ICON_SIZE_MENU); + close = pidgin_create_small_button(close); + gtk_box_pack_start(GTK_BOX(gtkblist->headline_hbox), close, FALSE, FALSE, 0); +#if GTK_CHECK_VERSION(2,12,0) + gtk_widget_set_tooltip_text(close, _("Close")); +#endif + g_signal_connect(close, "clicked", G_CALLBACK(headline_close_press_cb), gtkblist); + g_signal_connect(G_OBJECT(ebox), "enter-notify-event", G_CALLBACK(headline_box_enter_cb), gtkblist); g_signal_connect(G_OBJECT(ebox), "leave-notify-event", G_CALLBACK(headline_box_leave_cb), gtkblist); g_signal_connect(G_OBJECT(ebox), "button-press-event", G_CALLBACK(headline_box_press_cb), gtkblist); -#if 0 - /* I couldn't get this to work. The idea was to draw the focus-border only - * when hovering over the close image. So for now, the focus-border is - * always there. -- sad */ - gtk_widget_set_events(ebox, gtk_widget_get_events(ebox) | GDK_POINTER_MOTION_HINT_MASK); - g_signal_connect(G_OBJECT(ebox), "motion-notify-event", G_CALLBACK(headline_box_motion_cb), gtkblist); -#endif /****************************** GtkTreeView **********************************/ sw = gtk_scrolled_window_new(NULL,NULL); @@ -6720,7 +6932,7 @@ purple_signals_disconnect_by_handle(gtkblist); if (gtkblist->headline_close) - g_object_unref(G_OBJECT(gtkblist->headline_close)); + gdk_pixbuf_unref(gtkblist->headline_close); gtk_widget_destroy(gtkblist->window); @@ -7400,10 +7612,19 @@ purple_value_new_outgoing(PURPLE_TYPE_BOXED, "GString *"), purple_value_new(PURPLE_TYPE_BOOLEAN)); - - purple_signal_connect(purple_blist_get_handle(), "buddy-signed-on", gtk_blist_handle, PURPLE_CALLBACK(buddy_signonoff_cb), NULL); - purple_signal_connect(purple_blist_get_handle(), "buddy-signed-off", gtk_blist_handle, PURPLE_CALLBACK(buddy_signonoff_cb), NULL); - purple_signal_connect(purple_blist_get_handle(), "buddy-privacy-changed", gtk_blist_handle, PURPLE_CALLBACK(pidgin_blist_update_privacy_cb), NULL); + purple_signal_register(gtk_blist_handle, "drawing-buddy", + purple_marshal_POINTER__POINTER, + purple_value_new(PURPLE_TYPE_STRING), 1, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_BLIST_BUDDY)); + + purple_signal_connect(purple_blist_get_handle(), "buddy-signed-on", + gtk_blist_handle, PURPLE_CALLBACK(buddy_signonoff_cb), NULL); + purple_signal_connect(purple_blist_get_handle(), "buddy-signed-off", + gtk_blist_handle, PURPLE_CALLBACK(buddy_signonoff_cb), NULL); + purple_signal_connect(purple_blist_get_handle(), "buddy-privacy-changed", + gtk_blist_handle, PURPLE_CALLBACK(pidgin_blist_update_privacy_cb), NULL); + } void @@ -7815,100 +8036,7 @@ purple_account_set_enabled(account, PIDGIN_UI, FALSE); } -static void -edit_mood_cb(PurpleConnection *gc, PurpleRequestFields *fields) -{ - PurpleRequestField *mood_field, *text_field; - GList *l; - - mood_field = purple_request_fields_get_field(fields, "mood"); - text_field = purple_request_fields_get_field(fields, "text"); - l = purple_request_field_list_get_selected(mood_field); - - if (l) { - const char *mood = purple_request_field_list_get_data(mood_field, l->data); - const char *text = purple_request_field_string_get_value(text_field); - PurpleAccount *account = purple_connection_get_account(gc); - - if (mood != NULL && !purple_strequal(mood, "")) { - if (text) { - purple_account_set_status(account, "mood", TRUE, - PURPLE_MOOD_NAME, mood, - PURPLE_MOOD_COMMENT, text, - NULL); - } else { - purple_account_set_status(account, "mood", TRUE, - PURPLE_MOOD_NAME, mood, - NULL); - } - } else { - purple_account_set_status(account, "mood", FALSE, NULL); - } - } -} - -static void -set_mood_cb(GtkWidget *widget, PurpleAccount *account) -{ - PurplePresence *presence = purple_account_get_presence(account); - PurpleStatus *status = purple_presence_get_status(presence, "mood"); - const char *current_mood; - PurpleRequestFields *fields; - PurpleRequestFieldGroup *g; - PurpleRequestField *f; - PurpleConnection *gc = purple_account_get_connection(account); - PurplePluginProtocolInfo *prpl_info; - PurpleMood *mood; - - g_return_if_fail(gc->prpl != NULL); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); - - current_mood = purple_status_get_attr_string(status, PURPLE_MOOD_NAME); - - fields = purple_request_fields_new(); - g = purple_request_field_group_new(NULL); - f = purple_request_field_list_new("mood", _("Please select your mood from the list")); - - purple_request_field_list_add(f, _("None"), ""); - if (current_mood == NULL) - purple_request_field_list_add_selected(f, _("None")); - - /* TODO: rlaager wants this sorted. */ - for (mood = prpl_info->get_moods(account); - mood->mood != NULL ; mood++) { - char *path; - - if (mood->mood == NULL || mood->description == NULL) - continue; - - path = get_mood_icon_path(mood->mood); - purple_request_field_list_add_icon(f, _(mood->description), - path, (gpointer)mood->mood); - g_free(path); - - if (current_mood && !strcmp(current_mood, mood->mood)) - purple_request_field_list_add_selected(f, _(mood->description)); - } - purple_request_field_group_add_field(g, f); - - purple_request_fields_add_group(fields, g); - - /* if the connection allows setting a mood message */ - if (gc->flags & PURPLE_CONNECTION_SUPPORT_MOOD_MESSAGES) { - g = purple_request_field_group_new(NULL); - f = purple_request_field_string_new("text", - _("Message (optional)"), NULL, FALSE); - purple_request_field_group_add_field(g, f); - purple_request_fields_add_group(fields, g); - } - - purple_request_fields(gc, _("Edit User Mood"), _("Edit User Mood"), - NULL, fields, - _("OK"), G_CALLBACK(edit_mood_cb), - _("Cancel"), NULL, - purple_connection_get_account(gc), - NULL, NULL, gc); -} + void pidgin_blist_update_accounts_menu(void) @@ -8036,22 +8164,12 @@ PURPLE_PLUGIN_HAS_ACTIONS(plugin))) { if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, get_moods) && gc->flags & PURPLE_CONNECTION_SUPPORT_MOODS) { - GList *types; - - for (types = purple_account_get_status_types(account); - types != NULL ; types = types->next) { - PurpleStatusType *type = types->data; - - if (strcmp(purple_status_type_get_id(type), "mood") != 0) - continue; - + + if (purple_account_get_status(account, "mood")) { menuitem = gtk_menu_item_new_with_mnemonic(_("Set _Mood...")); g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(set_mood_cb), account); gtk_menu_shell_append(GTK_MENU_SHELL(submenu), menuitem); - - /* Be safe. It shouldn't match more than once anyway */ - break; } } if (PURPLE_PLUGIN_HAS_ACTIONS(plugin)) { diff -r c316749944c1 -r 2bdbf3fbd894 pidgin/gtkblist.h --- a/pidgin/gtkblist.h Sat Mar 13 08:18:25 2010 +0000 +++ b/pidgin/gtkblist.h Fri Mar 26 00:43:51 2010 +0000 @@ -119,7 +119,7 @@ GtkWidget *headline_hbox; /**< Hbox for headline notification */ GtkWidget *headline_label; /**< Label for headline notifications */ GtkWidget *headline_image; /**< Image for headline notifications */ - GdkPixbuf *headline_close; /**< Close image for closing the headline without triggering the callback */ + GdkPixbuf *headline_close; /**< @deprecated: Close image for closing the headline without triggering the callback */ GCallback headline_callback; /**< Callback for headline notifications */ gpointer headline_data; /**< User data for headline notifications */ GDestroyNotify headline_destroy; /**< Callback to use for destroying the headline-data */ diff -r c316749944c1 -r 2bdbf3fbd894 pidgin/gtkconv.c --- a/pidgin/gtkconv.c Sat Mar 13 08:18:25 2010 +0000 +++ b/pidgin/gtkconv.c Fri Mar 26 00:43:51 2010 +0000 @@ -229,7 +229,7 @@ } static gboolean -close_conv_cb(GtkWidget *w, GdkEventButton *dontuse, PidginConversation *gtkconv) +close_conv_cb(GtkButton *button, PidginConversation *gtkconv) { /* We are going to destroy the conversations immediately only if the 'close immediately' * preference is selected. Otherwise, close the conversation after a reasonable timeout @@ -1325,7 +1325,7 @@ { PidginWindow *win = data; - close_conv_cb(NULL, NULL, PIDGIN_CONVERSATION(pidgin_conv_window_get_active_conversation(win))); + close_conv_cb(NULL, PIDGIN_CONVERSATION(pidgin_conv_window_get_active_conversation(win))); } static void @@ -4824,52 +4824,6 @@ return FALSE; } -/* Close button {{{ */ -static gboolean -close_button_left_cb(GtkWidget *widget, GdkEventCrossing *event, GtkLabel *label) -{ - static GdkCursor *ptr = NULL; - if (ptr == NULL) { - ptr = gdk_cursor_new(GDK_LEFT_PTR); - } - - gtk_label_set_markup(label, "×"); - gdk_window_set_cursor(event->window, ptr); - return FALSE; -} - -static gboolean -close_button_entered_cb(GtkWidget *widget, GdkEventCrossing *event, GtkLabel *label) -{ - static GdkCursor *hand = NULL; - if (hand == NULL) { - hand = gdk_cursor_new(GDK_HAND2); - } - - gtk_label_set_markup(label, "×"); - gdk_window_set_cursor(event->window, hand); - return FALSE; -} - -static GtkWidget * -create_close_button(void) -{ - GtkWidget *ebox = gtk_event_box_new(); - GtkWidget *close_image; - - gtk_event_box_set_visible_window(GTK_EVENT_BOX(ebox), FALSE); - gtk_widget_set_events(ebox, GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK); - close_image = gtk_label_new("×"); - g_signal_connect(G_OBJECT(ebox), "enter-notify-event", G_CALLBACK(close_button_entered_cb), close_image); - g_signal_connect(G_OBJECT(ebox), "leave-notify-event", G_CALLBACK(close_button_left_cb), close_image); - gtk_widget_show(close_image); - gtk_container_add(GTK_CONTAINER(ebox), close_image); - - return ebox; -} - -/* }}} */ - /* Quick Find {{{ */ static gboolean pidgin_conv_end_quickfind(PidginConversation *gtkconv) @@ -4912,11 +4866,12 @@ pidgin_conv_setup_quickfind(PidginConversation *gtkconv, GtkWidget *container) { GtkWidget *widget = gtk_hbox_new(FALSE, 0); - GtkWidget *label, *entry, *close; + GtkWidget *label, *entry, *close, *image; gtk_box_pack_start(GTK_BOX(container), widget, FALSE, FALSE, 0); - close = create_close_button(); + image = gtk_image_new_from_stock(GTK_STOCK_CLOSE, GTK_ICON_SIZE_MENU); + close = pidgin_create_small_button(image); gtk_box_pack_start(GTK_BOX(widget), close, FALSE, FALSE, 0); gtk_tooltips_set_tip(gtkconv->tooltips, close, _("Close Find bar"), NULL); @@ -8677,7 +8632,7 @@ return FALSE; gtkconv = pidgin_conv_window_get_gtkconv_at_index(win, tab_clicked); - close_conv_cb(NULL, NULL, gtkconv); + close_conv_cb(NULL, gtkconv); return TRUE; } @@ -8945,7 +8900,7 @@ if (gconv != gtkconv) { - close_conv_cb(NULL, NULL, gconv); + close_conv_cb(NULL, gconv); } } } @@ -8957,7 +8912,7 @@ gtkconv = g_object_get_data(menu, "clicked_tab"); if (gtkconv) - close_conv_cb(NULL, NULL, gtkconv); + close_conv_cb(NULL, gtkconv); } static gboolean @@ -9421,7 +9376,7 @@ if (win->gtkconvs) { while (win->gtkconvs) { gboolean last = (win->gtkconvs->next == NULL); - close_conv_cb(NULL, NULL, win->gtkconvs->data); + close_conv_cb(NULL, win->gtkconvs->data); if (last) break; } @@ -9495,6 +9450,7 @@ GtkWidget *tab_cont = gtkconv->tab_cont; PurpleConversationType conv_type; const gchar *tmp_lab; + GtkWidget *close_image; conv_type = purple_conversation_get_type(conv); @@ -9506,12 +9462,12 @@ /* Close button. */ - gtkconv->close = create_close_button(); + close_image = gtk_image_new_from_stock(GTK_STOCK_CLOSE, GTK_ICON_SIZE_MENU); + gtkconv->close = pidgin_create_small_button(close_image); gtk_tooltips_set_tip(gtkconv->tooltips, gtkconv->close, _("Close conversation"), NULL); - g_signal_connect(G_OBJECT(gtkconv->close), "button-press-event", - G_CALLBACK(close_conv_cb), gtkconv); + g_signal_connect(gtkconv->close, "clicked", G_CALLBACK (close_conv_cb), gtkconv); /* Status icon. */ gtkconv->icon = gtk_image_new(); diff -r c316749944c1 -r 2bdbf3fbd894 pidgin/gtkdialogs.c --- a/pidgin/gtkdialogs.c Sat Mar 13 08:18:25 2010 +0000 +++ b/pidgin/gtkdialogs.c Fri Mar 26 00:43:51 2010 +0000 @@ -76,7 +76,6 @@ {"John 'rekkanoryo' Bailey", N_("bug master"), NULL}, {"Ethan 'Paco-Paco' Blanton", NULL, NULL}, {"Hylke Bons", N_("artist"), "hylkebons@gmail.com"}, - {"Thomas Butter", NULL, NULL}, /* feel free to not translate this */ {N_("Ka-Hing Cheung"), NULL, NULL}, {"Sadrul Habib Chowdhury", NULL, NULL}, @@ -87,8 +86,6 @@ {"Richard 'rlaager' Laager", NULL, "rlaager@pidgin.im"}, {"Sulabh 'sulabh_m' Mahajan", NULL, NULL}, {"Richard 'wabz' Nelson", NULL, NULL}, - {"Christopher 'siege' O'Brien", NULL, "taliesein@users.sf.net"}, - {"Bartosz Oler", NULL, NULL}, {"Etan 'deryni' Reisner", NULL, NULL}, {"Tim 'marv' Ringenbach", NULL, NULL}, {"Michael 'Maiku' Ruprecht", N_("voice and video"), NULL}, @@ -114,12 +111,15 @@ /* Order: Alphabetical by Last Name */ static const struct developer retired_developers[] = { {"Herman Bloggs", N_("win32 port"), "herman@bluedigits.com"}, + {"Thomas Butter", NULL, NULL}, {"Jim Duchek", N_("maintainer"), "jim@linuxpimps.com"}, {"Rob Flynn", N_("maintainer"), NULL}, {"Adam Fritzler", N_("libfaim maintainer"), NULL}, {"Christian 'ChipX86' Hammond", N_("webmaster"), NULL}, /* If "lazy bum" translates literally into a serious insult, use something else or omit it. */ {"Syd Logan", N_("hacker and designated driver [lazy bum]"), NULL}, + {"Christopher 'siege' O'Brien", NULL, "taliesein@users.sf.net"}, + {"Bartosz Oler", NULL, NULL}, {"Megan 'Cae' Schneider", N_("support/QA"), NULL}, {"Jim Seymour", N_("XMPP"), NULL}, {"Mark Spencer", N_("original author"), "markster@marko.net"}, diff -r c316749944c1 -r 2bdbf3fbd894 pidgin/gtkimhtml.c --- a/pidgin/gtkimhtml.c Sat Mar 13 08:18:25 2010 +0000 +++ b/pidgin/gtkimhtml.c Fri Mar 26 00:43:51 2010 +0000 @@ -152,6 +152,7 @@ MESSAGE_SEND, UNDO, REDO, + PASTE, LAST_SIGNAL }; static guint signals [LAST_SIGNAL] = { 0 }; @@ -1343,6 +1344,15 @@ return FALSE; } +static void +imhtml_paste_cb(GtkIMHtml *imhtml, const char *str) +{ + if (!str || !*str || !strcmp(str, "html")) + g_signal_emit_by_name(imhtml, "paste_clipboard"); + else if (!strcmp(str, "text")) + paste_unformatted_cb(NULL, imhtml); +} + static void imhtml_toggle_format(GtkIMHtml *imhtml, GtkIMHtmlButtons buttons) { /* since this function is the handler for the formatting keystrokes, @@ -1513,24 +1523,31 @@ NULL, 0, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); - signals [UNDO] = g_signal_new ("undo", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, - G_STRUCT_OFFSET (GtkIMHtmlClass, undo), - NULL, - NULL, - gtksourceview_marshal_VOID__VOID, - G_TYPE_NONE, - 0); - signals [REDO] = g_signal_new ("redo", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, - G_STRUCT_OFFSET (GtkIMHtmlClass, redo), - NULL, - NULL, - gtksourceview_marshal_VOID__VOID, - G_TYPE_NONE, - 0); + signals[PASTE] = g_signal_new("paste", + G_TYPE_FROM_CLASS(gobject_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + 0, + NULL, + 0, g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, G_TYPE_STRING); + signals [UNDO] = g_signal_new ("undo", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (GtkIMHtmlClass, undo), + NULL, + NULL, + gtksourceview_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + signals [REDO] = g_signal_new ("redo", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (GtkIMHtmlClass, redo), + NULL, + NULL, + gtksourceview_marshal_VOID__VOID, + G_TYPE_NONE, + 0); @@ -1615,10 +1632,10 @@ gtk_binding_entry_add_signal (binding_set, GDK_r, GDK_CONTROL_MASK, "format_function_clear", 0); gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0, "message_send", 0); gtk_binding_entry_add_signal (binding_set, GDK_Return, 0, "message_send", 0); - gtk_binding_entry_add_signal (binding_set, GDK_z, GDK_CONTROL_MASK, "undo", 0); - gtk_binding_entry_add_signal (binding_set, GDK_z, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "redo", 0); - gtk_binding_entry_add_signal (binding_set, GDK_F14, 0, "undo", 0); - + gtk_binding_entry_add_signal (binding_set, GDK_z, GDK_CONTROL_MASK, "undo", 0); + gtk_binding_entry_add_signal (binding_set, GDK_z, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "redo", 0); + gtk_binding_entry_add_signal (binding_set, GDK_F14, 0, "undo", 0); + gtk_binding_entry_add_signal(binding_set, GDK_v, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "paste", 1, G_TYPE_STRING, "text"); } static void gtk_imhtml_init (GtkIMHtml *imhtml) @@ -1689,6 +1706,7 @@ g_signal_connect(G_OBJECT(imhtml), "paste-clipboard", G_CALLBACK(paste_clipboard_cb), NULL); g_signal_connect_after(G_OBJECT(imhtml), "realize", G_CALLBACK(imhtml_realized_remove_primary), NULL); g_signal_connect(G_OBJECT(imhtml), "unrealize", G_CALLBACK(imhtml_destroy_add_primary), NULL); + g_signal_connect(G_OBJECT(imhtml), "paste", G_CALLBACK(imhtml_paste_cb), NULL); #ifndef _WIN32 g_signal_connect_after(G_OBJECT(GTK_IMHTML(imhtml)->text_buffer), "mark-set", diff -r c316749944c1 -r 2bdbf3fbd894 pidgin/gtkutils.c --- a/pidgin/gtkutils.c Sat Mar 13 08:18:25 2010 +0000 +++ b/pidgin/gtkutils.c Fri Mar 26 00:43:51 2010 +0000 @@ -153,6 +153,27 @@ } GtkWidget * +pidgin_create_small_button(GtkWidget *image) +{ + GtkWidget *button; + + button = gtk_button_new(); + gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE); + + /* don't allow focus on the close button */ + gtk_button_set_focus_on_click(GTK_BUTTON(button), FALSE); + + /* set style to make it as small as possible */ + gtk_widget_set_name(button, "pidgin-small-close-button"); + + gtk_widget_show(image); + + gtk_container_add(GTK_CONTAINER(button), image); + + return button; +} + +GtkWidget * pidgin_create_dialog(const char *title, guint border_width, const char *role, gboolean resizable) { GtkWindow *wnd = NULL; @@ -3448,6 +3469,16 @@ if (purple_running_gnome()) register_gnome_url_handlers(); + /* Used to make small buttons */ + gtk_rc_parse_string("style \"pidgin-small-close-button\"\n" + "{\n" + "GtkWidget::focus-padding = 0\n" + "GtkWidget::focus-line-width = 0\n" + "xthickness = 0\n" + "ythickness = 0\n" + "}\n" + "widget \"*.pidgin-small-close-button\" style \"pidgin-small-close-button\""); + #ifdef _WIN32 winpidgin_register_win32_url_handlers(); #endif diff -r c316749944c1 -r 2bdbf3fbd894 pidgin/gtkutils.h --- a/pidgin/gtkutils.h Sat Mar 13 08:18:25 2010 +0000 +++ b/pidgin/gtkutils.h Fri Mar 26 00:43:51 2010 +0000 @@ -109,6 +109,16 @@ GtkWidget *pidgin_create_imhtml(gboolean editable, GtkWidget **imhtml_ret, GtkWidget **toolbar_ret, GtkWidget **sw_ret); /** + * Creates a small button + * + * @param image A button image. + * + * @return A GtkButton created from the image. + * @since 2.7.0 + */ +GtkWidget *pidgin_create_small_button(GtkWidget *image); + +/** * Creates a new window * * @param title The window title, or @c NULL diff -r c316749944c1 -r 2bdbf3fbd894 pidgin/plugins/perl/common/Makefile.mingw --- a/pidgin/plugins/perl/common/Makefile.mingw Sat Mar 13 08:18:25 2010 +0000 +++ b/pidgin/plugins/perl/common/Makefile.mingw Fri Mar 26 00:43:51 2010 +0000 @@ -12,7 +12,6 @@ DEFINES := $(subst -DWIN32_LEAN_AND_MEAN,,$(DEFINES)) TARGET = Pidgin -EXTUTILS ?= C:/perl/lib/ExtUtils ## ## INCLUDE PATHS diff -r c316749944c1 -r 2bdbf3fbd894 pidgin/plugins/xmppconsole.c --- a/pidgin/plugins/xmppconsole.c Sat Mar 13 08:18:25 2010 +0000 +++ b/pidgin/plugins/xmppconsole.c Fri Mar 26 00:43:51 2010 +0000 @@ -845,7 +845,7 @@ /** summary */ N_("Send and receive raw XMPP stanzas."), /** description */ - N_("This plugin is useful for debbuging XMPP servers or clients."), + N_("This plugin is useful for debugging XMPP servers or clients."), "Sean Egan ", /**< author */ PURPLE_WEBSITE, /**< homepage */ diff -r c316749944c1 -r 2bdbf3fbd894 pidgin/win32/nsis/generate_gtk_zip.sh --- a/pidgin/win32/nsis/generate_gtk_zip.sh Sat Mar 13 08:18:25 2010 +0000 +++ b/pidgin/win32/nsis/generate_gtk_zip.sh Fri Mar 26 00:43:51 2010 +0000 @@ -14,26 +14,21 @@ CONTENTS_FILE=$INSTALL_DIR/CONTENTS #This needs to be changed every time there is any sort of change. -BUNDLE_VERSION=2.14.7.0 +BUNDLE_VERSION=2.16.6.0 -ATK="http://ftp.gnome.org/pub/gnome/binaries/win32/atk/1.24/atk_1.24.0-1_win32.zip ATK 1.24.0-1" +ATK="http://ftp.acc.umu.se/pub/gnome/binaries/win32/atk/1.26/atk_1.26.0-1_win32.zip ATK 1.26.0-1" CAIRO="http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/cairo_1.8.10-1_win32.zip Cairo 1.8.10-1" EXPAT="http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/expat_2.0.1-1_win32.zip Expat 2.0.1-1" FONTCONFIG="http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/fontconfig_2.8.0-2_win32.zip Fontconfig 2.8.0-2" FREETYPE="http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/freetype_2.3.11-2_win32.zip Freetype 2.3.11-2" GETTEXT="http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/gettext-runtime-0.17-1.zip Gettext 0.17-1" GLIB="http://ftp.gnome.org/pub/gnome/binaries/win32/glib/2.20/glib_2.20.5-1_win32.zip Glib 2.20.5-1" -GTK="http://ftp.gnome.org/pub/gnome/binaries/win32/gtk+/2.14/gtk+_2.14.7-1_win32.zip GTK+ 2.14.7-1" -LIBJPEG="http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/jpeg-6b-4.zip libjpeg 6b-4" -#Used by GTK+ -LIBPNG="http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/libpng_1.2.39-1_win32.zip libpng 1.2.39-1" -#Used by Cairo -LIBPNG2="http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/libpng_1.4.0-1_win32.zip libpng 1.4.0-1" -LIBTIFF="http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/libtiff_3.9.1-1_win32.zip libtiff 3.9.1-1" +GTK="http://ftp.acc.umu.se/pub/gnome/binaries/win32/gtk+/2.16/gtk+_2.16.6-2_win32.zip GTK+ 2.16.6-2" +LIBPNG="http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/libpng_1.4.0-1_win32.zip libpng 1.4.0-1" PANGO="http://ftp.gnome.org/pub/gnome/binaries/win32/pango/1.26/pango_1.26.2-1_win32.zip Pango 1.26.2-1" ZLIB="http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/zlib-1.2.3.zip zlib 1.2.3" -ALL="ATK CAIRO EXPAT FONTCONFIG FREETYPE GETTEXT GLIB GTK LIBJPEG LIBPNG LIBPNG2 LIBTIFF PANGO ZLIB" +ALL="ATK CAIRO EXPAT FONTCONFIG FREETYPE GETTEXT GLIB GTK LIBPNG PANGO ZLIB" mkdir -p $STAGE_DIR cd $STAGE_DIR diff -r c316749944c1 -r 2bdbf3fbd894 pidgin/win32/winpidgin.c --- a/pidgin/win32/winpidgin.c Sat Mar 13 08:18:25 2010 +0000 +++ b/pidgin/win32/winpidgin.c Fri Mar 26 00:43:51 2010 +0000 @@ -26,13 +26,10 @@ */ /* This is for ATTACH_PARENT_PROCESS */ -#define UNICODE -#define _UNICODE #ifndef _WIN32_WINNT #define _WIN32_WINNT 0x501 #endif #include -#include #include #include #include @@ -53,70 +50,70 @@ static LPFNPIDGINMAIN pidgin_main = NULL; static LPFNSETDLLDIRECTORY MySetDllDirectory = NULL; -static const TCHAR *get_win32_error_message(DWORD err) { - static TCHAR err_msg[512]; +static const wchar_t *get_win32_error_message(DWORD err) { + static wchar_t err_msg[512]; - FormatMessage( + FormatMessageW( FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR) &err_msg, sizeof(err_msg) / sizeof(TCHAR), NULL); + (LPWSTR) &err_msg, sizeof(err_msg) / sizeof(wchar_t), NULL); return err_msg; } -static BOOL read_reg_string(HKEY key, TCHAR *sub_key, TCHAR *val_name, LPBYTE data, LPDWORD data_len) { +static BOOL read_reg_string(HKEY key, wchar_t *sub_key, wchar_t *val_name, LPBYTE data, LPDWORD data_len) { HKEY hkey; BOOL ret = FALSE; LONG retv; - if (ERROR_SUCCESS == (retv = RegOpenKeyEx(key, sub_key, 0, + if (ERROR_SUCCESS == (retv = RegOpenKeyExW(key, sub_key, 0, KEY_QUERY_VALUE, &hkey))) { - if (ERROR_SUCCESS == (retv = RegQueryValueEx(hkey, val_name, + if (ERROR_SUCCESS == (retv = RegQueryValueExW(hkey, val_name, NULL, NULL, data, data_len))) ret = TRUE; else { - const TCHAR *err_msg = get_win32_error_message(retv); + const wchar_t *err_msg = get_win32_error_message(retv); - _tprintf(_T("Could not read reg key '%s' subkey '%s' value: '%s'.\nMessage: (%ld) %s\n"), - (key == HKEY_LOCAL_MACHINE) ? _T("HKLM") - : ((key == HKEY_CURRENT_USER) ? _T("HKCU") : _T("???")), + wprintf(L"Could not read reg key '%s' subkey '%s' value: '%s'.\nMessage: (%ld) %s\n", + (key == HKEY_LOCAL_MACHINE) ? L"HKLM" + : ((key == HKEY_CURRENT_USER) ? L"HKCU" : L"???"), sub_key, val_name, retv, err_msg); } RegCloseKey(hkey); } else { - TCHAR szBuf[80]; + wchar_t szBuf[80]; - FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, retv, 0, - (LPTSTR) &szBuf, sizeof(szBuf) / sizeof(TCHAR), NULL); - _tprintf(_T("Could not open reg subkey: %s\nError: (%ld) %s\n"), + FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, NULL, retv, 0, + (LPWSTR) &szBuf, sizeof(szBuf) / sizeof(wchar_t), NULL); + wprintf(L"Could not open reg subkey: %s\nError: (%ld) %s\n", sub_key, retv, szBuf); } return ret; } -static BOOL common_dll_prep(const TCHAR *path) { +static BOOL common_dll_prep(const wchar_t *path) { HMODULE hmod; HKEY hkey; struct _stat stat_buf; - TCHAR test_path[MAX_PATH + 1]; + wchar_t test_path[MAX_PATH + 1]; - _sntprintf(test_path, sizeof(test_path) / sizeof(TCHAR), - _T("%s\\libgtk-win32-2.0-0.dll"), path); - test_path[sizeof(test_path) / sizeof(TCHAR) - 1] = _T('\0'); + _snwprintf(test_path, sizeof(test_path) / sizeof(wchar_t), + L"%s\\libgtk-win32-2.0-0.dll", path); + test_path[sizeof(test_path) / sizeof(wchar_t) - 1] = L'\0'; - if (_tstat(test_path, &stat_buf) != 0) { + if (_wstat(test_path, &stat_buf) != 0) { printf("Unable to determine GTK+ path. \n" "Assuming GTK+ is in the PATH.\n"); return FALSE; } - _tprintf(_T("GTK+ path found: %s\n"), path); + wprintf(L"GTK+ path found: %s\n", path); - if ((hmod = GetModuleHandle(_T("kernel32.dll")))) { + if ((hmod = GetModuleHandleW(L"kernel32.dll"))) { MySetDllDirectory = (LPFNSETDLLDIRECTORY) GetProcAddress( hmod, "SetDllDirectoryW"); if (!MySetDllDirectory) @@ -133,44 +130,44 @@ /* For the rest, we set the current directory and make sure * SafeDllSearch is set to 0 where needed. */ else { - OSVERSIONINFO osinfo; + OSVERSIONINFOW osinfo; printf("Setting current directory to GTK+ dll directory\n"); - SetCurrentDirectory(path); + SetCurrentDirectoryW(path); /* For Windows 2000 (SP3+) / WinXP (No SP): * If SafeDllSearchMode is set to 1, Windows system directories are * searched for dlls before the current directory. Therefore we set it * to 0. */ - osinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - GetVersionEx(&osinfo); + osinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW); + GetVersionExW(&osinfo); if ((osinfo.dwMajorVersion == 5 && osinfo.dwMinorVersion == 0 - && _tcscmp(osinfo.szCSDVersion, _T("Service Pack 3")) >= 0) + && wcscmp(osinfo.szCSDVersion, L"Service Pack 3") >= 0) || (osinfo.dwMajorVersion == 5 && osinfo.dwMinorVersion == 1 - && _tcscmp(osinfo.szCSDVersion, _T("")) >= 0) + && wcscmp(osinfo.szCSDVersion, L"") >= 0) ) { DWORD regval = 1; DWORD reglen = sizeof(DWORD); printf("Using Win2k (SP3+) / WinXP (No SP)... Checking SafeDllSearch\n"); read_reg_string(HKEY_LOCAL_MACHINE, - _T("System\\CurrentControlSet\\Control\\Session Manager"), - _T("SafeDllSearchMode"), + L"System\\CurrentControlSet\\Control\\Session Manager", + L"SafeDllSearchMode", (LPBYTE) ®val, ®len); if (regval != 0) { printf("Trying to set SafeDllSearchMode to 0\n"); regval = 0; - if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, - _T("System\\CurrentControlSet\\Control\\Session Manager"), + if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, + L"System\\CurrentControlSet\\Control\\Session Manager", 0, KEY_SET_VALUE, &hkey ) == ERROR_SUCCESS) { - if (RegSetValueEx(hkey, - _T("SafeDllSearchMode"), 0, + if (RegSetValueExW(hkey, + L"SafeDllSearchMode", 0, REG_DWORD, (LPBYTE) ®val, sizeof(DWORD) ) != ERROR_SUCCESS) @@ -188,35 +185,35 @@ return TRUE; } -static BOOL dll_prep(const TCHAR *pidgin_dir) { - TCHAR path[MAX_PATH + 1]; - path[0] = _T('\0'); +static BOOL dll_prep(const wchar_t *pidgin_dir) { + wchar_t path[MAX_PATH + 1]; + path[0] = L'\0'; if (*pidgin_dir) { - _sntprintf(path, sizeof(path) / sizeof(TCHAR), _T("%s\\Gtk\\bin"), pidgin_dir); - path[sizeof(path) / sizeof(TCHAR)] = _T('\0'); + _snwprintf(path, sizeof(path) / sizeof(wchar_t), L"%s\\Gtk\\bin", pidgin_dir); + path[sizeof(path) / sizeof(wchar_t) - 1] = L'\0'; } return common_dll_prep(path); } -static void portable_mode_dll_prep(const TCHAR *pidgin_dir) { - /* need to be able to fit MAX_PATH + "PIDGIN_ASPELL_DIR=\\Aspell\\bin" in path2 */ - TCHAR path[MAX_PATH + 1]; - TCHAR path2[MAX_PATH + 33]; - const TCHAR *prev = NULL; +static void portable_mode_dll_prep(const wchar_t *pidgin_dir) { + /* need to be able to fit MAX_PATH + "PURPLEHOME=" in path2 */ + wchar_t path[MAX_PATH + 1]; + wchar_t path2[MAX_PATH + 12]; + const wchar_t *prev = NULL; /* We assume that GTK+ is installed under \\path\to\Pidgin\..\GTK * First we find \\path\to */ if (*pidgin_dir) /* pidgin_dir points to \\path\to\Pidgin */ - prev = _tcsrchr(pidgin_dir, _T('\\')); + prev = wcsrchr(pidgin_dir, L'\\'); if (prev) { int cnt = (prev - pidgin_dir); - _tcsncpy(path, pidgin_dir, cnt); - path[cnt] = _T('\0'); + wcsncpy(path, pidgin_dir, cnt); + path[cnt] = L'\0'; } else { printf("Unable to determine current executable path. \n" "This will prevent the settings dir from being set.\n" @@ -225,130 +222,126 @@ } /* Set $HOME so that the GTK+ settings get stored in the right place */ - _sntprintf(path2, sizeof(path2) / sizeof(TCHAR), _T("HOME=%s"), path); - _tputenv(path2); + _snwprintf(path2, sizeof(path2) / sizeof(wchar_t), L"HOME=%s", path); + _wputenv(path2); /* Set up the settings dir base to be \\path\to * The actual settings dir will be \\path\to\.purple */ - _sntprintf(path2, sizeof(path2) / sizeof(TCHAR), _T("PURPLEHOME=%s"), path); - _tprintf(_T("Setting settings dir: %s\n"), path2); - _tputenv(path2); - - _sntprintf(path2, sizeof(path2) / sizeof(TCHAR), _T("PIDGIN_ASPELL_DIR=%s\\Aspell\\bin"), path); - _tprintf(_T("%s\n"), path2); - _tputenv(path2); + _snwprintf(path2, sizeof(path2) / sizeof(wchar_t), L"PURPLEHOME=%s", path); + wprintf(L"Setting settings dir: %s\n", path2); + _wputenv(path2); if (!dll_prep(pidgin_dir)) { /* set the GTK+ path to be \\path\to\GTK\bin */ - _tcscat(path, _T("\\GTK\\bin")); + wcscat(path, L"\\GTK\\bin"); common_dll_prep(path); } } -static TCHAR* winpidgin_lcid_to_posix(LCID lcid) { - TCHAR *posix = NULL; +static wchar_t* winpidgin_lcid_to_posix(LCID lcid) { + wchar_t *posix = NULL; int lang_id = PRIMARYLANGID(lcid); int sub_id = SUBLANGID(lcid); switch (lang_id) { - case LANG_AFRIKAANS: posix = _T("af"); break; - case LANG_ARABIC: posix = _T("ar"); break; - case LANG_AZERI: posix = _T("az"); break; - case LANG_BENGALI: posix = _T("bn"); break; - case LANG_BULGARIAN: posix = _T("bg"); break; - case LANG_CATALAN: posix = _T("ca"); break; - case LANG_CZECH: posix = _T("cs"); break; - case LANG_DANISH: posix = _T("da"); break; - case LANG_ESTONIAN: posix = _T("et"); break; - case LANG_PERSIAN: posix = _T("fa"); break; - case LANG_GERMAN: posix = _T("de"); break; - case LANG_GREEK: posix = _T("el"); break; + case LANG_AFRIKAANS: posix = L"af"; break; + case LANG_ARABIC: posix = L"ar"; break; + case LANG_AZERI: posix = L"az"; break; + case LANG_BENGALI: posix = L"bn"; break; + case LANG_BULGARIAN: posix = L"bg"; break; + case LANG_CATALAN: posix = L"ca"; break; + case LANG_CZECH: posix = L"cs"; break; + case LANG_DANISH: posix = L"da"; break; + case LANG_ESTONIAN: posix = L"et"; break; + case LANG_PERSIAN: posix = L"fa"; break; + case LANG_GERMAN: posix = L"de"; break; + case LANG_GREEK: posix = L"el"; break; case LANG_ENGLISH: switch (sub_id) { case SUBLANG_ENGLISH_UK: - posix = _T("en_GB"); break; + posix = L"en_GB"; break; case SUBLANG_ENGLISH_AUS: - posix = _T("en_AU"); break; + posix = L"en_AU"; break; case SUBLANG_ENGLISH_CAN: - posix = _T("en_CA"); break; + posix = L"en_CA"; break; default: - posix = _T("en"); break; + posix = L"en"; break; } break; - case LANG_SPANISH: posix = _T("es"); break; - case LANG_BASQUE: posix = _T("eu"); break; - case LANG_FINNISH: posix = _T("fi"); break; - case LANG_FRENCH: posix = _T("fr"); break; - case LANG_GALICIAN: posix = _T("gl"); break; - case LANG_GUJARATI: posix = _T("gu"); break; - case LANG_HEBREW: posix = _T("he"); break; - case LANG_HINDI: posix = _T("hi"); break; - case LANG_HUNGARIAN: posix = _T("hu"); break; + case LANG_SPANISH: posix = L"es"; break; + case LANG_BASQUE: posix = L"eu"; break; + case LANG_FINNISH: posix = L"fi"; break; + case LANG_FRENCH: posix = L"fr"; break; + case LANG_GALICIAN: posix = L"gl"; break; + case LANG_GUJARATI: posix = L"gu"; break; + case LANG_HEBREW: posix = L"he"; break; + case LANG_HINDI: posix = L"hi"; break; + case LANG_HUNGARIAN: posix = L"hu"; break; case LANG_ICELANDIC: break; - case LANG_INDONESIAN: posix = _T("id"); break; - case LANG_ITALIAN: posix = _T("it"); break; - case LANG_JAPANESE: posix = _T("ja"); break; - case LANG_GEORGIAN: posix = _T("ka"); break; - case LANG_KANNADA: posix = _T("kn"); break; - case LANG_KOREAN: posix = _T("ko"); break; - case LANG_LITHUANIAN: posix = _T("lt"); break; - case LANG_MACEDONIAN: posix = _T("mk"); break; - case LANG_DUTCH: posix = _T("nl"); break; - case LANG_NEPALI: posix = _T("ne"); break; + case LANG_INDONESIAN: posix = L"id"; break; + case LANG_ITALIAN: posix = L"it"; break; + case LANG_JAPANESE: posix = L"ja"; break; + case LANG_GEORGIAN: posix = L"ka"; break; + case LANG_KANNADA: posix = L"kn"; break; + case LANG_KOREAN: posix = L"ko"; break; + case LANG_LITHUANIAN: posix = L"lt"; break; + case LANG_MACEDONIAN: posix = L"mk"; break; + case LANG_DUTCH: posix = L"nl"; break; + case LANG_NEPALI: posix = L"ne"; break; case LANG_NORWEGIAN: switch (sub_id) { case SUBLANG_NORWEGIAN_BOKMAL: - posix = _T("nb"); break; + posix = L"nb"; break; case SUBLANG_NORWEGIAN_NYNORSK: - posix = _T("nn"); break; + posix = L"nn"; break; } break; - case LANG_PUNJABI: posix = _T("pa"); break; - case LANG_POLISH: posix = _T("pl"); break; - case LANG_PASHTO: posix = _T("ps"); break; + case LANG_PUNJABI: posix = L"pa"; break; + case LANG_POLISH: posix = L"pl"; break; + case LANG_PASHTO: posix = L"ps"; break; case LANG_PORTUGUESE: switch (sub_id) { case SUBLANG_PORTUGUESE_BRAZILIAN: - posix = _T("pt_BR"); break; + posix = L"pt_BR"; break; default: - posix = _T("pt"); break; + posix = L"pt"; break; } break; - case LANG_ROMANIAN: posix = _T("ro"); break; - case LANG_RUSSIAN: posix = _T("ru"); break; - case LANG_SLOVAK: posix = _T("sk"); break; - case LANG_SLOVENIAN: posix = _T("sl"); break; - case LANG_ALBANIAN: posix = _T("sq"); break; + case LANG_ROMANIAN: posix = L"ro"; break; + case LANG_RUSSIAN: posix = L"ru"; break; + case LANG_SLOVAK: posix = L"sk"; break; + case LANG_SLOVENIAN: posix = L"sl"; break; + case LANG_ALBANIAN: posix = L"sq"; break; /* LANG_CROATIAN == LANG_SERBIAN == LANG_BOSNIAN */ case LANG_SERBIAN: switch (sub_id) { case SUBLANG_SERBIAN_LATIN: - posix = _T("sr@Latn"); break; + posix = L"sr@Latn"; break; case SUBLANG_SERBIAN_CYRILLIC: - posix = _T("sr"); break; + posix = L"sr"; break; case SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_CYRILLIC: case SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_LATIN: - posix = _T("bs"); break; + posix = L"bs"; break; case SUBLANG_CROATIAN_BOSNIA_HERZEGOVINA_LATIN: - posix = _T("hr"); break; + posix = L"hr"; break; } break; - case LANG_SWEDISH: posix = _T("sv"); break; - case LANG_TAMIL: posix = _T("ta"); break; - case LANG_TELUGU: posix = _T("te"); break; - case LANG_THAI: posix = _T("th"); break; - case LANG_TURKISH: posix = _T("tr"); break; - case LANG_UKRAINIAN: posix = _T("uk"); break; - case LANG_VIETNAMESE: posix = _T("vi"); break; - case LANG_XHOSA: posix = _T("xh"); break; + case LANG_SWEDISH: posix = L"sv"; break; + case LANG_TAMIL: posix = L"ta"; break; + case LANG_TELUGU: posix = L"te"; break; + case LANG_THAI: posix = L"th"; break; + case LANG_TURKISH: posix = L"tr"; break; + case LANG_UKRAINIAN: posix = L"uk"; break; + case LANG_VIETNAMESE: posix = L"vi"; break; + case LANG_XHOSA: posix = L"xh"; break; case LANG_CHINESE: switch (sub_id) { case SUBLANG_CHINESE_SIMPLIFIED: - posix = _T("zh_CN"); break; + posix = L"zh_CN"; break; case SUBLANG_CHINESE_TRADITIONAL: - posix = _T("zh_TW"); break; + posix = L"zh_TW"; break; default: - posix = _T("zh"); break; + posix = L"zh"; break; } break; case LANG_URDU: break; @@ -379,8 +372,8 @@ /* Deal with exceptions */ if (posix == NULL) { switch (lcid) { - case 0x0455: posix = _T("my_MM"); break; /* Myanmar (Burmese) */ - case 9999: posix = _T("ku"); break; /* Kurdish (from NSIS) */ + case 0x0455: posix = L"my_MM"; break; /* Myanmar (Burmese) */ + case 9999: posix = L"ku"; break; /* Kurdish (from NSIS) */ } } @@ -392,19 +385,19 @@ - Check NSIS Installer Language reg value - Use default user locale */ -static const TCHAR *winpidgin_get_locale() { - const TCHAR *locale = NULL; +static const wchar_t *winpidgin_get_locale() { + const wchar_t *locale = NULL; LCID lcid; - TCHAR data[10]; - DWORD datalen = sizeof(data) / sizeof(TCHAR); + wchar_t data[10]; + DWORD datalen = sizeof(data) / sizeof(wchar_t); /* Check if user set PIDGINLANG env var */ - if ((locale = _tgetenv(_T("PIDGINLANG")))) + if ((locale = _wgetenv(L"PIDGINLANG"))) return locale; - if (!portable_mode && read_reg_string(HKEY_CURRENT_USER, _T("SOFTWARE\\pidgin"), - _T("Installer Language"), (LPBYTE) &data, &datalen)) { - if ((locale = winpidgin_lcid_to_posix(_ttoi(data)))) + if (!portable_mode && read_reg_string(HKEY_CURRENT_USER, L"SOFTWARE\\pidgin", + L"Installer Language", (LPBYTE) &data, &datalen)) { + if ((locale = winpidgin_lcid_to_posix(_wtoi(data)))) return locale; } @@ -412,39 +405,39 @@ if ((locale = winpidgin_lcid_to_posix(lcid))) return locale; - return _T("en"); + return L"en"; } static void winpidgin_set_locale() { - const TCHAR *locale; - TCHAR envstr[25]; + const wchar_t *locale; + wchar_t envstr[25]; locale = winpidgin_get_locale(); - _sntprintf(envstr, sizeof(envstr) / sizeof(TCHAR), _T("LANG=%s"), locale); - _tprintf(_T("Setting locale: %s\n"), envstr); - _tputenv(envstr); + _snwprintf(envstr, sizeof(envstr) / sizeof(wchar_t), L"LANG=%s", locale); + wprintf(L"Setting locale: %s\n", envstr); + _wputenv(envstr); } static void winpidgin_add_stuff_to_path() { - TCHAR perl_path[MAX_PATH + 1]; - TCHAR *ppath = NULL; - TCHAR mit_kerberos_path[MAX_PATH + 1]; - TCHAR *mpath = NULL; + wchar_t perl_path[MAX_PATH + 1]; + wchar_t *ppath = NULL; + wchar_t mit_kerberos_path[MAX_PATH + 1]; + wchar_t *mpath = NULL; DWORD plen; printf("%s", "Looking for Perl... "); - plen = sizeof(perl_path) / sizeof(TCHAR); - if (read_reg_string(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Perl"), _T(""), + plen = sizeof(perl_path) / sizeof(wchar_t); + if (read_reg_string(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Perl", L"", (LPBYTE) &perl_path, &plen)) { /* We *could* check for perl510.dll, but it seems unnecessary. */ - _tprintf(_T("found in '%s'.\n"), perl_path); + wprintf(L"found in '%s'.\n", perl_path); - if (perl_path[_tcslen(perl_path) - 1] != _T('\\')) - _tcscat(perl_path, _T("\\")); - _tcscat(perl_path, _T("bin")); + if (perl_path[wcslen(perl_path) - 1] != L'\\') + wcscat(perl_path, L"\\"); + wcscat(perl_path, L"bin"); ppath = perl_path; } else @@ -452,47 +445,47 @@ printf("%s", "Looking for MIT Kerberos... "); - plen = sizeof(mit_kerberos_path) / sizeof(TCHAR); - if (read_reg_string(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\MIT\\Kerberos"), _T("InstallDir"), + plen = sizeof(mit_kerberos_path) / sizeof(wchar_t); + if (read_reg_string(HKEY_LOCAL_MACHINE, L"SOFTWARE\\MIT\\Kerberos", L"InstallDir", (LPBYTE) &mit_kerberos_path, &plen)) { /* We *could* check for gssapi32.dll */ - _tprintf(_T("found in '%s'.\n"), mit_kerberos_path); + wprintf(L"found in '%s'.\n", mit_kerberos_path); - if (mit_kerberos_path[_tcslen(mit_kerberos_path) - 1] != _T('\\')) - _tcscat(mit_kerberos_path, _T("\\")); - _tcscat(mit_kerberos_path, _T("bin")); + if (mit_kerberos_path[wcslen(mit_kerberos_path) - 1] != L'\\') + wcscat(mit_kerberos_path, L"\\"); + wcscat(mit_kerberos_path, L"bin"); mpath = mit_kerberos_path; } else printf("%s", "not found.\n"); if (ppath != NULL || mpath != NULL) { - const TCHAR *path = _tgetenv(_T("PATH")); - BOOL add_ppath = ppath != NULL && (path == NULL || !_tcsstr(path, ppath)); - BOOL add_mpath = mpath != NULL && (path == NULL || !_tcsstr(path, mpath)); - TCHAR *newpath; + const wchar_t *path = _wgetenv(L"PATH"); + BOOL add_ppath = ppath != NULL && (path == NULL || !wcsstr(path, ppath)); + BOOL add_mpath = mpath != NULL && (path == NULL || !wcsstr(path, mpath)); + wchar_t *newpath; int newlen; if (add_ppath || add_mpath) { /* Enough to add "PATH=" + path + ";" + ppath + ";" + mpath + \0 */ - newlen = 6 + (path ? _tcslen(path) + 1 : 0); + newlen = 6 + (path ? wcslen(path) + 1 : 0); if (add_ppath) - newlen += _tcslen(ppath) + 1; + newlen += wcslen(ppath) + 1; if (add_mpath) - newlen += _tcslen(mpath) + 1; - newpath = malloc(newlen * sizeof(TCHAR)); + newlen += wcslen(mpath) + 1; + newpath = malloc(newlen * sizeof(wchar_t)); - _sntprintf(newpath, newlen, _T("PATH=%s%s%s%s%s%s"), - path ? path : _T(""), - path ? _T(";") : _T(""), - add_ppath ? ppath : _T(""), - add_ppath ? _T(";") : _T(""), - add_mpath ? mpath : _T(""), - add_mpath ? _T(";") : _T("")); + _snwprintf(newpath, newlen, L"PATH=%s%s%s%s%s%s", + path ? path : L"", + path ? L";" : L"", + add_ppath ? ppath : L"", + add_ppath ? L";" : L"", + add_mpath ? mpath : L"", + add_mpath ? L";" : L""); - _tprintf(_T("New PATH: %s\n"), newpath); + wprintf(L"New PATH: %s\n", newpath); - _tputenv(newpath); + _wputenv(newpath); free(newpath); } } @@ -504,7 +497,7 @@ static BOOL winpidgin_set_running(BOOL fail_if_running) { HANDLE h; - if ((h = CreateMutex(NULL, FALSE, _T("pidgin_is_running")))) { + if ((h = CreateMutexW(NULL, FALSE, L"pidgin_is_running"))) { DWORD err = GetLastError(); if (err == ERROR_ALREADY_EXISTS) { if (fail_if_running) { @@ -512,14 +505,14 @@ printf("An instance of Pidgin is already running.\n"); - if((msg_win = FindWindowEx(NULL, NULL, _T("WinpidginMsgWinCls"), NULL))) + if((msg_win = FindWindowExW(NULL, NULL, L"WinpidginMsgWinCls", NULL))) if(SendMessage(msg_win, PIDGIN_WM_FOCUS_REQUEST, (WPARAM) NULL, (LPARAM) NULL)) return FALSE; /* If we get here, the focus request wasn't successful */ - MessageBox(NULL, - _T("An instance of Pidgin is already running"), + MessageBoxW(NULL, + L"An instance of Pidgin is already running", NULL, MB_OK | MB_TOPMOST); return FALSE; @@ -555,7 +548,7 @@ return; } - if (!(msg_win = FindWindowEx(NULL, NULL, _T("WinpidginMsgWinCls"), NULL))) { + if (!(msg_win = FindWindowExW(NULL, NULL, L"WinpidginMsgWinCls", NULL))) { printf("Unable to find an instance of Pidgin to handle protocol message.\n"); return; } @@ -576,8 +569,8 @@ GetWindowThreadProcessId(msg_win, &pid); if (!(process = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_WRITE, FALSE, pid))) { DWORD dw = GetLastError(); - const TCHAR *err_msg = get_win32_error_message(dw); - _tprintf(_T("Unable to open Pidgin process. (%u) %s\n"), (UINT) dw, err_msg); + const wchar_t *err_msg = get_win32_error_message(dw); + wprintf(L"Unable to open Pidgin process. (%u) %s\n", (UINT) dw, err_msg); return; } @@ -591,15 +584,15 @@ printf("Unable to send protocol message to Pidgin instance.\n"); } else { DWORD dw = GetLastError(); - const TCHAR *err_msg = get_win32_error_message(dw); - _tprintf(_T("Unable to write to remote memory. (%u) %s\n"), (UINT) dw, err_msg); + const wchar_t *err_msg = get_win32_error_message(dw); + wprintf(L"Unable to write to remote memory. (%u) %s\n", (UINT) dw, err_msg); } VirtualFreeEx(process, remote_msg, 0, MEM_RELEASE); } else { DWORD dw = GetLastError(); - const TCHAR *err_msg = get_win32_error_message(dw); - _tprintf(_T("Unable to allocate remote memory. (%u) %s\n"), (UINT) dw, err_msg); + const wchar_t *err_msg = get_win32_error_message(dw); + wprintf(L"Unable to allocate remote memory. (%u) %s\n", (UINT) dw, err_msg); } CloseHandle(process); @@ -610,11 +603,11 @@ int _stdcall WinMain (struct HINSTANCE__ *hInstance, struct HINSTANCE__ *hPrevInstance, char *lpszCmdLine, int nCmdShow) { - TCHAR errbuf[512]; - TCHAR pidgin_dir[MAX_PATH]; - TCHAR exe_name[MAX_PATH]; + wchar_t errbuf[512]; + wchar_t pidgin_dir[MAX_PATH]; + wchar_t exe_name[MAX_PATH]; HMODULE hmod; - TCHAR *tmp; + wchar_t *tmp; wchar_t *wtmp; int pidgin_argc; char **pidgin_argv; /* This is in utf-8 */ @@ -654,7 +647,7 @@ * (_istty() doesn't work for stuff using the GUI subsystem) */ if (_fileno(stdout) == -1 || _fileno(stdout) == -2) { LPFNATTACHCONSOLE MyAttachConsole = NULL; - if ((hmod = GetModuleHandle(_T("kernel32.dll")))) { + if ((hmod = GetModuleHandleW(L"kernel32.dll"))) { MyAttachConsole = (LPFNATTACHCONSOLE) GetProcAddress(hmod, "AttachConsole"); @@ -676,20 +669,20 @@ } /* Load exception handler if we have it */ - if (GetModuleFileName(NULL, pidgin_dir, MAX_PATH) != 0) { + if (GetModuleFileNameW(NULL, pidgin_dir, MAX_PATH) != 0) { /* primitive dirname() */ - tmp = _tcsrchr(pidgin_dir, _T('\\')); + tmp = wcsrchr(pidgin_dir, L'\\'); if (tmp) { HMODULE hmod; - tmp[0] = _T('\0'); + tmp[0] = L'\0'; /* tmp++ will now point to the executable file name */ - _tcscpy(exe_name, tmp + 1); + wcscpy(exe_name, tmp + 1); - _tcscat(pidgin_dir, _T("\\exchndl.dll")); - if ((hmod = LoadLibrary(pidgin_dir))) { + wcscat(pidgin_dir, L"\\exchndl.dll"); + if ((hmod = LoadLibraryW(pidgin_dir))) { FARPROC proc; /* exchndl.dll is built without UNICODE */ char debug_dir[MAX_PATH]; @@ -709,8 +702,7 @@ proc = GetProcAddress(hmod, "SetDebugInfoDir"); if (proc) { char *pidgin_dir_ansi = NULL; - tmp[0] = _T('\0'); -#ifdef _UNICODE + tmp[0] = L'\0'; i = WideCharToMultiByte(CP_ACP, 0, pidgin_dir, -1, NULL, 0, NULL, NULL); if (i != 0) { @@ -722,9 +714,6 @@ pidgin_dir_ansi = NULL; } } -#else - pidgin_dir_ansi = pidgin_dir; -#endif if (pidgin_dir_ansi != NULL) { _snprintf(debug_dir, sizeof(debug_dir) / sizeof(char), "%s\\pidgin-%s-dbgsym", @@ -733,30 +722,28 @@ printf(" Setting exchndl.dll DebugInfoDir to %s\n", debug_dir); (proc)(debug_dir); -#ifdef _UNICODE free(pidgin_dir_ansi); -#endif } } } - tmp[0] = _T('\0'); + tmp[0] = L'\0'; } } else { DWORD dw = GetLastError(); - const TCHAR *err_msg = get_win32_error_message(dw); - _sntprintf(errbuf, 512, - _T("Error getting module filename.\nError: (%u) %s"), + const wchar_t *err_msg = get_win32_error_message(dw); + _snwprintf(errbuf, 512, + L"Error getting module filename.\nError: (%u) %s", (UINT) dw, err_msg); - _tprintf(_T("%s\n"), errbuf); - MessageBox(NULL, errbuf, NULL, MB_OK | MB_TOPMOST); - pidgin_dir[0] = _T('\0'); + wprintf(L"%s\n", errbuf); + MessageBoxW(NULL, errbuf, NULL, MB_OK | MB_TOPMOST); + pidgin_dir[0] = L'\0'; } /* Determine if we're running in portable mode */ if (wcsstr(cmdLine, L"--portable-mode") - || (exe_name != NULL && _tcsstr(exe_name, _T("-portable.exe")))) { + || (exe_name != NULL && wcsstr(exe_name, L"-portable.exe"))) { printf("Running in PORTABLE mode.\n"); portable_mode = TRUE; } @@ -776,20 +763,20 @@ return 0; /* Now we are ready for Pidgin .. */ - if ((hmod = LoadLibrary(_T("pidgin.dll")))) + if ((hmod = LoadLibraryW(L"pidgin.dll"))) pidgin_main = (LPFNPIDGINMAIN) GetProcAddress(hmod, "pidgin_main"); if (!pidgin_main) { DWORD dw = GetLastError(); BOOL mod_not_found = (dw == ERROR_MOD_NOT_FOUND || dw == ERROR_DLL_NOT_FOUND); - const TCHAR *err_msg = get_win32_error_message(dw); + const wchar_t *err_msg = get_win32_error_message(dw); - _sntprintf(errbuf, 512, _T("Error loading pidgin.dll.\nError: (%u) %s%s%s"), + _snwprintf(errbuf, 512, L"Error loading pidgin.dll.\nError: (%u) %s%s%s", (UINT) dw, err_msg, - mod_not_found ? _T("\n") : _T(""), - mod_not_found ? _T("This probably means that GTK+ can't be found.") : _T("")); - _tprintf(_T("%s\n"), errbuf); - MessageBox(NULL, errbuf, _T("Error"), MB_OK | MB_TOPMOST); + mod_not_found ? L"\n" : L"", + mod_not_found ? L"This probably means that GTK+ can't be found." : L""); + wprintf(L"%s\n", errbuf); + MessageBoxW(NULL, errbuf, L"Error", MB_OK | MB_TOPMOST); return 0; } diff -r c316749944c1 -r 2bdbf3fbd894 pidgin/win32/wspell.c --- a/pidgin/win32/wspell.c Sat Mar 13 08:18:25 2010 +0000 +++ b/pidgin/win32/wspell.c Fri Mar 26 00:43:51 2010 +0000 @@ -95,41 +95,6 @@ SetErrorMode(old_error_mode); } -static void lookup_aspell_path() { - const char *tmp; - gchar *aspell_path; - - if ((tmp = g_getenv("PIDGIN_ASPELL_DIR"))) - aspell_path = g_strdup(tmp); - else - aspell_path = wpurple_read_reg_string(HKEY_LOCAL_MACHINE, "Software\\Aspell", "Path"); - - if (aspell_path != NULL) { - char *tmp = g_build_filename(aspell_path, "aspell-15.dll", NULL); - if (g_file_test(tmp, G_FILE_TEST_EXISTS)) { - const char *path = g_getenv("PATH"); - purple_debug_info("wspell", "Found Aspell in %s\n", aspell_path); - - g_free(tmp); - - tmp = g_strdup_printf("%s%s%s", (path ? path : ""), - (path ? G_SEARCHPATH_SEPARATOR_S : ""), - aspell_path); - - g_setenv("PATH", tmp, TRUE); - - } else - purple_debug_warning("wspell", "Couldn't find aspell-15.dll\n"); - - g_free(tmp); - g_free(aspell_path); - } else - purple_debug_warning("wspell", "Aspell installation not found (this isn't necessarily a problem)\n"); -} - void winpidgin_spell_init() { - /* We keep doing the aspell path thing so that previously installed dictionaries still work */ - lookup_aspell_path(); - load_gtkspell(); }