added mio_perdec_http_bcs()
This commit is contained in:
		| @ -818,6 +818,14 @@ static void on_dnc_resolve_brief (mio_svc_dnc_t* dnc, mio_dns_msg_t* reqmsg, mio | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static int print_qparam (mio_bcs_t* key, mio_bcs_t* val, void* ctx) | ||||||
|  | { | ||||||
|  | 	key->len = mio_perdec_http_bcs(key, key->ptr, MIO_NULL); | ||||||
|  | 	val->len = mio_perdec_http_bcs(val, val->ptr, MIO_NULL); | ||||||
|  | 	fprintf ((FILE*)ctx, "\t[%.*s] = [%.*s]\n", (int)key->len, key->ptr, (int)val->len, val->ptr); | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
| static void on_htts_thr_request (mio_t* mio, mio_dev_thr_iopair_t* iop, mio_svc_htts_thr_func_info_t* tfi, void* ctx) | static void on_htts_thr_request (mio_t* mio, mio_dev_thr_iopair_t* iop, mio_svc_htts_thr_func_info_t* tfi, void* ctx) | ||||||
| { | { | ||||||
| 	FILE* fp; | 	FILE* fp; | ||||||
| @ -840,7 +848,11 @@ static void on_htts_thr_request (mio_t* mio, mio_dev_thr_iopair_t* iop, mio_svc_ | |||||||
| 	fprintf (fp, "Content-Type: text/html\r\n\r\n"); | 	fprintf (fp, "Content-Type: text/html\r\n\r\n"); | ||||||
|  |  | ||||||
| 	fprintf (fp, "request path = %s\n", tfi->req_path); | 	fprintf (fp, "request path = %s\n", tfi->req_path); | ||||||
| 	if (tfi->req_param) fprintf (fp, "request param = %s\n", tfi->req_param); | 	if (tfi->req_param)  | ||||||
|  | 	{ | ||||||
|  | 		fprintf (fp, "request params:\n"); | ||||||
|  | 		mio_scan_http_qparam (tfi->req_param, print_qparam, fp); | ||||||
|  | 	} | ||||||
| 	for (i = 0; i < 100; i++) fprintf (fp, "%d * %d => %d\n", i, i, i * i); | 	for (i = 0; i < 100; i++) fprintf (fp, "%d * %d => %d\n", i, i, i * i); | ||||||
|  |  | ||||||
| 	fclose (fp); | 	fclose (fp); | ||||||
|  | |||||||
| @ -383,7 +383,6 @@ pdfdir = @pdfdir@ | |||||||
| prefix = @prefix@ | prefix = @prefix@ | ||||||
| program_transform_name = @program_transform_name@ | program_transform_name = @program_transform_name@ | ||||||
| psdir = @psdir@ | psdir = @psdir@ | ||||||
| runstatedir = @runstatedir@ |  | ||||||
| sbindir = @sbindir@ | sbindir = @sbindir@ | ||||||
| sharedstatedir = @sharedstatedir@ | sharedstatedir = @sharedstatedir@ | ||||||
| srcdir = @srcdir@ | srcdir = @srcdir@ | ||||||
|  | |||||||
							
								
								
									
										116
									
								
								mio/lib/http.c
									
									
									
									
									
								
							
							
						
						
									
										116
									
								
								mio/lib/http.c
									
									
									
									
									
								
							| @ -456,6 +456,41 @@ mio_oow_t mio_perdec_http_bcstr (const mio_bch_t* str, mio_bch_t* buf, mio_oow_t | |||||||
| 	return out - buf; | 	return out - buf; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | mio_oow_t mio_perdec_http_bcs (const mio_bcs_t* str, mio_bch_t* buf, mio_oow_t* ndecs) | ||||||
|  | { | ||||||
|  | 	const mio_bch_t* p = str->ptr; | ||||||
|  | 	const mio_bch_t* end = str->ptr + str->len; | ||||||
|  | 	mio_bch_t* out = buf; | ||||||
|  | 	mio_oow_t dec_count = 0; | ||||||
|  |  | ||||||
|  | 	while (p < end) | ||||||
|  | 	{ | ||||||
|  | 		if (*p == '%' && (p + 2) < end) | ||||||
|  | 		{ | ||||||
|  | 			int q = MIO_XDIGIT_TO_NUM(*(p + 1)); | ||||||
|  | 			if (q >= 0) | ||||||
|  | 			{ | ||||||
|  | 				int w = MIO_XDIGIT_TO_NUM(*(p + 2)); | ||||||
|  | 				if (w >= 0) | ||||||
|  | 				{ | ||||||
|  | 					/* we don't care if it contains a null character */ | ||||||
|  | 					*out++ = ((q << 4) + w); | ||||||
|  | 					p += 3; | ||||||
|  | 					dec_count++; | ||||||
|  | 					continue; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		*out++ = *p++; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/* [NOTE] this function deesn't insert '\0' at the end */ | ||||||
|  |  | ||||||
|  | 	if (ndecs) *ndecs = dec_count; | ||||||
|  | 	return out - buf; | ||||||
|  | } | ||||||
|  |  | ||||||
| #define IS_UNRESERVED(c) \ | #define IS_UNRESERVED(c) \ | ||||||
| 	(((c) >= 'A' && (c) <= 'Z') || \ | 	(((c) >= 'A' && (c) <= 'Z') || \ | ||||||
| 	 ((c) >= 'a' && (c) <= 'z') || \ | 	 ((c) >= 'a' && (c) <= 'z') || \ | ||||||
| @ -546,100 +581,61 @@ mio_bch_t* mio_perenc_http_bcstrdup (int opt, const mio_bch_t* str, mio_mmgr_t* | |||||||
| } | } | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #if 0 |  | ||||||
| int mio_scan_http_qparam (mio_htrd_t* htrd, const mio_bch_t* qparam) | int mio_scan_http_qparam (mio_bch_t* qparam, int (*qparamcb) (mio_bcs_t* key, mio_bcs_t* val, void* ctx), void* ctx) | ||||||
| { | { | ||||||
| 	mio_bcs_t key, val; | 	mio_bcs_t key, val; | ||||||
| 	const mio_bch_t* p, * end; | 	mio_bch_t* p, * end; | ||||||
| 	mio_bch_t* out; |  | ||||||
|  |  | ||||||
| 	p = qparam |  | ||||||
| 	if (!p) return 0; /* no param string to scan */ |  | ||||||
|  |  | ||||||
|  | 	p = qparam; | ||||||
| 	end = p + mio_count_bcstr(qparam); | 	end = p + mio_count_bcstr(qparam); | ||||||
|  |  | ||||||
| 	/* a key and a value pair including two terminating null  | 	key.ptr = p; key.len = 0; | ||||||
| 	 * can't exceed the the qparamstrlen + 2. only +1 below as there is |  | ||||||
| 	 * one more space for an internal terminating null */ |  | ||||||
| 	mio_becs_setlen (&htrd->tmp.qparam, cstr->len + 1); |  | ||||||
|  |  | ||||||
| 	/* let out point to the beginning of the qparam buffer. |  | ||||||
| 	 * the loop below emits percent-decode key and value to this buffer. */ |  | ||||||
| 	out = MIO_BECS_PTR(&htrd->tmp.qparam); |  | ||||||
|  |  | ||||||
| 	key.ptr = out; key.len = 0; |  | ||||||
| 	val.ptr = MIO_NULL; val.len = 0; | 	val.ptr = MIO_NULL; val.len = 0; | ||||||
|  |  | ||||||
| 	do | 	do | ||||||
| 	{ | 	{ | ||||||
| 		if (p >= end || *p == '&' || *p == ';') | 		if (p >= end || *p == '&' || *p == ';') | ||||||
| 		{ | 		{ | ||||||
| 			MIO_ASSERT (htrd->mio, key.ptr != MIO_NULL); | 			if (val.ptr) | ||||||
|  |  | ||||||
| 			*out++ = '\0';  |  | ||||||
| 			if (val.ptr == MIO_NULL)  |  | ||||||
| 			{ | 			{ | ||||||
| 				if (key.len == 0)  | 				val.len = p - val.ptr; | ||||||
| 				{ |  | ||||||
| 					/* both key and value are empty. |  | ||||||
| 					 * we don't need to do anything */ |  | ||||||
| 					goto next_octet; |  | ||||||
| 			} | 			} | ||||||
|  | 			else | ||||||
| 				val.ptr = out; | 			{ | ||||||
| 				*out++ = '\0';  | 				key.len = p - key.ptr; | ||||||
| 				MIO_ASSERT (htrd->mio, val.len == 0); | 				if (key.len == 0) goto next_octet; /* both key and value are empty. we don't need to do anything */ | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			/* set request parameter string callback before scanning */ | 			/* set request parameter string callback before scanning */ | ||||||
| 			MIO_ASSERT (htrd->mio, htrd->recbs.qparamstr != MIO_NULL); | 			if (qparamcb(&key, &val, ctx) <= -1) return -1; | ||||||
|  |  | ||||||
| 			if (htrd->recbs.qparamstr(htrd, &key, &val) <= -1) return -1; |  | ||||||
|  |  | ||||||
| 		next_octet: | 		next_octet: | ||||||
| 			if (p >= end) break; | 			if (p >= end) break; | ||||||
| 			p++; | 			p++; | ||||||
|  |  | ||||||
| 			out = MIO_BECS_PTR(&htrd->tmp.qparam); | 			key.ptr = p; key.len = 0; | ||||||
| 			key.ptr = out; key.len = 0; |  | ||||||
| 			val.ptr = MIO_NULL; val.len = 0; | 			val.ptr = MIO_NULL; val.len = 0; | ||||||
| 		} | 		} | ||||||
| 		else if (*p == '=') | 		else if (*p == '=') | ||||||
| 		{ | 		{ | ||||||
| 			*out++ = '\0'; p++; | 			if (!val.ptr) | ||||||
|  | 			{ | ||||||
| 			val.ptr = out; | 				key.len = p - key.ptr; | ||||||
|  | 				val.ptr = ++p; | ||||||
| 				/*val.len = 0; */ | 				/*val.len = 0; */ | ||||||
| 			} | 			} | ||||||
| 			else | 			else | ||||||
| 			{ | 			{ | ||||||
| 			if (*p == '%' && p + 2 <= end) | 				p++; | ||||||
| 			{ |  | ||||||
| 				int q = xdigit_to_num(*(p+1)); |  | ||||||
| 				if (q >= 0) |  | ||||||
| 				{ |  | ||||||
| 					int w = xdigit_to_num(*(p+2)); |  | ||||||
| 					if (w >= 0) |  | ||||||
| 					{ |  | ||||||
| 						/* unlike the path part, we don't care if it  |  | ||||||
| 						 * contains a null character */ |  | ||||||
| 						*out++ = ((q << 4) + w); |  | ||||||
| 						p += 3; |  | ||||||
| 						goto next; |  | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 			} | 		else | ||||||
|  | 		{ | ||||||
| 			*out++ = *p++; | 			p++; | ||||||
|  |  | ||||||
| 		next: |  | ||||||
| 			if (val.ptr) val.len++; |  | ||||||
| 			else key.len++; |  | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	while (1); | 	while (1); | ||||||
|  |  | ||||||
| 	mio_becs_clear (&htrd->tmp.qparam); |  | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| #endif |  | ||||||
|  | |||||||
| @ -220,6 +220,16 @@ MIO_EXPORT mio_oow_t mio_perdec_http_bcstr ( | |||||||
| 	mio_oow_t*       ndecs | 	mio_oow_t*       ndecs | ||||||
| ); | ); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * The mio_perdec_http_bcstr() function performs percent-decoding over a length-bound string. | ||||||
|  |  * It doesn't insert the terminating null. | ||||||
|  |  */ | ||||||
|  | MIO_EXPORT mio_oow_t mio_perdec_http_bcs ( | ||||||
|  | 	const mio_bcs_t* str,  | ||||||
|  | 	mio_bch_t*       buf, | ||||||
|  | 	mio_oow_t*       ndecs | ||||||
|  | ); | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * The mio_perenc_http_bcstr() function performs percent-encoding over a string. |  * The mio_perenc_http_bcstr() function performs percent-encoding over a string. | ||||||
|  * The caller must ensure that the output buffer \a buf is large enough. |  * The caller must ensure that the output buffer \a buf is large enough. | ||||||
| @ -243,6 +253,12 @@ MIO_EXPORT mio_bch_t* mio_perenc_http_bcstrdup ( | |||||||
| ); | ); | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | MIO_EXPORT int mio_scan_http_qparam ( | ||||||
|  | 	mio_bch_t*      qparam, | ||||||
|  | 	int (*qparamcb) (mio_bcs_t* key, mio_bcs_t* val, void* ctx), | ||||||
|  | 	void*           ctx | ||||||
|  | ); | ||||||
|  |  | ||||||
| /* ------------------------------------------------------------------------- */ | /* ------------------------------------------------------------------------- */ | ||||||
| /* HTTP SERVER SERVICE                                                       */ | /* HTTP SERVER SERVICE                                                       */ | ||||||
| /* ------------------------------------------------------------------------- */ | /* ------------------------------------------------------------------------- */ | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user