diff options
Diffstat (limited to 'src/LYExtern.c')
-rw-r--r-- | src/LYExtern.c | 178 |
1 files changed, 127 insertions, 51 deletions
diff --git a/src/LYExtern.c b/src/LYExtern.c index e042820c..9f5471db 100644 --- a/src/LYExtern.c +++ b/src/LYExtern.c @@ -66,16 +66,88 @@ static char *decode_string(char *s) #ifdef WIN_EX /* * Quote the path to make it safe for shell command processing. + * We always quote it not only includes spaces in it. + * At least we should quote paths which include "&". */ char *quote_pathname(char *pathname) { char *result = NULL; - if (strchr(pathname, ' ') != NULL) { - HTSprintf0(&result, "\"%s\"", pathname); - } else { - StrAllocCopy(result, pathname); + HTSprintf0(&result, "\"%s\"", pathname); + return result; +} + +/* + * Delete dangerous characters as local path. + * We delete '<>|' and also '%"'. + * '%' should be deleted because it's difficut to escape for all cases. + * So we can't treat paths which include '%'. + * '"' should be deleted because it's a obstacle to quote whole path. + */ +static void delete_danger_characters(char *src) +{ + char *dst; + + for (dst = src; *src != '\0'; src++) { + if (strchr("<>|%\"", *src) == NULL) { + *dst = *src; + dst++; + } } + *dst = '\0'; +} + +static char *escapeParameter(CONST char *parameter) +{ + size_t i; + size_t last = strlen(parameter); + size_t n = 0; + size_t encoded = 0; + size_t escaped = 0; + char *result; + char *needs_encoded = "<>|"; + char *needs_escaped = "%"; + char *needs_escaped_NT = "%&^"; + + for (i = 0; i < last; ++i) { + if (strchr(needs_encoded, parameter[i]) != NULL) { + ++encoded; + } + if (system_is_NT) { + if (strchr(needs_escaped_NT, parameter[i]) != NULL) { + ++escaped; + } + } else if (strchr(needs_escaped, parameter[i]) != NULL) { + ++escaped; + } + } + + result = (char *) malloc(last + encoded * 2 + escaped + 1); + if (result == NULL) + outofmem(__FILE__, "escapeParameter"); + + n = 0; + for (i = 0; i < last; i++) { + if (strchr(needs_encoded, parameter[i]) != NULL) { + sprintf(result + n, "%%%02X", (unsigned char) parameter[i]); + n += 3; + continue; + } + if (system_is_NT) { + if (strchr(needs_escaped_NT, parameter[i]) != NULL) { + result[n++] = '^'; + result[n++] = parameter[i]; + continue; + } + } else if (strchr(needs_escaped, parameter[i]) != NULL) { + result[n++] = '%'; /* parameter[i] is '%' */ + result[n++] = parameter[i]; + continue; + } + result[n++] = parameter[i]; + } + result[n] = '\0'; + return result; } #endif /* WIN_EX */ @@ -103,62 +175,66 @@ static char *format_command(char *command, char *cmdbuf = NULL; #if defined(WIN_EX) - if (*param != '"' && strchr(param, ' ') != NULL) { - char *cp = quote_pathname(param); - - format(&cmdbuf, command, cp); - FREE(cp); - } else { - char pram_string[LY_MAXPATH]; + char pram_string[LY_MAXPATH]; + char *escaped = NULL; + if (strnicmp("file://localhost/", param, 17) == 0) { + /* decode local path parameter for programs to be + able to interpret - TH */ LYstrncpy(pram_string, param, sizeof(pram_string) - 1); decode_string(pram_string); param = pram_string; + } else { + /* encode or escape URL parameter - TH */ + escaped = escapeParameter(param); + param = escaped; + } - if (isMAILTO_URL(param)) { - format(&cmdbuf, command, param + 7); - } else if (strnicmp("telnet://", param, 9) == 0) { - char host[sizeof(pram_string)]; - int last_pos; - - strcpy(host, param + 9); - last_pos = strlen(host) - 1; - if (last_pos > 1 && host[last_pos] == '/') - host[last_pos] = '\0'; - - format(&cmdbuf, command, host); - } else if (strnicmp("file://localhost/", param, 17) == 0) { - char e_buff[LY_MAXPATH], *p; - - p = param + 17; - *e_buff = 0; - if (strchr(p, ':') == NULL) { - sprintf(e_buff, "%.3s/", windows_drive); - } - strncat(e_buff, p, sizeof(e_buff) - strlen(e_buff) - 1); - p = strrchr(e_buff, '.'); - if (p) { - trimPoundSelector(p); - } + if (isMAILTO_URL(param)) { + format(&cmdbuf, command, param + 7); + } else if (strnicmp("telnet://", param, 9) == 0) { + char host[sizeof(pram_string)]; + int last_pos; + + LYstrncpy(host, param + 9, sizeof(host)); + last_pos = strlen(host) - 1; + if (last_pos > 1 && host[last_pos] == '/') + host[last_pos] = '\0'; + + format(&cmdbuf, command, host); + } else if (strnicmp("file://localhost/", param, 17) == 0) { + char e_buff[LY_MAXPATH], *p; + + p = param + 17; + delete_danger_characters(p); + *e_buff = 0; + if (strchr(p, ':') == NULL) { + sprintf(e_buff, "%.3s/", windows_drive); + } + strncat(e_buff, p, sizeof(e_buff) - strlen(e_buff) - 1); + p = strrchr(e_buff, '.'); + if (p) { + trimPoundSelector(p); + } - /* Less ==> short filename with backslashes, - * less ==> long filename with forward slashes, may be quoted - */ - if (ISUPPER(command[0])) { - format(&cmdbuf, - command, HTDOS_short_name(e_buff)); - } else { - if (*e_buff != '"' && strchr(e_buff, ' ') != NULL) { - p = quote_pathname(e_buff); - LYstrncpy(e_buff, p, sizeof(e_buff) - 1); - FREE(p); - } - format(&cmdbuf, command, e_buff); - } + /* Less ==> short filename with backslashes, + * less ==> long filename with forward slashes, may be quoted + */ + if (ISUPPER(command[0])) { + char *short_name = HTDOS_short_name(e_buff); + + p = quote_pathname(short_name); + format(&cmdbuf, command, p); + FREE(p); } else { - format(&cmdbuf, command, param); + p = quote_pathname(e_buff); + format(&cmdbuf, command, p); + FREE(p); } + } else { + format(&cmdbuf, command, param); } + FREE(escaped); #else format(&cmdbuf, command, param); #endif |