added fields to keep an original query path in qse_htre_t
changed proxying routines to use the original query path instead of percent-encoding back
This commit is contained in:
@ -80,8 +80,8 @@ typedef struct xtn_t
|
||||
|
||||
struct
|
||||
{
|
||||
const qse_char_t* ptr;
|
||||
const qse_char_t* end;
|
||||
const qse_char_t* ptr;
|
||||
const qse_char_t* end;
|
||||
} str;
|
||||
} u;
|
||||
} in;
|
||||
|
@ -318,7 +318,7 @@ static qse_mchar_t* parse_initial_line (qse_htrd_t* htrd, qse_mchar_t* line)
|
||||
|
||||
int q = xdigit_to_num(*(p+1));
|
||||
int w = xdigit_to_num(*(p+2));
|
||||
|
||||
|
||||
if (q >= 0 && w >= 0)
|
||||
{
|
||||
int t = (q << 4) + w;
|
||||
@ -330,6 +330,8 @@ static qse_mchar_t* parse_initial_line (qse_htrd_t* htrd, qse_mchar_t* line)
|
||||
|
||||
*out++ = t;
|
||||
p += 3;
|
||||
|
||||
htrd->re.flags |= QSE_HTRE_QPATH_PERDEC;
|
||||
}
|
||||
else *out++ = *p++;
|
||||
}
|
||||
@ -355,23 +357,32 @@ static qse_mchar_t* parse_initial_line (qse_htrd_t* htrd, qse_mchar_t* line)
|
||||
/* null-terminate the url part though we know the length */
|
||||
*out = QSE_MT('\0');
|
||||
|
||||
if (htrd->re.flags & QSE_HTRE_QPATH_PERDEC)
|
||||
{
|
||||
/* TODO: build the original qpath */
|
||||
htrd->re.orgpqath.ptr = XXX;
|
||||
htrd->re.orgpath.len = XXXX;
|
||||
}
|
||||
|
||||
if (param.ptr)
|
||||
{
|
||||
param.len = out - param.ptr;
|
||||
htrd->re.u.q.path = tmp.ptr;
|
||||
htrd->re.u.q.param = param.ptr;
|
||||
htrd->re.u.q.path = tmp;
|
||||
htrd->re.u.q.param = param;
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp.len = out - tmp.ptr;
|
||||
htrd->re.u.q.path = tmp.ptr;
|
||||
htrd->re.u.q.param = QSE_NULL;
|
||||
htrd->re.u.q.path = tmp;
|
||||
htrd->re.u.q.param.ptr = QSE_NULL;
|
||||
htrd->re.u.q.param.len = 0;
|
||||
}
|
||||
#else
|
||||
while (*p != QSE_MT('\0') && !is_space_octet(*p))
|
||||
{
|
||||
if (*p == QSE_MT('?') && param.ptr == QSE_NULL)
|
||||
{
|
||||
tmp.len = p - tmp.ptr; /* length of the path part */
|
||||
*p++ = QSE_MT('\0'); /* null-terminate the path part */
|
||||
param.ptr = p;
|
||||
}
|
||||
@ -380,33 +391,40 @@ static qse_mchar_t* parse_initial_line (qse_htrd_t* htrd, qse_mchar_t* line)
|
||||
|
||||
/* the url must be followed by a space */
|
||||
if (!is_space_octet(*p)) goto badre;
|
||||
param.len = p - param.ptr; /* length of the param part */
|
||||
*p = QSE_MT('\0'); /* null-terminate the path or param part */
|
||||
|
||||
if (param.ptr)
|
||||
{
|
||||
htrd->re.u.q.path = tmp.ptr;
|
||||
htrd->re.u.q.param = param.ptr;
|
||||
htrd->re.u.q.path = tmp;
|
||||
htrd->re.u.q.param = param;
|
||||
}
|
||||
else
|
||||
{
|
||||
htrd->re.u.q.path = tmp.ptr;
|
||||
htrd->re.u.q.param = QSE_NULL;
|
||||
htrd->re.u.q.path = tmp;
|
||||
htrd->re.u.q.param.ptr = QSE_NULL;
|
||||
htrd->re.u.q.param.len = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (htrd->option & QSE_HTRD_CANONQPATH)
|
||||
{
|
||||
qse_mchar_t* qpath = htrd->re.u.q.path;
|
||||
qse_mchar_t* qpath = htrd->re.u.q.path.ptr;
|
||||
|
||||
/* if the url begins with xxx://,
|
||||
* skip xxx:/ and canonicalize from the second slash */
|
||||
while (is_alpha_octet(*qpath)) qpath++;
|
||||
if (qse_mbszcmp (qpath, QSE_MT("://"), 3) == 0)
|
||||
{
|
||||
qpath = qpath + 2; /* set the position to the second / in :// */
|
||||
htrd->re.u.q.path.len = qse_canonmbspath (qpath, qpath, 0);
|
||||
htrd->re.u.q.path.len += qpath - htrd->re.u.q.path.ptr;
|
||||
}
|
||||
else
|
||||
qpath = htrd->re.u.q.path;
|
||||
|
||||
qse_canonmbspath (qpath, qpath, 0);
|
||||
{
|
||||
qpath = htrd->re.u.q.path.ptr;
|
||||
htrd->re.u.q.path.len = qse_canonmbspath (qpath, qpath, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* skip spaces after the url part */
|
||||
|
@ -78,6 +78,9 @@ void qse_htre_fini (qse_htre_t* re)
|
||||
qse_mbs_fini (&re->content);
|
||||
qse_htb_fini (&re->trailers);
|
||||
qse_htb_fini (&re->hdrtab);
|
||||
|
||||
if (re->orgqpath.buf)
|
||||
QSE_MMGR_FREE (re->mmgr, re->orgqpath.buf);
|
||||
}
|
||||
|
||||
void qse_htre_clear (qse_htre_t* re)
|
||||
@ -95,6 +98,9 @@ void qse_htre_clear (qse_htre_t* re)
|
||||
re->state = 0;
|
||||
re->flags = 0;
|
||||
|
||||
re->orgqpath.ptr = QSE_NULL;
|
||||
re->orgqpath.len = 0;
|
||||
|
||||
QSE_MEMSET (&re->version, 0, QSE_SIZEOF(re->version));
|
||||
QSE_MEMSET (&re->attr, 0, QSE_SIZEOF(re->attr));
|
||||
|
||||
@ -107,18 +113,6 @@ void qse_htre_clear (qse_htre_t* re)
|
||||
#endif
|
||||
}
|
||||
|
||||
int qse_htre_setstrfromcstr (
|
||||
qse_htre_t* re, qse_mbs_t* str, const qse_mcstr_t* cstr)
|
||||
{
|
||||
return (qse_mbs_ncpy (str, cstr->ptr, cstr->len) == (qse_size_t)-1)? -1: 0;
|
||||
}
|
||||
|
||||
int qse_htre_setstrfromxstr (
|
||||
qse_htre_t* re, qse_mbs_t* str, const qse_mcstr_t* xstr)
|
||||
{
|
||||
return (qse_mbs_ncpy (str, xstr->ptr, xstr->len) == (qse_size_t)-1)? -1: 0;
|
||||
}
|
||||
|
||||
const qse_htre_hdrval_t* qse_htre_getheaderval (
|
||||
const qse_htre_t* re, const qse_mchar_t* name)
|
||||
{
|
||||
@ -180,7 +174,7 @@ int qse_htre_walktrailers (
|
||||
qse_htb_walk (&re->trailers, walk_headers, &hwctx);
|
||||
return hwctx.ret;
|
||||
}
|
||||
|
||||
|
||||
int qse_htre_addcontent (
|
||||
qse_htre_t* re, const qse_mchar_t* ptr, qse_size_t len)
|
||||
{
|
||||
@ -266,11 +260,55 @@ void qse_htre_setconcb (qse_htre_t* re, qse_htre_concb_t concb, void* ctx)
|
||||
|
||||
int qse_htre_perdecqpath (qse_htre_t* re)
|
||||
{
|
||||
/* percent decode the query path */
|
||||
qse_size_t dec_count;
|
||||
|
||||
/* percent decode the query path*/
|
||||
|
||||
if (re->type != QSE_HTRE_Q || (re->flags & QSE_HTRE_QPATH_PERDEC)) return -1;
|
||||
if (qse_perdechttpstr (re->u.q.path, re->u.q.path) > 0)
|
||||
|
||||
QSE_ASSERT (re->orgqpath.len <= 0);
|
||||
QSE_ASSERT (re->orgqpath.ptr == QSE_NULL);
|
||||
|
||||
if (qse_isperencedhttpstr(re->u.q.path.ptr))
|
||||
{
|
||||
/* the string is percent-encoded. keep the original request
|
||||
* in a separately allocated buffer */
|
||||
|
||||
if (re->orgqpath.buf && re->u.q.path.len <= re->orgqpath.capa)
|
||||
{
|
||||
re->orgqpath.len = qse_mbscpy (re->orgqpath.buf, re->u.q.path.ptr);
|
||||
re->orgqpath.ptr = re->orgqpath.buf;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (re->orgqpath.buf)
|
||||
{
|
||||
QSE_MMGR_FREE (re->mmgr, re->orgqpath.buf);
|
||||
re->orgqpath.capa = 0;
|
||||
}
|
||||
|
||||
re->orgqpath.buf = qse_mbsxdup (re->u.q.path.ptr, re->u.q.path.len, re->mmgr);
|
||||
if (!re->orgqpath.buf) return -1;
|
||||
re->orgqpath.capa = re->u.q.path.len;
|
||||
|
||||
re->orgqpath.ptr = re->orgqpath.buf;
|
||||
re->orgqpath.len = re->orgqpath.capa;
|
||||
|
||||
/* orgqpath.buf and orgqpath.ptr are the same here. the caller
|
||||
* is free to change orgqpath.ptr to point to a differnt position
|
||||
* in the buffer. */
|
||||
}
|
||||
}
|
||||
|
||||
re->u.q.path.len = qse_perdechttpstr (re->u.q.path.ptr, re->u.q.path.ptr, &dec_count);
|
||||
if (dec_count > 0)
|
||||
{
|
||||
/* this assertion is to ensure that qse_isperencedhttpstr()
|
||||
* returned true when dec_count is greater than 0 */
|
||||
QSE_ASSERT (re->orgqpath.buf != QSE_NULL);
|
||||
QSE_ASSERT (re->orgqpath.ptr != QSE_NULL);
|
||||
re->flags |= QSE_HTRE_QPATH_PERDEC;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -387,7 +387,30 @@ qse_mchar_t* qse_fmthttptime (
|
||||
return buf;
|
||||
}
|
||||
|
||||
qse_size_t qse_perdechttpstr (const qse_mchar_t* str, qse_mchar_t* buf)
|
||||
int qse_isperencedhttpstr (const qse_mchar_t* str)
|
||||
{
|
||||
const qse_mchar_t* p = str;
|
||||
|
||||
while (*p != QSE_T('\0'))
|
||||
{
|
||||
if (*p == QSE_MT('%') && *(p + 1) != QSE_MT('\0') && *(p + 2) != QSE_MT('\0'))
|
||||
{
|
||||
int q = QSE_MXDIGITTONUM (*(p + 1));
|
||||
if (q >= 0)
|
||||
{
|
||||
/* return true if the first valid percent-encoded sequence is found */
|
||||
int w = QSE_MXDIGITTONUM (*(p + 2));
|
||||
if (w >= 0) return 1;
|
||||
}
|
||||
}
|
||||
|
||||
p++;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
qse_size_t qse_perdechttpstr (const qse_mchar_t* str, qse_mchar_t* buf, qse_size_t* ndecs)
|
||||
{
|
||||
const qse_mchar_t* p = str;
|
||||
qse_mchar_t* out = buf;
|
||||
@ -395,16 +418,15 @@ qse_size_t qse_perdechttpstr (const qse_mchar_t* str, qse_mchar_t* buf)
|
||||
|
||||
while (*p != QSE_T('\0'))
|
||||
{
|
||||
if (*p == QSE_MT('%') && *(p+1) != QSE_MT('\0') && *(p+2) != QSE_MT('\0'))
|
||||
if (*p == QSE_MT('%') && *(p + 1) != QSE_MT('\0') && *(p + 2) != QSE_MT('\0'))
|
||||
{
|
||||
int q = QSE_MXDIGITTONUM (*(p+1));
|
||||
int q = QSE_MXDIGITTONUM (*(p + 1));
|
||||
if (q >= 0)
|
||||
{
|
||||
int w = QSE_MXDIGITTONUM (*(p+2));
|
||||
int w = QSE_MXDIGITTONUM (*(p + 2));
|
||||
if (w >= 0)
|
||||
{
|
||||
/* unlike the path part, we don't care if it
|
||||
* contains a null character */
|
||||
/* we don't care if it contains a null character */
|
||||
*out++ = ((q << 4) + w);
|
||||
p += 3;
|
||||
dec_count++;
|
||||
@ -412,12 +434,13 @@ qse_size_t qse_perdechttpstr (const qse_mchar_t* str, qse_mchar_t* buf)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*out++ = *p++;
|
||||
}
|
||||
|
||||
*out = QSE_MT('\0');
|
||||
/*return out - buf;*/
|
||||
return dec_count;
|
||||
if (ndecs) *ndecs = dec_count;
|
||||
return out - buf;
|
||||
}
|
||||
|
||||
#define IS_UNRESERVED(c) \
|
||||
@ -429,12 +452,15 @@ qse_size_t qse_perdechttpstr (const qse_mchar_t* str, qse_mchar_t* buf)
|
||||
|
||||
#define TO_HEX(v) (QSE_MT("0123456789ABCDEF")[(v) & 15])
|
||||
|
||||
qse_size_t qse_perenchttpstr (int opt, const qse_mchar_t* str, qse_mchar_t* buf)
|
||||
qse_size_t qse_perenchttpstr (int opt, const qse_mchar_t* str, qse_mchar_t* buf, qse_size_t* nencs)
|
||||
{
|
||||
const qse_mchar_t* p = str;
|
||||
qse_mchar_t* out = buf;
|
||||
qse_size_t enc_count = 0;
|
||||
|
||||
/* this function doesn't accept the size of the buffer. the caller must
|
||||
* ensure that the buffer is large enough */
|
||||
|
||||
if (opt & QSE_PERENCHTTPSTR_KEEP_SLASH)
|
||||
{
|
||||
while (*p != QSE_T('\0'))
|
||||
@ -466,8 +492,8 @@ qse_size_t qse_perenchttpstr (int opt, const qse_mchar_t* str, qse_mchar_t* buf)
|
||||
}
|
||||
}
|
||||
*out = QSE_MT('\0');
|
||||
/*return out - buf;*/
|
||||
return enc_count;
|
||||
if (nencs) *nencs = enc_count;
|
||||
return out - buf;
|
||||
}
|
||||
|
||||
qse_mchar_t* qse_perenchttpstrdup (int opt, const qse_mchar_t* str, qse_mmgr_t* mmgr)
|
||||
@ -500,7 +526,7 @@ qse_mchar_t* qse_perenchttpstrdup (int opt, const qse_mchar_t* str, qse_mmgr_t*
|
||||
if (buf == QSE_NULL) return QSE_NULL;
|
||||
|
||||
/* perform actual escaping */
|
||||
qse_perenchttpstr (opt, str, buf);
|
||||
qse_perenchttpstr (opt, str, buf, QSE_NULL);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
@ -1051,18 +1051,24 @@ static int task_init_proxy (
|
||||
proxy->qpath_pos_in_reqfwdbuf = QSE_STR_LEN(proxy->reqfwdbuf);
|
||||
if (arg->req->flags & QSE_HTRE_QPATH_PERDEC)
|
||||
{
|
||||
/* the query path has been percent-decoded. so encode it back */
|
||||
/* the query path has been percent-decoded. get the original qpath*/
|
||||
|
||||
/*
|
||||
qse_mchar_t* qpath, * qpath_enc;
|
||||
qse_size_t x;
|
||||
|
||||
qpath = qse_htre_getqpath(arg->req);
|
||||
qpath_enc = qse_perenchttpstrdup (QSE_PERENCHTTPSTR_KEEP_SLASH, qpath, httpd->mmgr);
|
||||
if (qpath_enc == QSE_NULL) goto nomem_oops;
|
||||
|
||||
|
||||
x = qse_mbs_cat (proxy->reqfwdbuf, qpath_enc);
|
||||
if (qpath != qpath_enc) QSE_MMGR_FREE (httpd->mmgr, qpath_enc);
|
||||
|
||||
if (x == (qse_size_t)-1) goto nomem_oops;
|
||||
*/
|
||||
|
||||
if (qse_mbs_cat (proxy->reqfwdbuf, qse_htre_getorgqpath(arg->req)) == (qse_size_t)-1) goto nomem_oops;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
Reference in New Issue
Block a user