added more cgi related code
This commit is contained in:
		| @ -45,8 +45,9 @@ enum qse_htrd_option_t | ||||
| { | ||||
| 	QSE_HTRD_SKIPEMPTYLINES  = (1 << 0), /**< skip leading empty lines before the initial line */ | ||||
| 	QSE_HTRD_SKIPINITIALLINE = (1 << 1), /**< skip processing an initial line */ | ||||
| 	QSE_HTRD_REQUEST         = (1 << 2), /**< parse input as a request */ | ||||
| 	QSE_HTRD_RESPONSE        = (1 << 3)  /**< parse input as a response */ | ||||
| 	QSE_HTRD_HURRIED         = (1 << 2), /**< trigger a callback also after headers without processing contents */ | ||||
| 	QSE_HTRD_REQUEST         = (1 << 3), /**< parse input as a request */ | ||||
| 	QSE_HTRD_RESPONSE        = (1 << 4)  /**< parse input as a response */ | ||||
| }; | ||||
|  | ||||
| typedef enum qse_htrd_option_t qse_htrd_option_t; | ||||
| @ -96,15 +97,6 @@ struct qse_htrd_t | ||||
| 		void* chl; | ||||
| 	} fed;  | ||||
|  | ||||
| #if 0 | ||||
| 	struct | ||||
| 	{ | ||||
| 		/* temporary space to store a key and value pair | ||||
| 		 * during the call to qse_http_scanqparamstr() */ | ||||
| 		qse_htob_t qparam;  | ||||
| 	} tmp; | ||||
| #endif | ||||
|  | ||||
| 	enum  | ||||
| 	{ | ||||
| 		QSE_HTRD_RETYPE_Q, | ||||
|  | ||||
| @ -35,23 +35,27 @@ struct qse_htre_t | ||||
| 	qse_http_version_t version; | ||||
|  | ||||
| 	int qmethod_or_sstatus;  | ||||
| 	qse_htob_t qpath_or_smesg; | ||||
| 	qse_htob_t qparam; | ||||
| 	qse_mbs_t qpath_or_smesg; | ||||
| 	qse_mbs_t qparam; | ||||
|  | ||||
| 	/* special attributes derived from the header */ | ||||
| 	struct | ||||
| 	{ | ||||
| 		int chunked;		 | ||||
| 		int content_length; | ||||
| 		int content_length_set; | ||||
| 		qse_size_t content_length; | ||||
| 		int connection_close; | ||||
| 		int expect_continue; | ||||
|  | ||||
| 		/* indicates if the content has been filled */ | ||||
| 		int hurried; | ||||
| 	} attr; | ||||
|  | ||||
| 	/* header table */ | ||||
| 	qse_htb_t hdrtab; | ||||
| 	 | ||||
| 	/* content octets */ | ||||
| 	qse_htob_t content; | ||||
| 	qse_mbs_t content; | ||||
|  | ||||
| 	/* if set, the rest of the contents are discarded */ | ||||
| 	int discard; | ||||
| @ -140,13 +144,13 @@ void qse_htre_clear ( | ||||
|  | ||||
| int qse_htre_setstrfromcstr ( | ||||
| 	qse_htre_t*        re, | ||||
| 	qse_htob_t*        str, | ||||
| 	qse_mbs_t*         str, | ||||
| 	const qse_mcstr_t* cstr | ||||
| ); | ||||
|  | ||||
| int qse_htre_setstrfromxstr ( | ||||
| 	qse_htre_t*        re, | ||||
| 	qse_htob_t*        str, | ||||
| 	qse_mbs_t*         str, | ||||
| 	const qse_mxstr_t* xstr | ||||
| ); | ||||
|  | ||||
|  | ||||
| @ -38,35 +38,35 @@ static QSE_INLINE int is_space_octet (qse_mchar_t c) | ||||
|  | ||||
| static QSE_INLINE int is_purespace_octet (qse_mchar_t c) | ||||
| { | ||||
| 	return c == ' ' || c == '\t'; | ||||
| 	return c == QSE_MT(' ') || c == QSE_MT('\t'); | ||||
| } | ||||
|  | ||||
| static QSE_INLINE int is_upalpha_octet (qse_mchar_t c) | ||||
| { | ||||
| 	return c >= 'A' && c <= 'Z'; | ||||
| 	return c >= QSE_MT('A') && c <= QSE_MT('Z'); | ||||
| } | ||||
|  | ||||
| static QSE_INLINE int is_loalpha_octet (qse_mchar_t c) | ||||
| { | ||||
| 	return c >= 'a' && c <= 'z'; | ||||
| 	return c >= QSE_MT('a') && c <= QSE_MT('z'); | ||||
| } | ||||
|  | ||||
| static QSE_INLINE int is_alpha_octet (qse_mchar_t c) | ||||
| { | ||||
| 	return (c >= 'A' && c <= 'Z') || | ||||
| 	       (c >= 'a' && c <= 'z'); | ||||
| 	return (c >= QSE_MT('A') && c <= QSE_MT('Z')) || | ||||
| 	       (c >= QSE_MT('a') && c <= QSE_MT('z')); | ||||
| } | ||||
|  | ||||
| static QSE_INLINE int is_digit_octet (qse_mchar_t c) | ||||
| { | ||||
| 	return c >= '0' && c <= '9'; | ||||
| 	return c >= QSE_MT('0') && c <= QSE_MT('9'); | ||||
| } | ||||
|  | ||||
| static QSE_INLINE int is_xdigit_octet (qse_mchar_t c) | ||||
| { | ||||
| 	return (c >= '0' && c <= '9') || | ||||
| 	       (c >= 'A' && c <= 'F') || | ||||
| 	       (c >= 'a' && c <= 'f'); | ||||
| 	return (c >= QSE_MT('0') && c <= QSE_MT('9')) || | ||||
| 	       (c >= QSE_MT('A') && c <= QSE_MT('F')) || | ||||
| 	       (c >= QSE_MT('a') && c <= QSE_MT('f')); | ||||
| } | ||||
|  | ||||
| static QSE_INLINE int digit_to_num (qse_mchar_t c) | ||||
| @ -534,6 +534,7 @@ static QSE_INLINE int capture_content_length ( | ||||
| 	} | ||||
|  | ||||
| 	htrd->re.attr.content_length = len; | ||||
| 	htrd->re.attr.content_length_set = 1; | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| @ -562,10 +563,10 @@ static QSE_INLINE int capture_transfer_encoding ( | ||||
| 	n = compare_octets (QSE_HTB_VPTR(pair), QSE_HTB_VLEN(pair), "chunked", 7); | ||||
| 	if (n == 0) | ||||
| 	{ | ||||
| 		if (htrd->re.attr.content_length > 0) | ||||
| 		/* if (htrd->re.attr.content_length > 0) */ | ||||
| 		if (htrd->re.attr.content_length_set) | ||||
| 		{ | ||||
| 			/* content-length is greater than 0  | ||||
| 			 * while transfer-encoding: chunked is specified. */ | ||||
| 			/* both content-length and 'transfer-encoding: chunked' are specified. */ | ||||
| 			goto badre; | ||||
| 		} | ||||
|  | ||||
| @ -881,7 +882,7 @@ static const qse_mchar_t* getchunklen (qse_htrd_t* htrd, const qse_mchar_t* ptr, | ||||
| 	/* this function must be called in the GET_CHUNK_LEN context */ | ||||
| 	QSE_ASSERT (htrd->fed.s.chunk.phase == GET_CHUNK_LEN); | ||||
|  | ||||
| //qse_printf (QSE_T("CALLING getchunklen [%d]\n"), *ptr); | ||||
| /*qse_printf (QSE_T("CALLING getchunklen [%d]\n"), *ptr);*/ | ||||
| 	if (htrd->fed.s.chunk.count <= 0) | ||||
| 	{ | ||||
| 		/* skip leading spaces if the first character of | ||||
| @ -911,7 +912,7 @@ static const qse_mchar_t* getchunklen (qse_htrd_t* htrd, const qse_mchar_t* ptr, | ||||
| 			if (htrd->fed.s.chunk.count <= 0) | ||||
| 			{ | ||||
| 				/* empty line - no more chunk */ | ||||
| //qse_printf (QSE_T("empty line chunk done....\n")); | ||||
| /*qse_printf (QSE_T("empty line chunk done....\n"));*/ | ||||
| 				htrd->fed.s.chunk.phase = GET_CHUNK_DONE; | ||||
| 			} | ||||
| 			else if (htrd->fed.s.chunk.len <= 0) | ||||
| @ -919,13 +920,13 @@ static const qse_mchar_t* getchunklen (qse_htrd_t* htrd, const qse_mchar_t* ptr, | ||||
| 				/* length explicity specified to 0 | ||||
| 				   get trailing headers .... */ | ||||
| 				htrd->fed.s.chunk.phase = GET_CHUNK_TRAILERS; | ||||
| //qse_printf (QSE_T("SWITCH TO GET_CHUNK_TRAILERS....\n")); | ||||
| /*qse_printf (QSE_T("SWITCH TO GET_CHUNK_TRAILERS....\n"));*/ | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				/* ready to read the chunk data... */ | ||||
| 				htrd->fed.s.chunk.phase = GET_CHUNK_DATA; | ||||
| //qse_printf (QSE_T("SWITCH TO GET_CHUNK_DATA....\n")); | ||||
| /*qse_printf (QSE_T("SWITCH TO GET_CHUNK_DATA....\n"));*/ | ||||
| 			} | ||||
|  | ||||
| 			htrd->fed.s.need = htrd->fed.s.chunk.len; | ||||
| @ -933,7 +934,7 @@ static const qse_mchar_t* getchunklen (qse_htrd_t* htrd, const qse_mchar_t* ptr, | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| //qse_printf (QSE_T("XXXXXXXXXXXXXXXXXxxx [%c]\n"), *ptr); | ||||
| /*qse_printf (QSE_T("XXXXXXXXXXXXXXXXXxxx [%c]\n"), *ptr);*/ | ||||
| 			htrd->errnum = QSE_HTRD_EBADRE; | ||||
| 			return QSE_NULL; | ||||
| 		} | ||||
| @ -1102,6 +1103,53 @@ int qse_htrd_feed (qse_htrd_t* htrd, const qse_mchar_t* req, qse_size_t len) | ||||
| 					if (parse_initial_line_and_headers (htrd, req, ptr - req) <= -1) | ||||
| 						return -1; | ||||
|  | ||||
| 					if (htrd->option & QSE_HTRD_HURRIED) | ||||
| 					{ | ||||
| 						int n; | ||||
|  | ||||
| 						/* it pushes any trailing data into the content in this mode. | ||||
| 						 * so the handler knows if there is contents fed to this reader. */ | ||||
| 						if (push_to_buffer (htrd, &htrd->re.content, ptr, end - ptr) <= -1)  | ||||
| 							return -1; | ||||
| 					 | ||||
|  | ||||
| 						htrd->re.attr.hurried = 1; | ||||
| 						htrd->errnum = QSE_HTRD_ENOERR;	 | ||||
| 						if (htrd->retype == QSE_HTRD_RETYPE_S) | ||||
| 						{ | ||||
| 							QSE_ASSERTX ( | ||||
| 								htrd->recbs->response != QSE_NULL, | ||||
| 								"set response callback before feeding" | ||||
| 							); | ||||
| 							n = htrd->recbs->response (htrd, &htrd->re); | ||||
| 						} | ||||
| 						else | ||||
| 						{ | ||||
| 							QSE_ASSERTX ( | ||||
| 								htrd->recbs->request != QSE_NULL, | ||||
| 								"set request callback before feeding" | ||||
| 							); | ||||
| 							n = htrd->recbs->request (htrd, &htrd->re); | ||||
| 						} | ||||
|  | ||||
| 						/* qse_mbs_clear (&htrd->re.content); */ | ||||
|  | ||||
| 						if (n <= -1) | ||||
| 						{ | ||||
| 							if (htrd->errnum == QSE_HTRD_ENOERR) | ||||
| 								htrd->errnum = QSE_HTRD_ERECBS;	 | ||||
| 	 | ||||
| 							/* need to clear request on error?  | ||||
| 							clear_feed (htrd); */ | ||||
| 							return -1; | ||||
| 						} | ||||
|  | ||||
| 						/* if QSE_HTRD_HURRIED is set, we do not handle expect_continue */ | ||||
| 						/* if QSE_HTRD_HURRIED is set, we handle a single request only */ | ||||
|  | ||||
| 						return 0; | ||||
| 					} | ||||
|  | ||||
| 					if (htrd->retype == QSE_HTRD_RETYPE_Q &&  | ||||
| 					    htrd->re.attr.expect_continue &&  | ||||
| 					    htrd->recbs->expect_continue && ptr >= end) | ||||
| @ -1115,6 +1163,8 @@ int qse_htrd_feed (qse_htrd_t* htrd, const qse_mchar_t* req, qse_size_t len) | ||||
| 						 * not fed here? | ||||
| 						 */  | ||||
|  | ||||
| 						htrd->re.attr.hurried = 0; | ||||
| 						htrd->errnum = QSE_HTRD_ENOERR;	 | ||||
| 						n = htrd->recbs->expect_continue (htrd, &htrd->re); | ||||
|  | ||||
| 						if (n <= -1) | ||||
| @ -1136,7 +1186,7 @@ int qse_htrd_feed (qse_htrd_t* htrd, const qse_mchar_t* req, qse_size_t len) | ||||
| 					if (htrd->re.attr.chunked) | ||||
| 					{ | ||||
| 						/* transfer-encoding: chunked */ | ||||
| 						QSE_ASSERT (htrd->re.attr.content_length <= 0); | ||||
| 						QSE_ASSERT (!htrd->re.attr.content_length_set); | ||||
| 	 | ||||
| 					dechunk_start: | ||||
| 						htrd->fed.s.chunk.phase = GET_CHUNK_LEN; | ||||
| @ -1251,6 +1301,7 @@ int qse_htrd_feed (qse_htrd_t* htrd, const qse_mchar_t* req, qse_size_t len) | ||||
| 					{ | ||||
| 						int n; | ||||
|  | ||||
| 						htrd->re.attr.hurried = 0; | ||||
| 						htrd->errnum = QSE_HTRD_ENOERR; | ||||
|  | ||||
| 						if (htrd->retype == QSE_HTRD_RETYPE_S) | ||||
|  | ||||
| @ -61,13 +61,13 @@ void qse_htre_clear (qse_htre_t* re) | ||||
| } | ||||
|  | ||||
| int qse_htre_setstrfromcstr ( | ||||
| 	qse_htre_t* re, qse_htob_t* str, const qse_mcstr_t* cstr) | ||||
| 	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_htob_t* str, const qse_mxstr_t* xstr) | ||||
| 	qse_htre_t* re, qse_mbs_t* str, const qse_mxstr_t* xstr) | ||||
| { | ||||
| 	return (qse_mbs_ncpy (str, xstr->ptr, xstr->len) == (qse_size_t)-1)? -1: 0; | ||||
| } | ||||
|  | ||||
| @ -667,7 +667,11 @@ struct task_cgi_t | ||||
| 	const qse_char_t* path; | ||||
|  | ||||
| 	qse_htrd_t* htrd; | ||||
|  | ||||
| 	qse_mbs_t* res; | ||||
| 	qse_mchar_t* res_ptr; | ||||
| 	qse_size_t   res_left;	 | ||||
|  | ||||
| 	qse_pio_t* pio; | ||||
|  | ||||
| 	qse_mchar_t buf[MAX_SEND_SIZE]; | ||||
| @ -701,6 +705,8 @@ static int cgi_htrd_handle_request (qse_htrd_t* htrd, qse_htre_t* req) | ||||
| 	task_cgi_t* cgi = xtn->cgi; | ||||
| 	const qse_mchar_t* status; | ||||
|  | ||||
| 	QSE_ASSERT (req->attr.hurried); | ||||
|  | ||||
| 	status = qse_htre_getheaderval (req, QSE_MT("Status")); | ||||
| 	if (status) | ||||
| 	{ | ||||
| @ -726,7 +732,24 @@ static int cgi_htrd_handle_request (qse_htrd_t* htrd, qse_htre_t* req) | ||||
| 		if (qse_mbs_cat (cgi->res, buf) == (qse_size_t)-1) return -1; | ||||
| 	} | ||||
|  | ||||
| 	if (!req->attr.content_length_set) | ||||
| 	{ | ||||
| 		if (qse_mbs_cat (cgi->res, QSE_MT("Transfer-Encoding: chunked\r\n")) == (qse_size_t)-1) return -1; | ||||
| 	} | ||||
|  | ||||
| 	if (qse_htre_walkheaders (req, walk_cgi_headers, cgi) <= -1) return -1; | ||||
|  | ||||
| 	if (qse_htre_getcontentlen(req) > 0) | ||||
| 	{ | ||||
| 		if (!req->attr.content_length_set) | ||||
| 		{ | ||||
| 			qse_mchar_t buf[64]; | ||||
| 			snprintf (buf, QSE_COUNTOF(buf), QSE_MT("%lX\r\n"), (unsigned long)qse_htre_getcontentlen(req)); | ||||
| 			if (qse_mbs_cat (cgi->res, buf) == (qse_size_t)-1) return -1; | ||||
| 		} | ||||
| 		if (qse_mbs_ncat (cgi->res, qse_htre_getcontentptr(req), qse_htre_getcontentlen(req)) == (qse_size_t)-1) return -1; | ||||
| 	} | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| @ -755,9 +778,10 @@ static void task_fini_cgi ( | ||||
| 	if (cgi->pio) qse_pio_close (cgi->pio); | ||||
| 	if (cgi->res) qse_mbs_close (cgi->res); | ||||
| 	if (cgi->htrd) qse_htrd_close (cgi->htrd); | ||||
| qse_printf (QSE_T("task_fini_cgi\n")); | ||||
| } | ||||
|  | ||||
| static int task_main_cgi_3 ( | ||||
| static int task_main_cgi_5 ( | ||||
| 	qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task) | ||||
| { | ||||
| 	task_cgi_t* cgi = (task_cgi_t*)task->ctx; | ||||
| @ -765,6 +789,76 @@ static int task_main_cgi_3 ( | ||||
|  | ||||
| 	QSE_ASSERT (cgi->pio != QSE_NULL); | ||||
|  | ||||
| qse_printf (QSE_T("task_main_cgi_5\n")); | ||||
| { | ||||
| char buf[64]; | ||||
| snprintf (buf, sizeof(buf), "%lX\r\n", cgi->buflen); | ||||
| send (client->handle.i, buf, strlen(buf), 0); | ||||
| } | ||||
| /* TODO: check if cgi outputs more than content-length if it is set... */ | ||||
| 	n = send (client->handle.i, cgi->buf, cgi->buflen, 0); | ||||
| 	if (n <= -1) | ||||
| 	{ | ||||
| 		/* can't return internal server error any more... */ | ||||
| /* TODO: logging ... */ | ||||
| 		return -1; | ||||
| 	} | ||||
| send (client->handle.i, "\r\n", 2, 0); | ||||
|  | ||||
| 	QSE_MEMCPY (&cgi->buf[0], &cgi->buf[n], cgi->buflen - n); | ||||
| 	cgi->buflen -= n; | ||||
|  | ||||
| 	if (cgi->buflen > 0) return 1; | ||||
|  | ||||
| send (client->handle.i, "0\r\n\r\n", 5, 0); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int task_main_cgi_4 ( | ||||
| 	qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task) | ||||
| { | ||||
| 	task_cgi_t* cgi = (task_cgi_t*)task->ctx; | ||||
| 	qse_ssize_t n; | ||||
| 	 | ||||
| 	QSE_ASSERT (cgi->pio != QSE_NULL); | ||||
| qse_printf (QSE_T("task_main_cgi_4\n")); | ||||
|  | ||||
| /* TODO: check if cgi outputs more than content-length if it is set... */ | ||||
| 	 /* <- can i make it non-block?? or use select??? pio_tryread()? */ | ||||
| 	n = qse_pio_read ( | ||||
| 		cgi->pio,  | ||||
| 		&cgi->buf[cgi->buflen],  | ||||
| 		QSE_SIZEOF(cgi->buf) - cgi->buflen, | ||||
| 		QSE_PIO_OUT | ||||
| 	); | ||||
| 	if (n <= -1) | ||||
| 	{ | ||||
| 		/* can't return internal server error any more... */ | ||||
| /* TODO: logging ... */ | ||||
| 		return -1; | ||||
| 	} | ||||
| 	if (n == 0)  | ||||
| 	{ | ||||
| 		if (cgi->buflen > 0) | ||||
| 		{ | ||||
| 			task->main = task_main_cgi_4; | ||||
| 			return task_main_cgi_5 (httpd, client, task); | ||||
| 		} | ||||
| 		else  | ||||
| 		{ | ||||
| send (client->handle.i, "0\r\n\r\n", 5, 0); | ||||
| 			return 0; | ||||
| 		} | ||||
| 	} | ||||
| 			 | ||||
| 	cgi->buflen += n; | ||||
|  | ||||
| { | ||||
| char buf[64]; | ||||
| snprintf (buf, sizeof(buf), "%lX\r\n", cgi->buflen); | ||||
| send (client->handle.i, buf, strlen(buf), 0); | ||||
| } | ||||
|  | ||||
| 	n = send (client->handle.i, cgi->buf, cgi->buflen, 0); | ||||
| 	if (n <= -1) | ||||
| 	{ | ||||
| @ -772,11 +866,43 @@ static int task_main_cgi_3 ( | ||||
| /* TODO: logging ... */ | ||||
| 		return -1; | ||||
| 	} | ||||
| send (client->handle.i, "\r\n", 2, 0); | ||||
|  | ||||
| 	QSE_MEMCPY (&cgi->buf[0], &cgi->buf[n], cgi->buflen - n); | ||||
| 	cgi->buflen -= n; | ||||
|  | ||||
| 	return (cgi->buflen > 0)? 1: 0; | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
| static int task_main_cgi_3 ( | ||||
| 	qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task) | ||||
| { | ||||
| 	task_cgi_t* cgi = (task_cgi_t*)task->ctx; | ||||
| 	qse_ssize_t n; | ||||
| 	qse_size_t count; | ||||
|  | ||||
| qse_printf (QSE_T("task_main_cgi_3\n")); | ||||
| 	count = MAX_SEND_SIZE; | ||||
| 	if (count >= cgi->res_left) count = cgi->res_left; | ||||
|  | ||||
| 	n = send ( | ||||
| 		client->handle.i, | ||||
| 		cgi->res_ptr, | ||||
| 		count, | ||||
| 		0 | ||||
| 	); | ||||
|  | ||||
| 	if (n <= -1) return -1; | ||||
|  | ||||
| 	cgi->res_left -= n; | ||||
| 	if (cgi->res_left <= 0)  | ||||
| 	{ | ||||
| 		task->main = task_main_cgi_4; | ||||
| 		return task_main_cgi_4 (httpd, client, task); | ||||
| 	} | ||||
|  | ||||
| 	cgi->res_ptr += n; | ||||
| 	return 1; /* more work to do */ | ||||
| } | ||||
|  | ||||
| static int task_main_cgi_2 ( | ||||
| @ -802,12 +928,11 @@ static int task_main_cgi_2 ( | ||||
| 	} | ||||
| 	if (n == 0)  | ||||
| 	{ | ||||
| 		if (cgi->buflen > 0) | ||||
| 		{ | ||||
| 			task->main = task_main_cgi_3; | ||||
| 			return task_main_cgi_3 (httpd, client, task); | ||||
| 		} | ||||
| 		else return 0; | ||||
| 		/* end of output from cgi before it has seen a header. | ||||
| 		 * the cgi script must be crooked. */ | ||||
| /* TODO: logging */ | ||||
| 		qse_pio_kill (cgi->pio); | ||||
| 		return -1; | ||||
| 	} | ||||
| 			 | ||||
| 	cgi->buflen += n; | ||||
| @ -818,20 +943,19 @@ static int task_main_cgi_2 ( | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	cgi->buflen = 0; | ||||
|  | ||||
| #if 0 | ||||
| 	n = send (client->handle.i, cgi->buf, cgi->buflen, 0); | ||||
| 	if (n <= -1) | ||||
| 	if (QSE_MBS_LEN(cgi->res) > 0) | ||||
| 	{ | ||||
| 		/* can't return internal server error any more... */ | ||||
| /* TODO: logging ... */ | ||||
| 		return -1; | ||||
| 		/* the headers and probably some contents are ready */ | ||||
| 		cgi->res_ptr = QSE_MBS_PTR(cgi->res); | ||||
| 		cgi->res_left = QSE_MBS_LEN(cgi->res); | ||||
|  | ||||
| 		task->main = task_main_cgi_3; | ||||
| 		return task_main_cgi_3 (httpd, client, task); | ||||
| 	} | ||||
|  | ||||
| 	QSE_MEMCPY (&cgi->buf[0], &cgi->buf[n], cgi->buflen - n); | ||||
| 	cgi->buflen -= n; | ||||
| #endif | ||||
|  | ||||
| 	/* complete headers not seen yet. i need to be called again */ | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
| @ -850,7 +974,12 @@ return 0; | ||||
| 	xtn = (cgi_htrd_xtn_t*) qse_htrd_getxtn (cgi->htrd); | ||||
| 	xtn->cgi = cgi; | ||||
| 	qse_htrd_setrecbs (cgi->htrd, &cgi_htrd_cbs); | ||||
| 	qse_htrd_setoption (cgi->htrd, QSE_HTRD_SKIPINITIALLINE | QSE_HTRD_REQUEST); | ||||
| 	qse_htrd_setoption ( | ||||
| 		cgi->htrd,  | ||||
| 		QSE_HTRD_SKIPINITIALLINE |  | ||||
| 		QSE_HTRD_HURRIED |  | ||||
| 		QSE_HTRD_REQUEST | ||||
| 	); | ||||
|  | ||||
| 	cgi->res = qse_mbs_open (httpd->mmgr, 0, 256); | ||||
| 	if (cgi->res == QSE_NULL) | ||||
|  | ||||
| @ -61,11 +61,11 @@ qse_printf (QSE_T("content = [%.*S]\n"), | ||||
|  | ||||
| 		if (dot && qse_mbscmp (dot, QSE_MT(".cgi")) == 0) | ||||
| 		{ | ||||
| qse_httpd_entaskcgi (httpd, client, QSE_NULL, QSE_T("/bin/ls -l /etc")); | ||||
| qse_httpd_entaskcgi (httpd, client, QSE_NULL, QSE_T("/tmp/test.cgi")); | ||||
| 			goto done; | ||||
| 		} | ||||
|  | ||||
| 		rangestr = qse_htre_gethdrval (req, "Range"); | ||||
| 		rangestr = qse_htre_getheaderval (req, "Range"); | ||||
| 		if (rangestr && qse_parsehttprange (rangestr, &range) <= -1) | ||||
| 		{ | ||||
| #if 0 | ||||
|  | ||||
		Reference in New Issue
	
	Block a user