Rework sokoke_spawn_command internals
Caller decides if the command and the argument are quoted, otherwise quoting only affects %s. The actual quoting is split to allow use in test cases. The Hildon version was dropped. The GAppInfo version was dropped. A test case with a cuple examples was added.
This commit is contained in:
parent
262ded5222
commit
aa1ffbf1d0
5 changed files with 160 additions and 117 deletions
|
@ -491,7 +491,7 @@ addons_open_in_editor_clicked_cb (GtkWidget* toolitem,
|
||||||
|
|
||||||
g_object_get (settings, "text-editor", &text_editor, NULL);
|
g_object_get (settings, "text-editor", &text_editor, NULL);
|
||||||
if (text_editor && *text_editor)
|
if (text_editor && *text_editor)
|
||||||
sokoke_spawn_program (text_editor, element->fullpath);
|
sokoke_spawn_program (text_editor, TRUE, element->fullpath, TRUE);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
gchar* element_uri = g_filename_to_uri (element->fullpath, NULL, NULL);
|
gchar* element_uri = g_filename_to_uri (element->fullpath, NULL, NULL);
|
||||||
|
|
|
@ -2495,9 +2495,9 @@ midori_browser_subscribe_to_news_feed (MidoriBrowser* browser,
|
||||||
/* Special-case Liferea because a helper script may be required */
|
/* Special-case Liferea because a helper script may be required */
|
||||||
if (g_str_equal (browser->news_aggregator, "liferea")
|
if (g_str_equal (browser->news_aggregator, "liferea")
|
||||||
&& g_find_program_in_path ("liferea-add-feed"))
|
&& g_find_program_in_path ("liferea-add-feed"))
|
||||||
sokoke_spawn_program ("liferea-add-feed", feed);
|
sokoke_spawn_program ("liferea-add-feed", FALSE, feed, TRUE);
|
||||||
else
|
else
|
||||||
sokoke_spawn_program (browser->news_aggregator, feed);
|
sokoke_spawn_program (browser->news_aggregator, TRUE, feed, TRUE);
|
||||||
g_free (feed);
|
g_free (feed);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -3483,7 +3483,7 @@ _action_source_view_activate (GtkAction* action,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sokoke_spawn_program (text_editor, filename);
|
sokoke_spawn_program (text_editor, TRUE, filename, TRUE);
|
||||||
g_free (filename);
|
g_free (filename);
|
||||||
}
|
}
|
||||||
g_free (text_editor);
|
g_free (text_editor);
|
||||||
|
|
175
midori/sokoke.c
175
midori/sokoke.c
|
@ -228,7 +228,7 @@ sokoke_open_with_response_cb (GtkWidget* dialog,
|
||||||
{
|
{
|
||||||
const gchar* command = gtk_entry_get_text (entry);
|
const gchar* command = gtk_entry_get_text (entry);
|
||||||
const gchar* uri = g_object_get_data (G_OBJECT (dialog), "uri");
|
const gchar* uri = g_object_get_data (G_OBJECT (dialog), "uri");
|
||||||
sokoke_spawn_program (command, uri);
|
sokoke_spawn_program (command, FALSE, uri, TRUE);
|
||||||
}
|
}
|
||||||
gtk_widget_destroy (dialog);
|
gtk_widget_destroy (dialog);
|
||||||
}
|
}
|
||||||
|
@ -379,90 +379,87 @@ sokoke_show_uri (GdkScreen* screen,
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sokoke_prepare_command:
|
||||||
|
* @command: the command, properly quoted
|
||||||
|
* @argument: any arguments, properly quoted
|
||||||
|
* @quote_command: if %TRUE, @command will be quoted
|
||||||
|
* @quote_argument: if %TRUE, @argument will be quoted, ie. a URI or filename
|
||||||
|
*
|
||||||
|
* If @command contains %s, @argument will be quoted and inserted into
|
||||||
|
* @command, which is left unquoted regardless of @quote_command.
|
||||||
|
*
|
||||||
|
* Return value: the command prepared for spawning
|
||||||
|
**/
|
||||||
|
gchar*
|
||||||
|
sokoke_prepare_command (const gchar* command,
|
||||||
|
gboolean quote_command,
|
||||||
|
const gchar* argument,
|
||||||
|
gboolean quote_argument)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (command != NULL, FALSE);
|
||||||
|
g_return_val_if_fail (argument != NULL, FALSE);
|
||||||
|
|
||||||
|
g_print ("Preparing command: %s %d %s %d\n",
|
||||||
|
command, quote_command, argument, quote_argument);
|
||||||
|
|
||||||
|
{
|
||||||
|
gchar* uri_format;
|
||||||
|
gchar* real_command;
|
||||||
|
gchar* command_ready;
|
||||||
|
|
||||||
|
/* .desktop files accept %u as URI, we cheap and treat it like %s */
|
||||||
|
if ((uri_format = strstr (command, "%u")))
|
||||||
|
uri_format[1] = 's';
|
||||||
|
|
||||||
|
real_command = quote_command ? g_shell_quote (command) : g_strdup (command);
|
||||||
|
|
||||||
|
if (strstr (command, "%s"))
|
||||||
|
{
|
||||||
|
gchar* argument_quoted = g_shell_quote (argument);
|
||||||
|
command_ready = sokoke_replace_variables (real_command, "%s", argument_quoted);
|
||||||
|
g_free (argument_quoted);
|
||||||
|
}
|
||||||
|
else if (quote_argument)
|
||||||
|
{
|
||||||
|
gchar* argument_quoted = g_shell_quote (argument);
|
||||||
|
command_ready = g_strconcat (real_command, " ", argument_quoted, NULL);
|
||||||
|
g_free (argument_quoted);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
command_ready = g_strconcat (real_command, " ", argument, NULL);
|
||||||
|
g_free (real_command);
|
||||||
|
return command_ready;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sokoke_spawn_program:
|
||||||
|
* @command: the command, properly quoted
|
||||||
|
* @argument: any arguments, properly quoted
|
||||||
|
* @quote_command: if %TRUE, @command will be quoted
|
||||||
|
* @quote_argument: if %TRUE, @argument will be quoted, ie. a URI or filename
|
||||||
|
*
|
||||||
|
* If @command contains %s, @argument will be quoted and inserted into
|
||||||
|
* @command, which is left unquoted regardless of @quote_command.
|
||||||
|
*
|
||||||
|
* Return value: %TRUE on success, %FALSE if an error occurred
|
||||||
|
**/
|
||||||
gboolean
|
gboolean
|
||||||
sokoke_spawn_program (const gchar* command,
|
sokoke_spawn_program (const gchar* command,
|
||||||
const gchar* argument)
|
gboolean quote_command,
|
||||||
|
const gchar* argument,
|
||||||
|
gboolean quote_argument)
|
||||||
{
|
{
|
||||||
GError* error;
|
GError* error;
|
||||||
|
gchar* command_ready;
|
||||||
|
gchar** argv;
|
||||||
|
|
||||||
g_return_val_if_fail (command != NULL, FALSE);
|
g_return_val_if_fail (command != NULL, FALSE);
|
||||||
g_return_val_if_fail (argument != NULL, FALSE);
|
g_return_val_if_fail (argument != NULL, FALSE);
|
||||||
|
|
||||||
if (!g_strstr_len (argument, 8, "://")
|
command_ready = sokoke_prepare_command (command, quote_command, argument, quote_argument);
|
||||||
&& !g_str_has_prefix (argument, "about:"))
|
g_print ("Launching command: %s\n", command_ready);
|
||||||
{
|
|
||||||
gboolean success;
|
|
||||||
|
|
||||||
#if HAVE_HILDON
|
|
||||||
osso_context_t* osso;
|
|
||||||
DBusConnection* dbus;
|
|
||||||
|
|
||||||
osso = osso_initialize (PACKAGE_NAME, PACKAGE_VERSION, FALSE, NULL);
|
|
||||||
if (!osso)
|
|
||||||
{
|
|
||||||
sokoke_message_dialog (GTK_MESSAGE_ERROR,
|
|
||||||
_("Could not run external program."),
|
|
||||||
"Failed to initialize libosso", FALSE);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
dbus = (DBusConnection *) osso_get_dbus_connection (osso);
|
|
||||||
if (!dbus)
|
|
||||||
{
|
|
||||||
osso_deinitialize (osso);
|
|
||||||
sokoke_message_dialog (GTK_MESSAGE_ERROR,
|
|
||||||
_("Could not run external program."),
|
|
||||||
"Failed to get dbus connection from osso context", FALSE);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
error = NULL;
|
|
||||||
/* FIXME: This is not correct, find a proper way to do this */
|
|
||||||
success = (osso_application_top (osso, command, argument) == OSSO_OK);
|
|
||||||
osso_deinitialize (osso);
|
|
||||||
#else
|
|
||||||
GAppInfo* info;
|
|
||||||
GFile* file;
|
|
||||||
GList* files;
|
|
||||||
|
|
||||||
info = g_app_info_create_from_commandline (command,
|
|
||||||
NULL, G_APP_INFO_CREATE_NONE, NULL);
|
|
||||||
file = g_file_new_for_commandline_arg (argument);
|
|
||||||
files = g_list_append (NULL, file);
|
|
||||||
|
|
||||||
error = NULL;
|
|
||||||
success = g_app_info_launch (info, files, NULL, &error);
|
|
||||||
g_object_unref (file);
|
|
||||||
g_list_free (files);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!success)
|
|
||||||
{
|
|
||||||
sokoke_message_dialog (GTK_MESSAGE_ERROR,
|
|
||||||
_("Could not run external program."),
|
|
||||||
error ? error->message : "", FALSE);
|
|
||||||
if (error)
|
|
||||||
g_error_free (error);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* FIXME: Implement Hildon specific version */
|
|
||||||
gchar* uri_format;
|
|
||||||
gchar* argument_quoted;
|
|
||||||
gchar* command_ready;
|
|
||||||
gchar** argv;
|
|
||||||
|
|
||||||
if ((uri_format = strstr (command, "%u")))
|
|
||||||
uri_format[1] = 's';
|
|
||||||
|
|
||||||
argument_quoted = g_shell_quote (argument);
|
|
||||||
if (strstr (command, "%s"))
|
|
||||||
command_ready = g_strdup_printf (command, argument_quoted);
|
|
||||||
else
|
|
||||||
command_ready = g_strconcat (command, " ", argument_quoted, NULL);
|
|
||||||
g_free (argument_quoted);
|
|
||||||
|
|
||||||
error = NULL;
|
error = NULL;
|
||||||
if (!g_shell_parse_argv (command_ready, NULL, &argv, &error))
|
if (!g_shell_parse_argv (command_ready, NULL, &argv, &error))
|
||||||
|
@ -488,8 +485,6 @@ sokoke_spawn_program (const gchar* command,
|
||||||
}
|
}
|
||||||
|
|
||||||
g_strfreev (argv);
|
g_strfreev (argv);
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -498,23 +493,19 @@ sokoke_spawn_app (const gchar* uri,
|
||||||
gboolean private)
|
gboolean private)
|
||||||
{
|
{
|
||||||
const gchar* executable = midori_app_get_command_line ()[0];
|
const gchar* executable = midori_app_get_command_line ()[0];
|
||||||
/* "midori"
|
gchar* uri_quoted = g_shell_quote (uri);
|
||||||
"/usr/bin/midori"
|
gchar* argument;
|
||||||
"c:/Program Files/Midori/bin/midori.exe" */
|
|
||||||
gchar* quoted = g_shell_quote (executable);
|
|
||||||
gchar* command;
|
|
||||||
if (private)
|
if (private)
|
||||||
{
|
{
|
||||||
gchar* quoted_config = g_shell_quote (sokoke_set_config_dir (NULL));
|
gchar* config_quoted = g_shell_quote (sokoke_set_config_dir (NULL));
|
||||||
command = g_strconcat (quoted, " -c ", quoted_config,
|
argument = g_strconcat ("-c ", config_quoted,
|
||||||
" -p", NULL);
|
" -p ", uri_quoted, NULL);
|
||||||
g_free (quoted_config);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
command = g_strconcat (quoted, " -a", NULL);
|
argument = g_strconcat ("-a ", uri_quoted, NULL);
|
||||||
g_free (quoted);
|
g_free (uri_quoted);
|
||||||
sokoke_spawn_program (command, uri);
|
sokoke_spawn_program (executable, TRUE, argument, FALSE);
|
||||||
g_free (command);
|
g_free (argument);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
@ -42,9 +42,17 @@ sokoke_show_uri (GdkScreen* screen,
|
||||||
guint32 timestamp,
|
guint32 timestamp,
|
||||||
GError** error);
|
GError** error);
|
||||||
|
|
||||||
|
gchar*
|
||||||
|
sokoke_prepare_command (const gchar* command,
|
||||||
|
gboolean quote_command,
|
||||||
|
const gchar* argument,
|
||||||
|
gboolean quote_argument);
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
sokoke_spawn_program (const gchar* command,
|
sokoke_spawn_program (const gchar* command,
|
||||||
const gchar* argument);
|
gboolean quote_command,
|
||||||
|
const gchar* argument,
|
||||||
|
gboolean quote_argument);
|
||||||
|
|
||||||
void
|
void
|
||||||
sokoke_spawn_app (const gchar* uri,
|
sokoke_spawn_app (const gchar* uri,
|
||||||
|
|
|
@ -287,6 +287,49 @@ magic_uri_prefetch (void)
|
||||||
g_assert (!sokoke_prefetch_uri (NULL, "javascript: alert()", NULL, NULL));
|
g_assert (!sokoke_prefetch_uri (NULL, "javascript: alert()", NULL, NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
magic_uri_commands (void)
|
||||||
|
{
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
const gchar* command;
|
||||||
|
gboolean quote;
|
||||||
|
const gchar* expected;
|
||||||
|
} CommandItem;
|
||||||
|
|
||||||
|
static const CommandItem commands[] = {
|
||||||
|
{ "midori", TRUE, NULL },
|
||||||
|
{ "/usr/bin/midori", TRUE, NULL },
|
||||||
|
{ "C:/Program Files/Midori/bin/midori.exe", TRUE, NULL },
|
||||||
|
{ "C:/Programme/Midori/bin/midori.exe", TRUE, NULL },
|
||||||
|
};
|
||||||
|
static const CommandItem arguments[] = {
|
||||||
|
{ "-a 'http://lunduke.com/?p=3606'", FALSE, NULL },
|
||||||
|
{ "about:private", FALSE, NULL },
|
||||||
|
};
|
||||||
|
guint i, j;
|
||||||
|
|
||||||
|
for (i = 0; i < G_N_ELEMENTS (commands); i++)
|
||||||
|
for (j = 0; j < G_N_ELEMENTS (arguments); j++)
|
||||||
|
{
|
||||||
|
gchar* input = g_strconcat (commands[i].command, " ", arguments[j].command, NULL);
|
||||||
|
gchar* ce = commands[i].expected ? commands[i].expected
|
||||||
|
: g_strconcat ("'", commands[i].command, "'", NULL);
|
||||||
|
gchar* ae = arguments[j].expected ? arguments[j].expected
|
||||||
|
: (arguments[j].quote ? g_strconcat ("'", arguments[j].command, "'", NULL)
|
||||||
|
: g_strdup (arguments[j].command));
|
||||||
|
gchar* expected = g_strconcat (ce, " ", ae, NULL);
|
||||||
|
gchar* result = sokoke_prepare_command (commands[i].command,
|
||||||
|
commands[i].quote, arguments[j].command, arguments[j].quote);
|
||||||
|
katze_assert_str_equal (input, result, expected);
|
||||||
|
g_free (input);
|
||||||
|
g_free (ce);
|
||||||
|
g_free (ae);
|
||||||
|
g_free (expected);
|
||||||
|
g_free (result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc,
|
main (int argc,
|
||||||
char** argv)
|
char** argv)
|
||||||
|
@ -303,6 +346,7 @@ main (int argc,
|
||||||
g_test_add_func ("/magic-uri/fingerprint", magic_uri_fingerprint);
|
g_test_add_func ("/magic-uri/fingerprint", magic_uri_fingerprint);
|
||||||
g_test_add_func ("/magic-uri/format", magic_uri_format);
|
g_test_add_func ("/magic-uri/format", magic_uri_format);
|
||||||
g_test_add_func ("/magic-uri/prefetch", magic_uri_prefetch);
|
g_test_add_func ("/magic-uri/prefetch", magic_uri_prefetch);
|
||||||
|
g_test_add_func ("/magic-uri/commands", magic_uri_commands);
|
||||||
|
|
||||||
return g_test_run ();
|
return g_test_run ();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue