changeset 27449:14131ba5a07c

merge of '51d199ba5dd8a81f6276f19421c8f7e0158dcb98' and 'ac87c285c7056f86005dc157b9870745de471f74'
author Elliott Sales de Andrade <qulogic@pidgin.im>
date Mon, 06 Jul 2009 05:27:30 +0000
parents a6d84d9de605 (diff) b41b69e8b341 (current diff)
children c374d57b3215
files ChangeLog ChangeLog.API
diffstat 14 files changed, 218 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Mon Jul 06 04:19:26 2009 +0000
+++ b/ChangeLog	Mon Jul 06 05:27:30 2009 +0000
@@ -10,10 +10,6 @@
 	  in a group on the buddy list. (Paul Aurich)
 	* Removed the unmaintained and unneeded toc protocol plugin.
 	* Fixed NTLM authentication on big-endian systems.
-	* The Pidgin and Purple perl modules are no longer installed into @INC,
-	  this should hopefully prevent some minor confusion.
-	* Use GLib's implementations of SHA1, SHA256, and MD5 when available.
-	  (GLib 2.14 or higher)
 
 	libpurple:
 	* Various memory cleanups when unloading libpurple. (Nick Hebner)
@@ -32,6 +28,7 @@
 	  "off" variable.  Set it to any value to turn it on and unset it to turn
 	  it off.  This will optionally be used to only show less useful debug
 	  information on an as-needed basis.
+	* Add support for receiving handwritten (ink) messages on MSN.
 
 	Gadu-Gadu:
 	* Accounts can specify a server to which to connect.
--- a/ChangeLog.API	Mon Jul 06 04:19:26 2009 +0000
+++ b/ChangeLog.API	Mon Jul 06 05:27:30 2009 +0000
@@ -74,6 +74,7 @@
 		  emitted), but this signal was not emitted.
 		* Added a client_type field in the get_ui_info core UI op. See
 		  core.h for details.
+		* Added introspection of signals exposed via the D-Bus API.
 
 		Deprecated:
 		* buddy-added and buddy-removed blist signals
--- a/libpurple/Makefile.am	Mon Jul 06 04:19:26 2009 +0000
+++ b/libpurple/Makefile.am	Mon Jul 06 05:27:30 2009 +0000
@@ -1,5 +1,6 @@
 EXTRA_DIST = \
 		dbus-analyze-functions.py \
+		dbus-analyze-signals.py \
 		dbus-analyze-types.py \
 		marshallers.list \
 		purple-notifications-example \
@@ -169,6 +170,7 @@
 	dbus-bindings.c \
 	dbus-client-binding.c \
 	dbus-client-binding.h \
+	dbus-signals.c \
 	dbus-types.c \
 	dbus-types.h \
 	marshallers.c \
@@ -189,6 +191,10 @@
 purple_build_coreheaders = $(addprefix $(srcdir)/, $(purple_coreheaders)) \
 		$(purple_builtheaders)
 dbus_build_exported = $(addprefix $(srcdir)/, $(dbus_exported))
+# We should probably make this better
+dbus_signals = $(purple_coresources) \
+	protocols/irc/irc.c \
+	protocols/jabber/libxmpp.c
 
 dbus-types.c: dbus-analyze-types.py $(purple_build_coreheaders)
 	cat $(purple_build_coreheaders) | $(PYTHON) $(srcdir)/dbus-analyze-types.py --pattern=PURPLE_DBUS_DEFINE_TYPE\(%s\) > $@
@@ -199,8 +205,11 @@
 dbus-bindings.c: dbus-analyze-functions.py $(dbus_exported)
 	cat $(dbus_build_exported) | $(PYTHON) $(srcdir)/dbus-analyze-functions.py > $@
 
-dbus-server.$(OBJEXT): dbus-bindings.c dbus-types.c dbus-types.h
-dbus-server.lo: dbus-bindings.c dbus-types.c dbus-types.h
+dbus-signals.c: dbus-analyze-signals.py $(dbus_signals)
+	cat $(dbus_signals) | $(PYTHON) $(srcdir)/dbus-analyze-signals.py > $@
+
+dbus-server.$(OBJEXT): dbus-bindings.c dbus-signals.c dbus-types.c dbus-types.h
+dbus-server.lo: dbus-bindings.c dbus-signals.c dbus-types.c dbus-types.h
 $(libpurple_la_OBJECTS): dbus-types.h
 
 # libpurple-client
@@ -240,9 +249,10 @@
 bin_SCRIPTS = purple-remote purple-send purple-send-async purple-url-handler
 
 BUILT_SOURCES = $(purple_builtheaders) \
