changeset 20869:2a6ef74f5a4e

merge of '3efb5d625e5a73423be8be77a6baeed0b65f7e55' and 'c848ad4c20988b5dac9ac164455d3ba2d7307230'
author Sadrul Habib Chowdhury <imadil@gmail.com>
date Wed, 10 Oct 2007 01:06:16 +0000
parents e0ce7124d2d4 (current diff) 817425918f92 (diff)
children c026361d4e63 acf284962b40
files
diffstat 52 files changed, 453 insertions(+), 242 deletions(-) [+]
line wrap: on
line diff
--- a/.mtn-ignore	Wed Oct 10 01:01:21 2007 +0000
+++ b/.mtn-ignore	Wed Oct 10 01:06:16 2007 +0000
@@ -21,7 +21,7 @@
 config.status
 config.sub
 configure$
-finch/finch
+finch/finch$
 finch/libgnt/gntmarshal.c
 finch/libgnt/gntmarshal.h
 depcomp
--- a/doc/C-HOWTO.dox	Wed Oct 10 01:01:21 2007 +0000
+++ b/doc/C-HOWTO.dox	Wed Oct 10 01:06:16 2007 +0000
@@ -269,3 +269,4 @@
   you may have guessed, this also gets read when libpurple is probing your
   plugin.  If this is missing, the plugin will not load.
  */
+// vim: syntax=c.doxygen
--- a/doc/account-signals.dox	Wed Oct 10 01:01:21 2007 +0000
+++ b/doc/account-signals.dox	Wed Oct 10 01:06:16 2007 +0000
@@ -11,6 +11,8 @@
   @signal account-status-changed
  @endsignals
 
+ @see account.h
+
  <hr>
 
  @signaldef account-added
@@ -101,4 +103,4 @@
  @endsignaldef
 
  */
-// vim: syntax=c tw=75 et
+// vim: syntax=c.doxygen tw=75 et
--- a/doc/blist-signals.dox	Wed Oct 10 01:01:21 2007 +0000
+++ b/doc/blist-signals.dox	Wed Oct 10 01:06:16 2007 +0000
@@ -13,6 +13,8 @@
   @signal blist-node-aliased
  @endsignals
 
+ @see blist.h
+
  <hr>
 
  @signaldef buddy-status-changed
@@ -105,4 +107,4 @@
   @endsignaldef
 
  */
-// vim: syntax=c tw=75 et
+// vim: syntax=c.doxygen tw=75 et
--- a/doc/certificate-signals.dox	Wed Oct 10 01:01:21 2007 +0000
+++ b/doc/certificate-signals.dox	Wed Oct 10 01:06:16 2007 +0000
@@ -5,6 +5,8 @@
   @signal certificate-deleted
  @endsignals
 
+ @see certificate.h
+
  <hr>
 
  @signaldef certificate-stored
@@ -28,4 +30,4 @@
  @endsignaldef
 
  */
-// vim: syntax=c tw=75 et
+// vim: syntax=c.doxygen tw=75 et
--- a/doc/cipher-signals.dox	Wed Oct 10 01:01:21 2007 +0000
+++ b/doc/cipher-signals.dox	Wed Oct 10 01:06:16 2007 +0000
@@ -5,6 +5,8 @@
   @signal cipher-removed
  @endsignals
 
+ @see cipher.h
+
  <hr>
 
  @signaldef cipher-added
@@ -26,4 +28,4 @@
  @endsignaldef
 
  */
-// vim: syntax=c tw=75 et
+// vim: syntax=c.doxygen tw=75 et
--- a/doc/connection-signals.dox	Wed Oct 10 01:01:21 2007 +0000
+++ b/doc/connection-signals.dox	Wed Oct 10 01:06:16 2007 +0000
@@ -7,6 +7,8 @@
   @signal signed-off
  @endsignals
 
+ @see connection.h
+
  <hr>
 
  @signaldef signing-on
@@ -46,4 +48,4 @@
  @endsignaldef
 
  */
-// vim: syntax=c tw=75 et
+// vim: syntax=c.doxygen tw=75 et
--- a/doc/conversation-signals.dox	Wed Oct 10 01:01:21 2007 +0000
+++ b/doc/conversation-signals.dox	Wed Oct 10 01:06:16 2007 +0000
@@ -32,6 +32,8 @@
   @signal conversation-extended-menu
  @endsignals
 
