shithub: choc

Download patch

ref: eebddb1fff7d6b87ef7938881b2e5c9fdb702dad
parent: 12bac584e165493f91435ffacb2b4633c593346c
author: Simon Howard <fraggle@gmail.com>
date: Tue Apr 29 20:24:38 EDT 2014

system: Escape special characters for Zenity.

When invoking Zenity to display an error message, some characters can
have special meanings to the shell. Escape these properly so that the
error message is always shown correctly.

This fixes #355.

--- a/src/i_system.c
+++ b/src/i_system.c
@@ -262,6 +262,7 @@
     exit(0);
 }
 
+#if !defined(_WIN32) && !defined(__MACOSX__)
 #define ZENITY_BINARY "/usr/bin/zenity"
 
 // returns non-zero if zenity is available
@@ -271,11 +272,56 @@
     return system(ZENITY_BINARY " --help >/dev/null 2>&1") == 0;
 }
 
+// Escape special characters in the given string so that they can be
+// safely enclosed in shell quotes.
+
+static char *EscapeShellString(char *string)
+{
+    char *result;
+    char *r, *s;
+
+    // In the worst case, every character might be escaped.
+    result = malloc(strlen(string) * 2 + 3);
+    r = result;
+
+    // Enclosing quotes.
+    *r = '"';
+    ++r;
+
+    for (s = string; *s != '\0'; ++s)
+    {
+        // From the bash manual:
+        //
+        //  "Enclosing characters in double quotes preserves the literal
+        //   value of all characters within the quotes, with the exception
+        //   of $, `, \, and, when history expansion is enabled, !."
+        //
+        // Therefore, escape these characters by prefixing with a backslash.
+
+        if (strchr("$`\\!", *s) != NULL)
+        {
+            *r = '\\';
+            ++r;
+        }
+
+        *r = *s;
+        ++r;
+    }
+
+    // Enclosing quotes.
+    *r = '"';
+    ++r;
+    *r = '\0';
+
+    return result;
+}
+
 // Open a native error box with a message using zenity
 
 static int ZenityErrorBox(char *message)
 {
-    int *result;
+    int result;
+    char *escaped_message;
     char *errorboxpath;
     static size_t errorboxpath_size;
 
@@ -284,16 +330,23 @@
         return 0;
     }
 
-    errorboxpath_size = strlen(ZENITY_BINARY) + strlen(message) + 19;
+    escaped_message = EscapeShellString(message);
+
+    errorboxpath_size = strlen(ZENITY_BINARY) + strlen(escaped_message) + 19;
     errorboxpath = malloc(errorboxpath_size);
-    M_snprintf(errorboxpath, errorboxpath_size, "%s --error --text=\"%s\"", ZENITY_BINARY, message);
+    M_snprintf(errorboxpath, errorboxpath_size, "%s --error --text=%s",
+               ZENITY_BINARY, escaped_message);
 
     result = system(errorboxpath);
 
     free(errorboxpath);
+    free(escaped_message);
 
     return result;
 }
+
+#endif /* !defined(_WIN32) && !defined(__MACOSX__) */
+
 
 //
 // I_Error