+	dbus-bindings.c \
+	dbus-signals.c \
 	dbus-types.c \
 	dbus-types.h \
-	dbus-bindings.c \
 	marshallers.c \
 	marshallers.h \
 	purple-client-bindings.c \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/dbus-analyze-signals.py	Mon Jul 06 05:27:30 2009 +0000
@@ -0,0 +1,60 @@
+# This program takes a C source as the input and produces the list of
+# all signals registered.
+#
+# Output is:
+#   <signal name="Changed">
+#       <arg name="new_value" type="b"/>
+#   </signal>
+
+import re
+import sys
+
+# List "excluded" contains signals that shouldn't be exported via
+# DBus.  If you remove a signal from this list, please make sure
+# that it does not break "make" with the configure option
+# "--enable-dbus" turned on.
+
+excluded = [\
+    # purple_dbus_signal_emit_purple prevents our "dbus-method-called"
+    # signal from being propagated to dbus.
+	"dbus-method-called",
+    ]
+
+registerregex = re.compile("purple_signal_register[^;]+\"([\w\-]+)\"[^;]+(purple_marshal_\w+)[^;]+;")
+nameregex = re.compile('[-_][a-z]')
+
+print "/* Generated by %s.  Do not edit! */" % sys.argv[0]
+print "const char *dbus_signals = "
+for match in registerregex.finditer(sys.stdin.read()):
+    signal = match.group(1)
+    marshal = match.group(2)
+    if signal in excluded:
+        continue
+
+    signal = nameregex.sub(lambda x:x.group()[1].upper(), '-'+signal)
+    print "\"<signal name='%s'>\\n\""%signal
+
+    args = marshal.split('_')
+    # ['purple', 'marshal', <return type>, '', args...]
+    if len(args) > 4:
+        for arg in args[4:]:
+            if arg == "POINTER":
+                type = 'p'
+            elif arg == "ENUM":
+                type = 'i'
+            elif arg == "INT":
+                type = 'i'
+            elif arg == "UINT":
+                type = 'u'
+            elif arg == "INT64":
+                type = 'x'
+            elif arg == "UINT64":
+                type = 't'
+            elif arg == "BOOLEAN":
+                type = 'b'
+            print "\"<arg type='%s'/>\\n\""%type
+
+    print "\"</signal>\\n\""
+
+print ";"
+
--- a/libpurple/dbus-server.c	Mon Jul 06 04:19:26 2009 +0000
+++ b/libpurple/dbus-server.c	Mon Jul 06 05:27:30 2009 +0000
@@ -421,6 +421,7 @@
 }
 
 #include "dbus-bindings.c"
+#include "dbus-signals.c"
 
 static gboolean
 purple_dbus_dispatch_cb(DBusConnection *connection,
@@ -489,6 +490,9 @@
 	DBusMessage *reply;
 	GString *str;
 	GList *bindings_list, *node;
+	const char *signals;
+	const char *type;
+	const char *pointer_type;
 
 	str = g_string_sized_new(0x1000); /* TODO: why this size? */
 
@@ -529,6 +533,19 @@
 		}
 	}
 
+	if (sizeof(int) == sizeof(dbus_int32_t))
+		pointer_type = "type='i'";
+	else
+		pointer_type = "type='x'";
+
+	signals = dbus_signals;
+	while ((type = strstr(signals, "type='p'")) != NULL) {
+		g_string_append_len(str, signals, type - signals);
+		g_string_append(str, pointer_type);
+		signals = type + sizeof("type='p'") - 1;
+	}
+	g_string_append(str, signals);
+
 	g_string_append(str, "</interface>\n</node>\n");
 
 	reply = dbus_message_new_method_return(message);
--- a/libpurple/dbus-server.h	Mon Jul 06 04:19:26 2009 +0000
+++ b/libpurple/dbus-server.h	Mon Jul 06 05:27:30 2009 +0000
@@ -192,9 +192,9 @@
 /**
 
  Macro #DBUS_EXPORT expands to nothing.  It is used to indicate to the
- dbus-analize-functions.py script that the given function should be
+ dbus-analyze-functions.py script that the given function should be
  available to other applications through DBUS.  If
- dbus-analize-functions.py is run without the "--export-only" option,
+ dbus-analyze-functions.py is run without the "--export-only" option,
  this prefix is ignored.
 
  */
@@ -204,7 +204,7 @@
 /*
    Here we include the list of #PURPLE_DBUS_DECLARE_TYPE statements for
    all structs defined in purple.  This file has been generated by the
-   #dbus-analize-types.py script.
+   #dbus-analyze-types.py script.
 */
 
 #include "dbus-types.h"
