changeset 15620:1078be435cc8

merge of 'cf12e304d75ad46da438f94ffdd3f9f722cfa2ec' and 'd54bd5c1ef3d6e9714fdaf19bf478555da7435df'
author Mark Doliner <mark@kingant.net>
date Sun, 11 Feb 2007 19:28:23 +0000
parents 7e0c0062c428 (current diff) 62b3ff6e513a (diff)
children 4049f4d94c33
files
diffstat 12 files changed, 174 insertions(+), 27 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog.API	Sun Feb 11 04:22:22 2007 +0000
+++ b/ChangeLog.API	Sun Feb 11 19:28:23 2007 +0000
@@ -256,6 +256,7 @@
 	* gaim_account_supports_offline_message()
 	* gaim_conversation_close_logs(), to force a conversation's log(s) to
 	  be closed.  New logs will be opened as necessary.
+	* gaim_got_protocol_handler_uri()
 	* gaim_plugin_get_id()
 	* gaim_plugin_get_name()
 	* gaim_plugin_get_version()
@@ -417,6 +418,7 @@
 	* "log-displaying"
 	* "savedstatus-changed"
 	* "sendto-extended-menu"
+	* "uri-handler"
 
 	Signals - Removed:
 	* "account-away": replaced by account-status-changed
--- a/libpurple/core.c	Sun Feb 11 04:22:22 2007 +0000
+++ b/libpurple/core.c	Sun Feb 11 19:28:23 2007 +0000
@@ -83,6 +83,13 @@
 	/* The signals subsystem is important and should be first. */
 	gaim_signals_init();
 
+	gaim_signal_register(core, "uri-handler",
+		gaim_marshal_BOOLEAN__POINTER_POINTER_POINTER,
+		gaim_value_new(GAIM_TYPE_BOOLEAN), 3,
+		gaim_value_new(GAIM_TYPE_STRING), /* Protocol */
+		gaim_value_new(GAIM_TYPE_STRING), /* Command */
+		gaim_value_new(GAIM_TYPE_BOXED, "GHashTable *")); /* Parameters */
+
 	gaim_signal_register(core, "quitting", gaim_marshal_VOID, NULL, 0);
 
 	/* The prefs subsystem needs to be initialized before static protocols
--- a/libpurple/log.c	Sun Feb 11 04:22:22 2007 +0000
+++ b/libpurple/log.c	Sun Feb 11 19:28:23 2007 +0000
@@ -1016,7 +1016,9 @@
 gboolean gaim_log_common_is_deletable(GaimLog *log)
 {
 	GaimLogCommonLoggerData *data;
+#ifndef _WIN32
 	gchar *dirname;
+#endif
 
 	g_return_val_if_fail(log != NULL, FALSE);
 
@@ -1435,7 +1437,7 @@
 
 static char *txt_logger_read(GaimLog *log, GaimLogReadFlags *flags)
 {
-	char *read, *minus_header, *minus_header2;
+	char *read, *minus_header;
 	GaimLogCommonLoggerData *data = log->logger_data;
 	*flags = 0;
 	if (!data || !data->path)
@@ -1745,7 +1747,7 @@
 {
 	struct old_logger_data *data = log->logger_data;
 	FILE *file = g_fopen(gaim_stringref_value(data->pathref), "rb");
-	char *tmp, *read = g_malloc(data->length + 1);
+	char *read = g_malloc(data->length + 1);
 	fseek(file, data->offset, SEEK_SET);
 	fread(read, data->length, 1, file);
 	fclose(file);
--- a/libpurple/plugins/perl/common/Makefile.mingw	Sun Feb 11 04:22:22 2007 +0000
+++ b/libpurple/plugins/perl/common/Makefile.mingw	Sun Feb 11 19:28:23 2007 +0000
@@ -12,7 +12,7 @@
 EXTUTILS ?= C:/perl/lib/ExtUtils
 PERL_PLUGIN_TOP := ..
 
-CFLAGS += -Wno-comment
+CFLAGS += -Wno-comment -Wno-unused
 
 ##
 ## INCLUDE PATHS
--- a/libpurple/util.c	Sun Feb 11 04:22:22 2007 +0000
+++ b/libpurple/util.c	Sun Feb 11 19:28:23 2007 +0000
@@ -23,6 +23,7 @@
 #include "internal.h"
 
 #include "conversation.h"
+#include "core.h"
 #include "debug.h"
 #include "notify.h"
 #include "prpl.h"
@@ -2995,6 +2996,69 @@
 /**************************************************************************
  * URI/URL Functions
  **************************************************************************/
