/pidgin/main: 0f7e07af75fc: Fix security-related url notificatio...

Tomasz Wasilczyk tomkiewicz at cpw.pidgin.im
Tue Jan 28 10:38:09 EST 2014


Changeset: 0f7e07af75fc0441e163fb38bf47732be724cbab
Author:	 Tomasz Wasilczyk <tomkiewicz at cpw.pidgin.im>
Date:	 2013-06-22 19:08 +0200
Branch:	 release-2.x.y
URL: https://hg.pidgin.im/pidgin/main/rev/0f7e07af75fc

Description:

Fix security-related url notification issues: xdg-open remote execution, replacing g_spawn_command_line_ with g_spawn_ and opera 'open in current tab' bug

diffstat:

 pidgin/gtknotify.c |  409 ++++++++++++++++++++++++++++++----------------------
 1 files changed, 234 insertions(+), 175 deletions(-)

diffs (truncated from 473 to 300 lines):

diff --git a/pidgin/gtknotify.c b/pidgin/gtknotify.c
--- a/pidgin/gtknotify.c
+++ b/pidgin/gtknotify.c
@@ -1192,51 +1192,85 @@ pidgin_close_notify(PurpleNotifyType typ
 }
 
 #ifndef _WIN32
-static gint
-uri_command(const char *command, gboolean sync)
+static gboolean
+uri_command(GSList *arg_list, gboolean sync)
 {
 	gchar *tmp;
 	GError *error = NULL;
-	gint ret = 0;
+	GSList *it;
+	gchar **argv;
+	gint argc, i;
+	gchar *program;
 
-	purple_debug_misc("gtknotify", "Executing %s\n", command);
+	g_return_val_if_fail(arg_list != NULL, FALSE);
 
-	if (!purple_program_is_valid(command))
-	{
-		tmp = g_strdup_printf(_("The browser command \"%s\" is invalid."),
-							  command ? command : "(none)");
+	program = arg_list->data;
+	purple_debug_misc("gtknotify", "Executing %s (%s)\n", program,
+		sync ? "sync" : "async");
+
+	if (!purple_program_is_valid(program)) {
+		purple_debug_error("gtknotify", "Command \"%s\" is invalid\n",
+			program);
+		tmp = g_strdup_printf(
+			_("The browser command \"%s\" is invalid."),
+			program ? program : "(null)");
 		purple_notify_error(NULL, NULL, _("Unable to open URL"), tmp);
 		g_free(tmp);
 
-	}
-	else if (sync)
-	{
-		gint status;
-
-		if (!g_spawn_command_line_sync(command, NULL, NULL, &status, &error))
-		{
-			tmp = g_strdup_printf(_("Error launching \"%s\": %s"),
-										command, error->message);
-			purple_notify_error(NULL, NULL, _("Unable to open URL"), tmp);
-			g_free(tmp);
-			g_error_free(error);
-		}
-		else
-			ret = status;
-	}
-	else
-	{
-		if (!g_spawn_command_line_async(command, &error))
-		{
-			tmp = g_strdup_printf(_("Error launching \"%s\": %s"),
-										command, error->message);
-			purple_notify_error(NULL, NULL, _("Unable to open URL"), tmp);
-			g_free(tmp);
-			g_error_free(error);
-		}
+		return FALSE;
 	}
 
-	return ret;
+	argc = g_slist_length(arg_list);
+	argv = g_new(gchar*, argc + 1);
+	i = 0;
+	for (it = arg_list; it; it = g_slist_next(it)) {
+		if (purple_debug_is_verbose()) {
+			purple_debug_misc("gtknotify", "argv[%d] = \"%s\"\n",
+				i, (gchar*)it->data);
+		}
+		argv[i++] = it->data;
+	}
+	argv[i] = NULL;
+
+	if (sync) {
+		gint exit_status = 0;
+
+		if (g_spawn_sync(NULL, argv, NULL, G_SPAWN_SEARCH_PATH |
+			G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL,
+			NULL, NULL, NULL, NULL, &exit_status, &error) &&
+			exit_status == 0)
+		{
+			g_free(argv);
+			return TRUE;
+		}
+
+		purple_debug_error("gtknotify",
+			"Error launching \"%s\": %s (status: %d)\n", program,
+			error ? error->message : "(null)", exit_status);
+		tmp = g_strdup_printf(_("Error launching \"%s\": %s"), program,
+			error ? error->message : "(null)");
+		g_error_free(error);
+		purple_notify_error(NULL, NULL, _("Unable to open URL"), tmp);
+		g_free(tmp);
+
+		g_free(argv);
+		return FALSE;
+	}
+
+	if (g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH |
+		G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL, NULL,
+		NULL, NULL, &error))
+	{
+		g_free(argv);
+		return TRUE;
+	}
+
+	purple_debug_warning("gtknotify", "Error launching \"%s\": %s\n",
+		program, error ? error->message : "(null)");
+	g_error_free(error);
+
+	g_free(argv);
+	return FALSE;
 }
 #endif /* _WIN32 */
 
