changeset 30253:35cbe4684177

propagate from branch 'im.pidgin.pidgin' (head 1ccb1507e6594c80788043ea114c7fb942828e48) to branch 'im.pidgin.cpw.malu.ft_thumbnails' (head b439e619df4a497e9807614d87f9fb47308d648b)
author Elliott Sales de Andrade <qulogic@pidgin.im>
date Sun, 25 Apr 2010 21:40:33 +0000
parents 0f1df8098d00 (diff) 45ec328db5bd (current diff)
children ee3a87e92316
files
diffstat 13 files changed, 180 insertions(+), 79 deletions(-) [+]
line wrap: on
line diff
--- a/COPYRIGHT	Sun Apr 25 21:24:06 2010 +0000
+++ b/COPYRIGHT	Sun Apr 25 21:40:33 2010 +0000
@@ -245,6 +245,7 @@
 Jochen Kemnade
 Yann Kerherve
 Gordian Klein
+Marten Klencke
 Krzysztof Klinikowski
 Akuke Kok
 Kir Kolyshkin
@@ -294,6 +295,7 @@
 Paolo Maggi
 Sulabh Mahajan
 Willian T. Mahan
+Jonathan Maltz
 Tobias Markmann
 Kris Marsh
 Fidel Martinez
--- a/ChangeLog	Sun Apr 25 21:24:06 2010 +0000
+++ b/ChangeLog	Sun Apr 25 21:40:33 2010 +0000
@@ -18,6 +18,8 @@
 	  GnuTLS manual for documentation on the format of the priority
 	  strings.
 	* Fix autoconf detection of Python.  (Brad Smith)
+	* Fix a crash when a Windows proxy (from IE) does not have a port.
+	  (Marten Klencke)
 
 	Pidgin:
 	* Moved the "Debugging Information" section of the About box to a
@@ -39,12 +41,14 @@
 	* 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)
+	* Plugins can now handle markup in buddy names by attaching to the
+	  "drawing-buddy" signal. (Daniele Ricci, Andrea Piccinelli)
 	* Be more accommodating when scaling down large images for use as
 	  buddy icons.
 	* The 'Message Timestamp Formats' plugin allows changing the timestamp
 	  format from the timestamps' context menu in conversation log.
+	* The 'Message Timestamp Formats' plugin allows forcing 12-hour
+	  timestamps.  (Jonathan Maltz)
 	* Fix pastes from Chrome (rich-text pastes and probably URLs
 	  having garbage appended to them)
 
@@ -58,9 +62,9 @@
 
 	AIM and ICQ:
 	* 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)
+	  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 for
 	  ICQ.  Previously only icons between 48x48 and 52x64 were allowed.
 	* When using the clientLogin authentication method, prompt for a
@@ -77,22 +81,27 @@
 	* 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).
 	* Present a better error message when authentication fails while trying
 	  to connect to Facebook.  (David Reiss, Facebook)
+	* 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).
+	* Send whitespace keepalives if we haven't sent data in a while (2
+	  minutes).  This fixes an issue with Openfire disconnecting a
+	  libpurple-baesd client that has just been quiet for about 6
+	  minutes.
 
 	Yahoo/Yahoo JAPAN:
-	* Attempt to better handle transparent proxies interfering with HTTP-based
-	  login.
+	* Attempt to better handle transparent proxies interfering with
+	  HTTP-based login.
 	* Fix handling of P2P packets, thus fixing the loss of some messages.
 	* Retrieve the pager server address from Yahoo!'s servers directly.
 	* Removed the "Pager server" account option, as it is no longer needed.
-	* The authentication code is now less order-sensitive with the components
-	  of the server's response.
+	* The authentication code is now less order-sensitive with the
+	  components of the server's response.
 	* The authentication process now acts more like the official client.
 
 	Finch:
