added qse_env_append() and related functions.

fixed how to handle multiple values with the same key when setting an environment variable for a cgi script
This commit is contained in:
2014-10-11 14:33:26 +00:00
parent 0f229c15f5
commit bd64702fd4
5 changed files with 200 additions and 50 deletions

View File

@ -111,8 +111,6 @@ struct cgi_client_req_hdr_ctx_t
qse_env_t* env;
};
static int cgi_capture_client_header (
qse_htre_t* req, const qse_mchar_t* key, const qse_htre_hdrval_t* val, void* ctx)
{
@ -140,8 +138,6 @@ static int cgi_capture_client_header (
if (*ptr == QSE_MT('-')) *ptr = '_';
}
/* insert the last value only */
while (val->next) val = val->next;
ret = qse_env_insertmbs (hdrctx->env, http_key, val->ptr);
if (ret <= -1)
{
@ -149,8 +145,18 @@ static int cgi_capture_client_header (
hdrctx->httpd->errnum = QSE_HTTPD_ENOMEM;
return -1;
}
QSE_MMGR_FREE (req->mmgr, http_key);
/* append values with the same key */
while ((val = val->next))
{
if (qse_env_appendmbs (hdrctx->env, QSE_MT(", ")) <= -1 ||
qse_env_appendmbs (hdrctx->env, val->ptr) <= -1)
{
hdrctx->httpd->errnum = QSE_HTTPD_ENOMEM;
return -1;
}
}
}
return 0;
@ -442,19 +448,20 @@ static int cgi_add_env (
qparam = qse_htre_getqparam(req);
#ifdef _WIN32
qse_env_insert (env, QSE_T("PATH"), QSE_NULL);
if (qse_env_insert (env, QSE_T("PATH"), QSE_NULL) <= -1) goto oops_nomem;
#else
qse_env_insertmbs (env, QSE_MT("LANG"), QSE_NULL);
qse_env_insertmbs (env, QSE_MT("PATH"), QSE_NULL);
if (qse_env_insertmbs (env, QSE_MT("LANG"), QSE_NULL) <= -1 ||
qse_env_insertmbs (env, QSE_MT("PATH"), QSE_NULL)) goto oops_nomem;
#endif
qse_env_insertmbs (env, QSE_MT("GATEWAY_INTERFACE"), QSE_MT("CGI/1.1"));
if (qse_env_insertmbs (env, QSE_MT("GATEWAY_INTERFACE"), QSE_MT("CGI/1.1")) <= -1) goto oops_nomem;
qse_mbsxfmt (buf, QSE_COUNTOF(buf), QSE_MT("HTTP/%d.%d"), (int)v->major, (int)v->minor);
qse_env_insertmbs (env, QSE_MT("SERVER_PROTOCOL"), buf);
if (qse_env_insertmbs (env, QSE_MT("SERVER_PROTOCOL"), buf) <= -1) goto oops_nomem;
if (qse_env_insertmbs (env, QSE_MT("SCRIPT_FILENAME"), path) <= -1 ||
qse_env_insertmbs (env, QSE_MT("SCRIPT_NAME"), script) <= -1 ||
qse_env_insertmbs (env, QSE_MT("DOCUMENT_ROOT"), root) <= -1) goto oops_nomem;
qse_env_insertmbs (env, QSE_MT("SCRIPT_FILENAME"), path);
qse_env_insertmbs (env, QSE_MT("SCRIPT_NAME"), script);
qse_env_insertmbs (env, QSE_MT("DOCUMENT_ROOT"), root);
if (suffix && suffix[0] != QSE_MT('\0'))
{
const qse_mchar_t* tmp[3];
@ -468,40 +475,50 @@ static int cgi_add_env (
if (tr)
{
qse_canonmbspath (tr, tr, 0);
qse_env_insertmbs (env, QSE_MT("PATH_TRANSLATED"), tr);
if (qse_env_insertmbs (env, QSE_MT("PATH_TRANSLATED"), tr) <= -1)
{
QSE_MMGR_FREE (httpd->mmgr, tr);
goto oops_nomem;
}
QSE_MMGR_FREE (httpd->mmgr, tr);
}
qse_env_insertmbs (env, QSE_MT("PATH_INFO"), suffix);
if (qse_env_insertmbs (env, QSE_MT("PATH_INFO"), suffix) <= -1) goto oops_nomem;
}
qse_env_insertmbs (env, QSE_MT("REQUEST_METHOD"), qse_htre_getqmethodname(req));
qse_env_insertmbs (env, QSE_MT("REQUEST_URI"), qse_htre_getqpath(req));
if (qparam) qse_env_insertmbs (env, QSE_MT("QUERY_STRING"), qparam);
if (qse_env_insertmbs (env, QSE_MT("REQUEST_METHOD"), qse_htre_getqmethodname(req)) <= -1 ||
qse_env_insertmbs (env, QSE_MT("REQUEST_URI"), qse_htre_getqpath(req)) <= -1) goto oops_nomem;
if (qparam && qse_env_insertmbs (env, QSE_MT("QUERY_STRING"), qparam) <= -1) goto oops_nomem;
qse_fmtuintmaxtombs (buf, QSE_COUNTOF(buf), content_length, 10, -1, QSE_MT('\0'), QSE_NULL);
qse_env_insertmbs (env, QSE_MT("CONTENT_LENGTH"), buf);
if (content_type) qse_env_insertmbs (env, QSE_MT("CONTENT_TYPE"), content_type);
if (qse_env_insertmbs (env, QSE_MT("CONTENT_LENGTH"), buf) <= -1) goto oops_nomem;
if (content_type && qse_env_insertmbs (env, QSE_MT("CONTENT_TYPE"), content_type) <= -1) goto oops_nomem;
if (chunked) qse_env_insertmbs (env, QSE_MT("TRANSFER_ENCODING"), QSE_MT("chunked"));
if (chunked && qse_env_insertmbs (env, QSE_MT("TRANSFER_ENCODING"), QSE_MT("chunked")) <= 1) goto oops_nomem;
qse_env_insertmbs (env, "SERVER_SOFTWARE", qse_httpd_getname(httpd));
if (qse_env_insertmbs (env, "SERVER_SOFTWARE", qse_httpd_getname(httpd)) <= -1) goto oops_nomem;
qse_nwadtombs (&client->local_addr, buf, QSE_COUNTOF(buf), QSE_NWADTOMBS_PORT);
qse_env_insertmbs (env, QSE_MT("SERVER_PORT"), buf);
if (qse_env_insertmbs (env, QSE_MT("SERVER_PORT"), buf) <= -1) goto oops_nomem;
qse_nwadtombs (&client->local_addr, buf, QSE_COUNTOF(buf), QSE_NWADTOMBS_ADDR);
qse_env_insertmbs (env, QSE_MT("SERVER_ADDR"), buf);
qse_env_insertmbs (env, QSE_MT("SERVER_NAME"), buf); /* TODO: convert it to a host name */
if (qse_env_insertmbs (env, QSE_MT("SERVER_ADDR"), buf) <= -1) goto oops_nomem;
if (qse_env_insertmbs (env, QSE_MT("SERVER_NAME"), buf) <= -1) goto oops_nomem; /* TODO: convert it to a host name */
qse_nwadtombs (&client->remote_addr, buf, QSE_COUNTOF(buf), QSE_NWADTOMBS_PORT);
qse_env_insertmbs (env, QSE_MT("REMOTE_PORT"), buf);
if (qse_env_insertmbs (env, QSE_MT("REMOTE_PORT"), buf) <= -1) goto oops_nomem;
qse_nwadtombs (&client->remote_addr, buf, QSE_COUNTOF(buf), QSE_NWADTOMBS_ADDR);
qse_env_insertmbs (env, QSE_MT("REMOTE_ADDR"), buf);
if (qse_env_insertmbs (env, QSE_MT("REMOTE_ADDR"), buf) <= -1) goto oops_nomem;
ctx.httpd = httpd;
ctx.env = env;
if (qse_htre_walkheaders (req, cgi_capture_client_header, &ctx) <= -1) return -1;
if (qse_htre_walktrailers (req, cgi_capture_client_header, &ctx) <= -1) return -1;
if (qse_htre_walkheaders (req, cgi_capture_client_header, &ctx) <= -1 ||
qse_htre_walktrailers (req, cgi_capture_client_header, &ctx) <= -1) goto oops;
return 0;
oops_nomem:
httpd->errnum = QSE_HTTPD_ENOMEM;
oops:
return -1;
}
static int cgi_snatch_client_input (

View File

@ -201,6 +201,7 @@ static int proxy_capture_peer_header (qse_htre_t* req, const qse_mchar_t* key, c
{
task_proxy_t* proxy = (task_proxy_t*)ctx;
#if 0
if (!(proxy->httpd->opt.trait & QSE_HTTPD_PROXYNOVIA) && !(proxy->flags & PROXY_VIA_RETURNING))
{
if (qse_mbscasecmp (key, QSE_MT("Via")) == 0)
@ -229,6 +230,7 @@ static int proxy_capture_peer_header (qse_htre_t* req, const qse_mchar_t* key, c
qse_httpd_getname(proxy->httpd));
}
}
#endif
if (qse_mbscasecmp (key, QSE_MT("Connection")) != 0 &&
qse_mbscasecmp (key, QSE_MT("Transfer-Encoding")) != 0)
@ -258,9 +260,9 @@ static int proxy_capture_client_header (qse_htre_t* req, const qse_mchar_t* key,
task_proxy_t* proxy = (task_proxy_t*)ctx;
#if 0
if (!(proxy->flags & (PROXY_TRANSPARENT | PROXY_X_FORWARDED_FOR)))
if (!(proxy->flags & PROXY_TRANSPARENT))
{
if (qse_mbscasecmp (key, QSE_MT("X-Forwarded-For")) == 0)
if (!(proxy->flags & PROXY_X_FORWARDED_FOR) && qse_mbscasecmp (key, QSE_MT("X-Forwarded-For")) == 0)
{
/* append to X-Forwarded-For if it exists in the header.
* note that it add a comma even if the existing value is empty.
@ -274,7 +276,7 @@ static int proxy_capture_client_header (qse_htre_t* req, const qse_mchar_t* key,
return proxy_add_header_to_buffer_with_extra_data (proxy, proxy->reqfwdbuf, key, val, QSE_MT(", %hs"), extra);
}
}
#endif
if (!(proxy->httpd->opt.trait & QSE_HTTPD_PROXYNOVIA) && !(proxy->flags & PROXY_VIA))
{
@ -303,6 +305,7 @@ static int proxy_capture_client_header (qse_htre_t* req, const qse_mchar_t* key,
qse_httpd_getname(proxy->httpd));
}
}
#endif
/* EXPERIMENTAL: REMOVE HEADERS.
* FOR EXAMPLE, You can remove Referer or forge it to give analysis systems harder time */
@ -1145,6 +1148,9 @@ qse_mbs_ncat (proxy->reqfwdbuf, spc, QSE_COUNTOF(spc));
if (qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("X-Forwarded-Proto: ")) == (qse_size_t)-1 ||
qse_mbs_cat (proxy->reqfwdbuf, ((client->status & QSE_HTTPD_CLIENT_SECURE)? QSE_MT("https"): QSE_MT("http"))) == (qse_size_t)-1 ||
qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("\r\n")) == (qse_size_t)-1) goto nomem_oops;
/* TODO: support the Forwarded header in RFC7239.
* Forwarded: for=xxx;by=xxx;prot=xxxx */
}
proxy->resflags |= PROXY_RES_AWAIT_RESHDR;