+ @see conversation.h
+
  @signaldef writing-im-msg
   @signalproto
 gboolean (*writing_im_msg)(PurpleAccount *account, const char *who,
@@ -429,4 +431,4 @@
   @param list   A pointer to the list of actions.
  @endsignaldef
 */
-// vim: syntax=c tw=75 et
+// vim: syntax=c.doxygen tw=75 et
--- a/doc/core-signals.dox	Wed Oct 10 01:01:21 2007 +0000
+++ b/doc/core-signals.dox	Wed Oct 10 01:06:16 2007 +0000
@@ -4,6 +4,8 @@
   @signal quitting
  @endsignals
 
+ @see core.h
+
  <hr>
 
  @signaldef quitting
@@ -15,4 +17,4 @@
  @endsignaldef
 
  */
-// vim: syntax=c tw=75 et
+// vim: syntax=c.doxygen tw=75 et
--- a/doc/dbus-server-signals.dox	Wed Oct 10 01:01:21 2007 +0000
+++ b/doc/dbus-server-signals.dox	Wed Oct 10 01:06:16 2007 +0000
@@ -5,6 +5,8 @@
   @signal dbus-introspect
  @endsignals
 
+ @see dbus-server.h
+
  <hr>
 
  @signaldef dbus-method-called
@@ -29,4 +31,4 @@
  @endsignaldef
 
  */
-// vim: syntax=c tw=75 et
+// vim: syntax=c.doxygen tw=75 et
--- a/doc/gtkaccount-signals.dox	Wed Oct 10 01:01:21 2007 +0000
+++ b/doc/gtkaccount-signals.dox	Wed Oct 10 01:06:16 2007 +0000
@@ -4,6 +4,8 @@
   @signal account-modified
  @endsignals
 
+ @see gtkaccount.h
+
  <hr>
 
  @signaldef account-modified
@@ -15,4 +17,4 @@
   @param account The account that has been modified.
  @endsignaldef
 */
-// vim: syntax=c tw=75 et
+// vim: syntax=c.doxygen tw=75 et
--- a/doc/gtkblist-signals.dox	Wed Oct 10 01:01:21 2007 +0000
+++ b/doc/gtkblist-signals.dox	Wed Oct 10 01:06:16 2007 +0000
@@ -7,6 +7,8 @@
   @signal drawing-tooltip
  @endsignals
 
+ @see gtkblist.h
+
  <hr>
 
  @signaldef gtkblist-hiding
@@ -52,4 +54,4 @@
               a compact tooltip for a non-priority buddy.
  @endsignaldef
 */
-// vim: syntax=c tw=75 et
+// vim: syntax=c.doxygen tw=75 et
--- a/doc/gtkconv-signals.dox	Wed Oct 10 01:01:21 2007 +0000
+++ b/doc/gtkconv-signals.dox	Wed Oct 10 01:06:16 2007 +0000
@@ -139,4 +139,4 @@
  @endsignaldef
 
 */
-// vim: syntax=c tw=75 et
+// vim: syntax=c.doxygen tw=75 et
--- a/doc/gtkimhtml-signals.dox	Wed Oct 10 01:01:21 2007 +0000
+++ b/doc/gtkimhtml-signals.dox	Wed Oct 10 01:06:16 2007 +0000
@@ -8,6 +8,8 @@
   @signal format_function_update
  @endsignals
 
+ @see gtkimhtml.h
+
  <hr>
 
  @signaldef url_clicked
@@ -57,4 +59,4 @@
   @param data   User defined data.
  @endsignaldef
 */
-// vim: syntax=c tw=75 et
+// vim: syntax=c.doxygen tw=75 et
--- a/doc/gtklog-signals.dox	Wed Oct 10 01:01:21 2007 +0000
+++ b/doc/gtklog-signals.dox	Wed Oct 10 01:06:16 2007 +0000
@@ -4,6 +4,8 @@
   @signal log-displaying
  @endsignals
 
+ @see gtklog.h
+
  <hr>
 
  @signaldef log-displaying
@@ -17,4 +19,4 @@
  @endsignaldef
 
 */
-// vim: syntax=c tw=75 et
+// vim: syntax=c.doxygen tw=75 et
--- a/doc/imgstore-signals.dox	Wed Oct 10 01:01:21 2007 +0000
+++ b/doc/imgstore-signals.dox	Wed Oct 10 01:06:16 2007 +0000
@@ -4,6 +4,8 @@
   @signal image-deleting
  @endsignals
 
+ @see imgstore.h
+
  <hr>
 
  @signaldef image-deleting
@@ -11,7 +13,7 @@
 char *(*image_deleting)(const PurpleStoredImage *img);
   @endsignalproto
   @signaldesc
-   Emitted when a PurpleStoredImage is about to be destroyed.  This allows
+   Emitted when a #PurpleStoredImage is about to be destroyed.  This allows
    for what amounts to weak references.  Code can hold onto a pointer to
    the PurpleStoredImage without actually "holding" a reference.  They can
    then use a signal handler to let them know when their img is about to
@@ -21,4 +23,4 @@
  @endsignaldef
 
 */
-// vim: syntax=c tw=75 et
+// vim: syntax=c.doxygen tw=75 et
--- a/doc/log-signals.dox	Wed Oct 10 01:01:21 2007 +0000
+++ b/doc/log-signals.dox	Wed Oct 10 01:06:16 2007 +0000
@@ -4,6 +4,8 @@
   @signal log-timestamp
  @endsignals
 
+ @see log.h
+
  <hr>
 
  @signaldef log-timestamp
@@ -21,4 +23,4 @@
  @endsignaldef
 
 */
-// vim: syntax=c tw=75 et
+// vim: syntax=c.doxygen tw=75 et
--- a/doc/notify-signals.dox	Wed Oct 10 01:01:21 2007 +0000
+++ b/doc/notify-signals.dox	Wed Oct 10 01:06:16 2007 +0000
@@ -6,6 +6,8 @@
   @signal displaying-emails-notification
  @endsignals
 
+ @see notify.h
+
  @signaldef displaying-userinfo
   @signalproto
 void (*displaying_userinfo)(PurpleAccount *account, const char *who, PurpleNotifyUserInfo *user_info);
@@ -53,4 +55,4 @@
  @endsignaldef
 
 */
-// vim: syntax=c tw=75 et
+// vim: syntax=c.doxygen tw=75 et
--- a/doc/plugin-ids.dox	Wed Oct 10 01:01:21 2007 +0000
+++ b/doc/plugin-ids.dox	Wed Oct 10 01:06:16 2007 +0000
@@ -2,10 +2,10 @@
 
  @section Introduction
   Every plugin contains a unique identifier to prevent duplicate plugin
-  loading and conflicts. This, which will be called a plugin ID from here
-  on, must follow a specific format. This format categorizes a plugin and
-  makes duplicate IDs unlikely.
-
+  loading and conflicts. Third-party plugins (that is, plugins written by
+  anyone who is not a libpurple, Pidgin, or Finch developer) are expected
+  to use a plugin ID that follows a specific format. This format
+  categorizes plugins and makes duplicate IDs highly unlikely.
 
  @section Format
   The basic format of a plugin ID is as follows:
@@ -15,27 +15,79 @@
   The @em type indicator specifies the type of plugin. This must be one
   of the following:
 
-    - core      - Core plugin, capable of being loaded in any program using
-                  libpurple. It must not use any UI-specific code.
-    - prpl      - Protocol plugin, providing additional protocols to
-                  connect to.
-    - lopl      - Loader plugin, which loads scripts as plugins (like Perl
-                  or TCL).
-    - gtk       - GTK+ 2.x plugin. It may use GTK+ code, but cannot use any
-                  window toolkit code (such as X11 or Win32).
-    - gtk-x11   - GTK+ 2.x plugin using X11 code.
-    - gtk-win32 - GTK+ 2.x plugin using Win32 code.
-    - qpe       - Gaim for Qtopia plugin.
+    - core      - A core libpurple plugin, capable of being loaded in any
+                  program using libpurple. Core plugins may not contain any
+                  UI-specific code.
+    - prpl      - A protocol plugin. This is a special type of core plugin,
+                  which provides libpurple the ability to connect to
+                  another IM or chat network.
+    - lopl      - A loader plugin, which loads scripts as plugins. Perl and
+                  Tcl plugins are made possible by loader plugins.
+    - gtk       - A GTK+ 2.x (a.k.a. Pidgin) plugin. These plugins may use
+                  GTK+ code, but may not use window toolkit code, such as
+                  X11, Win32, Cocoa, or Carbon.
+    - gtk-x11   - A GTK+ 2.x plugin that uses X11 code. These plugins may
+                  use both GTK+ code and X11 code, allowing to hook into
+                  features specific to X11.
+    - gtk-win32 - A GTK+ plugin that uses Win32 code. These plugins may use
+                  both GTK+ code and Win32 code, allowing to hook into
+                  features available on Windows.
+    - gnt       - A GNT (a.k.a. Finch) plugin. These plugins may use GNT code.
+    - qpe       - A plugin for the (now-abandoned) Qutopia user interface.
+
+  The @em username must be a unique identifier for you. It
+  @em should be your http://developer.pidgin.im Trac user ID. Failing that, you
+  could use your SourceForge user ID or your Freenode IRC nickname, if you
+  have either. The http://developer.pidgin.im Trac user ID is preferred.
+  Do @em not leave this field blank!
+
+  The @em pluginname is the name of your plugin. It is usually all
+  lowercase letters and matches the static plugin ID (the first argument to
+  the PURPLE_INIT_PLUGIN() macro call), although it can be anything you
+  like. Do @em not include version information in the plugin ID--the
+  #PurplePluginInfo structure already has a field for this.
+
+ @section nospaces One Last Rule for Plugin IDs
+
+  The last rule of plugin IDs is the most important of all. Plugin IDs may
+  @em NOT contain spaces. If you need a space, use another hyphen (-).
 
-  The @em username must be a unique identifier for that person. It
-  @em should be your SourceForge ID. Do @em not leave this field
-  blank.
+ @section exceptions Exceptions to the Rule
+
+  As with any rule there are exceptions. If you browse through the source
+  tree you will see that the plugins we distribute with the Pidgin source
+  do not contain a username field. This is because while one developer may
+  have written each specific plugin, the plugins are maintained
+  collectively by the entire development team. This lack of a username
+  field is also an indicator that the plugin is one of our plugins and not
+  a third-party plugin.
+
+  Another exception to the rule is the <a
+  href="http://plugins.guifications.org/trac/wiki/PluginPack">Purple Plugin
+  Pack</a>. All plugins whose lives started in the Purple Plugin Pack use
+  <tt>"plugin_pack"</tt> for the username field to indicate origination in
+  the Purple Plugin Pack.
 
-  The @em pluginname is the name of your plugin. It can be whatever you like,
-  though it's common to keep it all lowercase. Do not use spaces! If you
-  want a space, use a '-'. Please do not put a version indicator in the ID.
-  The PurplePlugin structure already has a field for this.
+  These two exceptions are mentioned here for completeness. We don't
+  encourage breaking the conventions set forth by the rules outlined above.
+
+ @section examples Examples of Well-Chosen Plugin IDs
+
+  The following is a list of well-chosen Plugin IDs listing a few good examples.
 
+    - <tt>"gtk-amc_grim-guifications"</tt> - This is the plugin ID for the
+                                             Guifications 2.x plugin.
+    - <tt>"gtk-rlaager-album"</tt> - This is the plugin ID for the Album
+                                     plugin, which is now part of the
+                                     Purple Plugin Pack. Its ID follows the
+                                     rules because its life started prior
+                                     to its inclusion in the Plugin Pack.
+    - <tt>"core-rlaager-irchelper"</tt> - This is the plugin ID for the IRC
+                                          Helper plugin, which is now part
+                                          of the Purple Plugin Pack. Its ID
+                                          follows the rules because its
+                                          life started prior to its
+                                          inclusion in the Plugin Pack.
 
  @section plugin-db Plugin Database
   Although it doesn't exist yet, in time there will be a plugin database
@@ -45,4 +97,4 @@
 
  */
 
-// vim: syntax=c tw=75 et
+// vim: syntax=c.doxygen tw=75 et
--- a/doc/plugin-signals.dox	Wed Oct 10 01:01:21 2007 +0000
+++ b/doc/plugin-signals.dox	Wed Oct 10 01:06:16 2007 +0000
@@ -5,6 +5,8 @@
   @signal plugin-unload
  @endsignals
 
+ @see plugin.h
+
  <hr>
 
  @signaldef plugin-load
@@ -26,4 +28,4 @@
  @endsignaldef
 
  */
-// vim: syntax=c tw=75 et
+// vim: syntax=c.doxygen tw=75 et
--- a/doc/savedstatus-signals.dox	Wed Oct 10 01:01:21 2007 +0000
+++ b/doc/savedstatus-signals.dox	Wed Oct 10 01:06:16 2007 +0000
@@ -4,6 +4,8 @@
   @signal savedstatus-changed
  @endsignals
 
+ @see savedstatus.h
+
  <hr>
 
  @signaldef savedstatus-changed
@@ -15,4 +17,4 @@
  @endsignaldef
 
  */
-// vim: syntax=c tw=75 et
+// vim: syntax=c.doxygen tw=75 et
--- a/doc/sound-signals.dox	Wed Oct 10 01:01:21 2007 +0000
+++ b/doc/sound-signals.dox	Wed Oct 10 01:06:16 2007 +0000
@@ -4,6 +4,8 @@
   @signal playing-sound-event
  @endsignals
 
+ @see sound.h
+
  <hr>
 
  @signaldef playing-sound-event
@@ -18,4 +20,4 @@
  @endsignaldef
 
  */
-// vim: syntax=c tw=75 et
+// vim: syntax=c.doxygen tw=75 et
--- a/doc/xfer-signals.dox	Wed Oct 10 01:01:21 2007 +0000
+++ b/doc/xfer-signals.dox	Wed Oct 10 01:06:16 2007 +0000
@@ -12,6 +12,8 @@
   @signal file-send-complete
  @endsignals
 
+ @see ft.h
+
  <hr>
 
  @signaldef file-recv-accept
@@ -109,4 +111,4 @@
  @endsignaldef
 
  */
-// vim: syntax=c tw=75 et
+// vim: syntax=c.doxygen tw=75 et
--- a/libpurple/plugins/log_reader.c	Wed Oct 10 01:01:21 2007 +0000
+++ b/libpurple/plugins/log_reader.c	Wed Oct 10 01:06:16 2007 +0000
@@ -232,7 +232,6 @@
 	struct adium_logger_data *data;
 	GError *error = NULL;
 	gchar *read = NULL;
-	gsize length;
 
 	/* XXX: TODO: We probably want to set PURPLE_LOG_READ_NO_NEWLINE
 	 * XXX: TODO: for HTML logs. */
@@ -246,8 +245,9 @@
 	g_return_val_if_fail(data->path != NULL, g_strdup(""));
 
 	purple_debug_info("Adium log read", "Reading %s\n", data->path);
-	if (!g_file_get_contents(data->path, &read, &length, &error)) {
-		purple_debug_error("Adium log read", "Error reading log\n");
+	if (!g_file_get_contents(data->path, &read, NULL, &error)) {
+		purple_debug_error("Adium log read", "Error reading log: %s\n",
+					   (error && error->message) ? error->message : "Unknown error");
 		if (error)
 			g_error_free(error);
 		return g_strdup("");
@@ -1808,8 +1808,10 @@
 	error = NULL;
 	if (!g_file_get_contents(path, &contents, NULL, &error)) {
 		purple_debug_error("QIP logger",
-		                   "Couldn't read file %s: %s \n", path, error->message);
-		g_error_free(error);
+				   "Couldn't read file %s: %s \n", path,
+				   (error && error->message) ? error->message : "Unknown error");
+		if (error)
+			g_error_free(error);
 		g_free(path);
 		return list;
 	}
@@ -1937,13 +1939,11 @@
 	g_return_val_if_fail(data->path != NULL, g_strdup(""));
 	g_return_val_if_fail(data->length > 0, g_strdup(""));
 
-	error = NULL;
-	
-	contents = g_malloc(data->length + 2);
-
 	file = g_fopen(data->path, "rb");
 	g_return_val_if_fail(file != NULL, g_strdup(""));
-	
+
+	contents = g_malloc(data->length + 2);
+
 	fseek(file, data->offset, SEEK_SET);
 	fread(contents, data->length, 1, file);
 	fclose(file);
@@ -1955,8 +1955,10 @@
 	error = NULL;
 	if (!(utf8_string = g_convert(contents, -1, "UTF-8", "Cp1251", NULL, NULL, &error))) {
 		purple_debug_error("QIP logger",
-			"Couldn't convert file %s to UTF-8: %s\n", data->path, error->message);
-		g_error_free(error);
+			"Couldn't convert file %s to UTF-8: %s\n", data->path,
+				   (error && error->message) ? error->message : "Unknown error");
+		if (error)
+			g_error_free(error);
 		g_free(contents);
 		return g_strdup("");
 	}
@@ -2022,7 +2024,7 @@
 					g_string_append(formatted, "</font> ");
 
 					if (is_in_message) {
-						if (buddy_name != NULL && buddy->alias) {
+						if (buddy_name != NULL && buddy != NULL && buddy->alias) {
 							g_string_append_printf(formatted,
 								"<span style=\"color: #A82F2F;\">"
 								"<b>%s</b></span>: ", buddy->alias);
@@ -2052,7 +2054,9 @@
 				g_string_append(formatted, line);
 				g_string_append(formatted, "<br>");
 			}
-			line = ++c;
+
+			if (c)
+				line = ++c;
 		}
 	}
 	g_free(contents);
@@ -2151,18 +2155,18 @@
 
 	/* Calculate default Messenger Plus! log directory. */
 #ifdef _WIN32
+	path = NULL;
 	folder = wpurple_get_special_folder(CSIDL_PERSONAL);
 	if (folder) {
 		path = g_build_filename(folder, "My Chat Logs", NULL);
 		g_free(folder);
-	} else
-		path = g_strdup("");
+	}
 #else
 	path = g_build_filename(PURPLE_LOG_READER_WINDOWS_MOUNT_POINT,
 	                        "Documents and Settings", g_get_user_name(),
 	                        "My Documents", "My Chat Logs", NULL);
 #endif