--- a/finch/gntblist.c	Sun Apr 25 21:24:06 2010 +0000
+++ b/finch/gntblist.c	Sun Apr 25 21:40:33 2010 +0000
@@ -1117,6 +1117,8 @@
 			list = g_list_delete_link(list, list))
 	{
 		PurpleMenuAction *act = (PurpleMenuAction *) list->data;
+		if (!act)
+			continue;
 		act->data = node;
 		gnt_append_menu_action(menu, act, NULL);
 		g_signal_connect_swapped(G_OBJECT(menu), "destroy",
--- a/libpurple/protocols/gg/gg.c	Sun Apr 25 21:24:06 2010 +0000
+++ b/libpurple/protocols/gg/gg.c	Sun Apr 25 21:40:33 2010 +0000
@@ -1034,6 +1034,7 @@
 		case GG_STATUS_DND:
 		case GG_STATUS_DND_DESCR:
 			st = purple_primitive_get_id_from_type(PURPLE_STATUS_UNAVAILABLE);
+			break;
 		case GG_STATUS_BLOCKED:
 			/* user is blocking us.... */
 			st = "blocked";
--- a/libpurple/protocols/jabber/bosh.c	Sun Apr 25 21:24:06 2010 +0000
+++ b/libpurple/protocols/jabber/bosh.c	Sun Apr 25 21:40:33 2010 +0000
@@ -78,13 +78,11 @@
 	} state;
 	guint8 failed_connections;
 
-	int max_inactivity;
 	int wait;
 
 	int max_requests;
 	int requests;
 
-	guint inactivity_timer;
 	guint send_timer;
 };
 
@@ -239,8 +237,6 @@
 
 	if (conn->send_timer)
 		purple_timeout_remove(conn->send_timer);
-	if (conn->inactivity_timer)
-		purple_timeout_remove(conn->inactivity_timer);
 
 	purple_circ_buffer_destroy(conn->pending);
 
@@ -433,34 +429,14 @@
 	return FALSE;
 }
 
