fixed the problem of no percent-encoding of decoded query path in proxying
This commit is contained in:
		| @ -444,7 +444,7 @@ static qse_mchar_t* parse_initial_line (qse_htrd_t* htrd, qse_mchar_t* line) | ||||
| 	if (htrd->re.version.major > 1 ||  | ||||
| 	    (htrd->re.version.major == 1 && htrd->re.version.minor >= 1)) | ||||
| 	{ | ||||
| 		htrd->re.attr.flags |= QSE_HTRE_ATTR_KEEPALIVE; | ||||
| 		htrd->re.flags |= QSE_HTRE_ATTR_KEEPALIVE; | ||||
| 	} | ||||
|  | ||||
| 	return ++p; | ||||
| @ -500,14 +500,14 @@ static int capture_connection (qse_htrd_t* htrd, qse_htb_pair_t* pair) | ||||
| 	n = qse_mbscmp (val->ptr, QSE_MT("close")); | ||||
| 	if (n == 0) | ||||
| 	{ | ||||
| 		htrd->re.attr.flags &= ~QSE_HTRE_ATTR_KEEPALIVE; | ||||
| 		htrd->re.flags &= ~QSE_HTRE_ATTR_KEEPALIVE; | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	n = qse_mbscmp (val->ptr, QSE_MT("keep-alive")); | ||||
| 	if (n == 0) | ||||
| 	{ | ||||
| 		htrd->re.attr.flags |= QSE_HTRE_ATTR_KEEPALIVE; | ||||
| 		htrd->re.flags |= QSE_HTRE_ATTR_KEEPALIVE; | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| @ -523,7 +523,7 @@ static int capture_connection (qse_htrd_t* htrd, qse_htb_pair_t* pair) | ||||
| 	if (htrd->re.version.major < 1  ||  | ||||
| 	    (htrd->re.version.major == 1 && htrd->re.version.minor <= 0)) | ||||
| 	{ | ||||
| 		htrd->re.attr.flags &= ~QSE_HTRE_ATTR_KEEPALIVE; | ||||
| 		htrd->re.flags &= ~QSE_HTRE_ATTR_KEEPALIVE; | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
| @ -568,7 +568,7 @@ static int capture_content_length (qse_htrd_t* htrd, qse_htb_pair_t* pair) | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	if ((htrd->re.attr.flags & QSE_HTRE_ATTR_CHUNKED) && len > 0) | ||||
| 	if ((htrd->re.flags & QSE_HTRE_ATTR_CHUNKED) && len > 0) | ||||
| 	{ | ||||
| 		/* content-length is greater than 0  | ||||
| 		 * while transfer-encoding: chunked is specified. */ | ||||
| @ -576,7 +576,7 @@ static int capture_content_length (qse_htrd_t* htrd, qse_htb_pair_t* pair) | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	htrd->re.attr.flags |= QSE_HTRE_ATTR_LENGTH; | ||||
| 	htrd->re.flags |= QSE_HTRE_ATTR_LENGTH; | ||||
| 	htrd->re.attr.content_length = len; | ||||
| 	return 0; | ||||
| } | ||||
| @ -586,14 +586,14 @@ static int capture_expect (qse_htrd_t* htrd, qse_htb_pair_t* pair) | ||||
| 	qse_htre_hdrval_t* val; | ||||
|  | ||||
| 	/* Expect is included */ | ||||
| 	htrd->re.attr.flags |= QSE_HTRE_ATTR_EXPECT;  | ||||
| 	htrd->re.flags |= QSE_HTRE_ATTR_EXPECT;  | ||||
|  | ||||
| 	val = QSE_HTB_VPTR(pair); | ||||
| 	while (val)  | ||||
| 	{	 | ||||
| 		/* Expect: 100-continue is included */ | ||||
| 		if (qse_mbscasecmp (val->ptr, QSE_MT("100-continue")) == 0) | ||||
| 			htrd->re.attr.flags |= QSE_HTRE_ATTR_EXPECT100;  | ||||
| 			htrd->re.flags |= QSE_HTRE_ATTR_EXPECT100;  | ||||
| 		val = val->next; | ||||
| 	} | ||||
|  | ||||
| @ -623,13 +623,13 @@ static int capture_transfer_encoding (qse_htrd_t* htrd, qse_htb_pair_t* pair) | ||||
| 	if (n == 0) | ||||
| 	{ | ||||
| 		/* if (htrd->re.attr.content_length > 0) */ | ||||
| 		if (htrd->re.attr.flags & QSE_HTRE_ATTR_LENGTH) | ||||
| 		if (htrd->re.flags & QSE_HTRE_ATTR_LENGTH) | ||||
| 		{ | ||||
| 			/* both content-length and 'transfer-encoding: chunked' are specified. */ | ||||
| 			goto badre; | ||||
| 		} | ||||
|  | ||||
| 		htrd->re.attr.flags |= QSE_HTRE_ATTR_CHUNKED; | ||||
| 		htrd->re.flags |= QSE_HTRE_ATTR_CHUNKED; | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| @ -1232,10 +1232,10 @@ int qse_htrd_feed (qse_htrd_t* htrd, const qse_mchar_t* req, qse_size_t len) | ||||
| 					} | ||||
|  | ||||
| 					/* carry on processing content body fed together with the header */ | ||||
| 					if (htrd->re.attr.flags & QSE_HTRE_ATTR_CHUNKED) | ||||
| 					if (htrd->re.flags & QSE_HTRE_ATTR_CHUNKED) | ||||
| 					{ | ||||
| 						/* transfer-encoding: chunked */ | ||||
| 						QSE_ASSERT (!(htrd->re.attr.flags & QSE_HTRE_ATTR_LENGTH)); | ||||
| 						QSE_ASSERT (!(htrd->re.flags & QSE_HTRE_ATTR_LENGTH)); | ||||
|  | ||||
| 					dechunk_start: | ||||
| 						htrd->fed.s.chunk.phase = GET_CHUNK_LEN; | ||||
| @ -1279,8 +1279,8 @@ int qse_htrd_feed (qse_htrd_t* htrd, const qse_mchar_t* req, qse_size_t len) | ||||
| 						/* we need to read as many octets as | ||||
| 						 * Content-Length */ | ||||
| 						if ((htrd->option & QSE_HTRD_RESPONSE) &&  | ||||
| 						    !(htrd->re.attr.flags & QSE_HTRE_ATTR_LENGTH) && | ||||
| 						    !(htrd->re.attr.flags & QSE_HTRE_ATTR_KEEPALIVE)) | ||||
| 						    !(htrd->re.flags & QSE_HTRE_ATTR_LENGTH) && | ||||
| 						    !(htrd->re.flags & QSE_HTRE_ATTR_KEEPALIVE)) | ||||
| 						{ | ||||
| 							/* for a response, no content-length and  | ||||
| 							 * no chunk are specified and 'connection'  | ||||
|  | ||||
| @ -39,22 +39,22 @@ int qse_htre_init (qse_htre_t* re, qse_mmgr_t* mmgr) | ||||
| { | ||||
| 	static qse_htb_style_t style = | ||||
| 	{ | ||||
|           { | ||||
|                QSE_HTB_COPIER_DEFAULT, | ||||
|                QSE_HTB_COPIER_DEFAULT | ||||
|           }, | ||||
|           { | ||||
|                QSE_HTB_FREEER_DEFAULT, | ||||
|                free_hdrval | ||||
|           }, | ||||
|           QSE_HTB_COMPER_DEFAULT, | ||||
|           QSE_HTB_KEEPER_DEFAULT, | ||||
|           QSE_HTB_SIZER_DEFAULT, | ||||
|           QSE_HTB_HASHER_DEFAULT | ||||
| 		{ | ||||
| 			QSE_HTB_COPIER_DEFAULT, | ||||
| 			QSE_HTB_COPIER_DEFAULT | ||||
| 		}, | ||||
| 		{ | ||||
| 			QSE_HTB_FREEER_DEFAULT, | ||||
| 			free_hdrval | ||||
| 		}, | ||||
| 		QSE_HTB_COMPER_DEFAULT, | ||||
| 		QSE_HTB_KEEPER_DEFAULT, | ||||
| 		QSE_HTB_SIZER_DEFAULT, | ||||
| 		QSE_HTB_HASHER_DEFAULT | ||||
| 	}; | ||||
|  | ||||
| 	QSE_MEMSET (re, 0, QSE_SIZEOF(*re)); | ||||
| 	re->mmgr = mmgr;	 | ||||
| 	re->mmgr = mmgr; | ||||
|  | ||||
| 	if (qse_htb_init (&re->hdrtab, mmgr, 60, 70, 1, 1) <= -1) return -1; | ||||
| 	if (qse_htb_init (&re->trailers, mmgr, 20, 70, 1, 1) <= -1) return -1; | ||||
| @ -264,3 +264,11 @@ void qse_htre_setconcb (qse_htre_t* re, qse_htre_concb_t concb, void* ctx) | ||||
| 	re->concb_ctx = ctx; | ||||
| } | ||||
|  | ||||
| int qse_htre_perdecqpath (qse_htre_t* re) | ||||
| { | ||||
| 	/* 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) | ||||
| 		re->flags |= QSE_HTRE_QPATH_PERDEC; | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| @ -390,12 +390,13 @@ qse_size_t qse_perdechttpstr (const qse_mchar_t* str, qse_mchar_t* buf) | ||||
| { | ||||
| 	const qse_mchar_t* p = str; | ||||
| 	qse_mchar_t* out = buf; | ||||
| 	 | ||||
| 	qse_size_t dec_count = 0; | ||||
|  | ||||
| 	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)); | ||||
| 			int q = QSE_MXDIGITTONUM (*(p+1)); | ||||
| 			if (q >= 0) | ||||
| 			{ | ||||
| 				int w = QSE_MXDIGITTONUM (*(p+2)); | ||||
| @ -405,57 +406,89 @@ qse_size_t qse_perdechttpstr (const qse_mchar_t* str, qse_mchar_t* buf) | ||||
| 					 * contains a null character */ | ||||
| 					*out++ = ((q << 4) + w); | ||||
| 					p += 3; | ||||
| 					dec_count++; | ||||
| 					continue; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		*out++ = *p++; | ||||
| 	} | ||||
|  | ||||
| 	*out = QSE_MT('\0'); | ||||
| 	return out - buf; | ||||
| 	/*return out - buf;*/ | ||||
| 	return dec_count; | ||||
| } | ||||
|  | ||||
| #define IS_UNRESERVED(c) \ | ||||
| 	(((c) >= QSE_MT('A') && (c) <= QSE_MT('Z')) || \ | ||||
| 	 ((c) >= QSE_MT('a') && (c) <= QSE_MT('z')) || \ | ||||
| 	 ((c) >= QSE_MT('0') && (c) <= QSE_MT('9')) || \ | ||||
| 	 (c) == QSE_MT('-') || (c) == QSE_T('_') || \ | ||||
| 	 (c) == QSE_MT('.') || (c) == QSE_T('~')) | ||||
|  | ||||
| #define TO_HEX(v) (QSE_MT("0123456789ABCDEF")[(v) & 15]) | ||||
|  | ||||
| qse_size_t qse_perenchttpstr (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) | ||||
| { | ||||
| 	const qse_mchar_t* p = str; | ||||
| 	qse_mchar_t* out = buf; | ||||
| 	 | ||||
| 	while (*p != QSE_T('\0')) | ||||
| 	{ | ||||
| 		if (IS_UNRESERVED(*p)) *out++ = *p; | ||||
| 		else | ||||
| 		{ | ||||
|                *out++ = QSE_MT('%'); | ||||
|                *out++ = TO_HEX (*p >> 4); | ||||
|                *out++ = TO_HEX (*p & 15); | ||||
| 		} | ||||
| 		p++; | ||||
| 	} | ||||
| 	qse_size_t enc_count = 0; | ||||
|  | ||||
| 	if (opt & QSE_PERENCHTTPSTR_KEEP_SLASH) | ||||
| 	{ | ||||
| 		while (*p != QSE_T('\0')) | ||||
| 		{ | ||||
| 			if (IS_UNRESERVED(*p) || *p == QSE_MT('/')) *out++ = *p; | ||||
| 			else | ||||
| 			{ | ||||
| 				*out++ = QSE_MT('%'); | ||||
| 				*out++ = TO_HEX (*p >> 4); | ||||
| 				*out++ = TO_HEX (*p & 15); | ||||
| 				enc_count++; | ||||
| 			} | ||||
| 			p++; | ||||
| 		} | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		while (*p != QSE_T('\0')) | ||||
| 		{ | ||||
| 			if (IS_UNRESERVED(*p)) *out++ = *p; | ||||
| 			else | ||||
| 			{ | ||||
| 				*out++ = QSE_MT('%'); | ||||
| 				*out++ = TO_HEX (*p >> 4); | ||||
| 				*out++ = TO_HEX (*p & 15); | ||||
| 				enc_count++; | ||||
| 			} | ||||
| 			p++; | ||||
| 		} | ||||
| 	} | ||||
| 	*out = QSE_MT('\0'); | ||||
| 	return out - buf; | ||||
| 	/*return out - buf;*/ | ||||
| 	return enc_count; | ||||
| } | ||||
|  | ||||
| qse_mchar_t* qse_perenchttpstrdup (const qse_mchar_t* str, qse_mmgr_t* mmgr) | ||||
| qse_mchar_t* qse_perenchttpstrdup (int opt, const qse_mchar_t* str, qse_mmgr_t* mmgr) | ||||
| { | ||||
| 	qse_mchar_t* buf; | ||||
| 	qse_size_t len = 0; | ||||
| 	qse_size_t count = 0; | ||||
| 	 | ||||
| 	/* count the number of characters that should be encoded */ | ||||
| 	for (len = 0; str[len] != QSE_T('\0'); len++) | ||||
| 	if (opt & QSE_PERENCHTTPSTR_KEEP_SLASH) | ||||
| 	{ | ||||
| 		if (!IS_UNRESERVED(str[len])) count++; | ||||
| 		for (len = 0; str[len] != QSE_T('\0'); len++) | ||||
| 		{ | ||||
| 			if (!IS_UNRESERVED(str[len]) && str[len] != QSE_MT('/')) count++; | ||||
| 		} | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		for (len = 0; str[len] != QSE_T('\0'); len++) | ||||
| 		{ | ||||
| 			if (!IS_UNRESERVED(str[len])) count++; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	/* if there are no characters to escape, just return the original string */ | ||||
| @ -466,7 +499,7 @@ qse_mchar_t* qse_perenchttpstrdup (const qse_mchar_t* str, qse_mmgr_t* mmgr) | ||||
| 	if (buf == QSE_NULL) return QSE_NULL; | ||||
|  | ||||
| 	/* perform actual escaping */ | ||||
| 	qse_perenchttpstr (str, buf); | ||||
| 	qse_perenchttpstr (opt, str, buf); | ||||
|  | ||||
| 	return buf; | ||||
| } | ||||
|  | ||||
| @ -304,7 +304,7 @@ static int cgi_htrd_peek_script_output (qse_htrd_t* htrd, qse_htre_t* req) | ||||
| 	} | ||||
|  | ||||
| 	keepalive = cgi->keepalive; | ||||
| 	if (req->attr.flags & QSE_HTRE_ATTR_LENGTH) | ||||
| 	if (req->flags & QSE_HTRE_ATTR_LENGTH) | ||||
| 	{ | ||||
| 		cgi->resflags |= CGI_RES_SCRIPT_LENGTH; | ||||
| 		cgi->script_output_length = req->attr.content_length; | ||||
| @ -730,7 +730,7 @@ static int task_init_cgi ( | ||||
|  | ||||
| 	cgi->method = qse_htre_getqmethodtype(arg->req); | ||||
| 	cgi->version = *qse_htre_getversion(arg->req); | ||||
| 	cgi->keepalive = (arg->req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE); | ||||
| 	cgi->keepalive = (arg->req->flags & QSE_HTRE_ATTR_KEEPALIVE); | ||||
| 	cgi->nph = arg->nph; | ||||
| 	cgi->req = QSE_NULL; | ||||
|  | ||||
| @ -747,7 +747,7 @@ static int task_init_cgi ( | ||||
| 	} | ||||
|  | ||||
| 	if (!(arg->req->state & QSE_HTRE_COMPLETED) && | ||||
| 	    !(arg->req->attr.flags & QSE_HTRE_ATTR_LENGTH)) | ||||
| 	    !(arg->req->flags & QSE_HTRE_ATTR_LENGTH)) | ||||
| 	{ | ||||
| 		/* if the request is not completed and doesn't have | ||||
| 		 * content-length set, it's not really possible to | ||||
| @ -821,8 +821,8 @@ static int task_init_cgi ( | ||||
| 			 * should reach here. if content-length is set | ||||
| 			 * the length should match len. */ | ||||
| 			QSE_ASSERT (len > 0); | ||||
| 			QSE_ASSERT (!(arg->req->attr.flags & QSE_HTRE_ATTR_LENGTH) || | ||||
| 			            ((arg->req->attr.flags & QSE_HTRE_ATTR_LENGTH) &&  | ||||
| 			QSE_ASSERT (!(arg->req->flags & QSE_HTRE_ATTR_LENGTH) || | ||||
| 			            ((arg->req->flags & QSE_HTRE_ATTR_LENGTH) &&  | ||||
| 			             arg->req->attr.content_length == len)); | ||||
| 			cgi->reqflags |= CGI_REQ_GOTALL; | ||||
| 			content_length = len; | ||||
| @ -848,7 +848,7 @@ static int task_init_cgi ( | ||||
| 			cgi->req = arg->req;  | ||||
| 			qse_htre_setconcb (cgi->req, cgi_snatch_client_input, task); | ||||
|  | ||||
| 			QSE_ASSERT (arg->req->attr.flags & QSE_HTRE_ATTR_LENGTH); | ||||
| 			QSE_ASSERT (arg->req->flags & QSE_HTRE_ATTR_LENGTH); | ||||
| 			content_length = arg->req->attr.content_length; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| @ -155,7 +155,7 @@ static qse_size_t format_dirent ( | ||||
| 	 *       a lot of file names to escape. */ | ||||
|  | ||||
| 	/* perform percent-encoding for the anchor */ | ||||
| 	encname = qse_perenchttpstrdup (dirent->name, httpd->mmgr); | ||||
| 	encname = qse_perenchttpstrdup (0, dirent->name, httpd->mmgr); | ||||
| 	if (encname == QSE_NULL) | ||||
| 	{ | ||||
| 		httpd->errnum = QSE_HTTPD_ENOMEM; | ||||
| @ -602,7 +602,7 @@ qse_httpd_task_t* qse_httpd_entaskdir ( | ||||
| 				data.foot.ptr = dir->foot? dir->foot: qse_httpd_getname(httpd); | ||||
| 				data.foot.len = qse_mbslen(data.foot.ptr); | ||||
| 				data.version = *qse_htre_getversion(req); | ||||
| 				data.keepalive = (req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE); | ||||
| 				data.keepalive = (req->flags & QSE_HTRE_ATTR_KEEPALIVE); | ||||
| 				data.method = method; | ||||
|  | ||||
| 				QSE_MEMSET (&task, 0, QSE_SIZEOF(task)); | ||||
|  | ||||
| @ -541,7 +541,7 @@ qse_httpd_task_t* qse_httpd_entaskfile ( | ||||
| 	data.path.ptr = (qse_mchar_t*)path; | ||||
| 	data.path.len = qse_mbslen(path); | ||||
| 	data.version = *qse_htre_getversion(req); | ||||
| 	data.keepalive = (req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE); | ||||
| 	data.keepalive = (req->flags & QSE_HTRE_ATTR_KEEPALIVE); | ||||
| 	data.method = qse_htre_getqmethodtype(req); | ||||
|  | ||||
| 	xtnsize = QSE_SIZEOF(task_file_t) + data.path.len + 1; | ||||
|  | ||||
| @ -575,7 +575,7 @@ static int proxy_htrd_peek_peer_output (qse_htrd_t* htrd, qse_htre_t* res) | ||||
| 		proxy->resflags |= PROXY_RES_RECEIVED_RESHDR; | ||||
|  | ||||
| 		keepalive = proxy->keepalive; | ||||
| 		if (res->attr.flags & QSE_HTRE_ATTR_LENGTH) | ||||
| 		if (res->flags & QSE_HTRE_ATTR_LENGTH) | ||||
| 		{ | ||||
| 			/* the response from the peer is length based */ | ||||
| 			proxy->resflags |= PROXY_RES_PEER_LENGTH; | ||||
| @ -601,7 +601,7 @@ static int proxy_htrd_peek_peer_output (qse_htrd_t* htrd, qse_htre_t* res) | ||||
| 				/* chunk response when writing back to client */ | ||||
| 				proxy->resflags |= PROXY_RES_CLIENT_CHUNK; | ||||
|  | ||||
| 				if (res->attr.flags & QSE_HTRE_ATTR_CHUNKED) | ||||
| 				if (res->flags & QSE_HTRE_ATTR_CHUNKED) | ||||
| 				{ | ||||
| 					/* mark the peer output is chunked */ | ||||
| 					proxy->resflags |= PROXY_RES_PEER_CHUNK; | ||||
| @ -623,7 +623,7 @@ static int proxy_htrd_peek_peer_output (qse_htrd_t* htrd, qse_htre_t* res) | ||||
| 				/* and push the actual disconnection task */ | ||||
| 				if (qse_httpd_entaskdisconnect (httpd, xtn->client, xtn->task) == QSE_NULL) return -1; | ||||
|  | ||||
| 				if (res->attr.flags & QSE_HTRE_ATTR_CHUNKED) | ||||
| 				if (res->flags & QSE_HTRE_ATTR_CHUNKED) | ||||
| 					proxy->resflags |= PROXY_RES_PEER_CHUNK; | ||||
| 				else | ||||
| 					proxy->resflags |= PROXY_RES_PEER_CLOSE; | ||||
| @ -925,7 +925,7 @@ static int task_init_proxy ( | ||||
|  | ||||
| 	proxy->method = qse_htre_getqmethodtype(arg->req); | ||||
| 	proxy->version = *qse_htre_getversion(arg->req); | ||||
| 	proxy->keepalive = (arg->req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE); | ||||
| 	proxy->keepalive = (arg->req->flags & QSE_HTRE_ATTR_KEEPALIVE); | ||||
|  | ||||
| 	proxy->task = task; /* needed for url rewriting */ | ||||
|  | ||||
| @ -1030,6 +1030,7 @@ printf (">>>>>>>>>>>>>>>>>>>>>>>> [%s] <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n", proxy | ||||
| 	else | ||||
| 	{ | ||||
| 		int snatch_needed = 0; | ||||
| 		 | ||||
|  | ||||
| 		/* compose a request to send to the peer using the request | ||||
| 		 * received from the client */ | ||||
| @ -1038,7 +1039,26 @@ printf (">>>>>>>>>>>>>>>>>>>>>>>> [%s] <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n", proxy | ||||
| 			qse_mbs_cat (proxy->reqfwdbuf, QSE_MT(" ")) == (qse_size_t)-1) goto nomem_oops; | ||||
| 		 | ||||
| 		proxy->qpath_pos_in_reqfwdbuf = QSE_STR_LEN(proxy->reqfwdbuf); | ||||
| 		if (qse_mbs_cat (proxy->reqfwdbuf, qse_htre_getqpath(arg->req)) == (qse_size_t)-1) goto nomem_oops; | ||||
| 		if (arg->req->flags & QSE_HTRE_QPATH_PERDEC) | ||||
| 		{ | ||||
| 			/* the query path has been percent-decoded. so encode it back */ | ||||
| 			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); | ||||
| 			QSE_MMGR_FREE (httpd->mmgr, qpath_enc); | ||||
|  | ||||
| 			if (x == (qse_size_t)-1) goto nomem_oops; | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			/* the query path doesn't require encoding or it's never decoded */ | ||||
| 			if (qse_mbs_cat (proxy->reqfwdbuf, qse_htre_getqpath(arg->req)) == (qse_size_t)-1) goto nomem_oops; | ||||
| 		} | ||||
|  | ||||
| 		if (qse_htre_getqparam(arg->req)) | ||||
| 		{ | ||||
| @ -1081,7 +1101,7 @@ qse_mbs_ncat (proxy->reqfwdbuf, spc, QSE_COUNTOF(spc)); | ||||
| 		} | ||||
|  | ||||
| 		proxy->resflags |= PROXY_RES_AWAIT_RESHDR; | ||||
| 		if ((arg->req->attr.flags & QSE_HTRE_ATTR_EXPECT100) && | ||||
| 		if ((arg->req->flags & QSE_HTRE_ATTR_EXPECT100) && | ||||
| 		    (arg->req->version.major > 1 || (arg->req->version.major == 1 && arg->req->version.minor >= 1))) | ||||
| 		{ | ||||
| 			proxy->resflags |= PROXY_RES_AWAIT_100; | ||||
| @ -1115,8 +1135,8 @@ qse_mbs_ncat (proxy->reqfwdbuf, spc, QSE_COUNTOF(spc)); | ||||
| 		if (arg->req->state & QSE_HTRE_DISCARDED) | ||||
| 		{ | ||||
| 			/* no content to add */ | ||||
| 			if ((arg->req->attr.flags & QSE_HTRE_ATTR_LENGTH) ||  | ||||
| 			    (arg->req->attr.flags & QSE_HTRE_ATTR_CHUNKED)) | ||||
| 			if ((arg->req->flags & QSE_HTRE_ATTR_LENGTH) ||  | ||||
| 			    (arg->req->flags & QSE_HTRE_ATTR_CHUNKED)) | ||||
| 			{ | ||||
| 				/* i don't add chunk traiers if the  | ||||
| 				 * request content has been discarded */ | ||||
| @ -1129,15 +1149,15 @@ qse_mbs_ncat (proxy->reqfwdbuf, spc, QSE_COUNTOF(spc)); | ||||
| 		} | ||||
| 		else if (arg->req->state & QSE_HTRE_COMPLETED) | ||||
| 		{ | ||||
| 			if (arg->req->attr.flags & QSE_HTRE_ATTR_CHUNKED) | ||||
| 			if (arg->req->flags & QSE_HTRE_ATTR_CHUNKED) | ||||
| 			{ | ||||
| 				/* add trailers if any */ | ||||
| 				if (qse_htre_walktrailers (arg->req, proxy_capture_client_trailer, proxy) <= -1) goto nomem_oops; | ||||
| 			} | ||||
|  | ||||
| 			len = qse_htre_getcontentlen(arg->req); | ||||
| 			if (len > 0 || (arg->req->attr.flags & QSE_HTRE_ATTR_LENGTH) ||  | ||||
| 			               (arg->req->attr.flags & QSE_HTRE_ATTR_CHUNKED)) | ||||
| 			if (len > 0 || (arg->req->flags & QSE_HTRE_ATTR_LENGTH) ||  | ||||
| 			               (arg->req->flags & QSE_HTRE_ATTR_CHUNKED)) | ||||
| 			{ | ||||
| 				qse_mchar_t buf[64]; | ||||
|  | ||||
| @ -1163,7 +1183,7 @@ qse_mbs_ncat (proxy->reqfwdbuf, spc, QSE_COUNTOF(spc)); | ||||
| 				if (qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("\r\n")) == (qse_size_t)-1) goto nomem_oops; | ||||
| 			} | ||||
| 		} | ||||
| 		else if (arg->req->attr.flags & QSE_HTRE_ATTR_LENGTH) | ||||
| 		else if (arg->req->flags & QSE_HTRE_ATTR_LENGTH) | ||||
| 		{ | ||||
| 			/* the Content-Length header field is contained in the request. */ | ||||
| 			qse_mchar_t buf[64]; | ||||
| @ -1191,7 +1211,7 @@ qse_mbs_ncat (proxy->reqfwdbuf, spc, QSE_COUNTOF(spc)); | ||||
| 			/* if this request is not chunked nor not length based, | ||||
| 			 * the state should be QSE_HTRE_COMPLETED. so only a | ||||
| 			 * chunked request should reach here */ | ||||
| 			QSE_ASSERT (arg->req->attr.flags & QSE_HTRE_ATTR_CHUNKED); | ||||
| 			QSE_ASSERT (arg->req->flags & QSE_HTRE_ATTR_CHUNKED); | ||||
|  | ||||
| 			proxy->reqflags |= PROXY_REQ_FWDCHUNKED; | ||||
| 			if (qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("Transfer-Encoding: chunked\r\n")) == (qse_size_t)-1 || | ||||
|  | ||||
| @ -2087,7 +2087,7 @@ static int process_request ( | ||||
| 	 * any more. once it's decoded in the peek mode, | ||||
| 	 * the decoded query path is made available in the | ||||
| 	 * non-peek mode as well */ | ||||
| 	if (peek) qse_perdechttpstr (qse_htre_getqpath(req), qse_htre_getqpath(req)); | ||||
| 	if (peek) qse_htre_perdecqpath(req); | ||||
|  | ||||
| 	if (peek && (httpd->opt.trait & QSE_HTTPD_LOGACT)) | ||||
| 	{ | ||||
| @ -2154,11 +2154,11 @@ if (qse_htre_getcontentlen(req) > 0) | ||||
| 		else  | ||||
| 		{ | ||||
| 			if (mth == QSE_HTTP_POST && | ||||
| 				!(req->attr.flags & QSE_HTRE_ATTR_LENGTH) && | ||||
| 				!(req->attr.flags & QSE_HTRE_ATTR_CHUNKED)) | ||||
| 				!(req->flags & QSE_HTRE_ATTR_LENGTH) && | ||||
| 				!(req->flags & QSE_HTRE_ATTR_CHUNKED)) | ||||
| 			{ | ||||
| 				/* POST without Content-Length nor not chunked */ | ||||
| 				req->attr.flags &= ~QSE_HTRE_ATTR_KEEPALIVE; | ||||
| 				req->flags &= ~QSE_HTRE_ATTR_KEEPALIVE; | ||||
| 				qse_httpd_discardcontent (httpd, req); | ||||
| 				task = qse_httpd_entaskerr (httpd, client, QSE_NULL, 411, req); | ||||
| 				if (task)  | ||||
| @ -2234,7 +2234,7 @@ printf ("CANOT MAKE RESOURCE.... %s\n", qse_htre_getqpath(req)); | ||||
|  | ||||
| 			if (task == QSE_NULL) goto oops; | ||||
| 		} | ||||
| 		else if (req->attr.flags & QSE_HTRE_ATTR_PROXIED) | ||||
| 		else if (req->flags & QSE_HTRE_ATTR_PROXIED) | ||||
| 		{ | ||||
| 			/* the contents should be proxied.  | ||||
| 			 * do nothing locally */ | ||||
| @ -2246,7 +2246,7 @@ printf ("CANOT MAKE RESOURCE.... %s\n", qse_htre_getqpath(req)); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if (!(req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE) || mth == QSE_HTTP_CONNECT) | ||||
| 	if (!(req->flags & QSE_HTRE_ATTR_KEEPALIVE) || mth == QSE_HTTP_CONNECT) | ||||
| 	{ | ||||
| 		if (!peek) | ||||
| 		{ | ||||
| @ -2727,7 +2727,7 @@ static int make_resource ( | ||||
| 		case QSE_HTTPD_SERVERSTD_ROOT_PROXY: | ||||
| 			target->type = QSE_HTTPD_RSRC_PROXY; | ||||
| 			target->u.proxy = tmp.root.u.proxy; | ||||
| 			req->attr.flags |= QSE_HTRE_ATTR_PROXIED; | ||||
| 			req->flags |= QSE_HTRE_ATTR_PROXIED; | ||||
| 			return 0; | ||||
|  | ||||
| 		case QSE_HTTPD_SERVERSTD_ROOT_ERROR: | ||||
| @ -2797,7 +2797,7 @@ auth_ok: | ||||
|  | ||||
| 	/* if authentication is ok or no authentication is required, | ||||
| 	 * handle 'Expect: 100-continue' if it is contained in the header */ | ||||
| 	if ((req->attr.flags & QSE_HTRE_ATTR_EXPECT) && | ||||
| 	if ((req->flags & QSE_HTRE_ATTR_EXPECT) && | ||||
| 	    (req->version.major > 1 || (req->version.major == 1 && req->version.minor >= 1)) && | ||||
| 	    qse_htre_getcontentlen(req) <= 0) | ||||
| 	{ | ||||
| @ -2807,7 +2807,7 @@ auth_ok: | ||||
| 		 * if the partial or complete content is already received, | ||||
| 		 * we don't need to send '100 continue'. */ | ||||
|  | ||||
| 		if (req->attr.flags & QSE_HTRE_ATTR_EXPECT100) | ||||
| 		if (req->flags & QSE_HTRE_ATTR_EXPECT100) | ||||
| 		{ | ||||
| 			/* "Expect: 100-continue" in the header. | ||||
| 			 * mark to return "100 continue" */ | ||||
|  | ||||
| @ -242,7 +242,7 @@ qse_httpd_task_t* qse_httpd_entaskerr ( | ||||
| 		httpd, client, pred, code, QSE_NULL,  | ||||
| 		qse_htre_getqmethodtype(req),  | ||||
| 		qse_htre_getversion(req),  | ||||
| 		(req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE) | ||||
| 		(req->flags & QSE_HTRE_ATTR_KEEPALIVE) | ||||
| 	); | ||||
| } | ||||
|  | ||||
| @ -268,7 +268,7 @@ qse_httpd_task_t* qse_httpd_entaskauth ( | ||||
| 		httpd, client, pred, 401, (void*)realm,  | ||||
| 		qse_htre_getqmethodtype(req), | ||||
| 		qse_htre_getversion(req),  | ||||
| 		(req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE)); | ||||
| 		(req->flags & QSE_HTRE_ATTR_KEEPALIVE)); | ||||
| } | ||||
|  | ||||
|  | ||||
| @ -287,7 +287,7 @@ qse_httpd_task_t* qse_httpd_entaskreloc ( | ||||
| 		httpd, client, pred, 301, (void*)&reloc, | ||||
| 		qse_htre_getqmethodtype(req),  | ||||
| 		qse_htre_getversion(req),  | ||||
| 		(req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE)); | ||||
| 		(req->flags & QSE_HTRE_ATTR_KEEPALIVE)); | ||||
| } | ||||
|  | ||||
| qse_httpd_task_t* qse_httpd_entaskredir ( | ||||
| @ -303,7 +303,7 @@ qse_httpd_task_t* qse_httpd_entaskredir ( | ||||
| 		httpd, client, pred, 301, (void*)&reloc, | ||||
| 		qse_htre_getqmethodtype(req),  | ||||
| 		qse_htre_getversion(req),  | ||||
| 		(req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE)); | ||||
| 		(req->flags & QSE_HTRE_ATTR_KEEPALIVE)); | ||||
| } | ||||
|  | ||||
| /*------------------------------------------------------------------------*/ | ||||
| @ -324,7 +324,7 @@ qse_httpd_task_t* qse_httpd_entasknomod ( | ||||
| 		httpd, client, pred, 304, QSE_NULL,  | ||||
| 		qse_htre_getqmethodtype(req),  | ||||
| 		qse_htre_getversion(req),  | ||||
| 		(req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE)); | ||||
| 		(req->flags & QSE_HTRE_ATTR_KEEPALIVE)); | ||||
| } | ||||
|  | ||||
| /*------------------------------------------------------------------------*/ | ||||
| @ -340,7 +340,7 @@ qse_httpd_task_t* qse_httpd_entaskallow ( | ||||
|  | ||||
| 	msg = qse_httpstatustombs (code); | ||||
| 	version = qse_htre_getversion(req); | ||||
| 	keepalive = (req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE); | ||||
| 	keepalive = (req->flags & QSE_HTRE_ATTR_KEEPALIVE); | ||||
| 	return qse_httpd_entaskformat ( | ||||
| 		httpd, client, pred, | ||||
| 		QSE_MT("HTTP/%d.%d %d %s\r\nServer: %s\r\nDate: %s\r\nConnection: %s\r\nAllow: %s\r\nContent-Length: 0\r\n\r\n"), | ||||
|  | ||||
| @ -112,7 +112,7 @@ qse_httpd_task_t* qse_httpd_entasktext ( | ||||
| 		version->major, version->minor, | ||||
| 		qse_httpd_getname (httpd), | ||||
| 		qse_httpd_fmtgmtimetobb (httpd, QSE_NULL, 0), | ||||
| 		((req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE)? QSE_MT("keep-alive"): QSE_MT("close")), | ||||
| 		((req->flags & QSE_HTRE_ATTR_KEEPALIVE)? QSE_MT("keep-alive"): QSE_MT("close")), | ||||
| 		mime, b_tlen | ||||
| 	); | ||||
| 	if (pred == QSE_NULL) return QSE_NULL; | ||||
|  | ||||
		Reference in New Issue
	
	Block a user