-	purple_prefs_add_string("/plugins/core/log_reader/messenger_plus/log_directory", path);
+	purple_prefs_add_string("/plugins/core/log_reader/messenger_plus/log_directory", path ? path : "");
 	g_free(path);
 
 
@@ -2171,18 +2175,18 @@
 
 	/* Calculate default MSN message history directory. */
 #ifdef _WIN32
+	path = NULL;
 	folder = wpurple_get_special_folder(CSIDL_PERSONAL);
 	if (folder) {
 		path = g_build_filename(folder, "My Received Files", NULL);
 		g_free(folder);
-	} else
-		path = g_strdup("");
+	}
 #else
 	path = g_build_filename(PURPLE_LOG_READER_WINDOWS_MOUNT_POINT,
 	                        "Documents and Settings", g_get_user_name(),
 	                        "My Documents", "My Received Files", NULL);
 #endif
-	purple_prefs_add_string("/plugins/core/log_reader/msn/log_directory", path);
+	purple_prefs_add_string("/plugins/core/log_reader/msn/log_directory", path ? path : "");
 	g_free(path);
 
 
@@ -2261,22 +2265,22 @@
 			g_key_file_free(key_file);
 		}
 #else /* !GLIB_CHECK_VERSION(2,6,0) */
-		gsize length;
 		gchar *contents = NULL;
 
 		purple_debug_info("Trillian talk.ini read",
-					"Reading %s\n", path);
-		if (!g_file_get_contents(path, &contents, &length, &error)) {
+				  "Reading %s\n", path);
+		if (!g_file_get_contents(path, &contents, NULL, &error)) {
 			purple_debug_error("Trillian talk.ini read",
-			                   "Error reading talk.ini\n");
+					   "Error reading talk.ini: %s\n",
+					   (error && error->message) ? error->message : "Unknown error");
 			if (error)
 				g_error_free(error);