-static gboolean
-bosh_inactivity_cb(gpointer data)
+void
+jabber_bosh_connection_send_keepalive(PurpleBOSHConnection *bosh)
 {
-	PurpleBOSHConnection *bosh = data;
-	bosh->inactivity_timer = 0;
-
 	if (bosh->send_timer != 0)
 		purple_timeout_remove(bosh->send_timer);
 
 	/* clears bosh->send_timer */
 	send_timer_cb(bosh);
-
-	return FALSE;
-}
-
-static void
-restart_inactivity_timer(PurpleBOSHConnection *conn)
-{
-	if (conn->inactivity_timer != 0) {
-		purple_timeout_remove(conn->inactivity_timer);
-		conn->inactivity_timer = 0;
-	}
-
-	if (conn->max_inactivity != 0) {
-		conn->inactivity_timer =
-			purple_timeout_add_seconds(conn->max_inactivity - 5 /* rounding */,
-			                           bosh_inactivity_cb, conn);
-	}
 }
 
 static void jabber_bosh_connection_received(PurpleBOSHConnection *conn, xmlnode *node) {
@@ -541,19 +517,20 @@
 	}
 
 	if (inactivity) {
-		conn->max_inactivity = atoi(inactivity);
-		if (conn->max_inactivity <= 5) {
+		js->max_inactivity = atoi(inactivity);
+		if (js->max_inactivity <= 5) {
 			purple_debug_warning("jabber", "Ignoring bogusly small inactivity: %s\n",
 			                     inactivity);
-			conn->max_inactivity = 0;
+			/* Leave it at the default */
 		} else {
-			/* TODO: Integrate this with jabber.c keepalive checks... */
 			/* TODO: Can this check fail? It shouldn't */
-			if (conn->inactivity_timer == 0) {
+			js->max_inactivity -= 5; /* rounding */
+
+			if (js->inactivity_timer == 0) {
 				purple_debug_misc("jabber", "Starting BOSH inactivity timer "
 						"for %d secs (compensating for rounding)\n",
-						conn->max_inactivity - 5);
-				restart_inactivity_timer(conn);
+						js->max_inactivity);
+				jabber_stream_restart_inactivity_timer(js);
 			}
 		}
 	}
@@ -976,7 +953,7 @@
 	size_t len;
 
 	/* Sending something to the server, restart the inactivity timer */
-	restart_inactivity_timer(conn->bosh);
+	jabber_stream_restart_inactivity_timer(conn->bosh->js);
 
 	data = g_strdup_printf("POST %s HTTP/1.1\r\n"
 	                       "Host: %s\r\n"
--- a/libpurple/protocols/jabber/bosh.h	Sun Apr 25 21:24:06 2010 +0000
+++ b/libpurple/protocols/jabber/bosh.h	Sun Apr 25 21:40:33 2010 +0000
@@ -35,6 +35,7 @@
 void jabber_bosh_connection_destroy(PurpleBOSHConnection *conn);
 
 gboolean jabber_bosh_connection_is_ssl(PurpleBOSHConnection *conn);
+void jabber_bosh_connection_send_keepalive(PurpleBOSHConnection *conn);
 
 void jabber_bosh_connection_connect(PurpleBOSHConnection *conn);
 void jabber_bosh_connection_close(PurpleBOSHConnection *conn);
--- a/libpurple/protocols/jabber/jabber.c	Sun Apr 25 21:24:06 2010 +0000
+++ b/libpurple/protocols/jabber/jabber.c	Sun Apr 25 21:40:33 2010 +0000
@@ -71,6 +71,10 @@
 #include "jingle/rtp.h"
 
 #define PING_TIMEOUT 60
+/* Send a whitespace keepalive to the server if we haven't sent
+ * anything in the last 120 seconds
+ */
+#define DEFAULT_INACTIVITY_TIME 120
 
 GList *jabber_features = NULL;
 GList *jabber_identities = NULL;
@@ -363,6 +367,9 @@
 	if (len == -1)
 		len = strlen(data);
 
+	if (js->state == JABBER_STREAM_CONNECTED)
+		jabber_stream_restart_inactivity_timer(js);
+
 	if (js->writeh == 0)
 		ret = jabber_do_send(js, data, len);
 	else {
@@ -889,6 +896,7 @@
 	js->write_buffer = purple_circ_buffer_new(512);
 	js->old_length = 0;
 	js->keepalive_timeout = 0;
+	js->max_inactivity = DEFAULT_INACTIVITY_TIME;
 	/* Set the default protocol version to 1.0. Overridden in parser.c. */
 	js->protocol_version.major = 1;
 	js->protocol_version.minor = 0;
@@ -1583,6 +1591,8 @@
 
 	if (js->keepalive_timeout != 0)
 		purple_timeout_remove(js->keepalive_timeout);
+	if (js->inactivity_timer != 0)
+		purple_timeout_remove(js->inactivity_timer);
 
 	g_free(js->srv_rec);
 	js->srv_rec = NULL;
@@ -1634,6 +1644,9 @@
 		case JABBER_STREAM_CONNECTED:
 			/* Send initial presence */
 			jabber_presence_send(js, TRUE);
+			/* Start up the inactivity timer */
+			jabber_stream_restart_inactivity_timer(js);
+
 			purple_connection_set_state(js->gc, PURPLE_CONNECTED);
 			break;
 	}
@@ -1922,6 +1935,38 @@
 	       (!js->bosh && js->gsc);
 }
 
+static gboolean
+inactivity_cb(gpointer data)
+{
+	JabberStream *js = data;
+
+	/* We want whatever is sent to set this.  It's okay because
+	 * the eventloop unsets it via the return FALSE.
+	 */
+	js->inactivity_timer = 0;
+
+	if (js->bosh)
+		jabber_bosh_connection_send_keepalive(js->bosh);
+	else
+		jabber_send_raw(js, "\t", 1);
+
+	return FALSE;
+}
+
+void jabber_stream_restart_inactivity_timer(JabberStream *js)
+{
+	if (js->inactivity_timer != 0) {
+		purple_timeout_remove(js->inactivity_timer);
+		js->inactivity_timer = 0;
+	}
+
+	g_return_if_fail(js->max_inactivity > 0);
+
+	js->inactivity_timer =
+		purple_timeout_add_seconds(js->max_inactivity,
+		                           inactivity_cb, js);
+}
+
 const char *jabber_list_icon(PurpleAccount *a, PurpleBuddy *b)
 {
 	return "jabber";
--- a/libpurple/protocols/jabber/jabber.h	Sun Apr 25 21:24:06 2010 +0000
+++ b/libpurple/protocols/jabber/jabber.h	Sun Apr 25 21:40:33 2010 +0000
@@ -255,6 +255,8 @@
 
 	/* A purple timeout tag for the keepalive */
 	guint keepalive_timeout;
+	guint max_inactivity;
+	guint inactivity_timer;
 
 	PurpleSrvResponse *srv_rec;
 	guint srv_rec_idx;
@@ -349,6 +351,13 @@
  */
 gboolean jabber_stream_is_ssl(JabberStream *js);
 
+/**
+ * Restart the "we haven't sent anything in a while and should send
+ * something or the server will kick us off" timer (obviously
+ * called when sending something.  It's exposed for BOSH.)
+ */
+void jabber_stream_restart_inactivity_timer(JabberStream *js);
+
 /** PRPL functions */
 const char *jabber_list_icon(PurpleAccount *a, PurpleBuddy *b);
 const char* jabber_list_emblem(PurpleBuddy *b);
--- a/libpurple/protocols/msn/msg.c	Sun Apr 25 21:24:06 2010 +0000
+++ b/libpurple/protocols/msn/msg.c	Sun Apr 25 21:40:33 2010 +0000
@@ -970,14 +970,13 @@
 static void 
 got_wink_cb(MsnSlpCall *slpcall, const guchar *data, gsize size)
 {
-	FILE *f;
+	FILE *f = NULL;
 	char *path = NULL;
 	const char *who = slpcall->slplink->remote_user;
 	purple_debug_info("msn", "Received wink from %s\n", who);
 
-	if ((f = purple_mkstemp(&path, TRUE))) {
-		fwrite(data, size, 1, f);
-		fclose(f);
+	if ((f = purple_mkstemp(&path, TRUE)) &&
+	    (fwrite(data, 1, size, f) == size)) {
 		datacast_inform_user(slpcall->slplink->swboard,
 		                     who,
 		                     _("%s sent a wink. <a href='msn-wink://%s'>Click here to play it</a>"),
@@ -988,21 +987,22 @@
 		                     who,
 		                     _("%s sent a wink, but it could not be saved"),
 		                     NULL);
-	} 
+	}
+	if (f)
+		fclose(f);
 	g_free(path);
 }
 
 static void 
 got_voiceclip_cb(MsnSlpCall *slpcall, const guchar *data, gsize size)
 {
-	FILE *f;
+	FILE *f = NULL;
 	char *path = NULL;
 	const char *who = slpcall->slplink->remote_user;
 	purple_debug_info("msn", "Received voice clip from %s\n", who);
 
-	if ((f = purple_mkstemp(&path, TRUE))) {
-		fwrite(data, size, 1, f);
-		fclose(f);
+	if ((f = purple_mkstemp(&path, TRUE)) &&
+	    (fwrite(data, 1, size, f) == size)) {
 		datacast_inform_user(slpcall->slplink->swboard,
 		                     who,
 		                     _("%s sent a voice clip. <a href='audio://%s'>Click here to play it</a>"),
@@ -1013,7 +1013,9 @@
 		                     who,
 		                     _("%s sent a voice clip, but it could not be saved"),
 		                     NULL);
-	} 
+	}
+	if (f)
+		fclose(f);
 	g_free(path);
 }
 
--- a/libpurple/protocols/msn/session.c	Sun Apr 25 21:24:06 2010 +0000
+++ b/libpurple/protocols/msn/session.c	Sun Apr 25 21:40:33 2010 +0000
@@ -407,7 +407,7 @@
 
 	/* Prevent the connection progress going backwards, eg. if we get
 	 * transferred several times during login */
-	if (session->login_step > step)
+	if (session->login_step >= step)
 		return;
 
 	/* If we're already logged in, we're probably here because of a
--- a/libpurple/proxy.c	Sun Apr 25 21:24:06 2010 +0000
+++ b/libpurple/proxy.c	Sun Apr 25 21:40:33 2010 +0000
@@ -379,11 +379,16 @@
 	char *d;
 
 	d = g_strrstr(host, ":");
-	if (d)
+	if (d) {
 		*d = '\0';
-	d++;
-	if (*d)
-		sscanf(d, "%d", &port);
+
+		d++;
+		if (*d)
+			sscanf(d, "%d", &port);
+
+		if (port == 0)
+			port = default_port;
+	}
 
 	purple_proxy_info_set_host(info, host);
 	purple_proxy_info_set_port(info, port);
--- a/pidgin/gtkutils.c	Sun Apr 25 21:24:06 2010 +0000
+++ b/pidgin/gtkutils.c	Sun Apr 25 21:40:33 2010 +0000
@@ -2469,7 +2469,7 @@
 					break;
 				}
 
-				if (spec->max_filesize == 0 || length < spec->max_filesize) {
+				if (spec->max_filesize == 0 || length <= spec->max_filesize) {
 					/* We were able to save the image as this image type and
 					   have it be within the size constraints.  Great!  Return
 					   the image. */
@@ -2507,7 +2507,7 @@
 		new_height = orig_height * scale_factor;
 		g_object_unref(G_OBJECT(pixbuf));
 		pixbuf = gdk_pixbuf_scale_simple(original, new_width, new_height, GDK_INTERP_HYPER);
-	} while (new_width > 10 || new_height > 10);
+	} while ((new_width > 10 || new_height > 10) && new_width > spec->min_width && new_height > spec->min_height);
 	g_strfreev(prpl_formats);
 	g_object_unref(G_OBJECT(pixbuf));
 	g_object_unref(G_OBJECT(original));
