Damjan Jovanovic : winemenubuilder: Escape freedesktop exec keys properly.

Alexandre Julliard julliard at winehq.org
Tue May 11 12:09:37 CDT 2010


Module: wine
Branch: master
Commit: 745747688d23d60afbb65d2df0b7d60cecbf0ee5
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=745747688d23d60afbb65d2df0b7d60cecbf0ee5

Author: Damjan Jovanovic <damjan.jov at gmail.com>
Date:   Sat May  8 23:20:32 2010 +0200

winemenubuilder: Escape freedesktop exec keys properly.

---

 programs/winemenubuilder/winemenubuilder.c |  168 +++++++++++++++++-----------
 1 files changed, 103 insertions(+), 65 deletions(-)

diff --git a/programs/winemenubuilder/winemenubuilder.c b/programs/winemenubuilder/winemenubuilder.c
index 6569c0d..0797ec8 100644
--- a/programs/winemenubuilder/winemenubuilder.c
+++ b/programs/winemenubuilder/winemenubuilder.c
@@ -792,6 +792,36 @@ static BOOL create_directories(char *directory)
     return ret;
 }
 
+static char* wchars_to_utf8_chars(LPCWSTR string)
+{
+    char *ret;
+    INT size = WideCharToMultiByte(CP_UTF8, 0, string, -1, NULL, 0, NULL, NULL);
+    ret = HeapAlloc(GetProcessHeap(), 0, size);
+    if (ret)
+        WideCharToMultiByte(CP_UTF8, 0, string, -1, ret, size, NULL, NULL);
+    return ret;
+}
+
+static char* wchars_to_unix_chars(LPCWSTR string)
+{
+    char *ret;
+    INT size = WideCharToMultiByte(CP_UNIXCP, 0, string, -1, NULL, 0, NULL, NULL);
+    ret = HeapAlloc(GetProcessHeap(), 0, size);
+    if (ret)
+        WideCharToMultiByte(CP_UNIXCP, 0, string, -1, ret, size, NULL, NULL);
+    return ret;
+}
+
+static WCHAR* utf8_chars_to_wchars(LPCSTR string)
+{
+    WCHAR *ret;
+    INT size = MultiByteToWideChar(CP_UTF8, 0, string, -1, NULL, 0);
+    ret = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
+    if (ret)
+        MultiByteToWideChar(CP_UTF8, 0, string, -1, ret, size);
+    return ret;
+}
+
 /* extract an icon from an exe or icon file; helper for IPersistFile_fnSave */
 static char *extract_icon( LPCWSTR path, int index, const char *destFilename, BOOL bWait )
 {
@@ -945,7 +975,7 @@ static BOOL write_desktop_entry(const char *unix_link, const char *location, con
 
     fprintf(file, "[Desktop Entry]\n");
     fprintf(file, "Name=%s\n", linkname);
-    fprintf(file, "Exec=env WINEPREFIX=\"%s\" wine \"%s\" %s\n",
+    fprintf(file, "Exec=env WINEPREFIX=\"%s\" wine %s %s\n",
             wine_get_config_dir(), path, args);
     fprintf(file, "Type=Application\n");
     fprintf(file, "StartupNotify=true\n");
@@ -1154,35 +1184,63 @@ end:
     return ret;
 }
 
-/* This escapes \ in filenames */
+/* This escapes reserved characters in .desktop files' Exec keys. */
 static LPSTR escape(LPCWSTR arg)
 {
-    LPSTR narg, x;
-    LPCWSTR esc;
-    int len = 0, n;
+    int i, j;
+    WCHAR *escaped_string;
+    char *utf8_string;
 
-    esc = arg;
-    while((esc = strchrW(esc, '\\')))
+    escaped_string = HeapAlloc(GetProcessHeap(), 0, (4 * strlenW(arg) + 1) * sizeof(WCHAR));
+    if (escaped_string == NULL) return NULL;
+    for (i = j = 0; arg[i]; i++)
     {
-        esc++;
-        len++;
+        switch (arg[i])
+        {
+        case '\\':
+            escaped_string[j++] = '\\';
+            escaped_string[j++] = '\\';
+            escaped_string[j++] = '\\';
+            escaped_string[j++] = '\\';
+            break;
+        case ' ':
+        case '\t':
+        case '\n':
+        case '"':
+        case '\'':
+        case '>':
+        case '<':
+        case '~':
+        case '|':
+        case '&':
+        case ';':
+        case '$':
+        case '*':
+        case '?':
+        case '#':
+        case '(':
+        case ')':
+        case '`':
+            escaped_string[j++] = '\\';
+            escaped_string[j++] = '\\';
+            /* fall through */
+        default:
+            escaped_string[j++] = arg[i];
+            break;
+        }
     }
+    escaped_string[j] = 0;
 
-    len += WideCharToMultiByte(CP_UNIXCP, 0, arg, -1, NULL, 0, NULL, NULL);
-    narg = HeapAlloc(GetProcessHeap(), 0, len);
-
-    x = narg;
-    while (*arg)
+    utf8_string = wchars_to_utf8_chars(escaped_string);
+    if (utf8_string == NULL)
     {
-        n = WideCharToMultiByte(CP_UNIXCP, 0, arg, 1, x, len, NULL, NULL);
-        x += n;
-        len -= n;
-        if (*arg == '\\')
-            *x++='\\'; /* escape \ */
-        arg++;
+        WINE_ERR("out of memory\n");
+        goto end;
     }
-    *x = 0;
-    return narg;
+
+end:
+    HeapFree(GetProcessHeap(), 0, escaped_string);
+    return utf8_string;
 }
 
 /* Return a heap-allocated copy of the unix format difference between the two
@@ -1424,36 +1482,6 @@ static WCHAR* assoc_query(ASSOCSTR assocStr, LPCWSTR name, LPCWSTR extra)
     return value;
 }
 
-static char* wchars_to_utf8_chars(LPCWSTR string)
-{
-    char *ret;
-    INT size = WideCharToMultiByte(CP_UTF8, 0, string, -1, NULL, 0, NULL, NULL);
-    ret = HeapAlloc(GetProcessHeap(), 0, size);
-    if (ret)
-        WideCharToMultiByte(CP_UTF8, 0, string, -1, ret, size, NULL, NULL);
-    return ret;
-}
-
-static char* wchars_to_unix_chars(LPCWSTR string)
-{
-    char *ret;
-    INT size = WideCharToMultiByte(CP_UNIXCP, 0, string, -1, NULL, 0, NULL, NULL);
-    ret = HeapAlloc(GetProcessHeap(), 0, size);
-    if (ret)
-        WideCharToMultiByte(CP_UNIXCP, 0, string, -1, ret, size, NULL, NULL);
-    return ret;
-}
-
-static WCHAR* utf8_chars_to_wchars(LPCSTR string)
-{
-    WCHAR *ret;
-    INT size = MultiByteToWideChar(CP_UTF8, 0, string, -1, NULL, 0);
-    ret = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
-    if (ret)
-        MultiByteToWideChar(CP_UTF8, 0, string, -1, ret, size);
-    return ret;
-}
-
 static char *slashes_to_minuses(const char *string)
 {
     int i;
@@ -2135,7 +2163,7 @@ static BOOL generate_associations(const char *xdg_data_home, const char *package
             progIdW = reg_get_valW(HKEY_CLASSES_ROOT, extensionW, NULL);
             if (progIdW)
             {
-                progIdA = wchars_to_utf8_chars(progIdW);
+                progIdA = escape(progIdW);
                 if (progIdA == NULL)
                 {
                     WINE_ERR("out of memory\n");
@@ -2187,7 +2215,7 @@ static BOOL InvokeShellLinker( IShellLinkW *sl, LPCWSTR link, BOOL bWait )
     static const WCHAR startW[] = {'\\','c','o','m','m','a','n','d',
                                    '\\','s','t','a','r','t','.','e','x','e',0};
     char *link_name = NULL, *icon_name = NULL, *work_dir = NULL;
-    char *escaped_path = NULL, *escaped_args = NULL, *escaped_description = NULL;
+    char *escaped_path = NULL, *escaped_args = NULL, *description = NULL;
     WCHAR szTmp[INFOTIPSIZE];
     WCHAR szDescription[INFOTIPSIZE], szPath[MAX_PATH], szWorkDir[MAX_PATH];
     WCHAR szArgs[INFOTIPSIZE], szIconPath[MAX_PATH];
@@ -2311,7 +2339,12 @@ static BOOL InvokeShellLinker( IShellLinkW *sl, LPCWSTR link, BOOL bWait )
     /* escape the path and parameters */
     escaped_path = escape(szPath);
     escaped_args = escape(szArgs);
-    escaped_description = escape(szDescription);
+    description = wchars_to_utf8_chars(szDescription);
+    if (escaped_path == NULL || escaped_args == NULL || description == NULL)
+    {
+        WINE_ERR("out of memory allocating/escaping parameters\n");
+        goto cleanup;
+    }
 
     /* building multiple menus concurrently has race conditions */
     hsem = CreateSemaphoreA( NULL, 1, 1, "winemenubuilder_semaphore");
@@ -2333,7 +2366,7 @@ static BOOL InvokeShellLinker( IShellLinkW *sl, LPCWSTR link, BOOL bWait )
         location = heap_printf("%s/%s.desktop", xdg_desktop_dir, lastEntry);
         if (location)
         {
-            r = !write_desktop_entry(NULL, location, lastEntry, escaped_path, escaped_args, escaped_description, work_dir, icon_name);
+            r = !write_desktop_entry(NULL, location, lastEntry, escaped_path, escaped_args, description, work_dir, icon_name);
             if (r == 0)
                 chmod(location, 0755);
             HeapFree(GetProcessHeap(), 0, location);
@@ -2341,21 +2374,21 @@ static BOOL InvokeShellLinker( IShellLinkW *sl, LPCWSTR link, BOOL bWait )
     }
     else
     {
-        char *arg = heap_printf("/Unix \"%s\"", unix_link);
-        if (arg)
+        WCHAR *unix_linkW = utf8_chars_to_wchars(unix_link);
+        if (unix_linkW)
         {
-            WCHAR *warg = utf8_chars_to_wchars(arg);
-            if (warg)
+            char *escaped_lnk = escape(unix_linkW);
+            if (escaped_lnk)
             {
-                char *menuarg = escape(warg);
+                char *menuarg = heap_printf("/Unix %s", escaped_lnk);
                 if (menuarg)
                 {
-                    r = !write_menu_entry(unix_link, link_name, "start", menuarg, escaped_description, work_dir, icon_name);
+                    r = !write_menu_entry(unix_link, link_name, "start", menuarg, description, work_dir, icon_name);
                     HeapFree(GetProcessHeap(), 0, menuarg);
                 }
-                HeapFree(GetProcessHeap(), 0, warg);
+                HeapFree(GetProcessHeap(), 0, escaped_lnk);
             }
-            HeapFree(GetProcessHeap(), 0, arg);
+            HeapFree(GetProcessHeap(), 0, unix_linkW);
         }
     }
 
@@ -2368,7 +2401,7 @@ cleanup:
     HeapFree( GetProcessHeap(), 0, link_name );
     HeapFree( GetProcessHeap(), 0, escaped_args );
     HeapFree( GetProcessHeap(), 0, escaped_path );
-    HeapFree( GetProcessHeap(), 0, escaped_description );
+    HeapFree( GetProcessHeap(), 0, description );
     HeapFree( GetProcessHeap(), 0, unix_link);
 
     if (r && !bWait)
@@ -2424,6 +2457,11 @@ static BOOL InvokeShellLinkerForURL( IUniformResourceLocatorW *url, LPCWSTR link
     }
 
     escaped_urlPath = escape(urlPath);
+    if (escaped_urlPath == NULL)
+    {
+        WINE_ERR("couldn't escape url, out of memory\n");
+        goto cleanup;
+    }
 
     hSem = CreateSemaphoreA( NULL, 1, 1, "winemenubuilder_semaphore");
     if( WAIT_OBJECT_0 != MsgWaitForMultipleObjects( 1, &hSem, FALSE, INFINITE, QS_ALLINPUT ) )




More information about the wine-cvs mailing list