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