--- a/pidgin/plugins/timestamp_format.c	Sun Apr 25 21:24:06 2010 +0000
+++ b/pidgin/plugins/timestamp_format.c	Sun Apr 25 21:40:33 2010 +0000
@@ -12,6 +12,17 @@
 
 #include <time.h>
 
+static const char *format_12hour_hour(const struct tm *tm)
+{
+	static char hr[3];
+	int hour = tm->tm_hour % 12;
+	if (hour == 0)
+		hour = 12;
+
+	g_snprintf(hr, sizeof(hr), "%d", hour);
+	return hr;
+}
+
 static PurplePluginPrefFrame *
 get_plugin_pref_frame(PurplePlugin *plugin)
 {
@@ -24,10 +35,14 @@
 	ppref = purple_plugin_pref_new_with_label(_("Timestamp Format Options"));
 	purple_plugin_pref_frame_add(frame, ppref);
 
-	tmp = g_strdup_printf(_("_Force 24-hour time format"));
+	tmp = g_strdup_printf(_("_Force timestamp format:"));
 	ppref = purple_plugin_pref_new_with_name_and_label(
-			"/plugins/gtk/timestamp_format/force_24hr",
+			"/plugins/gtk/timestamp_format/force",
 			tmp);
+	purple_plugin_pref_set_type(ppref, PURPLE_PLUGIN_PREF_CHOICE);
+	purple_plugin_pref_add_choice(ppref, _("Use system default"), "default");
+	purple_plugin_pref_add_choice(ppref, _("12 hour time format"), "force12");
+	purple_plugin_pref_add_choice(ppref, _("24 hour time format"), "force24");
 	purple_plugin_pref_frame_add(frame, ppref);
 	g_free(tmp);
 
@@ -58,27 +73,50 @@
 static char *timestamp_cb_common(PurpleConversation *conv,
                                  time_t t,
                                  gboolean show_date,
-                                 gboolean force,
+                                 const char *force,
                                  const char *dates,
 								 gboolean parens)
 {
+	struct tm *tm;
+
 	g_return_val_if_fail(dates != NULL, NULL);
 
+	tm = localtime(&t);
+
 	if (show_date ||
 	    !strcmp(dates, "always") ||
 	    (conv != NULL && purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT && !strcmp(dates, "chats")))
 	{
-		struct tm *tm = localtime(&t);
-		if (force)
+		if (g_str_equal(force, "force24"))
 			return g_strdup_printf("%s%s%s", parens ? "(" : "", purple_utf8_strftime("%Y-%m-%d %H:%M:%S", tm), parens ? ")" : "");
-		else
+		else if (g_str_equal(force, "force12")) {
+			char *date = g_strdup_printf("%s", purple_utf8_strftime("%Y-%m-%d ", tm));
+			char *remtime = g_strdup_printf("%s", purple_utf8_strftime(":%M:%S %p", tm));
+			const char *hour = format_12hour_hour(tm);
+			char *output;
+
+			output = g_strdup_printf("%s%s%s%s%s",
+			                         parens ? "(" : "", date,
+									 hour, remtime, parens ? ")" : "");
+
+			g_free(date);
+			g_free(remtime);
+
+			return output;
+		} else
 			return g_strdup_printf("%s%s%s", parens ? "(" : "", purple_date_format_long(tm), parens ? ")" : "");
 	}
 
-	if (force)
-	{
-		struct tm *tm = localtime(&t);
+	if (g_str_equal(force, "force24"))
 		return g_strdup_printf("%s%s%s", parens ? "(" : "", purple_utf8_strftime("%H:%M:%S", tm), parens ? ")" : "");
+	else if (g_str_equal(force, "force12")) {
+		const char *hour = format_12hour_hour(tm);
+		char *remtime = g_strdup_printf("%s", purple_utf8_strftime(":%M:%S %p", tm));
+		char *output = g_strdup_printf("%s%s%s%s", parens ? "(" : "", hour, remtime, parens ? ")" : "");
+
+		g_free(remtime);
+
+		return output;
 	}
 
 	return NULL;
@@ -87,8 +125,8 @@
 static char *conversation_timestamp_cb(PurpleConversation *conv,
                                        time_t t, gboolean show_date, gpointer data)
 {
-	gboolean force = purple_prefs_get_bool(
-				"/plugins/gtk/timestamp_format/force_24hr");
+	const char *force = purple_prefs_get_string(
+				"/plugins/gtk/timestamp_format/force");
 	const char *dates = purple_prefs_get_string(
 				"/plugins/gtk/timestamp_format/use_dates/conversation");
 
@@ -99,8 +137,8 @@
 
 static char *log_timestamp_cb(PurpleLog *log, time_t t, gboolean show_date, gpointer data)
 {
-	gboolean force = purple_prefs_get_bool(
-				"/plugins/gtk/timestamp_format/force_24hr");
+	const char *force = purple_prefs_get_string(
+				"/plugins/gtk/timestamp_format/force");
 	const char *dates = purple_prefs_get_string(
 				"/plugins/gtk/timestamp_format/use_dates/log");
 
@@ -264,7 +302,17 @@
 	purple_prefs_add_none("/plugins/gtk");
 	purple_prefs_add_none("/plugins/gtk/timestamp_format");
 
-	purple_prefs_add_bool("/plugins/gtk/timestamp_format/force_24hr", TRUE);
+	if (!purple_prefs_exists("/plugins/gtk/timestamp_format/force") &&
+	    purple_prefs_exists("/plugins/gtk/timestamp_format/force_24hr"))
+	{
+		if (purple_prefs_get_bool(
+		   "/plugins/gtk/timestamp_format/force_24hr"))
+			purple_prefs_add_string("/plugins/gtk/timestamp_format/force", "force24");
+		else
+			purple_prefs_add_string("/plugins/gtk/timestamp_format/force", "default");
+	}
+	else
+		purple_prefs_add_string("/plugins/gtk/timestamp_format/force", "default");
 
 	purple_prefs_add_none("/plugins/gtk/timestamp_format/use_dates");
 	purple_prefs_add_string("/plugins/gtk/timestamp_format/use_dates/conversation", "automatic");