-			g_free(path);
 		} else {
-			char *line = contents;
-			while (*contents) {
-				if (*contents == '\n') {
-					*contents = '\0';
+			char *cursor, *line;
+			line = cursor = contents;
+			while (*cursor) {
+				if (*cursor == '\n') {
+					*cursor = '\0';
 
 					/* XXX: This assumes the first Directory key is under [Logging]. */
 					if (purple_str_has_prefix(line, "Directory=")) {
@@ -2288,25 +2292,29 @@
 						found = TRUE;
 					}
 
-					contents++;
-					line = contents;
+					cursor++;
+					line = cursor;
 				} else
-					contents++;
+					cursor++;
 			}
-			g_free(path);
 			g_free(contents);
 		}
+		g_free(path);
 #endif /* !GTK_CHECK_VERSION(2,6,0) */
 	} /* path */
 
 	if (!found) {
+		path = NULL;
 		folder = wpurple_get_special_folder(CSIDL_PROGRAM_FILES);
 		if (folder) {
 			path = g_build_filename(folder, "Trillian", "users",
 			                        "default", "logs", NULL);
 			g_free(folder);
-		} else
-			path = g_strdup("");
+		}
+
+		purple_prefs_add_string(
+			"/plugins/core/log_reader/trillian/log_directory", path ? path : "");
+		g_free(path);
 	}
 #else /* !defined(_WIN32) */
 	/* TODO: At some point, this could attempt to parse talk.ini
@@ -2317,28 +2325,27 @@
 	path = g_build_filename(PURPLE_LOG_READER_WINDOWS_MOUNT_POINT,
 	                        "Program Files", "Trillian", "users",
 	                        "default", "logs", NULL);
+	purple_prefs_add_string(
+		"/plugins/core/log_reader/trillian/log_directory", path);
+	g_free(path);
 #endif
 
-	/*XXX: Why do we even bother allocating it ? */
-	g_free(path);
-
-
 	/* Add QIP log directory preference. */
 	purple_prefs_add_none("/plugins/core/log_reader/qip");
 
 	/* Calculate default QIP log directory. */
 #ifdef _WIN32
+	path = NULL;
 	folder = wpurple_get_special_folder(CSIDL_PROGRAM_FILES);
 	if (folder) {
 		path = g_build_filename(folder, "QIP", "Users", NULL);
 		g_free(folder);
-	} else
-		path = g_strdup("");
+	}
 #else
 	path = g_build_filename(PURPLE_LOG_READER_WINDOWS_MOUNT_POINT,
 	                        "Program Files", "QIP", "Users", NULL);
 #endif
-	purple_prefs_add_string("/plugins/core/log_reader/qip/log_directory", path);
+	purple_prefs_add_string("/plugins/core/log_reader/qip/log_directory", path ? path : "");
 	g_free(path);
 }
 
--- a/libpurple/plugins/ssl/ssl-gnutls.c	Wed Oct 10 01:01:21 2007 +0000
+++ b/libpurple/plugins/ssl/ssl-gnutls.c	Wed Oct 10 01:06:16 2007 +0000
@@ -884,7 +884,7 @@
 	gnutls_x509_crt crt_dat;
 	/* GnuTLS time functions return this on error */
 	const time_t errval = (time_t) (-1);
-
+	gboolean success = TRUE;
 
 	g_return_val_if_fail(crt, FALSE);
 	g_return_val_if_fail(crt->scheme == &x509_gnutls, FALSE);
@@ -893,16 +893,16 @@
 
 	if (activation) {
 		*activation = gnutls_x509_crt_get_activation_time(crt_dat);
+		if (*activation == errval)
+			success = FALSE;
 	}
 	if (expiration) {
 		*expiration = gnutls_x509_crt_get_expiration_time(crt_dat);
+		if (*expiration == errval)
+			success = FALSE;
 	}
 
-	if (*activation == errval || *expiration == errval) {
-		return FALSE;
-	}
-
-	return TRUE;
+	return success;
 }
 
 /* X.509 certificate operations provided by this plugin */
--- a/libpurple/plugins/ssl/ssl-nss.c	Wed Oct 10 01:01:21 2007 +0000
+++ b/libpurple/plugins/ssl/ssl-nss.c	Wed Oct 10 01:06:16 2007 +0000
@@ -386,6 +386,7 @@
 static GList *
 ssl_nss_peer_certs(PurpleSslConnection *gsc)
 {
+#if 0
 	PurpleSslNssData *nss_data = PURPLE_SSL_NSS_DATA(gsc);
 	CERTCertificate *cert;
 /*
@@ -397,6 +398,10 @@
 	/* TODO: this is a blind guess */
 	cert = SSL_PeerCertificate(nss_data->fd);
 
+	if (cert)
+		CERT_DestroyCertificate(cert);
+#endif
+
 	
 
 	return NULL;
@@ -430,11 +435,12 @@
 			  filename);
 	
 	/* Load the raw data up */
-	g_return_val_if_fail(
-		g_file_get_contents(filename,
-				    &rawcert, &len,
-				    NULL ),
-		NULL);
+	if (!g_file_get_contents(filename,
+				 &rawcert, &len,
+				 NULL)) {
+		purple_debug_error("nss/x509", "Unable to read certificate file.\n");
+		return NULL;
+	}
 
 	/* Decode the certificate */
 	crt_dat = CERT_DecodeCertFromPackage(rawcert, len);
--- a/libpurple/protocols/bonjour/bonjour.c	Wed Oct 10 01:01:21 2007 +0000
+++ b/libpurple/protocols/bonjour/bonjour.c	Wed Oct 10 01:06:16 2007 +0000
@@ -188,6 +188,8 @@
 	if (bonjour_group != NULL)
 		purple_blist_remove_group(bonjour_group);
 
+	g_free(bd);
+	connection->proto_data = NULL;
 }
 
 static const char *
@@ -581,7 +583,7 @@
 			fullname = g_utf16_to_utf8(username, -1, NULL, NULL, NULL);
 	}
 
-	g_idle_add(_set_default_name_cb, fullname);
+	purple_timeout_add(0, _set_default_name_cb, fullname);
 
 	return NULL;
 }
--- a/libpurple/protocols/bonjour/parser.c	Wed Oct 10 01:01:21 2007 +0000
+++ b/libpurple/protocols/bonjour/parser.c	Wed Oct 10 01:06:16 2007 +0000
@@ -64,7 +64,7 @@
 			char *attrib_ns = NULL;
 
 			if (attributes[i+2]) {
-				attrib_ns = g_strdup((char*)attributes[i+2]);;
+				attrib_ns = g_strdup((char*)attributes[i+2]);
 			}
 
 			memcpy(attrib, attributes[i+3], attrib_len);
@@ -101,7 +101,7 @@
 		if(!xmlStrcmp(element_name, (xmlChar*) "stream")) {
 			/* Asynchronously close the conversation to prevent bonjour_parser_setup()
 			 * being called from within this context */
-			g_idle_add(_async_bonjour_jabber_stream_ended_cb, pb);
+			purple_timeout_add(0, _async_bonjour_jabber_stream_ended_cb, pb);
 		}
 		return;
 	}
--- a/libpurple/protocols/irc/irc.h	Wed Oct 10 01:01:21 2007 +0000
+++ b/libpurple/protocols/irc/irc.h	Wed Oct 10 01:06:16 2007 +0000
@@ -99,6 +99,8 @@
 int irc_send(struct irc_conn *irc, const char *buf);
 gboolean irc_blist_timeout(struct irc_conn *irc);
 
+char *irc_escape_privmsg(const char *text, gssize length);
+
 char *irc_mirc2html(const char *string);
 char *irc_mirc2txt(const char *string);
 
--- a/libpurple/protocols/irc/msgs.c	Wed Oct 10 01:01:21 2007 +0000
+++ b/libpurple/protocols/irc/msgs.c	Wed Oct 10 01:06:16 2007 +0000
@@ -1066,7 +1066,7 @@
 		return;
 	}
 
-	msg = g_markup_escape_text(tmp, -1);
+	msg = irc_escape_privmsg(tmp, -1);
 	g_free(tmp);
 
 	tmp = irc_mirc2html(msg);
--- a/libpurple/protocols/irc/parse.c	Wed Oct 10 01:01:21 2007 +0000
+++ b/libpurple/protocols/irc/parse.c	Wed Oct 10 01:06:16 2007 +0000
@@ -281,6 +281,61 @@
 	return purple_utf8_salvage(string);
 }
 
