[1/2] winemenubuilder: escape freedesktop exec keys properly
Damjan Jovanovic
damjan.jov at gmail.com
Sat May 8 16:20:32 CDT 2010
Changelog:
* winemenubuilder: escape freedesktop exec keys properly
Damjan Jovanovic
-------------- next part --------------
diff --git a/programs/winemenubuilder/winemenubuilder.c b/programs/winemenubuilder/winemenubuilder.c
index 6569c0d..49e0c7d 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,95 @@ 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 = NULL;
+ char *utf8_string = NULL;
+ int len = 0;
+
+ for (i = 0; arg[i]; i++)
+ {
+ if (arg[i] == '\\')
+ len += 4;
+ else if (arg[i] == ' ' ||
+ arg[i] == '\t' ||
+ arg[i] == '\n' ||
+ arg[i] == '"' ||
+ arg[i] == '\'' ||
+ arg[i] == '>' ||
+ arg[i] == '<' ||
+ arg[i] == '~' ||
+ arg[i] == '|' ||
+ arg[i] == '&' ||
+ arg[i] == ';' ||
+ arg[i] == '$' ||
+ arg[i] == '*' ||
+ arg[i] == '?' ||
+ arg[i] == '#' ||
+ arg[i] == '(' ||
+ arg[i] == ')' ||
+ arg[i] == '`')
+ len += 3;
+ else
+ len += 1;
+ }
- esc = arg;
- while((esc = strchrW(esc, '\\')))
+ escaped_string = HeapAlloc(GetProcessHeap(), 0, (len+1)*sizeof(WCHAR));
+ if (escaped_string == NULL)
{
- esc++;
- len++;
+ WINE_ERR("out of memory\n");
+ goto end;
}
+ j = 0;
+ for (i = 0; arg[i]; i++)
+ {
+ if (arg[i] == '\\')
+ {
+ escaped_string[j++] = '\\';
+ escaped_string[j++] = '\\';
+ escaped_string[j++] = '\\';
+ escaped_string[j++] = '\\';
+ }
+ else if (arg[i] == ' ' ||
+ arg[i] == '\t' ||
+ arg[i] == '\n' ||
+ arg[i] == '"' ||
+ arg[i] == '\'' ||
+ arg[i] == '>' ||
+ arg[i] == '<' ||
+ arg[i] == '~' ||
+ arg[i] == '|' ||
+ arg[i] == '&' ||
+ arg[i] == ';' ||
+ arg[i] == '$' ||
+ arg[i] == '*' ||
+ arg[i] == '?' ||
+ arg[i] == '#' ||
+ arg[i] == '(' ||
+ arg[i] == ')' ||
+ arg[i] == '`')
+ {
+ escaped_string[j++] = '\\';
+ escaped_string[j++] = '\\';
+ escaped_string[j++] = arg[i];
+ }
+ else
+ escaped_string[j++] = arg[i];
+ }
+ 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 +1514,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 +2195,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 +2247,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 +2371,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 +2398,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 +2406,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 +2433,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 +2489,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-patches
mailing list