--- a/libpurple/protocols/msn/msg.c	Mon Jul 06 04:19:26 2009 +0000
+++ b/libpurple/protocols/msn/msg.c	Mon Jul 06 05:27:30 2009 +0000
@@ -1048,3 +1048,14 @@
 	g_hash_table_destroy(body);
 }
 
+/* Only called from chats. Handwritten messages for IMs come as a SLP message */
+void
+msn_handwritten_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
+{
+	const char *body;
+	size_t body_len;
+
+	body = msn_message_get_bin_data(msg, &body_len);
+	msn_switchboard_show_ink(cmdproc->data, msg->remote_user, body);
+}
+
--- a/libpurple/protocols/msn/msg.h	Mon Jul 06 04:19:26 2009 +0000
+++ b/libpurple/protocols/msn/msg.h	Mon Jul 06 05:27:30 2009 +0000
@@ -345,4 +345,6 @@
 
 void msn_datacast_msg(MsnCmdProc *cmdproc, MsnMessage *msg);
 
+void msn_handwritten_msg(MsnCmdProc *cmdproc, MsnMessage *msg);
+
 #endif /* _MSN_MSG_H_ */
--- a/libpurple/protocols/msn/msn.h	Mon Jul 06 04:19:26 2009 +0000
+++ b/libpurple/protocols/msn/msn.h	Mon Jul 06 05:27:30 2009 +0000
@@ -138,7 +138,7 @@
 } MsnClientVerId;
 
 #define MSN_CLIENT_ID_VERSION      MSN_CLIENT_VER_7_0
-#define MSN_CLIENT_ID_CAPABILITIES MSN_CLIENT_CAP_PACKET
+#define MSN_CLIENT_ID_CAPABILITIES (MSN_CLIENT_CAP_PACKET|MSN_CLIENT_CAP_INK_GIF)
 
 #define MSN_CLIENT_ID \
 	((MSN_CLIENT_ID_VERSION    << 24) | \
--- a/libpurple/protocols/msn/slpcall.c	Mon Jul 06 04:19:26 2009 +0000
+++ b/libpurple/protocols/msn/slpcall.c	Mon Jul 06 05:27:30 2009 +0000
@@ -210,8 +210,51 @@
 	{
 		char *body_str;
 
-		body_str = g_strndup((const char *)body, body_len);
-		slpcall = msn_slp_sip_recv(slplink, body_str);
+		if (slpmsg->session_id == 64)
+		{
+			/* This is for handwritten messages (Ink) */
+			GError *error;
+			glong items_read, items_written;
+
+			body_str = g_utf16_to_utf8((gunichar2 *)body, body_len / 2,
+			                           &items_read, &items_written, &error);
+			body_len -= items_read * 2 + 2;
+			body += items_read * 2 + 2;
+			if (body_str == NULL
+			 || body_len <= 0
+			 || strstr(body_str, "image/gif") == NULL)
+			{
+				if (error != NULL)
+					purple_debug_error("msn",
+					                   "Unable to convert Ink header from UTF-16 to UTF-8: %s\n",
+					                   error->message);
+				else
+					purple_debug_error("msn",
+					                   "Received Ink in unknown format\n");
+				g_free(body_str);
+				return NULL;
+			}
+			g_free(body_str);
+
+			body_str = g_utf16_to_utf8((gunichar2 *)body, body_len / 2,
+			                           &items_read, &items_written, &error);
+			if (!body_str)
+			{
+				purple_debug_error("msn",
+				                   "Unable to convert Ink body from UTF-16 to UTF-8: %s\n",
+				                   error->message);
+				return NULL;
+			}
+
+			msn_switchboard_show_ink(slpmsg->slplink->swboard,
+			                         slplink->remote_user,
+			                         body_str);
+		}
+		else
+		{
+			body_str = g_strndup((const char *)body, body_len);
+			slpcall = msn_slp_sip_recv(slplink, body_str);
+		}
 		g_free(body_str);
 	}
 	else if (slpmsg->flags == 0x20 ||
--- a/libpurple/protocols/msn/switchboard.c	Mon Jul 06 04:19:26 2009 +0000
+++ b/libpurple/protocols/msn/switchboard.c	Mon Jul 06 05:27:30 2009 +0000
@@ -905,6 +905,47 @@
 #endif
 }
 
+void
+msn_switchboard_show_ink(MsnSwitchBoard *swboard, const char *passport,
+                         const char *data)
+{
+	PurpleConnection *gc;
+	guchar *image_data;
+	size_t image_len;
+	int imgid;
+	char *image_msg;
+
+	if (!purple_str_has_prefix(data, "base64:"))
+	{
+		purple_debug_error("msn", "Ignoring Ink not in Base64 format.\n");
+		return;
+	}
+
+	gc = purple_account_get_connection(swboard->session->account);
+
+	data += sizeof("base64:") - 1;
+	image_data = purple_base64_decode(data, &image_len);
+	if (!image_data || !image_len) 
+	{
+		purple_debug_error("msn", "Unable to decode Ink from Base64 format.\n");
+		return;
+	}
+
+	imgid = purple_imgstore_add_with_id(image_data, image_len, NULL);
+	image_msg = g_strdup_printf("<IMG ID=%d/>", imgid);
+
+	if (swboard->current_users > 1 ||
+		((swboard->conv != NULL) &&
+		 purple_conversation_get_type(swboard->conv) == PURPLE_CONV_TYPE_CHAT))
+		serv_got_chat_in(gc, swboard->chat_id, passport, 0, image_msg,
+						 time(NULL));
+	else
+		serv_got_im(gc, passport, image_msg, 0, time(NULL));
+
+	purple_imgstore_unref_by_id(imgid);
+	g_free(image_msg);
+}
+
 /**************************************************************************
  * Connect stuff
  **************************************************************************/
@@ -1239,6 +1280,8 @@
 						   msn_datacast_msg);
 	msn_table_add_msg_type(cbs_table, "text/x-msmsgsinvite",
 						   msn_invite_msg);