+/* This function is shamelessly stolen from glib--it is an old version of the
+ * private function append_escaped_text, used by g_markup_escape_text, whose
+ * behavior changed in glib 2.12. */
+static void irc_append_escaped_text(GString *str, const char *text, gssize length)
+{
+	const char *p = text;
+	const char *end = text + length;
+	const char *next = NULL;
+
+	while(p != end) {
+		next = g_utf8_next_char(p);
+
+		switch(*p) {
+			case '&':
+				g_string_append(str, "&amp;");
+				break;
+			case '<':
+				g_string_append(str, "&lt;");
+				break;
+			case '>':
+				g_string_append(str, "&gt;");
+				break;
+			case '\'':
+				g_string_append(str, "&apos;");
+				break;
+			case '"':
+				g_string_append(str, "&quot;");
+				break;
+			default:
+				g_string_append_len(str, p, next - p);
+				break;
+		}
+
+		p = next;
+	}
+}
+
+/* This function is shamelessly stolen from glib--it is an old version of the
+ * function g_markup_escape_text, whose behavior changed in glib 2.12. */
+char *irc_escape_privmsg(const char *text, gssize length)
+{
+	GString *str;
+
+	g_return_val_if_fail(text != NULL, NULL);
+
+	if(length < 0)
+		length = strlen(text);
+
+	str = g_string_sized_new(length);
+
+	irc_append_escaped_text(str, text, length);
+
+	return g_string_free(str, FALSE);
+}
+
 /* XXX tag closings are not necessarily correctly nested here!  If we
  *     get a ^O or reach the end of the string and there are open
  *     tags, they are closed in a fixed order ... this means, for
--- a/libpurple/protocols/jabber/chat.c	Wed Oct 10 01:01:21 2007 +0000
+++ b/libpurple/protocols/jabber/chat.c	Wed Oct 10 01:06:16 2007 +0000
@@ -964,7 +964,7 @@
 static void jabber_chat_disco_traffic_cb(JabberStream *js, xmlnode *packet, gpointer data)
 {
 	JabberChat *chat;
-	xmlnode *query;
+	/*xmlnode *query;*/
 	int id = GPOINTER_TO_INT(data);
 
 	if(!(chat = jabber_chat_find_by_id(js, id)))
@@ -974,6 +974,8 @@
 	 * support this request */
 	chat->xhtml = TRUE;
 
+	/* disabling this until more MUC servers support
+	 * announcing this
 	if(xmlnode_get_child(packet, "error")) {
 		return;
 	}
@@ -981,8 +983,6 @@
 	if(!(query = xmlnode_get_child(packet, "query")))
 		return;
 
-	/* disabling this until more MUC servers support
-	 * announcing this
 	chat->xhtml = FALSE;
 
 	for(x = xmlnode_get_child(query, "feature"); x; x = xmlnode_get_next_twin(x)) {
--- a/libpurple/protocols/jabber/google.c	Wed Oct 10 01:01:21 2007 +0000
+++ b/libpurple/protocols/jabber/google.c	Wed Oct 10 01:06:16 2007 +0000
@@ -110,7 +110,7 @@
 		tos[i] = (to_name != NULL ?  to_name : "");
 		froms[i] = (from != NULL ?  from : "");
 		subjects[i] = (subject != NULL ? subject : g_strdup(""));
-		urls[i] = (url != NULL ? url : "");
+		urls[i] = url;
 
 		tid = xmlnode_get_attrib(message, "tid");
 		if (tid &&
--- a/libpurple/protocols/jabber/iq.c	Wed Oct 10 01:01:21 2007 +0000
+++ b/libpurple/protocols/jabber/iq.c	Wed Oct 10 01:06:16 2007 +0000
@@ -248,7 +248,6 @@
 	JabberIq *iq;
 	const char *type, *from, *id;
 	xmlnode *query;
-	char *os = NULL;
 
 	type = xmlnode_get_attrib(packet, "type");
 
@@ -256,6 +255,7 @@
 		GHashTable *ui_info;
 		const char *ui_name = NULL, *ui_version = NULL;
 #if 0
+		char *os = NULL;
 		if(!purple_prefs_get_bool("/plugins/prpl/jabber/hide_os")) {
 			struct utsname osinfo;
 
@@ -290,10 +290,12 @@
 			xmlnode_insert_data(xmlnode_new_child(query, "version"), VERSION, -1);
 		}
 
+#if 0
 		if(os) {
 			xmlnode_insert_data(xmlnode_new_child(query, "os"), os, -1);
 			g_free(os);
 		}
+#endif
 
 		jabber_iq_send(iq);
 	}
--- a/libpurple/protocols/jabber/jabber.c	Wed Oct 10 01:01:21 2007 +0000
+++ b/libpurple/protocols/jabber/jabber.c	Wed Oct 10 01:06:16 2007 +0000
@@ -1914,7 +1914,7 @@
 			text = _("Authentication Failure");
 		}
 	} else if(!strcmp(packet->name, "stream:error") ||
-			 (!strcmp(packet->name, "error") &&
+			 (!strcmp(packet->name, "error") && xmlns &&
 				!strcmp(xmlns, "http://etherx.jabber.org/streams"))) {
 		if(xmlnode_get_child(packet, "bad-format")) {
 			text = _("Bad Format");
@@ -2189,55 +2189,67 @@
 	return PURPLE_CMD_RET_OK;
 }
 
+static gboolean _jabber_send_buzz(JabberStream *js, const char *username, char **error) {
+
+	JabberBuddy *jb;
+	JabberBuddyResource *jbr;
+	GList *iter;
+
+	if(!username)
+		return FALSE;
+
+	jb = jabber_buddy_find(js, username, FALSE);
+	if(!jb) {
+		*error = g_strdup_printf(_("Unable to buzz, because there is nothing known about user %s."), username);
+		return FALSE;
+	}
+
+	jbr = jabber_buddy_find_resource(jb, NULL);
+	if(!jbr) {
+		*error = g_strdup_printf(_("Unable to buzz, because user %s might be offline."), username);
+		return FALSE;
+	}
+
+	if(!jbr->caps) {
+		*error = g_strdup_printf(_("Unable to buzz, because there is nothing known about user %s."), username);
+		return FALSE;
+	}
+
+	for(iter = jbr->caps->features; iter; iter = g_list_next(iter)) {
+		if(!strcmp(iter->data, "http://www.xmpp.org/extensions/xep-0224.html#ns")) {
+			xmlnode *buzz, *msg = xmlnode_new("message");
+			gchar *to;
+
+			to = g_strdup_printf("%s/%s", username, jbr->name);
+			xmlnode_set_attrib(msg, "to", to);
+			g_free(to);
+
+			/* avoid offline storage */
+			xmlnode_set_attrib(msg, "type", "headline");
+
+			buzz = xmlnode_new_child(msg, "attention");
+			xmlnode_set_namespace(buzz, "http://www.xmpp.org/extensions/xep-0224.html#ns");
+
+			jabber_send(js, msg);
+			xmlnode_free(msg);
+
+			return TRUE;
+		}
+	}
+
+	*error = g_strdup_printf(_("Unable to buzz, because the user %s does not support it."), username);
+	return FALSE;
+}
+
 static PurpleCmdRet jabber_cmd_buzz(PurpleConversation *conv,
 		const char *cmd, char **args, char **error, void *data)
 {
 	JabberStream *js = conv->account->gc->proto_data;
-	xmlnode *msg, *buzz;
-	JabberBuddy *jb;
-	JabberBuddyResource *jbr;
-	char *to;
-	GList *iter;
 
 	if(!args || !args[0])
 		return PURPLE_CMD_RET_FAILED;
-	
-	jb = jabber_buddy_find(js, args[0], FALSE);
-	if(!jb) {
-		*error = g_strdup_printf(_("Unable to buzz, because there is nothing known about user %s."), args[0]);
-		return PURPLE_CMD_RET_FAILED;
-	}
-	
-	jbr = jabber_buddy_find_resource(jb, NULL);
-	if(!jbr) {
-		*error = g_strdup_printf(_("Unable to buzz, because user %s might be offline."), args[0]);
-		return PURPLE_CMD_RET_FAILED;
-	}
-	if(!jbr->caps) {
-		*error = g_strdup_printf(_("Unable to buzz, because there is nothing known about user %s."), args[0]);
-		return PURPLE_CMD_RET_FAILED;
-	}
-	for(iter = jbr->caps->features; iter; iter = g_list_next(iter)) {
-		if(!strcmp(iter->data, "http://www.xmpp.org/extensions/xep-0224.html#ns")) {
-			msg = xmlnode_new("message");
-			to = g_strdup_printf("%s/%s", args[0], jbr->name);
-			xmlnode_set_attrib(msg,"to",to);
-			g_free(to);
-			
-			/* avoid offline storage */
-			xmlnode_set_attrib(msg,"type","headline");
-			
-			buzz = xmlnode_new_child(msg,"attention");
-			xmlnode_set_namespace(buzz,"http://www.xmpp.org/extensions/xep-0224.html#ns");
-			
-			jabber_send(js,msg);
-			xmlnode_free(msg);
-			
-			return PURPLE_CMD_RET_OK;
-		}
-	}
-	*error = g_strdup_printf(_("Unable to buzz, because the user %s does not support it."), args[0]);
-	return PURPLE_CMD_RET_FAILED;
+
+	return _jabber_send_buzz(js, args[0], error)  ? PURPLE_CMD_RET_OK : PURPLE_CMD_RET_FAILED;
 }
 
 GList *jabber_attention_types(PurpleAccount *account)