@@ -1244,183 +1278,208 @@ static void *
 pidgin_notify_uri(const char *uri)
 {
 #ifndef _WIN32
-	char *escaped = g_shell_quote(uri);
-	char *command = NULL;
-	char *remote_command = NULL;
 	const char *web_browser;
 	int place;
+	gchar *uri_escaped, *uri_custom = NULL;
+	GSList *argv = NULL, *argv_remote = NULL;
+	gchar **usercmd_argv = NULL;
 
-	web_browser = purple_prefs_get_string(PIDGIN_PREFS_ROOT "/browsers/browser");
+	uri_escaped = g_uri_escape_string(uri, ":/%#,+", FALSE);
+
+	web_browser = purple_prefs_get_string(PIDGIN_PREFS_ROOT
+		"/browsers/browser");
 	place = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/browsers/place");
 
 	/* if they are running gnome, use the gnome web browser */
-	if (purple_running_gnome() == TRUE)
-	{
+	if (purple_running_gnome() == TRUE) {
 		char *tmp = g_find_program_in_path("xdg-open");
 		if (tmp == NULL)
-			command = g_strdup_printf("gnome-open %s", escaped);
+			argv = g_slist_append(argv, "gnome-open");
 		else
-			command = g_strdup_printf("xdg-open %s", escaped);
+			argv = g_slist_append(argv, "xdg-open");
 		g_free(tmp);
-	}
-	else if (purple_running_osx() == TRUE)
-	{
-		command = g_strdup_printf("open %s", escaped);
-	}
-	else if (!strcmp(web_browser, "epiphany") ||
+		argv = g_slist_append(argv, uri_escaped);
+	} else if (purple_running_osx() == TRUE) {
+		argv = g_slist_append(argv, "open");
+		argv = g_slist_append(argv, (gpointer)uri);
+	} else if (!strcmp(web_browser, "epiphany") ||
 		!strcmp(web_browser, "galeon"))
 	{
+		argv = g_slist_append(argv, (gpointer)web_browser);
+
 		if (place == PIDGIN_BROWSER_NEW_WINDOW)
-			command = g_strdup_printf("%s -w %s", web_browser, escaped);
+			argv = g_slist_append(argv, "-w");
 		else if (place == PIDGIN_BROWSER_NEW_TAB)
-			command = g_strdup_printf("%s -n %s", web_browser, escaped);
-		else
-			command = g_strdup_printf("%s %s", web_browser, escaped);
-	}
-	else if (!strcmp(web_browser, "xdg-open"))
-	{
-		command = g_strdup_printf("xdg-open %s", escaped);
-	}
-	else if (!strcmp(web_browser, "gnome-open"))
-	{
-		command = g_strdup_printf("gnome-open %s", escaped);
-	}
-	else if (!strcmp(web_browser, "kfmclient"))
-	{
-		command = g_strdup_printf("kfmclient openURL %s", escaped);
+			argv = g_slist_append(argv, "-n");
+
+		argv = g_slist_append(argv, (gpointer)uri);
+	} else if (!strcmp(web_browser, "xdg-open")) {
+		argv = g_slist_append(argv, "xdg-open");
+		argv = g_slist_append(argv, uri_escaped);
+	} else if (!strcmp(web_browser, "gnome-open")) {
+		argv = g_slist_append(argv, "gnome-open");
+		argv = g_slist_append(argv, uri_escaped);
+	} else if (!strcmp(web_browser, "kfmclient")) {
+		argv = g_slist_append(argv, "kfmclient");
+		argv = g_slist_append(argv, "openURL");
+		argv = g_slist_append(argv, (gpointer)uri);
 		/*
 		 * Does Konqueror have options to open in new tab
 		 * and/or current window?
 		 */
-	}
-	else if (!strcmp(web_browser, "mozilla") ||
-			 !strcmp(web_browser, "mozilla-firebird") ||
-			 !strcmp(web_browser, "firefox") ||
-			 !strcmp(web_browser, "seamonkey"))
+	} else if (!strcmp(web_browser, "mozilla") ||
+		!strcmp(web_browser, "mozilla-firebird") ||
+		!strcmp(web_browser, "firefox") ||
+		!strcmp(web_browser, "seamonkey"))
 	{
-		char *args = "";
+		argv = g_slist_append(argv, (gpointer)web_browser);
+		argv = g_slist_append(argv, uri_escaped);
 
-		command = g_strdup_printf("%s %s", web_browser, escaped);
+		g_assert(uri_custom == NULL);
+		if (place == PIDGIN_BROWSER_NEW_WINDOW) {
+			uri_custom = g_strdup_printf("openURL(%s,new-window)",
+				uri_escaped);
+		} else if (place == PIDGIN_BROWSER_NEW_TAB) {
+			uri_custom = g_strdup_printf("openURL(%s,new-tab)",
+				uri_escaped);
+		} else if (place == PIDGIN_BROWSER_CURRENT) {
+			uri_custom = g_strdup_printf("openURL(%s)",
+				uri_escaped);
+		}
 
-		/*
-		 * Firefox 0.9 and higher require a "-a firefox" option when
-		 * using -remote commands.  This breaks older versions of
-		 * mozilla.  So we include this other handly little string
-		 * when calling firefox.  If the API for remote calls changes
-		 * any more in firefox then firefox should probably be split
-		 * apart from mozilla-firebird and mozilla... but this is good
-		 * for now.
-		 */
-		if (!strcmp(web_browser, "firefox"))
-			args = "-a firefox";
+		if (uri_custom != NULL) {
+			argv_remote = g_slist_append(argv_remote,
+				(gpointer)web_browser);
+
+			/* Firefox 0.9 and higher require a "-a firefox" option
+			 * when using -remote commands. This breaks older
+			 * versions of mozilla. So we include this other handly
+			 * little string when calling firefox. If the API for
+			 * remote calls changes any more in firefox then firefox
+			 * should probably be split apart from mozilla-firebird
+			 * and mozilla... but this is good for now.
+			 */
+			if (!strcmp(web_browser, "firefox")) {
+				argv_remote = g_slist_append(argv_remote, "-a");
+				argv_remote = g_slist_append(argv_remote,
+					"firefox");
+			}
+
+			argv_remote = g_slist_append(argv_remote, "-remote");
+			argv_remote = g_slist_append(argv_remote, uri_custom);
+		}
+	} else if (!strcmp(web_browser, "netscape")) {
+		argv = g_slist_append(argv, "netscape");
+		argv = g_slist_append(argv, (gpointer)uri);
+
+		if (place == PIDGIN_BROWSER_NEW_WINDOW) {
+			uri_custom = g_strdup_printf("openURL(%s,new-window)",
+				uri_escaped);
+		} else if (place == PIDGIN_BROWSER_CURRENT) {
+			uri_custom = g_strdup_printf("openURL(%s)",
+				uri_escaped);
+		}
+
+		if (uri_custom) {
+			argv_remote = g_slist_append(argv_remote, "netscape");
+			argv_remote = g_slist_append(argv_remote, "-remote");
+			argv_remote = g_slist_append(argv_remote, uri_custom);
+		}
+	} else if (!strcmp(web_browser, "opera")) {
+		argv = g_slist_append(argv, "opera");
 
 		if (place == PIDGIN_BROWSER_NEW_WINDOW)
-			remote_command = g_strdup_printf("%s %s -remote "
-											 "openURL(%s,new-window)",
-											 web_browser, args, escaped);
+			argv = g_slist_append(argv, "-newwindow");
 		else if (place == PIDGIN_BROWSER_NEW_TAB)
-			remote_command = g_strdup_printf("%s %s -remote "
-											 "openURL(%s,new-tab)",
-											 web_browser, args, escaped);
+			argv = g_slist_append(argv, "-newpage");
 		else if (place == PIDGIN_BROWSER_CURRENT)
-			remote_command = g_strdup_printf("%s %s -remote "
-											 "openURL(%s)",
-											 web_browser, args, escaped);



More information about the Commits mailing list