+
+void gaim_got_protocol_handler_uri(const char *uri)
+{
+	char proto[11];
+	const char *tmp, *param_string;
+	char *cmd;
+	GHashTable *params = NULL;
+	int len;
+
+	if (!(tmp = strchr(uri, ':')) || tmp == uri) {
+		gaim_debug_error("util", "Malformed protocol handler message - missing protocol.\n");
+		return;
+	}
+
+	len = MIN(sizeof(proto) - 1, (tmp - uri));
+
+	strncpy(proto, uri, len);
+	proto[len] = '\0';
+
+	tmp++;
+	gaim_debug_info("util", "Processing message '%s' for protocol '%s'.\n", tmp, proto);
+
+	if ((param_string = strchr(tmp, '?'))) {
+		const char *keyend = NULL, *pairstart;
+		char *key, *value = NULL;
+
+		cmd = g_strndup(tmp, (param_string - tmp));
+		param_string++;
+
+		params = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+		pairstart = tmp = param_string;
+
+		while (*tmp || *pairstart) {
+			if (*tmp == '&' || !(*tmp)) {
+				/* If there is no explicit value */
+				if (keyend == NULL)
+					keyend = tmp;
+
+				if (keyend && keyend != pairstart) {
+					key = g_strndup(pairstart, (keyend - pairstart));
+					/* If there is an explicit value */
+					if (keyend != tmp && keyend != (tmp - 1))
+						value = g_strndup(keyend + 1, (tmp - keyend - 1));
+					g_hash_table_insert(params, key, value);
+				}
+				keyend = value = NULL;
+				pairstart = (*tmp) ? tmp + 1 : tmp;
+			} else if (*tmp == '=')
+				keyend = tmp;
+
+			if (*tmp)
+				tmp++;
+		}
+	} else
+		cmd = g_strdup(tmp);
+
+	gaim_signal_emit_return_1(gaim_get_core(), "uri-handler", proto, cmd, params);
+
+	g_free(cmd);
+	if (params)
+		g_hash_table_destroy(params);
+}
+
 gboolean
 gaim_url_parse(const char *url, char **ret_host, int *ret_port,
 			   char **ret_path, char **ret_user, char **ret_passwd)
--- a/libpurple/util.h	Sun Feb 11 04:22:22 2007 +0000
+++ b/libpurple/util.h	Sun Feb 11 19:28:23 2007 +0000
@@ -817,6 +817,8 @@
 /**************************************************************************/
 /*@{*/
 
