--- a/pidgin/gtknotify.c Sun Apr 14 13:01:27 2013 -0700
+++ b/pidgin/gtknotify.c Sat Jun 22 19:08:59 2013 +0200
@@ -1192,51 +1192,85 @@
-uri_command(const char *command, gboolean sync)
+uri_command(GSList *arg_list, gboolean sync)
- 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", + _("The browser command \"%s\" is invalid."), + program ? program : "(null)"); purple_notify_error(NULL, NULL, _("Unable to open URL"), tmp);
- 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);
- 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);
+ argc = g_slist_length(arg_list); + argv = g_new(gchar*, argc + 1); + for (it = arg_list; it; it = g_slist_next(it)) { + if (purple_debug_is_verbose()) { + purple_debug_misc("gtknotify", "argv[%d] = \"%s\"\n", + 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) && + 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)"); + purple_notify_error(NULL, NULL, _("Unable to open URL"), tmp); + if (g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH | + G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL, NULL, + purple_debug_warning("gtknotify", "Error launching \"%s\": %s\n", + program, error ? error->message : "(null)"); @@ -1244,183 +1278,208 @@
pidgin_notify_uri(const char *uri)
- char *escaped = g_shell_quote(uri);
- char *remote_command = NULL;
+ 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 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");
- command = g_strdup_printf("gnome-open %s", escaped);
+ argv = g_slist_append(argv, "gnome-open"); - command = g_strdup_printf("xdg-open %s", escaped);
+ argv = g_slist_append(argv, "xdg-open");
- 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);
- 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
- 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"))
+ 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)", + } else if (place == PIDGIN_BROWSER_NEW_TAB) { + uri_custom = g_strdup_printf("openURL(%s,new-tab)", + } else if (place == PIDGIN_BROWSER_CURRENT) { + uri_custom = g_strdup_printf("openURL(%s)", + 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
- if (!strcmp(web_browser, "firefox"))
+ /* 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, - if (place == PIDGIN_BROWSER_NEW_WINDOW)
- remote_command = g_strdup_printf("%s %s -remote "
- "openURL(%s,new-window)",
- web_browser, args, escaped);
- else if (place == PIDGIN_BROWSER_NEW_TAB)
- remote_command = g_strdup_printf("%s %s -remote "
- web_browser, args, escaped);
- else if (place == PIDGIN_BROWSER_CURRENT)
- remote_command = g_strdup_printf("%s %s -remote "
- web_browser, args, escaped);
- else if (!strcmp(web_browser, "netscape"))
- command = g_strdup_printf("netscape %s", escaped);
+ 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)", + } else if (place == PIDGIN_BROWSER_CURRENT) { + uri_custom = g_strdup_printf("openURL(%s)", + 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("netscape -remote "
- "openURL(%s,new-window)",
+ argv = g_slist_append(argv, "-newwindow"); + else if (place == PIDGIN_BROWSER_NEW_TAB) + argv = g_slist_append(argv, "-newpage"); else if (place == PIDGIN_BROWSER_CURRENT)
- remote_command = g_strdup_printf("netscape -remote "
- "openURL(%s)", escaped);
- else if (!strcmp(web_browser, "opera"))
- if (place == PIDGIN_BROWSER_NEW_WINDOW)
- command = g_strdup_printf("opera -newwindow %s", escaped);
- else if (place == PIDGIN_BROWSER_NEW_TAB)
- command = g_strdup_printf("opera -newpage %s", escaped);
- else if (place == PIDGIN_BROWSER_CURRENT)
- remote_command = g_strdup_printf("opera -remote "
- "openURL(%s)", escaped);
- command = g_strdup_printf("opera %s", escaped);
- command = g_strdup_printf("opera %s", escaped);
+ argv = g_slist_append(argv, "-activetab"); + /* `opera -remote "openURL(%s)"` command causes Pidgin's hang, + * if there is no Opera instance running.
- else if (!strcmp(web_browser, "google-chrome"))
- /* Google Chrome doesn't have command-line arguments that control the
- * opening of links from external calls. This is controlled solely from
- * a preference within Google Chrome. */
- command = g_strdup_printf("google-chrome %s", escaped);
- else if (!strcmp(web_browser, "chrome"))
+ argv = g_slist_append(argv, (gpointer)uri); + } else if (!strcmp(web_browser, "google-chrome")) { + /* Google Chrome doesn't have command-line arguments that + * control the opening of links from external calls. This is + * controlled solely from a preference within Google Chrome. + argv = g_slist_append(argv, "google-chrome"); + argv = g_slist_append(argv, (gpointer)uri); + } else if (!strcmp(web_browser, "chrome")) { + /* Chromium doesn't have command-line arguments that control + * the opening of links from external calls. This is controlled + * solely from a preference within Chromium. + argv = g_slist_append(argv, "chrome"); + argv = g_slist_append(argv, (gpointer)uri); + } else if (!strcmp(web_browser, "chromium-browser")) { /* Chromium doesn't have command-line arguments that control the
- * opening of links from external calls. This is controlled solely from
- * a preference within Chromium. */
- command = g_strdup_printf("chrome %s", escaped);
- else if (!strcmp(web_browser, "chromium-browser"))
- /* Chromium doesn't have command-line arguments that control the
- * opening of links from external calls. This is controlled solely from
- * a preference within Chromium. */
- command = g_strdup_printf("chromium-browser %s", escaped);
- else if (!strcmp(web_browser, "custom"))
- const char *web_command;
+ * opening of links from external calls. This is controlled + * solely from a preference within Chromium. + argv = g_slist_append(argv, "chromium-browser"); + argv = g_slist_append(argv, (gpointer)uri); + } else if (!strcmp(web_browser, "custom")) { + const char *usercmd_command; + gboolean uri_added = FALSE; - web_command = purple_prefs_get_string(PIDGIN_PREFS_ROOT "/browsers/manual_command");
+ usercmd_command = purple_prefs_get_string(PIDGIN_PREFS_ROOT + "/browsers/manual_command"); - if (web_command == NULL || *web_command == '\0')
+ if (usercmd_command == NULL || *usercmd_command == '\0') { purple_notify_error(NULL, NULL, _("Unable to open URL"),
- _("The 'Manual' browser command has been "
- "chosen, but no command has been set."));
+ _("The 'Manual' browser command has been " + "chosen, but no command has been set.")); - if (strstr(web_command, "%s"))
- command = purple_strreplace(web_command, "%s", escaped);
+ if (!g_shell_parse_argv(usercmd_command, &usercmd_argc, + &usercmd_argv, &error))
- * There is no "%s" in the browser command. Assume the user
- * wanted the URL tacked on to the end of the command.
- command = g_strdup_printf("%s %s", web_command, escaped);
+ purple_notify_error(NULL, NULL, _("Unable to open URL: " + "the 'Manual' browser command seems invalid."), + error ? error->message : NULL); + for (i = 0; i < usercmd_argc; i++) { + gchar *cmd_part = usercmd_argv[i]; + if (uri_added || strstr(cmd_part, "%s") == NULL) { + argv = g_slist_append(argv, cmd_part); + uri_custom = purple_strreplace(cmd_part, "%s", + argv = g_slist_append(argv, uri_custom); + /* There is no "%s" in the browser command. Assume the user + * wanted the URL tacked on to the end of the command. + argv = g_slist_append(argv, uri_escaped);
- if (remote_command != NULL)
+ if (argv_remote != NULL) { /* try the remote command first */
- if (uri_command(remote_command, TRUE) != 0)
- uri_command(command, FALSE);
+ if (!uri_command(argv_remote, TRUE)) + uri_command(argv, FALSE); + uri_command(argv, FALSE); - g_free(remote_command);
- uri_command(command, FALSE);
+ if (usercmd_argv != NULL) + g_strfreev(usercmd_argv); + g_slist_free(argv_remote); winpidgin_notify_uri(uri);