This patch changes pine's URL passing for external programs to not use _URL_ in the argument string but use the environment variable "URL" for that. Certainly SUSE-specific now. --- pine4.64/pine/mailview.c +++ pine4.64/pine/mailview.c @@ -5121,146 +5121,52 @@ int rv = 0; url_tool_t f; #define URL_MAX_LAUNCH (2 * MAILTMPLEN) +#define _URL_EXPANSION "\"$URL\"" if(handle->h.url.tool){ - char *toolp, *cmdp, *p, *q, cmd[URL_MAX_LAUNCH + 4]; - char *left_double_quote, *right_double_quote; - int mode, quotable = 0, copied = 0, double_quoted = 0; - int escape_single_quotes = 0; + char *toolp, *cmdp, *endp, cmd[URL_MAX_LAUNCH + 1]; + int mode, len, copied = 0; PIPE_S *syspipe; toolp = handle->h.url.tool; /* - * Figure out if we need to quote the URL. If there are shell - * metacharacters in it we want to quote it, because we don't want - * the shell to interpret them. However, if the user has already - * quoted the URL in the command definition we don't want to quote - * again. So, we try to see if there are a pair of unescaped - * quotes surrounding _URL_ in the cmd. - * If we quote when we shouldn't have, it'll cause it not to work. - * If we don't quote when we should have, it's a possible security - * problem (and it still won't work). - * - * In bash and ksh $( executes a command, so we use single quotes - * instead of double quotes to do our quoting. If configured command - * is double-quoted we change that to single quotes. - */ -#ifdef _WINDOWS - /* - * It should be safe to not quote any of the characters from the - * string below. It was quoting with '?' and '&' in a URL, which is - * unnecessary. Also the quoting code below only quotes with - * ' (single quote), so we'd want it to at least do double quotes - * instead, for Windows. + * Rather than trying to be smart about quoting and + * meta-characters, just stuff the URL into an environment + * variable and make the handler use it. */ - if(toolp) - quotable = 0; /* always never quote */ - else -#endif - /* quote shell specials */ - if(strpbrk(handle->h.url.path, "&*;<>?[]|~$(){}") != NULL){ - escape_single_quotes++; - if((p = strstr(toolp, "_URL_")) != NULL){ /* explicit arg? */ - int in_quote = 0; - - /* see whether or not it is already quoted */ - - quotable = 1; - - for(q = toolp; q < p; q++) - if(*q == '\'' && (q == toolp || q[-1] != '\\')) - in_quote = 1 - in_quote; - - if(in_quote){ - for(q = p+5; *q; q++) - if(*q == '\'' && q[-1] != '\\'){ - /* already single quoted, leave it alone */ - quotable = 0; - break; - } - } - if(quotable){ - in_quote = 0; - for(q = toolp; q < p; q++) - if(*q == '\"' && (q == toolp || q[-1] != '\\')){ - in_quote = 1 - in_quote; - if(in_quote) - left_double_quote = q; - } - - if(in_quote){ - for(q = p+5; *q; q++) - if(*q == '\"' && q[-1] != '\\'){ - /* we'll replace double quotes with singles */ - double_quoted = 1; - right_double_quote = q; - break; - } - } - } - } - else - quotable = 1; - } - else - quotable = 0; + setenv("URL", handle->h.url.path, 1); /* Build the command */ cmdp = cmd; - while(cmdp-cmd < URL_MAX_LAUNCH) - if((!*toolp && !copied) - || (*toolp == '_' && !strncmp(toolp + 1, "URL_", 4))){ + endp = cmd + sizeof(cmd) - 1; + do { + if (cmdp + 1 > endp) + return(url_launch_too_long(rv)); + + if (!*toolp && !copied) { /* implicit _URL_ at end */ - if(!*toolp) - *cmdp++ = ' '; + *endp++ = ' '; + toolp = "_URL_"; + } + + + if (strncmp(toolp, "_URL_", 5) != 0) { + *cmdp++ = *toolp++; + } + else { + toolp += 5; /* length of _URL_ */ - /* add single quotes */ - if(quotable && !double_quoted && cmdp-cmd < URL_MAX_LAUNCH) - *cmdp++ = '\''; - - copied = 1; - /* - * If the url.path contains a single quote we should escape - * that single quote to remove its special meaning. - * Since backslash-quote is ignored inside single quotes we - * close the quotes, backslash escape the quote, then open - * the quotes again. So - * 'fred's car' - * becomes 'fred'\''s car' - */ - for(p = handle->h.url.path; - p && *p && cmdp-cmd < URL_MAX_LAUNCH; p++){ - if(escape_single_quotes && *p == '\''){ - *cmdp++ = '\''; /* closing quote */ - *cmdp++ = '\\'; - *cmdp++ = '\''; /* opening quote comes from p below */ - } + if (cmdp + sizeof(_URL_EXPANSION) - 1 > endp) + return(url_launch_too_long(rv)); - *cmdp++ = *p; - } - - if(quotable && !double_quoted && cmdp-cmd < URL_MAX_LAUNCH){ - *cmdp++ = '\''; - *cmdp = '\0'; - } - - if(*toolp) - toolp += 5; /* length of "_URL_" */ - } - else{ - /* replace double quotes with single quotes */ - if(double_quoted && - (toolp == left_double_quote || toolp == right_double_quote)){ - *cmdp++ = '\''; - toolp++; - } - else if(!(*cmdp++ = *toolp++)) - break; + sstrcpy(&cmdp, _URL_EXPANSION); + copied = 1; } + } while (*toolp); if(cmdp-cmd >= URL_MAX_LAUNCH) return(url_launch_too_long(rv));