+void gaim_got_protocol_handler_uri(const char *uri);
+
 /**
  * Parses a URL, returning its host, port, file path, username and password.
  *
--- a/pidgin/Makefile.mingw	Sun Feb 11 04:22:22 2007 +0000
+++ b/pidgin/Makefile.mingw	Sun Feb 11 19:28:23 2007 +0000
@@ -135,7 +135,7 @@
 all: $(EXE_TARGET).exe $(GTKGAIM_TARGET).dll
 	$(MAKE) -C $(GAIM_GTK_PLUGINS_TOP) -f $(GAIM_WIN32_MAKEFILE)
 
-./win32/pidgin_exe_rc.rc: ./win32/pidgin_exe_rc.rc.in $(GAIM_TOP)/VERSION
+win32/pidgin_exe_rc.rc: win32/pidgin_exe_rc.rc.in $(GAIM_TOP)/VERSION
 	sed -e 's/@GAIM_VERSION@/$(GAIM_VERSION)/g' \
 	    -e 's/@ORIGINAL_FILENAME@/$(EXE_NAME)/' \
 	    $@.in > $@
@@ -150,7 +150,7 @@
 	$(MAKE) -C $(GAIM_GTK_SOUNDS_TOP) -f $(GAIM_WIN32_MAKEFILE) install
 	$(MAKE) -C $(GAIM_GTK_IDLETRACK_TOP) -f $(GAIM_WIN32_MAKEFILE) install
 
-./win32/pidgin_dll_rc.rc: ./win32/pidgin_dll_rc.rc.in $(GAIM_TOP)/VERSION
+win32/pidgin_dll_rc.rc: win32/pidgin_dll_rc.rc.in $(GAIM_TOP)/VERSION
 	sed -e 's/@GAIM_VERSION@/$(GAIM_VERSION)/g' \
 	    $@.in > $@
 
--- a/pidgin/gtkconv.c	Sun Feb 11 04:22:22 2007 +0000
+++ b/pidgin/gtkconv.c	Sun Feb 11 19:28:23 2007 +0000
@@ -7255,7 +7255,7 @@
 	GtkWidget *page;
 	GtkWidget *tab;
 
-	if (e->button == 2) {
+	if (e->button == 2 && e->type == GDK_BUTTON_PRESS) {
 		PidginConversation *gtkconv;
 		tab_clicked = pidgin_conv_get_tab_at_xy(win, e->x_root, e->y_root, NULL);
 
--- a/pidgin/win32/gtkwin32dep.c	Sun Feb 11 04:22:22 2007 +0000
+++ b/pidgin/win32/gtkwin32dep.c	Sun Feb 11 19:28:23 2007 +0000
@@ -49,6 +49,7 @@
 #include "gtkwin32dep.h"
 #include "win32dep.h"
 #include "gtkconv.h"
+#include "util.h"
 #include "wspell.h"
 
 /*
@@ -192,14 +193,20 @@
 	winpidgin_shell_execute(uri, "open", "http");
 }
 
-#define WM_FOCUS_REQUEST (WM_APP + 13)
+#define PIDGIN_WM_FOCUS_REQUEST (WM_APP + 13)
+#define PIDGIN_WM_PROTOCOL_HANDLE (WM_APP + 14)
 
 static LRESULT CALLBACK message_window_handler(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
 
-	if (msg == WM_FOCUS_REQUEST) {
+	if (msg == PIDGIN_WM_FOCUS_REQUEST) {
 		gaim_debug_info("winpidgin", "Got external Buddy List focus request.");
 		gaim_blist_set_visible(TRUE);
 		return TRUE;
+	} else if (msg == PIDGIN_WM_PROTOCOL_HANDLE) {
+		char *proto_msg = (char *) lparam;
+		gaim_debug_info("winpidgin", "Got protocol handler request: %s\n", proto_msg ? proto_msg : "");
+		gaim_got_protocol_handler_uri(proto_msg);
+		return TRUE;
 	}
 
 	return DefWindowProc(hwnd, msg, wparam, lparam);
--- a/pidgin/win32/pidgin_dll_rc.rc.in	Sun Feb 11 04:22:22 2007 +0000
+++ b/pidgin/win32/pidgin_dll_rc.rc.in	Sun Feb 11 19:28:23 2007 +0000
@@ -14,13 +14,13 @@
     BEGIN
       BLOCK "040904B0"
       BEGIN
-        VALUE "CompanyName", "The Gaim developer community"
-        VALUE "FileDescription", "GTK+ Gaim Library"
+        VALUE "CompanyName", "The Pidgin developer community"
+        VALUE "FileDescription", "GTK+ Pidgin Library"
         VALUE "FileVersion", "@GAIM_VERSION@"
-        VALUE "InternalName", "gtkgaim"
-        VALUE "LegalCopyright", "Copyright (C) 1998-2006 The Gaim developer community (See the COPYRIGHT file in the source distribution)."
-        VALUE "OriginalFilename", "gtkgaim.dll"
-        VALUE "ProductName", "Gaim"
+        VALUE "InternalName", "libpidgin"
+        VALUE "LegalCopyright", "Copyright (C) 1998-2007 The Pidgin developer community (See the COPYRIGHT file in the source distribution)."
+        VALUE "OriginalFilename", "pidgin.dll"
+        VALUE "ProductName", "Pidgin"
         VALUE "ProductVersion", "@GAIM_VERSION@"
       END
     END
--- a/pidgin/win32/pidgin_exe_rc.rc.in	Sun Feb 11 04:22:22 2007 +0000
+++ b/pidgin/win32/pidgin_exe_rc.rc.in	Sun Feb 11 19:28:23 2007 +0000
@@ -17,13 +17,13 @@
     BEGIN
       BLOCK "040904B0"
       BEGIN
-        VALUE "CompanyName", "The Gaim developer community"
-        VALUE "FileDescription", "Gaim"
+        VALUE "CompanyName", "The Pidgin developer community"
+        VALUE "FileDescription", "Pidgin"
         VALUE "FileVersion", "@GAIM_VERSION@"
-        VALUE "InternalName", "gaim"
-        VALUE "LegalCopyright", "Copyright (C) 1998-2006 The Gaim developer community (See the COPYRIGHT file in the source distribution)."
+        VALUE "InternalName", "pidgin"
+        VALUE "LegalCopyright", "Copyright (C) 1998-2007 The Pidgin developer community (See the COPYRIGHT file in the source distribution)."
         VALUE "OriginalFilename", "@ORIGINAL_FILENAME@"
-        VALUE "ProductName", "Gaim"
+        VALUE "ProductName", "Pidgin"
         VALUE "ProductVersion", "@GAIM_VERSION@"
       END
     END
--- a/pidgin/win32/winpidgin.c	Sun Feb 11 04:22:22 2007 +0000
+++ b/pidgin/win32/winpidgin.c	Sun Feb 11 19:28:23 2007 +0000
@@ -433,7 +433,8 @@
 	putenv(envstr);
 }
 
-#define WM_FOCUS_REQUEST (WM_APP + 13)
+#define PIDGIN_WM_FOCUS_REQUEST (WM_APP + 13)
+#define PIDGIN_WM_PROTOCOL_HANDLE (WM_APP + 14)
 
 static BOOL winpidgin_set_running() {
 	HANDLE h;
@@ -443,7 +444,7 @@
 			HWND msg_win;
 
 			if((msg_win = FindWindow(TEXT("WinpidginMsgWinCls"), NULL)))
-				if(SendMessage(msg_win, WM_FOCUS_REQUEST, (WPARAM) NULL, (LPARAM) 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 */
@@ -458,12 +459,67 @@
 	return TRUE;
 }
 
