*
* Parameters:
* const char *url The requested URL (with leading /).
+ * const char *orig_uri The original URI before rewriting (if any)
* int post_len Length of the POST body.
* const char *cookie For set HTTP_COOKIE.
* const char *content_type For set CONTENT_TYPE.
*/
static void send_cgi_and_exit(
const char *url,
+ const char *orig_uri,
const char *request,
int post_len,
const char *cookie,
const char *content_type) NORETURN;
static void send_cgi_and_exit(
const char *url,
+ const char *orig_uri,
const char *request,
int post_len,
const char *cookie,
setenv1("PATH_INFO", script); /* set to /PATH_INFO or "" */
setenv1("REQUEST_METHOD", request);
if (g_query) {
- putenv(xasprintf("%s=%s?%s", "REQUEST_URI", url, g_query));
+ putenv(xasprintf("%s=%s?%s", "REQUEST_URI", orig_uri, g_query));
} else {
- setenv1("REQUEST_URI", url);
+ setenv1("REQUEST_URI", orig_uri);
}
if (script != NULL)
*script = '\0'; /* cut off /PATH_INFO */
/* protect listing "cgi-bin/" */
send_headers_and_exit(HTTP_FORBIDDEN);
}
- send_cgi_and_exit(urlcopy, prequest, length, cookie, content_type);
+ send_cgi_and_exit(urlcopy, urlcopy, prequest, length, cookie, content_type);
}
#endif
- if (urlp[-1] == '/')
+ if (urlp[-1] == '/') {
+ /* When index_page string is appended to <dir>/ URL, it overwrites
+ * the query string. If we fall back to call /cgi-bin/index.cgi,
+ * query string would be lost and not available to the CGI.
+ * Work around it by making a deep copy.
+ */
+ if (ENABLE_FEATURE_HTTPD_CGI)
+ g_query = xstrdup(g_query); /* ok for NULL too */
strcpy(urlp, index_page);
+ }
if (stat(tptr, &sb) == 0) {
#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR
char *suffix = strrchr(tptr, '.');
Htaccess *cur;
for (cur = script_i; cur; cur = cur->next) {
if (strcmp(cur->before_colon + 1, suffix) == 0) {
- send_cgi_and_exit(urlcopy, prequest, length, cookie, content_type);
+ send_cgi_and_exit(urlcopy, urlcopy, prequest, length, cookie, content_type);
}
}
}
/* It's a dir URL and there is no index.html
* Try cgi-bin/index.cgi */
if (access("/cgi-bin/index.cgi"+1, X_OK) == 0) {
- urlp[0] = '\0';
- g_query = urlcopy;
- send_cgi_and_exit("/cgi-bin/index.cgi", prequest, length, cookie, content_type);
+ urlp[0] = '\0'; /* remove index_page */
+ send_cgi_and_exit("/cgi-bin/index.cgi", urlcopy, prequest, length, cookie, content_type);
}
}
/* else fall through to send_file, it errors out if open fails: */
unsigned long long size_total;
int odd;
DIR *dirp;
- char *QUERY_STRING;
-
- QUERY_STRING = getenv("QUERY_STRING");
- if (!QUERY_STRING
- || QUERY_STRING[0] != '/'
- || strstr(QUERY_STRING, "//")
- || strstr(QUERY_STRING, "/../")
- || strcmp(strrchr(QUERY_STRING, '/'), "/..") == 0
+ char *location;
+
+ location = getenv("REQUEST_URI");
+ if (!location)
+ return 1;
+
+ /* drop URL arguments if any */
+ strchrnul(location, '?')[0] = '\0';
+
+ if (location[0] != '/'
+ || strstr(location, "//")
+ || strstr(location, "/../")
+ || strcmp(strrchr(location, '/'), "/..") == 0
) {
return 1;
}
if (chdir("..")
- || (QUERY_STRING[1] && chdir(QUERY_STRING + 1))
+ || (location[1] && chdir(location + 1))
) {
return 1;
}
"\r\n" /* Mandatory empty line after headers */
"<html><head><title>Index of ");
/* Guard against directories with &, > etc */
- fmt_html(QUERY_STRING);
+ fmt_html(location);
fmt_str(
"</title>\n"
STYLE_STR
"</head>" "\n"
"<body>" "\n"
"<h1>Index of ");
- fmt_html(QUERY_STRING);
+ fmt_html(location);
fmt_str(
"</h1>" "\n"
"<table>" "\n"