added the shebang field to cgi.
changed qse_httpd_getoption()/qse_httpd_setoption() to qse_httpd_getopt()/qse_httpd_setopt() with QSE_HTTPD_TRAIT fixed a bug of not passing the pred argument in qse_httpd_entaskrsrc().
This commit is contained in:
		| @ -185,6 +185,7 @@ static int httpd_main (int argc, qse_char_t* argv[]) | |||||||
| 	qse_httpd_t* httpd = QSE_NULL; | 	qse_httpd_t* httpd = QSE_NULL; | ||||||
| 	qse_ntime_t tmout; | 	qse_ntime_t tmout; | ||||||
| 	int ret = -1, i; | 	int ret = -1, i; | ||||||
|  | 	int trait; | ||||||
| 	static qse_httpd_server_cbstd_t cbstd = { makersrc, freersrc }; | 	static qse_httpd_server_cbstd_t cbstd = { makersrc, freersrc }; | ||||||
|  |  | ||||||
| 	if (argc <= 1) | 	if (argc <= 1) | ||||||
| @ -218,7 +219,8 @@ static int httpd_main (int argc, qse_char_t* argv[]) | |||||||
|  |  | ||||||
| 	qse_httpd_setname (httpd, QSE_MT("qsehttpd 1.0")); | 	qse_httpd_setname (httpd, QSE_MT("qsehttpd 1.0")); | ||||||
|  |  | ||||||
| 	qse_httpd_setoption (httpd, QSE_HTTPD_CGIERRTONUL); | 	trait = QSE_HTTPD_CGIERRTONUL; | ||||||
|  | 	qse_httpd_setopt (httpd, QSE_HTTPD_TRAIT, &trait); | ||||||
|  |  | ||||||
| 	tmout.sec = 10; | 	tmout.sec = 10; | ||||||
| 	tmout.nsec = 0; | 	tmout.nsec = 0; | ||||||
| @ -259,7 +261,6 @@ int qse_main (int argc, qse_achar_t* argv[]) | |||||||
| 		qse_setdflcmgrbyid (QSE_CMGR_SLMB); | 		qse_setdflcmgrbyid (QSE_CMGR_SLMB); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  |  | ||||||
| 	if (WSAStartup (MAKEWORD(2,0), &wsadata) != 0) | 	if (WSAStartup (MAKEWORD(2,0), &wsadata) != 0) | ||||||
| 	{ | 	{ | ||||||
| 		qse_fprintf (QSE_STDERR, QSE_T("Failed to start up winsock\n")); | 		qse_fprintf (QSE_STDERR, QSE_T("Failed to start up winsock\n")); | ||||||
|  | |||||||
| @ -58,13 +58,20 @@ enum qse_httpd_errnum_t | |||||||
| }; | }; | ||||||
| typedef enum qse_httpd_errnum_t qse_httpd_errnum_t; | typedef enum qse_httpd_errnum_t qse_httpd_errnum_t; | ||||||
|  |  | ||||||
| enum qse_httpd_option_t | enum qse_httpd_opt_t | ||||||
|  | { | ||||||
|  | 	QSE_HTTPD_TRAIT | ||||||
|  | }; | ||||||
|  | typedef enum qse_httpd_opt_t qse_httpd_opt_t; | ||||||
|  |  | ||||||
|  | enum qse_httpd_trait_t | ||||||
| { | { | ||||||
| 	QSE_HTTPD_MUTECLIENT   = (1 << 0), | 	QSE_HTTPD_MUTECLIENT   = (1 << 0), | ||||||
| 	QSE_HTTPD_CGIERRTONUL  = (1 << 1), | 	QSE_HTTPD_CGIERRTONUL  = (1 << 1), | ||||||
| 	QSE_HTTPD_CGINOCLOEXEC = (1 << 2), | 	QSE_HTTPD_CGINOCLOEXEC = (1 << 2), | ||||||
| 	QSE_HTTPD_CGINOCHUNKED = (1 << 3) | 	QSE_HTTPD_CGINOCHUNKED = (1 << 3) | ||||||
| }; | }; | ||||||
|  | typedef enum qse_httpd_trait_t qse_httpd_trait_t; | ||||||
|  |  | ||||||
| typedef struct qse_httpd_stat_t qse_httpd_stat_t; | typedef struct qse_httpd_stat_t qse_httpd_stat_t; | ||||||
| struct qse_httpd_stat_t | struct qse_httpd_stat_t | ||||||
| @ -383,8 +390,18 @@ enum qse_httpd_rsrc_type_t | |||||||
| }; | }; | ||||||
| typedef enum qse_httpd_rsrc_type_t qse_httpd_rsrc_type_t; | typedef enum qse_httpd_rsrc_type_t qse_httpd_rsrc_type_t; | ||||||
|  |  | ||||||
| typedef struct qse_httpd_rsrc_t qse_httpd_rsrc_t; | typedef struct qse_httpd_rsrc_cgi_t qse_httpd_rsrc_cgi_t; | ||||||
|  | struct qse_httpd_rsrc_cgi_t | ||||||
|  | { | ||||||
|  | 	const qse_mchar_t* path; | ||||||
|  | 	const qse_mchar_t* script; | ||||||
|  | 	const qse_mchar_t* suffix; | ||||||
|  | 	const qse_mchar_t* docroot; | ||||||
|  | 	const qse_mchar_t* shebang;  | ||||||
|  | 	int nph; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | typedef struct qse_httpd_rsrc_t qse_httpd_rsrc_t; | ||||||
| struct qse_httpd_rsrc_t | struct qse_httpd_rsrc_t | ||||||
| { | { | ||||||
| 	qse_httpd_rsrc_type_t type; | 	qse_httpd_rsrc_type_t type; | ||||||
| @ -394,14 +411,9 @@ struct qse_httpd_rsrc_t | |||||||
| 		{ | 		{ | ||||||
| 			const qse_mchar_t* realm; | 			const qse_mchar_t* realm; | ||||||
| 		} auth; | 		} auth; | ||||||
| 		struct  |  | ||||||
| 		{ | 		qse_httpd_rsrc_cgi_t cgi; | ||||||
| 			const qse_mchar_t* path; |  | ||||||
| 			const qse_mchar_t* script; |  | ||||||
| 			const qse_mchar_t* suffix; |  | ||||||
| 			const qse_mchar_t* docroot; |  | ||||||
| 			int nph; |  | ||||||
| 		} cgi;	 |  | ||||||
| 		struct | 		struct | ||||||
| 		{ | 		{ | ||||||
| 			const qse_mchar_t* path; | 			const qse_mchar_t* path; | ||||||
| @ -481,6 +493,7 @@ struct qse_httpd_server_cgistd_t | |||||||
| 	const qse_mchar_t*  ext; | 	const qse_mchar_t*  ext; | ||||||
| 	qse_size_t          len; | 	qse_size_t          len; | ||||||
| 	int                 nph; | 	int                 nph; | ||||||
|  | 	const qse_mchar_t*  shebang; /* optional, can be #QSE_NULL */ | ||||||
| }; | }; | ||||||
|  |  | ||||||
| typedef struct qse_httpd_server_mimestd_t qse_httpd_server_mimestd_t; | typedef struct qse_httpd_server_mimestd_t qse_httpd_server_mimestd_t; | ||||||
| @ -551,13 +564,16 @@ QSE_EXPORT void qse_httpd_seterrnum ( | |||||||
| 	qse_httpd_errnum_t errnum | 	qse_httpd_errnum_t errnum | ||||||
| ); | ); | ||||||
|  |  | ||||||
| QSE_EXPORT int qse_httpd_getoption ( | QSE_EXPORT int qse_httpd_getopt ( | ||||||
| 	qse_httpd_t* httpd | 	qse_httpd_t*    httpd, | ||||||
|  | 	qse_httpd_opt_t id, | ||||||
|  | 	void*           value | ||||||
| ); | ); | ||||||
|  |  | ||||||
| QSE_EXPORT void qse_httpd_setoption ( | QSE_EXPORT int qse_httpd_setopt ( | ||||||
| 	qse_httpd_t*    httpd, | 	qse_httpd_t*    httpd, | ||||||
| 	int          option | 	qse_httpd_opt_t id, | ||||||
|  | 	const void*     value | ||||||
| ); | ); | ||||||
|  |  | ||||||
| /** | /** | ||||||
| @ -758,11 +774,7 @@ QSE_EXPORT qse_httpd_task_t* qse_httpd_entaskcgi ( | |||||||
| 	qse_httpd_t*              httpd, | 	qse_httpd_t*              httpd, | ||||||
| 	qse_httpd_client_t*       client, | 	qse_httpd_client_t*       client, | ||||||
| 	qse_httpd_task_t*         pred, | 	qse_httpd_task_t*         pred, | ||||||
| 	const qse_mchar_t*        path, | 	qse_httpd_rsrc_cgi_t*     cgi, | ||||||
| 	const qse_mchar_t*        script, |  | ||||||
| 	const qse_mchar_t*        suffix, |  | ||||||
| 	const qse_mchar_t*        docroot, |  | ||||||
| 	int                       nph, |  | ||||||
| 	qse_htre_t*               req | 	qse_htre_t*               req | ||||||
| ); | ); | ||||||
|  |  | ||||||
|  | |||||||
| @ -33,6 +33,7 @@ struct task_cgi_arg_t | |||||||
| 	qse_mcstr_t script; | 	qse_mcstr_t script; | ||||||
| 	qse_mcstr_t suffix; | 	qse_mcstr_t suffix; | ||||||
| 	qse_mcstr_t docroot; | 	qse_mcstr_t docroot; | ||||||
|  | 	qse_mcstr_t shebang; | ||||||
| 	int nph; | 	int nph; | ||||||
| 	qse_htre_t* req; | 	qse_htre_t* req; | ||||||
| }; | }; | ||||||
| @ -47,6 +48,7 @@ struct task_cgi_t | |||||||
| 	const qse_mchar_t* script; | 	const qse_mchar_t* script; | ||||||
| 	const qse_mchar_t* suffix; | 	const qse_mchar_t* suffix; | ||||||
| 	const qse_mchar_t* docroot; | 	const qse_mchar_t* docroot; | ||||||
|  | 	const qse_mchar_t* shebang; | ||||||
| 	qse_http_version_t version; | 	qse_http_version_t version; | ||||||
| 	int keepalive; /* taken from the request */ | 	int keepalive; /* taken from the request */ | ||||||
| 	int nph; | 	int nph; | ||||||
| @ -706,10 +708,12 @@ static int task_init_cgi ( | |||||||
| 	cgi->script = cgi->path + arg->path.len + 1; | 	cgi->script = cgi->path + arg->path.len + 1; | ||||||
| 	cgi->suffix = cgi->script + arg->script.len + 1; | 	cgi->suffix = cgi->script + arg->script.len + 1; | ||||||
| 	cgi->docroot = cgi->suffix + arg->suffix.len + 1; | 	cgi->docroot = cgi->suffix + arg->suffix.len + 1; | ||||||
|  | 	cgi->shebang = cgi->docroot + arg->docroot.len + 1; | ||||||
| 	qse_mbscpy ((qse_mchar_t*)cgi->path, arg->path.ptr); | 	qse_mbscpy ((qse_mchar_t*)cgi->path, arg->path.ptr); | ||||||
| 	qse_mbscpy ((qse_mchar_t*)cgi->script, arg->script.ptr); | 	qse_mbscpy ((qse_mchar_t*)cgi->script, arg->script.ptr); | ||||||
| 	qse_mbscpy ((qse_mchar_t*)cgi->suffix, arg->suffix.ptr); | 	qse_mbscpy ((qse_mchar_t*)cgi->suffix, arg->suffix.ptr); | ||||||
| 	qse_mbscpy ((qse_mchar_t*)cgi->docroot, arg->docroot.ptr); | 	qse_mbscpy ((qse_mchar_t*)cgi->docroot, arg->docroot.ptr); | ||||||
|  | 	qse_mbscpy ((qse_mchar_t*)cgi->shebang, arg->shebang.ptr); | ||||||
|  |  | ||||||
| 	cgi->version = *qse_htre_getversion(arg->req); | 	cgi->version = *qse_htre_getversion(arg->req); | ||||||
| 	cgi->keepalive = (arg->req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE); | 	cgi->keepalive = (arg->req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE); | ||||||
| @ -737,7 +741,7 @@ static int task_init_cgi ( | |||||||
| 		 * such a request to entask a cgi script dropping the | 		 * such a request to entask a cgi script dropping the | ||||||
| 		 * content */ | 		 * content */ | ||||||
|  |  | ||||||
| 		if (httpd->option & QSE_HTTPD_CGINOCHUNKED) | 		if (httpd->opt.trait & QSE_HTTPD_CGINOCHUNKED) | ||||||
| 		{ | 		{ | ||||||
| 			qse_htre_discardcontent (arg->req); | 			qse_htre_discardcontent (arg->req); | ||||||
| 			cgi->reqflags |= CGI_REQ_GOTALL; | 			cgi->reqflags |= CGI_REQ_GOTALL; | ||||||
| @ -1332,8 +1336,9 @@ static int task_main_cgi ( | |||||||
| 	qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task) | 	qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task) | ||||||
| { | { | ||||||
| 	task_cgi_t* cgi = (task_cgi_t*)task->ctx; | 	task_cgi_t* cgi = (task_cgi_t*)task->ctx; | ||||||
| 	int pio_options; | 	int pio_options, x; | ||||||
| 	int http_errnum = 500; | 	int http_errnum = 500; | ||||||
|  | 	qse_mchar_t* xpath; | ||||||
|  |  | ||||||
| 	if (cgi->init_failed) goto oops; | 	if (cgi->init_failed) goto oops; | ||||||
|  |  | ||||||
| @ -1368,16 +1373,31 @@ static int task_main_cgi ( | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	pio_options = QSE_PIO_READOUT | QSE_PIO_WRITEIN | QSE_PIO_MBSCMD; | 	pio_options = QSE_PIO_READOUT | QSE_PIO_WRITEIN | QSE_PIO_MBSCMD; | ||||||
| 	if (httpd->option & QSE_HTTPD_CGIERRTONUL) | 	if (httpd->opt.trait & QSE_HTTPD_CGIERRTONUL) | ||||||
| 		pio_options |= QSE_PIO_ERRTONUL; | 		pio_options |= QSE_PIO_ERRTONUL; | ||||||
| 	else | 	else | ||||||
| 		pio_options |= QSE_PIO_ERRTOOUT; | 		pio_options |= QSE_PIO_ERRTOOUT; | ||||||
| 	if (httpd->option & QSE_HTTPD_CGINOCLOEXEC)  | 	if (httpd->opt.trait & QSE_HTTPD_CGINOCLOEXEC)  | ||||||
| 		pio_options |= QSE_PIO_NOCLOEXEC; | 		pio_options |= QSE_PIO_NOCLOEXEC; | ||||||
|  |  | ||||||
| 	if (qse_pio_init ( | 	if (cgi->shebang[0] != QSE_MT('\0')) | ||||||
| 		&cgi->pio, httpd->mmgr, (const qse_char_t*)cgi->path,  | 	{ | ||||||
| 		cgi->env, pio_options) <= -1) | 		const qse_mchar_t* tmp[4]; | ||||||
|  | 		tmp[0] = cgi->shebang; | ||||||
|  | 		tmp[1] = QSE_MT(" "); | ||||||
|  | 		tmp[2] = cgi->path; | ||||||
|  | 		tmp[3] = QSE_NULL; | ||||||
|  | 		xpath = qse_mbsadup (tmp, QSE_NULL, httpd->mmgr); | ||||||
|  | 		if (xpath == QSE_NULL) goto oops; | ||||||
|  | 	} | ||||||
|  | 	else xpath = cgi->path; | ||||||
|  |  | ||||||
|  | 	x = qse_pio_init ( | ||||||
|  | 		&cgi->pio, httpd->mmgr, (const qse_char_t*)xpath, | ||||||
|  | 		cgi->env, pio_options); | ||||||
|  | 	if (xpath != cgi->path) QSE_MMGR_FREE (httpd->mmgr, xpath); | ||||||
|  |  | ||||||
|  | 	if (x <= -1) | ||||||
| 	{ | 	{ | ||||||
| 		qse_pio_errnum_t errnum; | 		qse_pio_errnum_t errnum; | ||||||
|  |  | ||||||
| @ -1468,30 +1488,31 @@ qse_httpd_task_t* qse_httpd_entaskcgi ( | |||||||
| 	qse_httpd_t* httpd, | 	qse_httpd_t* httpd, | ||||||
| 	qse_httpd_client_t* client, | 	qse_httpd_client_t* client, | ||||||
| 	qse_httpd_task_t* pred, | 	qse_httpd_task_t* pred, | ||||||
| 	const qse_mchar_t* path,  | 	qse_httpd_rsrc_cgi_t* cgi, | ||||||
| 	const qse_mchar_t* script, |  | ||||||
| 	const qse_mchar_t* suffix, |  | ||||||
| 	const qse_mchar_t* docroot, |  | ||||||
| 	int                nph, |  | ||||||
| 	qse_htre_t*        req) | 	qse_htre_t*        req) | ||||||
| { | { | ||||||
| 	qse_httpd_task_t task; | 	qse_httpd_task_t task; | ||||||
| 	task_cgi_arg_t arg; | 	task_cgi_arg_t arg; | ||||||
|  | 	qse_httpd_rsrc_cgi_t rsrc; | ||||||
|  |  | ||||||
| 	if (script == QSE_NULL) script = qse_htre_getqpath(req); | 	rsrc = *cgi; | ||||||
| 	if (suffix == QSE_NULL) suffix = QSE_MT(""); | 	if (rsrc.script == QSE_NULL) rsrc.script = qse_htre_getqpath(req); | ||||||
| 	if (docroot == QSE_NULL) docroot = QSE_MT(""); | 	if (rsrc.suffix == QSE_NULL) rsrc.suffix = QSE_MT(""); | ||||||
|  | 	if (rsrc.docroot == QSE_NULL) rsrc.docroot = QSE_MT(""); | ||||||
|  | 	if (rsrc.shebang == QSE_NULL) rsrc.shebang = QSE_MT(""); | ||||||
|  |  | ||||||
| 	arg.path.ptr = path; | 	arg.path.ptr = rsrc.path; | ||||||
| 	arg.path.len = qse_mbslen(path); | 	arg.path.len = qse_mbslen(rsrc.path); | ||||||
| 	arg.script.ptr = script; | 	arg.script.ptr = rsrc.script; | ||||||
| 	arg.script.len = qse_mbslen(script); | 	arg.script.len = qse_mbslen(rsrc.script); | ||||||
| 	arg.suffix.ptr = suffix; | 	arg.suffix.ptr = rsrc.suffix; | ||||||
| 	arg.suffix.len = qse_mbslen(suffix); | 	arg.suffix.len = qse_mbslen(rsrc.suffix); | ||||||
| 	arg.docroot.ptr = docroot; | 	arg.docroot.ptr = rsrc.docroot; | ||||||
| 	arg.docroot.len = qse_mbslen(docroot); | 	arg.docroot.len = qse_mbslen(rsrc.docroot); | ||||||
|  | 	arg.nph = rsrc.nph; | ||||||
|  | 	arg.shebang.ptr = rsrc.shebang; | ||||||
|  | 	arg.shebang.len = qse_mbslen(rsrc.shebang); | ||||||
| 	arg.req = req; | 	arg.req = req; | ||||||
| 	arg.nph = nph; |  | ||||||
|  |  | ||||||
| 	QSE_MEMSET (&task, 0, QSE_SIZEOF(task)); | 	QSE_MEMSET (&task, 0, QSE_SIZEOF(task)); | ||||||
| 	task.init = task_init_cgi; | 	task.init = task_init_cgi; | ||||||
| @ -1502,10 +1523,11 @@ qse_httpd_task_t* qse_httpd_entaskcgi ( | |||||||
| 	return qse_httpd_entask ( | 	return qse_httpd_entask ( | ||||||
| 		httpd, client, pred, &task,  | 		httpd, client, pred, &task,  | ||||||
| 		QSE_SIZEOF(task_cgi_t) +  | 		QSE_SIZEOF(task_cgi_t) +  | ||||||
| 		((arg.path.len + 1) * QSE_SIZEOF(*path)) +  | 		((arg.path.len + 1) * QSE_SIZEOF(*arg.path.ptr)) +  | ||||||
| 		((arg.script.len + 1) * QSE_SIZEOF(*script)) +  | 		((arg.script.len + 1) * QSE_SIZEOF(*arg.script.ptr)) +  | ||||||
| 		((arg.suffix.len + 1) * QSE_SIZEOF(*suffix)) + | 		((arg.suffix.len + 1) * QSE_SIZEOF(*arg.suffix.ptr)) + | ||||||
| 		((arg.docroot.len + 1) * QSE_SIZEOF(*docroot)) | 		((arg.docroot.len + 1) * QSE_SIZEOF(*arg.docroot.ptr)) + | ||||||
|  | 		((arg.shebang.len + 1) * QSE_SIZEOF(*arg.shebang.ptr)) | ||||||
| 	); | 	); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | |||||||
| @ -885,7 +885,6 @@ static int task_main_proxy_5 ( | |||||||
| 	task_proxy_t* proxy = (task_proxy_t*)task->ctx; | 	task_proxy_t* proxy = (task_proxy_t*)task->ctx; | ||||||
| 	qse_ssize_t n; | 	qse_ssize_t n; | ||||||
|  |  | ||||||
| 	//QSE_ASSERT (proxy->pio_inited); |  | ||||||
| qse_printf (QSE_T("task_main_proxy_5 trigger[0].mask=%d trigger[1].mask=%d trigger[2].mask=%d\n"),  | qse_printf (QSE_T("task_main_proxy_5 trigger[0].mask=%d trigger[1].mask=%d trigger[2].mask=%d\n"),  | ||||||
| 	task->trigger[0].mask, task->trigger[1].mask, task->trigger[2].mask); | 	task->trigger[0].mask, task->trigger[1].mask, task->trigger[2].mask); | ||||||
|  |  | ||||||
| @ -932,8 +931,6 @@ static int task_main_proxy_4 ( | |||||||
| { | { | ||||||
| 	task_proxy_t* proxy = (task_proxy_t*)task->ctx; | 	task_proxy_t* proxy = (task_proxy_t*)task->ctx; | ||||||
| 	 | 	 | ||||||
| 	//QSE_ASSERT (proxy->pio_inited); |  | ||||||
|  |  | ||||||
| qse_printf (QSE_T("task_main_proxy_4 trigger[0].mask=%d trigger[1].mask=%d trigger[2].mask=%d\n"),  | qse_printf (QSE_T("task_main_proxy_4 trigger[0].mask=%d trigger[1].mask=%d trigger[2].mask=%d\n"),  | ||||||
| 	task->trigger[0].mask, task->trigger[1].mask, task->trigger[2].mask); | 	task->trigger[0].mask, task->trigger[1].mask, task->trigger[2].mask); | ||||||
|  |  | ||||||
|  | |||||||
| @ -2049,6 +2049,7 @@ static int attempt_cgi ( | |||||||
| 				target->u.cgi.script = script; | 				target->u.cgi.script = script; | ||||||
| 				target->u.cgi.suffix = QSE_NULL; | 				target->u.cgi.suffix = QSE_NULL; | ||||||
| 				target->u.cgi.docroot = docroot; | 				target->u.cgi.docroot = docroot; | ||||||
|  | 				target->u.cgi.shebang = cgistd[i].shebang; | ||||||
| 				return 1; | 				return 1; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| @ -2095,6 +2096,7 @@ static int attempt_cgi ( | |||||||
| 				target->u.cgi.script = script; | 				target->u.cgi.script = script; | ||||||
| 				target->u.cgi.suffix = suffix; | 				target->u.cgi.suffix = suffix; | ||||||
| 				target->u.cgi.docroot = docroot; | 				target->u.cgi.docroot = docroot; | ||||||
|  | 				target->u.cgi.shebang = cgistd[i].shebang; | ||||||
| 				return 1; | 				return 1; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| @ -2154,7 +2156,7 @@ auth_ok: | |||||||
| 	if (stx <= -1) | 	if (stx <= -1) | ||||||
| 	{ | 	{ | ||||||
| 		/* this OS may fail in stat_file() if the path contains the trailing  | 		/* this OS may fail in stat_file() if the path contains the trailing  | ||||||
| 		 * separator. it 's beause of the way FindFirstFile() or DosQueryPathInfo() | 		 * separator. it's beause of the way FindFirstFile() or DosQueryPathInfo() | ||||||
| 		 * is ussed in stat_file(). let me work around it here. */ | 		 * is ussed in stat_file(). let me work around it here. */ | ||||||
| 		qse_size_t pl = qse_mbslen(xpath); | 		qse_size_t pl = qse_mbslen(xpath); | ||||||
| 		if (pl > 1 && xpath[pl - 1] == QSE_MT('/'))  | 		if (pl > 1 && xpath[pl - 1] == QSE_MT('/'))  | ||||||
| @ -2271,11 +2273,12 @@ qse_httpd_server_t* qse_httpd_attachserverstd ( | |||||||
| 	qse_uint16_t default_port; | 	qse_uint16_t default_port; | ||||||
| 	qse_uri_t xuri; | 	qse_uri_t xuri; | ||||||
|  |  | ||||||
|  |  | ||||||
| 	static qse_httpd_server_cgistd_t server_cgistd[] =  | 	static qse_httpd_server_cgistd_t server_cgistd[] =  | ||||||
| 	{ | 	{ | ||||||
| 		{ QSE_MT(".cgi"), 4, 0 }, | 		{ QSE_MT(".cgi"), 4, 0, QSE_NULL }, | ||||||
| 		{ QSE_MT(".nph"), 4, 1 }, | 		{ QSE_MT(".nph"), 4, 1, QSE_NULL }, | ||||||
| 		{ QSE_NULL,       0, 0 } | 		{ QSE_NULL,       0, 0, QSE_NULL } | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	static qse_httpd_server_mimestd_t server_mimestd[] = | 	static qse_httpd_server_mimestd_t server_mimestd[] = | ||||||
| @ -2458,7 +2461,7 @@ int qse_httpd_getserveroptstd ( | |||||||
| 		case QSE_HTTPD_SERVER_CGISTD: | 		case QSE_HTTPD_SERVER_CGISTD: | ||||||
| 		case QSE_HTTPD_SERVER_MIMESTD: | 		case QSE_HTTPD_SERVER_MIMESTD: | ||||||
| 		case QSE_HTTPD_SERVER_IDXSTD: | 		case QSE_HTTPD_SERVER_IDXSTD: | ||||||
| 			*(qse_mchar_t**)value = (void*)server_xtn->cfg2.a[id - QSE_HTTPD_SERVER_CBSTD]; | 			*(void**)value = (void*)server_xtn->cfg2.a[id - QSE_HTTPD_SERVER_CBSTD]; | ||||||
| 			return 0; | 			return 0; | ||||||
| 	}	 | 	}	 | ||||||
|  |  | ||||||
|  | |||||||
| @ -405,45 +405,42 @@ qse_httpd_task_t* qse_httpd_entaskrsrc ( | |||||||
| 	switch (rsrc->type) | 	switch (rsrc->type) | ||||||
| 	{ | 	{ | ||||||
| 		case QSE_HTTPD_RSRC_AUTH: | 		case QSE_HTTPD_RSRC_AUTH: | ||||||
| 			task = qse_httpd_entaskauth (httpd, client, QSE_NULL, rsrc->u.auth.realm, req); | 			task = qse_httpd_entaskauth (httpd, client, pred, rsrc->u.auth.realm, req); | ||||||
| 			break; | 			break; | ||||||
|  |  | ||||||
| 		case QSE_HTTPD_RSRC_CGI: | 		case QSE_HTTPD_RSRC_CGI: | ||||||
| 			task = qse_httpd_entaskcgi ( | 			task = qse_httpd_entaskcgi (httpd, client, pred, &rsrc->u.cgi, req); | ||||||
| 				httpd, client, QSE_NULL, rsrc->u.cgi.path, |  | ||||||
| 				rsrc->u.cgi.script, rsrc->u.cgi.suffix,  |  | ||||||
| 				rsrc->u.cgi.docroot, rsrc->u.cgi.nph, req); |  | ||||||
| 			break; | 			break; | ||||||
|  |  | ||||||
| 		case QSE_HTTPD_RSRC_DIR: | 		case QSE_HTTPD_RSRC_DIR: | ||||||
| 			qse_httpd_discardcontent (httpd, req); | 			qse_httpd_discardcontent (httpd, req); | ||||||
| 			task = qse_httpd_entaskdir (httpd, client, QSE_NULL, rsrc->u.dir.path, req); | 			task = qse_httpd_entaskdir (httpd, client, pred, rsrc->u.dir.path, req); | ||||||
| 			break; | 			break; | ||||||
|  |  | ||||||
| 		case QSE_HTTPD_RSRC_ERR: | 		case QSE_HTTPD_RSRC_ERR: | ||||||
| 			qse_httpd_discardcontent (httpd, req); | 			qse_httpd_discardcontent (httpd, req); | ||||||
| 			task = qse_httpd_entaskerr (httpd, client, QSE_NULL, rsrc->u.err.code, req); | 			task = qse_httpd_entaskerr (httpd, client, pred, rsrc->u.err.code, req); | ||||||
| 			break; | 			break; | ||||||
|  |  | ||||||
| 		case QSE_HTTPD_RSRC_FILE: | 		case QSE_HTTPD_RSRC_FILE: | ||||||
| 			qse_httpd_discardcontent (httpd, req); | 			qse_httpd_discardcontent (httpd, req); | ||||||
| 			task = qse_httpd_entaskfile (httpd, client, QSE_NULL, rsrc->u.file.path, rsrc->u.file.mime, req); | 			task = qse_httpd_entaskfile (httpd, client, pred, rsrc->u.file.path, rsrc->u.file.mime, req); | ||||||
| 			break; | 			break; | ||||||
| 	 | 	 | ||||||
| 		case QSE_HTTPD_RSRC_PROXY: | 		case QSE_HTTPD_RSRC_PROXY: | ||||||
| 			task = qse_httpd_entaskproxy (httpd, client, QSE_NULL, &rsrc->u.proxy.dst, &rsrc->u.proxy.src, req); | 			task = qse_httpd_entaskproxy (httpd, client, pred, &rsrc->u.proxy.dst, &rsrc->u.proxy.src, req); | ||||||
| 			break; | 			break; | ||||||
|  |  | ||||||
| 		case QSE_HTTPD_RSRC_RELOC: | 		case QSE_HTTPD_RSRC_RELOC: | ||||||
| 			task = qse_httpd_entaskreloc (httpd, client, QSE_NULL, rsrc->u.reloc.dst, req); | 			task = qse_httpd_entaskreloc (httpd, client, pred, rsrc->u.reloc.dst, req); | ||||||
| 			break; | 			break; | ||||||
|  |  | ||||||
| 		case QSE_HTTPD_RSRC_REDIR: | 		case QSE_HTTPD_RSRC_REDIR: | ||||||
| 			task = qse_httpd_entaskredir (httpd, client, QSE_NULL, rsrc->u.redir.dst, req); | 			task = qse_httpd_entaskredir (httpd, client, pred, rsrc->u.redir.dst, req); | ||||||
| 			break; | 			break; | ||||||
|  |  | ||||||
| 		case QSE_HTTPD_RSRC_TEXT: | 		case QSE_HTTPD_RSRC_TEXT: | ||||||
| 			task = qse_httpd_entasktext (httpd, client, QSE_NULL, rsrc->u.text.ptr, rsrc->u.text.mime, req); | 			task = qse_httpd_entasktext (httpd, client, pred, rsrc->u.text.ptr, rsrc->u.text.mime, req); | ||||||
| 			break; | 			break; | ||||||
|  |  | ||||||
| 		default: | 		default: | ||||||
|  | |||||||
| @ -109,14 +109,30 @@ void* qse_httpd_getxtn (qse_httpd_t* httpd) | |||||||
| 	return QSE_XTN (httpd); | 	return QSE_XTN (httpd); | ||||||
| } | } | ||||||
|  |  | ||||||
| int qse_httpd_getoption (qse_httpd_t* httpd) | int qse_httpd_getopt (qse_httpd_t* httpd, qse_httpd_opt_t id, void* value) | ||||||
| { | { | ||||||
| 	return httpd->option; | 	switch (id) | ||||||
|  | 	{ | ||||||
|  | 		case QSE_HTTPD_TRAIT: | ||||||
|  | 			*(int*)value = httpd->opt.trait; | ||||||
|  | 			return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	httpd->errnum = QSE_HTTPD_EINVAL; | ||||||
|  | 	return -1; | ||||||
| } | } | ||||||
|  |  | ||||||
| void qse_httpd_setoption (qse_httpd_t* httpd, int option) | int qse_httpd_setopt (qse_httpd_t* httpd, qse_httpd_opt_t id, const void* value) | ||||||
| { | { | ||||||
| 	httpd->option = option; | 	switch (id) | ||||||
|  | 	{ | ||||||
|  | 		case QSE_HTTPD_TRAIT: | ||||||
|  | 			httpd->opt.trait = *(const int*)value; | ||||||
|  | 			return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	httpd->errnum = QSE_HTTPD_EINVAL; | ||||||
|  | 	return -1; | ||||||
| } | } | ||||||
|  |  | ||||||
| /* --------------------------------------------------- */ | /* --------------------------------------------------- */ | ||||||
| @ -640,7 +656,7 @@ qse_printf (QSE_T("Debug: connection closed %d\n"), client->handle.i); | |||||||
| 		 * if QSE_HTTPD_MUTECLIENT is on, attempt to handle | 		 * if QSE_HTTPD_MUTECLIENT is on, attempt to handle | ||||||
| 		 * it as a half-close under a certain condition. */ | 		 * it as a half-close under a certain condition. */ | ||||||
|  |  | ||||||
| 		if (httpd->option & QSE_HTTPD_MUTECLIENT && | 		if (httpd->opt.trait & QSE_HTTPD_MUTECLIENT && | ||||||
| 		    client->task.head && client->htrd->clean) | 		    client->task.head && client->htrd->clean) | ||||||
| 		{ | 		{ | ||||||
| 			/* there is still more tasks to finish and  | 			/* there is still more tasks to finish and  | ||||||
|  | |||||||
| @ -35,7 +35,10 @@ struct qse_httpd_t | |||||||
| 	qse_httpd_scb_t* scb; /* system callbacks */ | 	qse_httpd_scb_t* scb; /* system callbacks */ | ||||||
| 	qse_httpd_rcb_t* rcb; /* request callbacks */ | 	qse_httpd_rcb_t* rcb; /* request callbacks */ | ||||||
|  |  | ||||||
| 	int option; | 	struct | ||||||
|  | 	{ | ||||||
|  | 		int trait; | ||||||
|  | 	} opt; | ||||||
| 	int stopreq; | 	int stopreq; | ||||||
|  |  | ||||||
| 	qse_mchar_t sname[128]; /* server name for the server header */ | 	qse_mchar_t sname[128]; /* server name for the server header */ | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user