diff --git a/util/wmmenugen.h b/util/wmmenugen.h index 6ccefc93..1250954a 100644 --- a/util/wmmenugen.h +++ b/util/wmmenugen.h @@ -30,6 +30,7 @@ #define F_RESTART_SELF (1 << 1) #define F_RESTART_OTHER (1 << 2) #define F_QUIT (1 << 3) +#define F_FREE_CMD_LINE (1 << 4) /* a representation of a Window Maker menu entry. all menus are diff --git a/util/wmmenugen_parse_xdg.c b/util/wmmenugen_parse_xdg.c index 02c7b007..0d329ddf 100644 --- a/util/wmmenugen_parse_xdg.c +++ b/util/wmmenugen_parse_xdg.c @@ -76,6 +76,7 @@ static int getBooleanValue(const char *line); static void getMenuHierarchyFor(char **xdgmenuspec); static int compare_matchlevel(int *current_level, const char *found_locale); static Bool xdg_to_wm(XDGMenuEntry *xdg, WMMenuEntry *wmentry); +static char *parse_xdg_exec(char *exec); static void init_xdg_storage(XDGMenuEntry *xdg); static void init_wm_storage(WMMenuEntry *wm); @@ -221,17 +222,78 @@ static Bool xdg_to_wm(XDGMenuEntry *xdg, WMMenuEntry *wm) *p = '\0'; } - if (xdg->Exec) - wm->CmdLine = xdg->Exec; - else /* xdg->TryExec */ + if (xdg->Exec) { + wm->CmdLine = parse_xdg_exec(xdg->Exec); + if (!wm->CmdLine) + return False; + } else /* xdg->TryExec */ wm->CmdLine = xdg->TryExec; wm->SubMenu = xdg->Category; wm->Flags = xdg->Flags; + if (wm->CmdLine != xdg->TryExec) + wm->Flags |= F_FREE_CMD_LINE; return True; } +static char *parse_xdg_exec(char *exec) +{ + char *cmd_line, *dst, *src; + Bool quoted = False; + + cmd_line = wstrdup(exec); + + for (dst = src = cmd_line; *src; src++) { + if (quoted) { + if (*src == '"') + quoted = False; + else if (*src == '\\') + switch (*++src) { + case '"': + case '`': + case '$': + case '\\': + *dst++ = *src; + break; + default: + goto err_out; + } + else + *dst++ = *src; + } else { + if (*src == '"') + quoted = True; + else if (*src == '%') { + src++; + if (*src == '%') + *dst++ = *src; + else if (strchr ("fFuUdDnNickvm", *src)) + *dst++ = *src; + else + /* + * Invalid field-code. + */ + goto err_out; + } else + *dst++ = *src; + } + } + + if (quoted) + goto err_out; + + do + *dst = '\0'; + while (dst > cmd_line && isspace(*--dst)); + + return cmd_line; + +err_out: + wfree(cmd_line); + return NULL; +} + /* (re-)initialize a XDGMenuEntry storage */ static void init_xdg_storage(XDGMenuEntry *xdg) @@ -261,6 +323,9 @@ static void init_xdg_storage(XDGMenuEntry *xdg) */ static void init_wm_storage(WMMenuEntry *wm) { + if (wm->Flags & F_FREE_CMD_LINE) + wfree(wm->CmdLine); + wm->Name = NULL; wm->CmdLine = NULL; wm->Flags = 0;