added more lines for http parsing
This commit is contained in:
		| @ -1,5 +1,5 @@ | |||||||
| /* | /* | ||||||
|  * $Id: htb.h 356 2010-09-07 12:29:25Z hyunghwan.chung $ |  * $Id: htb.h 362 2010-10-26 13:01:16Z hyunghwan.chung $ | ||||||
|  * |  * | ||||||
|     Copyright 2006-2009 Chung, Hyung-Hwan. |     Copyright 2006-2009 Chung, Hyung-Hwan. | ||||||
|     This file is part of QSE. |     This file is part of QSE. | ||||||
| @ -444,9 +444,9 @@ void qse_htb_clear ( | |||||||
|  * The qse_htb_walk() function traverses a hash table. |  * The qse_htb_walk() function traverses a hash table. | ||||||
|  */ |  */ | ||||||
| void qse_htb_walk ( | void qse_htb_walk ( | ||||||
| 	qse_htb_t* htb,          /**< hash table */ | 	qse_htb_t*       htb,    /**< hash table */ | ||||||
| 	qse_htb_walker_t walker, /**< callback function for each pair */ | 	qse_htb_walker_t walker, /**< callback function for each pair */ | ||||||
| 	void* ctx                /**< pointer to user-specific data */ | 	void*            ctx     /**< pointer to user-specific data */ | ||||||
| ); | ); | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  | |||||||
| @ -7,6 +7,7 @@ | |||||||
|  |  | ||||||
| #include <qse/types.h> | #include <qse/types.h> | ||||||
| #include <qse/macros.h> | #include <qse/macros.h> | ||||||
|  | #include <qse/cmn/htb.h> | ||||||
|  |  | ||||||
|  |  | ||||||
| typedef struct qse_http_octb_t qse_http_octb_t; | typedef struct qse_http_octb_t qse_http_octb_t; | ||||||
| @ -69,14 +70,25 @@ struct qse_http_t | |||||||
| 			QSE_HTTP_REQ_POST | 			QSE_HTTP_REQ_POST | ||||||
| 		} method; | 		} method; | ||||||
|  |  | ||||||
| 		const qse_byte_t* path;	 | 		struct | ||||||
| 		const qse_byte_t* args; | 		{ | ||||||
|  | 			qse_byte_t* ptr; | ||||||
|  | 			qse_size_t  len; | ||||||
|  | 		} path; | ||||||
|  |  | ||||||
|  | 		struct | ||||||
|  | 		{ | ||||||
|  | 			qse_byte_t* ptr; | ||||||
|  | 			qse_size_t  len; | ||||||
|  | 		} args; | ||||||
|  |  | ||||||
| 		struct | 		struct | ||||||
| 		{ | 		{ | ||||||
| 			short major; | 			short major; | ||||||
| 			short minor; | 			short minor; | ||||||
| 		} version; | 		} version; | ||||||
|  |  | ||||||
|  | 		qse_htb_t hdr; | ||||||
| 	} req; | 	} req; | ||||||
|  |  | ||||||
| }; | }; | ||||||
|  | |||||||
| @ -218,6 +218,11 @@ static QSE_INLINE int is_space_octet (qse_byte_t c) | |||||||
| 	return c == ' ' || c == '\t' || c == '\r'; | 	return c == ' ' || c == '\t' || c == '\r'; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static QSE_INLINE int is_purespace_octet (qse_byte_t c) | ||||||
|  | { | ||||||
|  | 	return c == ' ' || c == '\t'; | ||||||
|  | } | ||||||
|  |  | ||||||
| static QSE_INLINE int is_upalpha_octet (qse_byte_t c) | static QSE_INLINE int is_upalpha_octet (qse_byte_t c) | ||||||
| { | { | ||||||
| 	return c >= 'A' && c <= 'Z'; | 	return c >= 'A' && c <= 'Z'; | ||||||
| @ -370,11 +375,19 @@ qse_http_t* qse_http_init (qse_http_t* http, qse_mmgr_t* mmgr) | |||||||
| 	http->state.crlf = 0; | 	http->state.crlf = 0; | ||||||
| 	http->state.plen = 0; | 	http->state.plen = 0; | ||||||
| 	init_buffer (http, &http->req.raw); | 	init_buffer (http, &http->req.raw); | ||||||
|  |  | ||||||
|  | 	if (qse_htb_init (&http->req.hdr, mmgr, 60, 70) == QSE_NULL)  | ||||||
|  | 	{ | ||||||
|  | 		fini_buffer (http, &http->req.raw); | ||||||
|  | 		return QSE_NULL; | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	return http; | 	return http; | ||||||
| } | } | ||||||
|  |  | ||||||
| void qse_http_fini (qse_http_t* http) | void qse_http_fini (qse_http_t* http) | ||||||
| { | { | ||||||
|  | 	qse_htb_fini (&http->req.hdr); | ||||||
| 	fini_buffer (http, &http->req.raw); | 	fini_buffer (http, &http->req.raw); | ||||||
| } | } | ||||||
|  |  | ||||||
| @ -421,11 +434,11 @@ static qse_byte_t* parse_http_req (qse_http_t* http, qse_byte_t* line) | |||||||
| 	while (is_space_octet(*p)) p++; | 	while (is_space_octet(*p)) p++; | ||||||
|  |  | ||||||
| 	/* process the url part */ | 	/* process the url part */ | ||||||
| 	http->req.path = p;  | 	http->req.path.ptr = p;  | ||||||
| 	http->req.args = QSE_NULL; | 	http->req.args.ptr = QSE_NULL; | ||||||
|  |  | ||||||
| 	tmp = p; | 	tmp = p; | ||||||
| 	while (!is_space_octet(*p))  | 	while (*p != '\0' && !is_space_octet(*p))  | ||||||
| 	{ | 	{ | ||||||
| 		if (*p == '%') | 		if (*p == '%') | ||||||
| 		{ | 		{ | ||||||
| @ -448,12 +461,13 @@ static qse_byte_t* parse_http_req (qse_http_t* http, qse_byte_t* line) | |||||||
| 		} | 		} | ||||||
| 		else if (*p == '?') | 		else if (*p == '?') | ||||||
| 		{ | 		{ | ||||||
| 			if (!http->req.args) | 			if (!http->req.args.ptr) | ||||||
| 			{ | 			{ | ||||||
| 				/* ? must be explicit to be a argument instroducer.  | 				/* ? must be explicit to be a argument instroducer.  | ||||||
| 				 * %3f is just a literal. */ | 				 * %3f is just a literal. */ | ||||||
| 				*tmp++ = '\0'; | 				http->req.path.len = tmp - http->req.path.ptr; | ||||||
| 				http->req.args = tmp; | 				/**tmp++ = '\0';*/ | ||||||
|  | 				http->req.args.ptr = tmp; | ||||||
| 				p++; | 				p++; | ||||||
| 			} | 			} | ||||||
| 			else *tmp++ = *p++; | 			else *tmp++ = *p++; | ||||||
| @ -464,8 +478,11 @@ static qse_byte_t* parse_http_req (qse_http_t* http, qse_byte_t* line) | |||||||
| 	/* the url must be followed by a space */ | 	/* the url must be followed by a space */ | ||||||
| 	if (!is_space_octet(*p)) goto badreq; | 	if (!is_space_octet(*p)) goto badreq; | ||||||
|  |  | ||||||
| 	/* null-terminate the url part */ | 	if (http->req.args.ptr) | ||||||
| 	*tmp = '\0'; | 		http->req.args.len = tmp - http->req.args.ptr; | ||||||
|  | 	else | ||||||
|  | 		http->req.path.len = tmp - http->req.path.ptr; | ||||||
|  | 	/* *tmp = '\0'; */ /* null-terminate the url part */ | ||||||
|  |  | ||||||
| 	/* skip spaces after the url part */ | 	/* skip spaces after the url part */ | ||||||
| 	do { p++; } while (is_space_octet(*p)); | 	do { p++; } while (is_space_octet(*p)); | ||||||
| @ -499,13 +516,14 @@ qse_printf (QSE_T("parse_http_req ....\n")); | |||||||
| 	return ++p; | 	return ++p; | ||||||
|  |  | ||||||
| badreq: | badreq: | ||||||
|  | qse_printf (QSE_T("BADREQ\n")); | ||||||
| 	http->errnum = QSE_HTTP_EBADREQ; | 	http->errnum = QSE_HTTP_EBADREQ; | ||||||
| 	return QSE_NULL; | 	return QSE_NULL; | ||||||
| } | } | ||||||
|  |  | ||||||
| qse_byte_t* parse_http_header (qse_http_t* http, qse_byte_t* line) | qse_byte_t* parse_http_header (qse_http_t* http, qse_byte_t* line) | ||||||
| { | { | ||||||
| 	qse_byte_t* p = line, * mark; | 	qse_byte_t* p = line, * last; | ||||||
| 	struct | 	struct | ||||||
| 	{ | 	{ | ||||||
| 		qse_byte_t* ptr; | 		qse_byte_t* ptr; | ||||||
| @ -517,28 +535,65 @@ qse_byte_t* parse_http_header (qse_http_t* http, qse_byte_t* line) | |||||||
| 	while (is_space_octet(*p)) p++; | 	while (is_space_octet(*p)) p++; | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| 	name.ptr = p; | 	QSE_ASSERT (!is_whspace_octet(*p)); | ||||||
| 	while (!is_whspace_octet(*p) && *p != ':') p++; |  | ||||||
| 	name.len = p - name.ptr; | 	/* check the field name */ | ||||||
|  | 	name.ptr = last = p; | ||||||
|  | 	while (*p != '\0' && *p != '\n' && *p != ':') | ||||||
|  | 	{ | ||||||
|  | 		if (!is_space_octet(*p++)) last = p; | ||||||
|  | 	} | ||||||
|  | 	name.len = last - name.ptr; | ||||||
|  |  | ||||||
| 	mark = p; while (is_space_octet(*p)) p++; |  | ||||||
| 	if (*p != ':') goto badhdr; | 	if (*p != ':') goto badhdr; | ||||||
| 	*mark = '\0'; | 	*last = '\0'; | ||||||
|  |  | ||||||
| 	/* skip the colon and spaces after it */ | 	/* skip the colon and spaces after it */ | ||||||
| 	do { p++; } while (is_space_octet(*p)); | 	do { p++; } while (is_space_octet(*p)); | ||||||
|  |  | ||||||
| 	value.ptr = p; | 	value.ptr = last = p; | ||||||
| 	do { p++; } while (!is_whspace_octet(*p)); | 	while (*p != '\0' && *p != '\n') | ||||||
| 	value.len = p - value.ptr; | 	{ | ||||||
|  | 		if (!is_space_octet(*p++)) last = p; | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	/* skip trailing spaces on the line */ | 	value.len = last - value.ptr; | ||||||
| 	mark = p; while (is_space_octet(*p)) p++; |  | ||||||
| 	if (*p != '\n') goto badhdr; /* not ending with a new line */ | 	if (*p != '\n') goto badhdr; /* not ending with a new line */ | ||||||
| 	*mark = '\0'; |  | ||||||
|  |  | ||||||
|  | 	/* peep at the beginning of the next line to check if it is  | ||||||
|  | 	 * the continuation */ | ||||||
|  | 	if (is_purespace_octet (*++p)) | ||||||
|  | 	{ | ||||||
|  | 		qse_byte_t* cpydst; | ||||||
|  |  | ||||||
|  | 		cpydst = p - 1; | ||||||
|  | 		if (*(cpydst-1) == '\r') cpydst--; | ||||||
|  |  | ||||||
|  | 		/* process all continued lines */ | ||||||
|  | 		do  | ||||||
|  | 		{ | ||||||
|  | 			while (*p != '\0' && *p != '\n') | ||||||
|  | 			{ | ||||||
|  | 				*cpydst = *p++;  | ||||||
|  | 				if (!is_space_octet(*cpydst++)) last = cpydst; | ||||||
|  | 			}  | ||||||
|  | 	 | ||||||
|  | 			value.len = last - value.ptr; | ||||||
|  | 			if (*p != '\n') goto badhdr; | ||||||
|  |  | ||||||
|  | 			if (*(cpydst-1) == '\r') cpydst--; | ||||||
|  | 		} | ||||||
|  | 		while (is_purespace_octet(*++p)); | ||||||
|  | 	} | ||||||
|  | 	*last = '\0'; | ||||||
|  |  | ||||||
|  | 	if (qse_htb_insert (&http->req.hdr, | ||||||
|  | 		name.ptr, name.len, value.ptr, value.len) == QSE_NULL) | ||||||
|  | 	{ | ||||||
|  | 		http->errnum = QSE_HTTP_ENOMEM; | ||||||
|  | 		return QSE_NULL; | ||||||
|  | 	} | ||||||
|  |  | ||||||
| qse_printf (QSE_T("<<%S>> => <<%S>>\n"),  name.ptr, value.ptr); |  | ||||||
| 	return p; | 	return p; | ||||||
|  |  | ||||||
| badhdr: | badhdr: | ||||||
| @ -547,6 +602,10 @@ qse_printf (QSE_T("BADHDR\n"),  name.ptr, value.ptr); | |||||||
| 	return QSE_NULL; | 	return QSE_NULL; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static qse_htb_walk_t walk (qse_htb_t* htb, qse_htb_pair_t* pair, void* ctx) | ||||||
|  | { | ||||||
|  | qse_printf (QSE_T("HEADER OK %d[%S] %d[%S]\n"),  (int)pair->klen, pair->kptr, (int)pair->vlen, pair->vptr); | ||||||
|  | } | ||||||
|  |  | ||||||
| /* feed the percent encoded string */ | /* feed the percent encoded string */ | ||||||
| int qse_http_feed (qse_http_t* http, const qse_byte_t* ptr, qse_size_t len) | int qse_http_feed (qse_http_t* http, const qse_byte_t* ptr, qse_size_t len) | ||||||
| @ -603,6 +662,9 @@ int qse_http_feed (qse_http_t* http, const qse_byte_t* ptr, qse_size_t len) | |||||||
| 					if (p == QSE_NULL) return -1; | 					if (p == QSE_NULL) return -1; | ||||||
| 				} | 				} | ||||||
| 				while (1); | 				while (1); | ||||||
|  | 					 | ||||||
|  | qse_htb_walk (&http->req.hdr, walk, QSE_NULL); | ||||||
|  | /* TODO: do the main job here... before the raw buffer is cleared out... */ | ||||||
| 			 | 			 | ||||||
| 				clear_buffer (http, &http->req.raw); | 				clear_buffer (http, &http->req.raw); | ||||||
| 				req = ptr; /* let ptr point to the next character to '\n' */ | 				req = ptr; /* let ptr point to the next character to '\n' */ | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user