diff --git a/thunar/thunar-chooser-dialog.c b/thunar/thunar-chooser-dialog.c index 1ce3f32..5e04bb8 100644 --- a/thunar/thunar-chooser-dialog.c +++ b/thunar/thunar-chooser-dialog.c @@ -38,6 +38,7 @@ #include #include #include +#include @@ -397,7 +398,9 @@ thunar_chooser_dialog_response (GtkDialog *widget, GError *error = NULL; gchar *path; gchar *name; - gchar *s; + gchar *s1; + gchar *s2; + gboolean prev_char_escaped = FALSE; GList list; /* no special processing for non-accept responses */ @@ -421,9 +424,22 @@ thunar_chooser_dialog_response (GtkDialog *widget, /* determine the path for the custom command */ path = g_strdup (exec); - s = strchr (path, ' '); - if (G_UNLIKELY (s != NULL)) - *s = '\0'; + prev_char_escaped = FALSE; + s1 = path; + s2 = path + strlen(path) + 1; + while (s1 < s2) + { + if (G_UNLIKELY (*s1 == '\\' && !prev_char_escaped)) + prev_char_escaped = TRUE; + else if (G_UNLIKELY (prev_char_escaped)) + prev_char_escaped = FALSE; + else if (G_UNLIKELY (*s1 == ' ')) + break; + s1++; + } + + if (s1 < s2) + *s1 = '\0'; /* determine the name from the path of the custom command */ name = g_path_get_basename (path); @@ -750,6 +766,7 @@ thunar_chooser_dialog_browse_clicked (GtkWidget *button, GtkFileFilter *filter; GtkWidget *chooser; gchar *filename; + gchar *escaped_filename; gchar *s; chooser = gtk_file_chooser_dialog_new (_("Select an Application"), @@ -847,8 +864,10 @@ thunar_chooser_dialog_browse_clicked (GtkWidget *button, if (gtk_dialog_run (GTK_DIALOG (chooser)) == GTK_RESPONSE_ACCEPT) { filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (chooser)); - gtk_entry_set_text (GTK_ENTRY (dialog->custom_entry), filename); + escaped_filename = thunar_util_str_shell_escape (filename); + gtk_entry_set_text (GTK_ENTRY (dialog->custom_entry), escaped_filename); g_free (filename); + g_free (escaped_filename); } gtk_widget_destroy (chooser); diff --git a/thunar/thunar-util.c b/thunar/thunar-util.c index 22ffcce..339e3b3 100644 --- a/thunar/thunar-util.c +++ b/thunar/thunar-util.c @@ -62,6 +62,10 @@ +static const char ESCAPE_SHELL_CHARS[] = " !#$%()&{}[]`?|<>;*\\\"'"; + + + /** * thunar_util_strrchr_offset: * @str: haystack @@ -174,6 +178,84 @@ thunar_util_str_get_extension (const gchar *filename) +/** + * thunar_util_str_escape: + * @src: string to escape. + * @src_len: amount of chars to use from src; set to -1 to use the full string. + * @escaped_chars: chars to escape. + * @escape_non_printable: yup, that. + * + * Escapes up to @src_len chars from @src. Discard the rest. + * Adapted from the Midnight Commander project (https://www.midnight-commander.org/). + * + * Return value: pointer for gchar or NULL. +**/ +gchar * +thunar_util_str_escape (const gchar *src, gsize src_len, const char *escaped_chars, + gboolean escape_non_printable) +{ + GString *ret; + gsize curr_index; + /* do NOT break allocation semantics */ + if (src == NULL) + return NULL; + + if (*src == '\0') + return strdup (""); + + ret = g_string_new (""); + + if (src_len == (gsize) (-1)) + src_len = strlen (src); + + for (curr_index = 0; curr_index < src_len; curr_index++) + { + if (escape_non_printable) + { + switch (src[curr_index]) + { + case '\n': + g_string_append (ret, "\\n"); + continue; + case '\t': + g_string_append (ret, "\\t"); + continue; + case '\b': + g_string_append (ret, "\\b"); + continue; + case '\0': + g_string_append (ret, "\\0"); + continue; + } + } + + if (strchr (escaped_chars, (int) src[curr_index])) + g_string_append_c (ret, '\\'); + + g_string_append_c (ret, src[curr_index]); + } + return g_string_free (ret, FALSE); +} + + + +/** + * thunar_util_str_shell_escape: + * @src: string to escape. + * + * Wrapper. Escape full string @src for shell. + * Adapted from the Midnight Commander project (https://www.midnight-commander.org/). + * + * Return value: pointer for gchar or NULL. +**/ +gchar * +thunar_util_str_shell_escape (const gchar *src) +{ + return thunar_util_str_escape (src, -1, ESCAPE_SHELL_CHARS, FALSE); +} + + + void thunar_util_load_bookmarks (GFile *bookmarks_file, ThunarBookmarksFunc foreach_func, diff --git a/thunar/thunar-util.h b/thunar/thunar-util.h index b80f070..1e45121 100644 --- a/thunar/thunar-util.h +++ b/thunar/thunar-util.h @@ -33,6 +33,13 @@ typedef void (*ThunarBookmarksFunc) (GFile *file, gchar *thunar_util_str_get_extension (const gchar *name) G_GNUC_WARN_UNUSED_RESULT; +gchar *thunar_util_str_escape (const gchar *src, + gsize src_len, + const char *escaped_chars, + gboolean escape_non_printable) G_GNUC_WARN_UNUSED_RESULT; + +gchar *thunar_util_str_shell_escape (const gchar *src) G_GNUC_WARN_UNUSED_RESULT; + void thunar_util_load_bookmarks (GFile *bookmarks_file, ThunarBookmarksFunc foreach_func, gpointer user_data);