@@ -2258,23 +2270,16 @@
 
 gboolean jabber_send_attention(PurpleConnection *gc, const char *username, guint code)
 {
-	PurpleConversation *conv;
-	char *error;
-	char *args[1];
-	PurpleCmdRet ret;
-
-	conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY, username, gc->account);
-
-	args[0] = (char *)username;
+	JabberStream *js = gc->proto_data;
+	gchar *error = NULL;
 
-	ret = jabber_cmd_buzz(conv, "buzz", args, &error, NULL);
-
-	if (ret == PURPLE_CMD_RET_FAILED) {
+	if (!_jabber_send_buzz(js, username, &error)) {
 		purple_debug_error("jabber", "jabber_send_attention: jabber_cmd_buzz failed with error: %s\n", error ? error : "(NULL)");
+		g_free(error);
 		return FALSE;
-	} else {
-		return TRUE;
 	}
+
+	return TRUE;
 }
 
 
--- a/libpurple/protocols/jabber/parser.c	Wed Oct 10 01:01:21 2007 +0000
+++ b/libpurple/protocols/jabber/parser.c	Wed Oct 10 01:06:16 2007 +0000
@@ -80,7 +80,7 @@
 			char *attrib_ns = NULL;
 
 			if (attributes[i+2]) {
-				attrib_ns = g_strdup((char*)attributes[i+2]);;
+				attrib_ns = g_strdup((char*)attributes[i+2]);
 			}
 
 			memcpy(attrib, attributes[i+3], attrib_len);
--- a/libpurple/protocols/jabber/roster.c	Wed Oct 10 01:01:21 2007 +0000
+++ b/libpurple/protocols/jabber/roster.c	Wed Oct 10 01:06:16 2007 +0000
@@ -67,8 +67,10 @@
 	if(!groups) {
 		if(!buddies)
 			g2 = g_slist_append(g2, g_strdup(_("Buddies")));
-		else
+		else {
+			g_slist_free(buddies);
 			return;
+		}
 	}
 
 	my_bare_jid = g_strdup_printf("%s@%s", js->user->node, js->user->domain);
@@ -229,6 +231,11 @@
 			remove_purple_buddies(js, jid);
 		} else {
 			GSList *groups = NULL;
+
+			if (js->server_caps & JABBER_CAP_GOOGLE_ROSTER)
+				if (!jabber_google_roster_incoming(js, item))
+					continue;
+
 			for(group = xmlnode_get_child(item, "group"); group; group = xmlnode_get_next_twin(group)) {
 				char *group_name;
 
@@ -237,10 +244,9 @@
 
 				if (g_slist_find_custom(groups, group_name, (GCompareFunc)purple_utf8_strcasecmp) == NULL)
 					groups = g_slist_append(groups, group_name);
+				else
+					g_free(group_name);
 			}
-			if (js->server_caps & JABBER_CAP_GOOGLE_ROSTER)
-				if (!jabber_google_roster_incoming(js, item))
-					continue;
 			add_purple_buddies_to_groups(js, jid, name, groups);
 		}
 	}
@@ -263,6 +269,9 @@
 	JabberIq *iq;
 	xmlnode *query, *item, *group;
 
+	if(!(b = purple_find_buddy(js->gc->account, name)))
+		return;
+
 	if(grps) {
 		groups = grps;
 	} else {
@@ -277,9 +286,6 @@
 		}
 	}
 
-	if(!(b = purple_find_buddy(js->gc->account, name)))
-		return;
-
 	iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:roster");
 
 	query = xmlnode_get_child(iq->node, "query");
@@ -397,12 +403,12 @@
 void jabber_roster_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy,
 		PurpleGroup *group) {
 	GSList *buddies = purple_find_buddies(gc->account, buddy->name);
-	GSList *groups = NULL;
 
 	buddies = g_slist_remove(buddies, buddy);
 	if(buddies != NULL) {
 		PurpleBuddy *tmpbuddy;
 		PurpleGroup *tmpgroup;
+		GSList *groups = NULL;
 
 		while(buddies) {
 			tmpbuddy = buddies->data;
@@ -412,6 +418,7 @@
 		}
 
 		jabber_roster_update(gc->proto_data, buddy->name, groups);
+		g_slist_free(groups);
 	} else {
 		JabberIq *iq = jabber_iq_new_query(gc->proto_data, JABBER_IQ_SET,
 				"jabber:iq:roster");
@@ -423,9 +430,4 @@
 
 		jabber_iq_send(iq);
 	}
-
-	if(buddies)
-		g_slist_free(buddies);
-	if(groups)
-		g_slist_free(groups);
 }
--- a/libpurple/protocols/jabber/usermood.c	Wed Oct 10 01:01:21 2007 +0000
+++ b/libpurple/protocols/jabber/usermood.c	Wed Oct 10 01:06:16 2007 +0000
@@ -26,6 +26,7 @@
 #include <string.h>
 #include "internal.h"
 #include "request.h"
+#include "debug.h"
 
 static const char *moodstrings[] = {
 	"afraid",
@@ -145,9 +146,26 @@
 }
 
 static void do_mood_set_from_fields(PurpleConnection *gc, PurpleRequestFields *fields) {
-	JabberStream *js = gc->proto_data;
-	
-	jabber_mood_set(js, moodstrings[purple_request_fields_get_choice(fields, "mood")], purple_request_fields_get_string(fields, "text"));
+	JabberStream *js;
+	int max_mood_idx;
+	int selected_mood = purple_request_fields_get_choice(fields, "mood");
+
+	if (!PURPLE_CONNECTION_IS_VALID(gc)) {
+		purple_debug_error("jabber", "Unable to set mood; account offline.\n");
+		return;
+	}
+
+	js = gc->proto_data;
+
+	/* This is ugly, but protects us from unexpected values. */
+	for (max_mood_idx = 0; moodstrings[max_mood_idx]; max_mood_idx++);
+
+	if (selected_mood < 0 || selected_mood >= max_mood_idx) {
+		purple_debug_error("jabber", "Invalid mood index (%d) selected.\n", selected_mood);
+		return;
+	}
+
+	jabber_mood_set(js, moodstrings[selected_mood], purple_request_fields_get_string(fields, "text"));
 }
 
 static void do_mood_set_mood(PurplePluginAction *action) {
--- a/libpurple/protocols/msn/contact.c	Wed Oct 10 01:01:21 2007 +0000
+++ b/libpurple/protocols/msn/contact.c	Wed Oct 10 01:06:16 2007 +0000
@@ -1177,7 +1177,7 @@
 		purple_debug_warning("MSN CL", "Unable to retrieve user %s from the userlist!\n", passport);
 	}
 
-	if (user->uid != NULL) {
+	if (user != NULL && user->uid != NULL) {
 		contact_xml = g_strdup_printf(MSN_CONTACT_ID_XML, user->uid);
 	} else {
 		contact_xml = g_strdup_printf(MSN_CONTACT_XML, passport);
--- a/libpurple/protocols/msn/msn.c	Wed Oct 10 01:01:21 2007 +0000
+++ b/libpurple/protocols/msn/msn.c	Wed Oct 10 01:06:16 2007 +0000
@@ -943,7 +943,7 @@
 			imdata->msg = body_str;
 			imdata->flags = flags;
 			imdata->when = time(NULL);
-			g_idle_add(msn_send_me_im, imdata);
+			purple_timeout_add(0, msn_send_me_im, imdata);
 		}
 
 		msn_message_destroy(msg);
@@ -1103,7 +1103,7 @@
 	userlist = session->userlist;
 	who = msn_normalize(gc->account, buddy->name);
 
-	purple_debug_info("MSN","Add user:%s to group:%s\n", who, group->name);
+	purple_debug_info("MSN","Add user:%s to group:%s\n", who, (group && group->name) ? group->name : "(null)");
 	if (!session->logged_in)
 	{
 #if 0
--- a/libpurple/protocols/msn/notification.c	Wed Oct 10 01:01:21 2007 +0000
+++ b/libpurple/protocols/msn/notification.c	Wed Oct 10 01:06:16 2007 +0000
@@ -230,11 +230,9 @@
 {
 	MsnSession *session;
 	PurpleAccount *account;
-	PurpleConnection *gc;
 
 	session = cmdproc->session;
 	account = session->account;
-	gc = purple_account_get_connection(account);
 
 	if (!g_ascii_strcasecmp(cmd->params[1], "OK"))
 	{
@@ -450,7 +448,7 @@
 	const char *passport;
 	const char *content_type;
 
-	purple_debug_info("MSNP14","Process UBM payload:%s\n",payload);
+	purple_debug_info("MSNP14","Process UBM payload:%.*s\n", len, payload);
 	msg = msn_message_new_from_cmd(cmdproc->session, cmd);
 
 	msn_message_parse_payload(msg, payload, len,MSG_LINE_DEM,MSG_BODY_DEM);
@@ -533,7 +531,7 @@
 	}else{
 		g_return_if_fail(cmd->payload_cb != NULL);
 
-		purple_debug_info("MSNP14","UBM payload:{%s}\n",cmd->payload);
+		purple_debug_info("MSNP14","UBM payload:{%.*s}\n", cmd->payload_len, cmd->payload);
 		ubm_cmd_post(cmdproc, cmd, cmd->payload, cmd->payload_len);
 	}
 }
@@ -1616,7 +1614,6 @@
 {
 	MsnSession *session;
 	PurpleAccount *account;
-	PurpleConnection *gc;
 	MsnUser *user;
 	const char *passport;
 	char *psm_str, *currentmedia_str, *str;
@@ -1626,7 +1623,6 @@
 
 	session = cmdproc->session;
 	account = session->account;
-	gc = purple_account_get_connection(account);
 
 	passport = cmd->params[0];
 	user = msn_userlist_find_user(session->userlist, passport);
--- a/libpurple/protocols/msn/oim.c	Wed Oct 10 01:01:21 2007 +0000
+++ b/libpurple/protocols/msn/oim.c	Wed Oct 10 01:06:16 2007 +0000
@@ -608,8 +608,9 @@
 	purple_debug_info("MSN OIM:OIM", "%s", xmlmsg);
 
 	node = xmlnode_from_str(xmlmsg, strlen(xmlmsg));
-	if (strcmp(node->name, "MD") != 0) {
-		xmlnode_free(node);
+	if (!node || !node->name || strcmp(node->name, "MD") != 0) {
+		if (node)
+			xmlnode_free(node);
 		return;
 	}
 
--- a/libpurple/protocols/msn/soap.c	Wed Oct 10 01:01:21 2007 +0000
+++ b/libpurple/protocols/msn/soap.c	Wed Oct 10 01:06:16 2007 +0000
@@ -131,6 +131,7 @@
 				MsnSoapSslErrorCbFunction error_cb)
 {
 	purple_debug_misc("MSN SOAP","Initializing SOAP connection\n");
+	g_free(soapconn->login_host);
 	soapconn->login_host = g_strdup(host);
 	soapconn->ssl_conn = ssl;
 	soapconn->connect_cb = connect_cb;
@@ -204,11 +205,9 @@
 void
 msn_soap_destroy(MsnSoapConn *soapconn)
 {
-	if(soapconn->login_host)
-		g_free(soapconn->login_host);
+	g_free(soapconn->login_host);
 
-	if(soapconn->login_path)
-		g_free(soapconn->login_path);
+	g_free(soapconn->login_path);
 
 	/*remove the write handler*/
 	if (soapconn->output_handler > 0){
--- a/libpurple/protocols/msn/userlist.c	Wed Oct 10 01:01:21 2007 +0000
+++ b/libpurple/protocols/msn/userlist.c	Wed Oct 10 01:06:16 2007 +0000
@@ -227,11 +227,8 @@
 	}
 	else if (list_id == MSN_LIST_RL)
 	{
-		PurpleConnection *gc;
 		PurpleConversation *convo;
 
-		gc = purple_account_get_connection(account);
-
 		purple_debug_info("msn",
 						"%s has added you to his or her buddy list.\n",
 						passport);
--- a/libpurple/protocols/oscar/oscar.c	Wed Oct 10 01:01:21 2007 +0000
+++ b/libpurple/protocols/oscar/oscar.c	Wed Oct 10 01:06:16 2007 +0000
@@ -1721,7 +1721,6 @@
 {
 	PurpleConnection *gc;
 	PurpleAccount *account;
-	PurplePresence *presence;
 	struct buddyinfo *bi;
 	time_t time_idle = 0, signon = 0;
 	int type = 0;
@@ -1734,7 +1733,6 @@
 
 	gc = od->gc;
 	account = purple_connection_get_account(gc);
-	presence = purple_account_get_presence(account);
 
 	va_start(ap, fr);
 	info = va_arg(ap, aim_userinfo_t *);
--- a/libpurple/tests/test_cipher.c	Wed Oct 10 01:01:21 2007 +0000
+++ b/libpurple/tests/test_cipher.c	Wed Oct 10 01:06:16 2007 +0000
@@ -8,7 +8,6 @@
 #include "tests.h"
 
 #include "../cipher.h"
-#include "../signal.h"
 
 /******************************************************************************
  * MD4 Tests
--- a/libpurple/util.c	Wed Oct 10 01:01:21 2007 +0000
+++ b/libpurple/util.c	Wed Oct 10 01:06:16 2007 +0000
@@ -2548,15 +2548,14 @@
 
 	filename_full = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", user_dir, filename);
 
-	ret = purple_util_write_data_to_file_absolute(filename_full,
-						      data,size);
+	ret = purple_util_write_data_to_file_absolute(filename_full, data, size);
 
 	g_free(filename_full);
 	return ret;
 }
 
 gboolean
-purple_util_write_data_to_file_absolute(const char *filename_full, const char *data, size_t size)
+purple_util_write_data_to_file_absolute(const char *filename_full, const char *data, gssize size)
 {
 	gchar *filename_temp;
 	FILE *file;
--- a/libpurple/util.h	Wed Oct 10 01:01:21 2007 +0000
+++ b/libpurple/util.h	Wed Oct 10 01:06:16 2007 +0000
@@ -607,7 +607,7 @@
  *
  */
 gboolean
-purple_util_write_data_to_file_absolute(const char *filename_full, const char *data, size_t size);
+purple_util_write_data_to_file_absolute(const char *filename_full, const char *data, gssize size);
 
 /**
  * Read the contents of a given file and parse the results into an
--- a/libpurple/xmlnode.c	Wed Oct 10 01:01:21 2007 +0000
+++ b/libpurple/xmlnode.c	Wed Oct 10 01:06:16 2007 +0000
@@ -146,6 +146,19 @@
 	}
 }
 
+/* Compare two nullable xmlns strings.
+ * They are considered equal if they're both NULL or the strings are equal
+ */
+static gboolean _xmlnode_compare_xmlns(const char *xmlns1, const char *xmlns2) {
+	gboolean equal = FALSE;
+
+	if (xmlns1 == NULL && xmlns2 == NULL)
+		equal = TRUE;
+	else if (xmlns1 != NULL && xmlns2 != NULL && !strcmp(xmlns1, xmlns2))
+		equal = TRUE;
+
+	return equal;
+}
 
 void
 xmlnode_remove_attrib_with_namespace(xmlnode *node, const char *attr, const char *xmlns)
@@ -159,7 +172,7 @@
 	{
 		if(attr_node->type == XMLNODE_TYPE_ATTRIB &&
 		   !strcmp(attr_node->name, attr) &&
-		   !strcmp(attr_node->xmlns, xmlns))
+		   _xmlnode_compare_xmlns(xmlns, attr_node->xmlns))
 		{
 			if(node->child == attr_node) {
 				node->child = attr_node->next;
@@ -238,7 +251,8 @@
 
 	for(x = node->child; x; x = x->next) {
 		if(x->type == XMLNODE_TYPE_ATTRIB &&
-		   !strcmp(attr, x->name) && !strcmp(x->xmlns, xmlns)) {
+		   !strcmp(attr, x->name) &&
+		   _xmlnode_compare_xmlns(xmlns, x->xmlns)) {
 			return x->data;
 		}
 	}
@@ -326,6 +340,7 @@
 	child_name = names[1];
 
 	for(x = parent->child; x; x = x->next) {
+		/* XXX: Is it correct to ignore the namespace for the match if none was specified? */
 		const char *xmlns = NULL;
 		if(ns)
 			xmlns = xmlnode_get_namespace(x);
@@ -673,6 +688,7 @@
 	g_return_val_if_fail(node->type == XMLNODE_TYPE_TAG, NULL);
 
 	for(sibling = node->next; sibling; sibling = sibling->next) {
+		/* XXX: Is it correct to ignore the namespace for the match if none was specified? */
 		const char *xmlns = NULL;
 		if(ns)
 			xmlns = xmlnode_get_namespace(sibling);
--- a/pidgin/gtkblist.c	Wed Oct 10 01:01:21 2007 +0000
+++ b/pidgin/gtkblist.c	Wed Oct 10 01:06:16 2007 +0000
@@ -4347,7 +4347,6 @@
                                 gpointer user_data)
 {
 	PurpleAccount *account;
-	PurpleStatusType *status_type;
 	gchar *escaped, *text;
 	GtkWidget *button, *label, *image, *hbox;
 	GdkPixbuf *pixbuf;
@@ -4362,8 +4361,8 @@
 	hbox = gtk_hbox_new(FALSE, 6);
 
 	/* Create the icon */
-	if ((status_type = purple_account_get_status_type_with_primitive(account,
-							PURPLE_STATUS_OFFLINE))) {
+	if (purple_account_get_status_type_with_primitive(account,
+							PURPLE_STATUS_OFFLINE) != NULL) {
 		pixbuf = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_SMALL);
 		if (pixbuf != NULL) {
 			image = gtk_image_new_from_pixbuf(pixbuf);
@@ -5367,7 +5366,7 @@
 			   BUDDY_ICON_COLUMN, avatar,
 			   BUDDY_ICON_VISIBLE_COLUMN, biglist,
 			   EMBLEM_COLUMN, emblem,
-			   EMBLEM_VISIBLE_COLUMN, emblem,
+			   EMBLEM_VISIBLE_COLUMN, (emblem != NULL),
 			   PROTOCOL_ICON_COLUMN, pidgin_create_prpl_icon(buddy->account, PIDGIN_PRPL_ICON_SMALL),
 			   PROTOCOL_ICON_VISIBLE_COLUMN, purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_protocol_icons"),
 			   BGCOLOR_COLUMN, NULL,
@@ -5378,6 +5377,8 @@
 
 	g_free(mark);
 	g_free(idle);
+	if(emblem)
+		g_object_unref(emblem);
 	if(status)
 		g_object_unref(status);
 	if(avatar)
@@ -5549,6 +5550,8 @@
 				-1);
 
 		g_free(mark);
+		if(emblem)
+			g_object_unref(emblem);
 		if(status)
 			g_object_unref(status);
 		if(avatar)
--- a/pidgin/gtkconv.c	Wed Oct 10 01:01:21 2007 +0000
+++ b/pidgin/gtkconv.c	Wed Oct 10 01:06:16 2007 +0000
@@ -2498,11 +2498,16 @@
 	gtk_list_store_set(GTK_LIST_STORE(gtkconv->infopane_model), 
 			&(gtkconv->infopane_iter),
 			CONV_EMBLEM_COLUMN, emblem, -1);
+	if (emblem)
+		g_object_unref(emblem);
 
 	if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_protocol_icons")) {
+		emblem = pidgin_create_prpl_icon(gtkconv->active_conv->account, PIDGIN_PRPL_ICON_SMALL);
 		gtk_list_store_set(GTK_LIST_STORE(gtkconv->infopane_model),
 			&(gtkconv->infopane_iter),
-			CONV_PROTOCOL_ICON_COLUMN, pidgin_create_prpl_icon(gtkconv->active_conv->account, PIDGIN_PRPL_ICON_SMALL), -1);
+			CONV_PROTOCOL_ICON_COLUMN, emblem, -1);
+		if (emblem)
+			g_object_unref(emblem);
 	}
 
 	/* XXX seanegan Why do I have to do this? */
@@ -4358,45 +4363,54 @@
 	gtk_menu_shell_insert(GTK_MENU_SHELL(menu), menuitem, 1);
 }
 
-
 static void resize_imhtml_cb(PidginConversation *gtkconv)
 {
 	GtkTextBuffer *buffer;
 	GtkTextIter iter;
-        int wrapped_lines;
-        int lines;
-        GdkRectangle oneline;
+	int wrapped_lines;
+	int lines;
+	GdkRectangle oneline;
 	GtkRequisition sr;
-        int height;
-        int pad_top, pad_inside, pad_bottom;
+	int height, diff;
+	int pad_top, pad_inside, pad_bottom;
 
 	buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->entry));
 
-        wrapped_lines = 1;
-        gtk_text_buffer_get_start_iter(buffer, &iter);
-        gtk_text_view_get_iter_location(GTK_TEXT_VIEW(gtkconv->entry), &iter, &oneline);
-        while (gtk_text_view_forward_display_line(GTK_TEXT_VIEW(gtkconv->entry), &iter))
-                wrapped_lines++;
-
-        lines = gtk_text_buffer_get_line_count(buffer);
-
-        /* Show a maximum of 4 lines */
-        lines = MIN(lines, 4);
-        wrapped_lines = MIN(wrapped_lines, 4);
-
-        pad_top = gtk_text_view_get_pixels_above_lines(GTK_TEXT_VIEW(gtkconv->entry));
-        pad_bottom = gtk_text_view_get_pixels_below_lines(GTK_TEXT_VIEW(gtkconv->entry));
-        pad_inside = gtk_text_view_get_pixels_inside_wrap(GTK_TEXT_VIEW(gtkconv->entry));
-
-        height = (oneline.height + pad_top + pad_bottom) * lines;
-        height += (oneline.height + pad_inside) * (wrapped_lines - lines);
+	wrapped_lines = 1;
+	gtk_text_buffer_get_start_iter(buffer, &iter);
+	gtk_text_view_get_iter_location(GTK_TEXT_VIEW(gtkconv->entry), &iter, &oneline);
+	while (gtk_text_view_forward_display_line(GTK_TEXT_VIEW(gtkconv->entry), &iter))
+		wrapped_lines++;
+
+	lines = gtk_text_buffer_get_line_count(buffer);
+
+	/* Show a maximum of 4 lines */
+	lines = MIN(lines, 4);
+	wrapped_lines = MIN(wrapped_lines, 4);
+
+	pad_top = gtk_text_view_get_pixels_above_lines(GTK_TEXT_VIEW(gtkconv->entry));
+	pad_bottom = gtk_text_view_get_pixels_below_lines(GTK_TEXT_VIEW(gtkconv->entry));
+	pad_inside = gtk_text_view_get_pixels_inside_wrap(GTK_TEXT_VIEW(gtkconv->entry));
+
+	height = (oneline.height + pad_top + pad_bottom) * lines;
+	height += (oneline.height + pad_inside) * (wrapped_lines - lines);
 
 	gtkconv->auto_resize = TRUE;
-        g_idle_add(reset_auto_resize_cb, gtkconv);
-	gtk_widget_size_request(gtkconv->lower_hbox, &sr);
-	if (sr.height < height + PIDGIN_HIG_BOX_SPACE) {
+	g_idle_add(reset_auto_resize_cb, gtkconv);
+
+	diff = height - gtkconv->entry->allocation.height;
+
+	if (diff > 0) {
+		gtk_widget_size_request(gtkconv->lower_hbox, &sr);
 		gtkconv->entry_growing = TRUE;
-	        gtk_widget_set_size_request(gtkconv->lower_hbox, -1, height + PIDGIN_HIG_BOX_SPACE);
+
+		/* uncomment this to auto resize even after the user manually
+		   resizes
+		gtk_paned_set_position(GTK_PANED(gtkconv->lower_hbox->parent->parent),
+			-1);
+		*/
+		gtk_widget_set_size_request(gtkconv->lower_hbox, -1,
+			diff + gtkconv->lower_hbox->allocation.height);
 	}
 }
 
@@ -4728,7 +4742,6 @@
 	g_object_set(rend, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
 #endif
 
-
 	rend = gtk_cell_renderer_pixbuf_new();
 	gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(gtkconv->infopane), rend, FALSE);
 	gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(gtkconv->infopane), rend, "pixbuf", CONV_PROTOCOL_ICON_COLUMN, NULL);
--- a/pidgin/win32/winpidgin.c	Wed Oct 10 01:01:21 2007 +0000
+++ b/pidgin/win32/winpidgin.c	Wed Oct 10 01:06:16 2007 +0000
@@ -545,7 +545,7 @@
 	if (strstr(lpszCmdLine, "-d") || strstr(lpszCmdLine, "-h") || strstr(lpszCmdLine, "-v")) {
 		/* If stdout hasn't been redirected to a file, alloc a console
 		 *  (_istty() doesn't work for stuff using the GUI subsystem) */
-		if (_fileno(stdout) == -1) {
+		if (_fileno(stdout) == -1 || _fileno(stdout) == -2) {
 			LPFNATTACHCONSOLE MyAttachConsole = NULL;
 			if ((hmod = GetModuleHandle("kernel32.dll"))) {
 				MyAttachConsole =