+	msn_table_add_msg_type(cbs_table, "image/gif",
+						   msn_handwritten_msg);
 }
 
 void
--- a/libpurple/protocols/msn/switchboard.h	Mon Jul 06 04:19:26 2009 +0000
+++ b/libpurple/protocols/msn/switchboard.h	Mon Jul 06 05:27:30 2009 +0000
@@ -280,4 +280,14 @@
  */
 void msn_invite_msg(MsnCmdProc *cmdproc, MsnMessage *msg);
 
+/**
+ * Shows an ink message from this switchboard.
+ *
+ * @param swboard  The switchboard.
+ * @param passport The user that sent the ink.
+ * @param data     The ink data.
+ */
+void msn_switchboard_show_ink(MsnSwitchBoard *swboard, const char *passport,
+                              const char *data);
+
 #endif /* _MSN_SWITCHBOARD_H_ */
--- a/pidgin/gtksmiley.c	Mon Jul 06 04:19:26 2009 +0000
+++ b/pidgin/gtksmiley.c	Mon Jul 06 05:27:30 2009 +0000
@@ -74,6 +74,7 @@
 static void
 pidgin_smiley_destroy(PidginSmiley *smiley)
 {
+	g_object_set_data(G_OBJECT(smiley->smiley), "edit-dialog", NULL);
 	gtk_widget_destroy(smiley->parent);
 	g_free(smiley->filename);
 	if (smiley->custom_pixbuf)
@@ -402,6 +403,7 @@
 			smiley ? GTK_STOCK_SAVE : GTK_STOCK_ADD, GTK_RESPONSE_ACCEPT,
 			NULL);
 	s->parent = window;
+	g_object_set_data(G_OBJECT(smiley), "edit-dialog", window);
 
 	gtk_container_set_border_width(GTK_CONTAINER(window), PIDGIN_HIG_BORDER);
 
@@ -650,8 +652,12 @@
 smiley_edit_iter(SmileyManager *dialog, GtkTreeIter *iter)
 {
 	PurpleSmiley *smiley = NULL;
+	GtkWidget *window = NULL;
 	gtk_tree_model_get(GTK_TREE_MODEL(dialog->model), iter, SMILEY, &smiley, -1);
-	pidgin_smiley_edit(gtk_widget_get_toplevel(GTK_WIDGET(dialog->treeview)), smiley);
+	if ((window = g_object_get_data(G_OBJECT(smiley), "edit-dialog")) != NULL)
+		gtk_window_present(GTK_WINDOW(window));
+	else
+		pidgin_smiley_edit(gtk_widget_get_toplevel(GTK_WIDGET(dialog->treeview)), smiley);
 	g_object_unref(G_OBJECT(smiley));
 }
 
--- a/pidgin/plugins/disco/xmppdisco.c	Mon Jul 06 04:19:26 2009 +0000
+++ b/pidgin/plugins/disco/xmppdisco.c	Mon Jul 06 05:27:30 2009 +0000
@@ -500,6 +500,10 @@
 			++list->fetch_count;
 			pidgin_disco_list_ref(list);
 		}
+		else {
+			pidgin_disco_list_set_in_progress(list, FALSE);
+			g_free(cb_data);
+		}
 	}
 	else {
 		error = xmlnode_get_child(iq, "error");