+#define PROTO_HANDLER_SWITCH "--protocolhandler="
 
-#ifdef __GNUC__
-#  ifndef _stdcall
-#    define _stdcall  __attribute__((stdcall))
-#  endif
-#endif
+static void handle_protocol(char *cmd) {
+	char *remote_msg, *tmp1, *tmp2;
+	int len;
+	SIZE_T len_written;
+	HWND msg_win;
+	DWORD pid;
+	HANDLE process;
+
+	/* The start of the message */
+	tmp1 = cmd + strlen(PROTO_HANDLER_SWITCH);
+
+	/* The end of the message */
+	if ((tmp2 = strchr(tmp1, ' ')))
+		len = (tmp2 - tmp1);
+	else
+		len = strlen(tmp1);
+
+	if (len == 0) {
+		printf("No protocol message specified.\n");
+		return;
+	}
+
+	if (!(msg_win = FindWindow(TEXT("WinpidginMsgWinCls"), NULL))) {
+		printf("Unable to find an instance of Pidgin to handle protocol message.\n");
+		return;
+	}
+
+	GetWindowThreadProcessId(msg_win, &pid);
+	if (!(process = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_WRITE, FALSE, pid))) {
+		DWORD dw = GetLastError();
+		const char *err_msg = get_win32_error_message(dw);
+		printf("Unable to open Pidgin process. (%u) %s\n", (UINT) dw, err_msg);
+		return;
+	}
+
+	printf("Trying to handle protocol message:\n'%*s'\n", len, tmp1);
+
+	/* MEM_COMMIT initializes the memory to zero,
+	 * so we don't need to worry that our section of tmp1 isn't nul-terminated */
+	if ((remote_msg = (char*) VirtualAllocEx(process, NULL, len + 1, MEM_COMMIT, PAGE_READWRITE))) {
+		if (WriteProcessMemory(process, remote_msg, tmp1, len, &len_written)) {
+			if (!SendMessage(msg_win, PIDGIN_WM_PROTOCOL_HANDLE, len_written, (LPARAM) remote_msg))
+				printf("Unable to send protocol message to Pidgin instance.\n");
+		} else {
+			DWORD dw = GetLastError();
+			const char *err_msg = get_win32_error_message(dw);
+			printf("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 char *err_msg = get_win32_error_message(dw);
+		printf("Unable to allocate remote memory. (%u) %s\n", (UINT) dw, err_msg);
+	}
+
+	CloseHandle(process);
+}
+
 
 int _stdcall
 WinMain (struct HINSTANCE__ *hInstance, struct HINSTANCE__ *hPrevInstance,
@@ -471,6 +527,7 @@
 	char errbuf[512];
 	char pidgindir[MAX_PATH];
 	HMODULE hmod;
+	char *tmp;
 
 	/* If debug or help or version flag used, create console for output */
 	if (strstr(lpszCmdLine, "-d") || strstr(lpszCmdLine, "-h") || strstr(lpszCmdLine, "-v")) {
@@ -491,10 +548,16 @@
 		}
 	}
 
+	/* If this is a protocol handler invocation, deal with it accordingly */
+	if ((tmp = strstr(lpszCmdLine, PROTO_HANDLER_SWITCH)) != NULL) {
+		handle_protocol(tmp);
+		return 0;
+	}
+
 	/* Load exception handler if we have it */
 	if (GetModuleFileName(NULL, pidgindir, MAX_PATH) != 0) {
-		char *tmp = pidgindir;
 		char *prev = NULL;
+		tmp = pidgindir;
 
 		while ((tmp = strchr(tmp, '\\'))) {
 			prev = tmp;