simplified relocation handling
deleted qse_httpd_entaskredir() and related definitions added virtual(function pointer) cgi support. improved pio to read /dev/fd implemented QSE_PIO_FNCCMD for qse_pio_t
This commit is contained in:
		| @ -437,7 +437,7 @@ static qse_wchar_t* get_env (qse_env_t* env, const qse_wchar_t* name, int* free) | ||||
| 				*free = 0; | ||||
| 				return eq + 1; | ||||
| 			} | ||||
| 			p++;	 | ||||
| 			p++; | ||||
| 		} | ||||
| 	} | ||||
| 	*/ | ||||
| @ -464,10 +464,10 @@ static qse_wchar_t* get_env (qse_env_t* env, const qse_wchar_t* name, int* free) | ||||
|  | ||||
| 			QSE_MMGR_FREE (env->mmgr, dup); | ||||
|  | ||||
| 			p++;	 | ||||
| 			p++; | ||||
| 		} | ||||
| 	} | ||||
| 				 | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| @ -494,10 +494,10 @@ static qse_mchar_t* get_env (qse_env_t* env, const qse_mchar_t* name, int* free) | ||||
| 				*free = 0; | ||||
| 				return eq + 1; | ||||
| 			} | ||||
| 			p++;	 | ||||
| 			p++; | ||||
| 		} | ||||
| 	} | ||||
| 				 | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
| #endif | ||||
| @ -587,14 +587,14 @@ static int load_curenv (qse_env_t* env) | ||||
| 		if (*envstr != QSE_WT('=') && | ||||
| 		    add_envstrw (env, envstr) <= -1) { ret = -1; goto done; } | ||||
| 		envstr += qse_wcslen (envstr) + 1; | ||||
| 	}		 | ||||
| 	} | ||||
| #else | ||||
| 	while (*envstr != QSE_MT('\0')) | ||||
| 	{ | ||||
| 		if (*envstr != QSE_MT('=') && | ||||
| 		    add_envstrm (env, envstr) <= -1) { ret = -1; goto done; } | ||||
| 		envstr += qse_mbslen (envstr) + 1; | ||||
| 	}		 | ||||
| 	} | ||||
| #endif | ||||
|  | ||||
| done: | ||||
| @ -614,7 +614,7 @@ done: | ||||
| 		while (*p) | ||||
| 		{ | ||||
| 			if (add_envstrw (env, *p) <= -1) return -1; | ||||
| 			p++;	 | ||||
| 			p++; | ||||
| 		} | ||||
| 	} | ||||
| 	*/ | ||||
| @ -635,11 +635,10 @@ done: | ||||
| 			QSE_MMGR_FREE (env->mmgr, dup); | ||||
| 			if (n <= -1) return -1; | ||||
|  | ||||
| 			p++;	 | ||||
| 			p++; | ||||
| 		} | ||||
| 	} | ||||
| 				 | ||||
| 				 | ||||
|  | ||||
| 	return 0; | ||||
|  | ||||
| #else | ||||
| @ -656,10 +655,10 @@ done: | ||||
| 		while (*p) | ||||
| 		{ | ||||
| 			if (add_envstrm (env, *p) <= -1) return -1; | ||||
| 			p++;	 | ||||
| 			p++; | ||||
| 		} | ||||
| 	} | ||||
| 				 | ||||
|  | ||||
| 	return 0; | ||||
| #endif | ||||
| } | ||||
|  | ||||
							
								
								
									
										1047
									
								
								qse/lib/cmn/pio.c
									
									
									
									
									
								
							
							
						
						
									
										1047
									
								
								qse/lib/cmn/pio.c
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -316,7 +316,7 @@ qse_task_slice_t* qse_task_create ( | ||||
| 	tmp = ((qse_uint8_t*)(slice + 1)) + stksize - QSE_SIZEOF(void*); | ||||
|  | ||||
| 	tmp = (qse_uint8_t*)tmp - QSE_SIZEOF(void*); | ||||
| 	*(void**)tmp = NULL; /* t1 */ | ||||
| 	*(void**)tmp = QSE_NULL; /* t1 */ | ||||
|  | ||||
| 	tmp = (qse_uint8_t*)tmp - QSE_SIZEOF(void*); | ||||
| 	*(void**)tmp = slice; /* t2 */ | ||||
|  | ||||
| @ -56,6 +56,7 @@ const qse_mchar_t* qse_httpstatustombs (int code) | ||||
| 		case 304: msg = QSE_MT("Not Modified"); break; | ||||
| 		case 305: msg = QSE_MT("Use Proxy"); break; | ||||
| 		case 307: msg = QSE_MT("Temporary Redirect"); break; | ||||
| 		case 308: msg = QSE_MT("Permanent Redirect"); break; | ||||
|  | ||||
| 		case 400: msg = QSE_MT("Bad Request"); break; | ||||
| 		case 401: msg = QSE_MT("Unauthorized"); break; | ||||
|  | ||||
| @ -44,6 +44,7 @@ struct task_cgi_arg_t | ||||
| 	qse_mcstr_t root; | ||||
| 	qse_mcstr_t shebang; | ||||
| 	int nph; | ||||
| 	qse_httpd_fnc_t fnc; | ||||
| 	qse_htre_t* req; | ||||
| }; | ||||
|  | ||||
| @ -63,6 +64,7 @@ struct task_cgi_t | ||||
| 	qse_http_version_t version; | ||||
| 	int keepalive; /* taken from the request */ | ||||
| 	int nph; | ||||
| 	qse_pio_fnc_t fnc; | ||||
|  | ||||
| 	qse_htrd_t* script_htrd; | ||||
| 	qse_env_t* env; | ||||
| @ -705,7 +707,7 @@ static int task_init_cgi ( | ||||
| 	qse_size_t len; | ||||
| 	const qse_mchar_t* ptr; | ||||
| 	const qse_htre_hdrval_t* tmp; | ||||
| 	 | ||||
|  | ||||
| 	cgi = (task_cgi_t*)qse_httpd_gettaskxtn (httpd, task); | ||||
| 	arg = (task_cgi_arg_t*)task->ctx; | ||||
|  | ||||
| @ -733,6 +735,12 @@ static int task_init_cgi ( | ||||
| 	cgi->keepalive = (arg->req->flags & QSE_HTRE_ATTR_KEEPALIVE); | ||||
| 	cgi->nph = arg->nph; | ||||
| 	cgi->req = QSE_NULL; | ||||
| 	if (arg->fnc.ptr)  | ||||
| 	{ | ||||
| 		/* the function pointer is set */ | ||||
| 		cgi->fnc.ptr = arg->fnc.ptr; | ||||
| 		cgi->fnc.ctx = arg->fnc.ctx; | ||||
| 	} | ||||
|  | ||||
| 	content_length = 0; | ||||
| 	if (arg->req->state & QSE_HTRE_DISCARDED) goto done; | ||||
| @ -1432,6 +1440,7 @@ static int task_main_cgi ( | ||||
| 		cgi_script_htrd_xtn_t* xtn; | ||||
| 		cgi->script_htrd = qse_htrd_open (httpd->mmgr, QSE_SIZEOF(cgi_script_htrd_xtn_t)); | ||||
| 		if (cgi->script_htrd == QSE_NULL) goto oops; | ||||
|  | ||||
| 		xtn = (cgi_script_htrd_xtn_t*) qse_htrd_getxtn (cgi->script_htrd); | ||||
| 		xtn->cgi = cgi; | ||||
| 		xtn->task = task; | ||||
| @ -1460,22 +1469,30 @@ static int task_main_cgi ( | ||||
| 	if (httpd->opt.trait & QSE_HTTPD_CGINOCLOEXEC)  | ||||
| 		pio_options |= QSE_PIO_NOCLOEXEC; | ||||
|  | ||||
| 	if (cgi->shebang[0] != QSE_MT('\0')) | ||||
| 	if (cgi->fnc.ptr) | ||||
| 	{ | ||||
| 		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; | ||||
| 		xpath = (qse_mchar_t*)&cgi->fnc; | ||||
| 		pio_options |= QSE_PIO_FNCCMD; | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		if (cgi->shebang[0] != QSE_MT('\0')) | ||||
| 		{ | ||||
| 			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; | ||||
| 	} | ||||
| 	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 (xpath != cgi->path && xpath != &cgi->fnc) QSE_MMGR_FREE (httpd->mmgr, xpath); | ||||
|  | ||||
| 	if (x <= -1) | ||||
| 	{ | ||||
| @ -1539,6 +1556,12 @@ static int task_main_cgi ( | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		/* no forwarding buffer. the request should not send any contents | ||||
| 		 * to the cgi script. close the input to the script */ | ||||
| 		qse_pio_end (&cgi->pio, QSE_PIO_IN); | ||||
| 	} | ||||
|  | ||||
| 	task->main = cgi->nph? task_main_cgi_4_nph: task_main_cgi_2; | ||||
| 	return 1; | ||||
| @ -1575,11 +1598,35 @@ qse_httpd_task_t* qse_httpd_entaskcgi ( | ||||
| 	task_cgi_arg_t arg; | ||||
| 	qse_httpd_rsrc_cgi_t rsrc; | ||||
|  | ||||
| 	QSE_MEMSET (&arg, 0, QSE_SIZEOF(arg)); | ||||
|  | ||||
| 	rsrc = *cgi; | ||||
| 	if (rsrc.flags & QSE_HTTPD_RSRC_CGI_FNC) | ||||
| 	{ | ||||
| 		/* rsrc.script must carry a pointer to qse_pio_fnc_t */ | ||||
| 		if (rsrc.script == QSE_NULL || ((qse_pio_fnc_t*)rsrc.script)->ptr == QSE_NULL) | ||||
| 		{ | ||||
| 			httpd->errnum = QSE_HTTPD_EINVAL; | ||||
| 			return QSE_NULL; | ||||
| 		} | ||||
|  | ||||
| 		arg.fnc.ptr = (qse_httpd_fncptr_t)rsrc.path; | ||||
| 		arg.fnc.ctx = (void*)rsrc.shebang; | ||||
|  | ||||
| 		/* reset the script to an empty string for less interference  | ||||
| 		 * with code handling normal script */ | ||||
| 		rsrc.path = QSE_MT(""); | ||||
| 		rsrc.shebang = QSE_MT(""); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		QSE_ASSERT (rsrc.path != QSE_NULL); | ||||
| 		if (rsrc.shebang == QSE_NULL) rsrc.shebang = QSE_MT(""); | ||||
| 	} | ||||
|  | ||||
| 	if (rsrc.script == QSE_NULL) rsrc.script = qse_htre_getqpath(req); | ||||
| 	if (rsrc.suffix == QSE_NULL) rsrc.suffix = QSE_MT(""); | ||||
| 	if (rsrc.root == QSE_NULL) rsrc.root = QSE_MT(""); | ||||
| 	if (rsrc.shebang == QSE_NULL) rsrc.shebang = QSE_MT(""); | ||||
|  | ||||
| 	arg.path.ptr = (qse_mchar_t*)rsrc.path; | ||||
| 	arg.path.len = qse_mbslen(rsrc.path); | ||||
| @ -1589,7 +1636,7 @@ qse_httpd_task_t* qse_httpd_entaskcgi ( | ||||
| 	arg.suffix.len = qse_mbslen(rsrc.suffix); | ||||
| 	arg.root.ptr = (qse_mchar_t*)rsrc.root; | ||||
| 	arg.root.len = qse_mbslen(rsrc.root); | ||||
| 	arg.nph = rsrc.nph; | ||||
| 	arg.nph = ((rsrc.flags & QSE_HTTPD_RSRC_CGI_NPH) != 0); | ||||
| 	arg.shebang.ptr = (qse_mchar_t*)rsrc.shebang; | ||||
| 	arg.shebang.len = qse_mbslen(rsrc.shebang); | ||||
| 	arg.req = req; | ||||
|  | ||||
| @ -1983,7 +1983,7 @@ printf ("XXXXXXXXXXXXXXXXXXXXXXXXXX URL REWRITTEN TO [%s].....\n", new_url); | ||||
| 		{ | ||||
| 			/* check if it begins with redirection code followed by a colon */ | ||||
| 			int redir_code = 0; | ||||
| 			qse_httpd_status_reloc_t reloc; | ||||
| 			qse_httpd_rsrc_reloc_t reloc; | ||||
| 			const qse_mchar_t* nuptr = new_url; | ||||
| 			do | ||||
| 			{ | ||||
| @ -1996,11 +1996,14 @@ printf ("XXXXXXXXXXXXXXXXXXXXXXXXXX URL REWRITTEN TO [%s].....\n", new_url); | ||||
| 				/* no colon is found after digits. it's probably a normal url */ | ||||
| 				goto normal_url; | ||||
| 			} | ||||
| 			if (redir_code != 301 && redir_code != 302 && redir_code != 307) redir_code = 301; | ||||
| 			if (redir_code != 301 && redir_code != 302 && redir_code != 303 &&  | ||||
| 			    redir_code != 307 && redir_code != 308) redir_code = 302; | ||||
| 			nuptr++; | ||||
|  | ||||
| 			/* relocation code is given explictly, no slash appending is needed. | ||||
| 			 * use qse_httpd_entask_status() rather than qse_httpd_entaskreloc(). */ | ||||
| 			reloc.flags = 0;  | ||||
| 			reloc.dst = nuptr; | ||||
| 			reloc.redir = 0; /* don't want to append extra / */ | ||||
|  | ||||
| 			if (qse_httpd_entask_status ( | ||||
| 				httpd, proxy->client, proxy->task, redir_code, &reloc, | ||||
|  | ||||
| @ -1547,7 +1547,7 @@ static int file_stat ( | ||||
| 	 * for a file. it is mainly used to get a file size and timestamps | ||||
| 	 * of a regular file. so it should fail for a non-regular file. | ||||
| 	 * note that STAT_REG is passed to stat_file for it */ | ||||
| 	return stat_file (httpd, path, hst, STAT_REG);	 | ||||
| 	return stat_file (httpd, path, hst, STAT_REG); | ||||
| } | ||||
|  | ||||
| static int file_purge (qse_httpd_t* httpd, const qse_mchar_t* path) | ||||
| @ -2444,10 +2444,13 @@ static void free_resource ( | ||||
| 				QSE_MMGR_FREE (httpd->mmgr, (qse_mchar_t*)target->u.cgi.suffix); | ||||
| 			if (target->u.cgi.script != qpath)  | ||||
| 				QSE_MMGR_FREE (httpd->mmgr, (qse_mchar_t*)target->u.cgi.script); | ||||
| 			if (target->u.cgi.path != qpath) | ||||
| 				QSE_MMGR_FREE (httpd->mmgr, (qse_mchar_t*)target->u.cgi.path); | ||||
| 			if (target->u.cgi.shebang) | ||||
| 				QSE_MMGR_FREE (httpd->mmgr, (qse_mchar_t*)target->u.cgi.shebang); | ||||
| 			if (!(target->u.cgi.flags & QSE_HTTPD_RSRC_CGI_FNC)) | ||||
| 			{ | ||||
| 				if (target->u.cgi.path != qpath) | ||||
| 					QSE_MMGR_FREE (httpd->mmgr, (qse_mchar_t*)target->u.cgi.path); | ||||
| 				if (target->u.cgi.shebang) | ||||
| 					QSE_MMGR_FREE (httpd->mmgr, (qse_mchar_t*)target->u.cgi.shebang); | ||||
| 			} | ||||
|  | ||||
| 			break; | ||||
|  | ||||
| @ -2457,8 +2460,8 @@ static void free_resource ( | ||||
| 			break; | ||||
|  | ||||
| 		case QSE_HTTPD_RSRC_FILE: | ||||
| 			if (target->u.cgi.path != qpath) | ||||
| 				QSE_MMGR_FREE (httpd->mmgr, (qse_mchar_t*)target->u.cgi.path); | ||||
| 			if (target->u.file.path != qpath) | ||||
| 				QSE_MMGR_FREE (httpd->mmgr, (qse_mchar_t*)target->u.file.path); | ||||
| 			break; | ||||
|  | ||||
| 		case QSE_HTTPD_RSRC_RELOC: | ||||
| @ -2466,11 +2469,6 @@ static void free_resource ( | ||||
| 				QSE_MMGR_FREE (httpd->mmgr, (qse_mchar_t*)target->u.reloc.dst); | ||||
| 			break; | ||||
|  | ||||
| 		case QSE_HTTPD_RSRC_REDIR: | ||||
| 			if (target->u.redir.dst != qpath) | ||||
| 				QSE_MMGR_FREE (httpd->mmgr, (qse_mchar_t*)target->u.redir.dst); | ||||
| 			break; | ||||
|  | ||||
| 		default: | ||||
| 			/* nothing to do */ | ||||
| 			break; | ||||
| @ -2573,22 +2571,19 @@ static int attempt_cgi ( | ||||
| 				#endif | ||||
|  | ||||
| 				/* create a relocation resource */ | ||||
| 				QSE_MEMSET (target, 0, QSE_SIZEOF(*target)); | ||||
| 				target->type = QSE_HTTPD_RSRC_RELOC; | ||||
| 				target->u.reloc.dst = merge_paths (httpd, tmp->qpath, tmp->idxfile); | ||||
| 				if (target->u.reloc.dst == QSE_NULL) goto oops; | ||||
|  | ||||
| 				/* free tmp->xpath here upon success since it's not used for relocation. | ||||
| 				 * it is freed by the called upon failure so the 'oops' part don't free it */ | ||||
| 				 * upon failure, it is freed by the caller. so the 'oops' part  | ||||
| 				 * of this function doesn't free it. */ | ||||
| 				QSE_MMGR_FREE (httpd->mmgr, tmp->xpath); | ||||
| 				return 1; | ||||
| 			} | ||||
| 			else script = (qse_mchar_t*)tmp->qpath; | ||||
|  | ||||
| 			if (cgi.shebang) | ||||
| 			{ | ||||
| 				shebang = qse_mbsdup (cgi.shebang, httpd->mmgr); | ||||
| 				if (shebang == QSE_NULL) goto oops; | ||||
| 			} | ||||
|  | ||||
| 			goto bingo; | ||||
| 		} | ||||
| 	} | ||||
| @ -2619,14 +2614,13 @@ static int attempt_cgi ( | ||||
| 					 */ | ||||
| 					merge_paths_to_buf (httpd, tmp->root.u.path.val, tmp->qpath_rp, slash - tmp->qpath_rp, tmp->xpath); | ||||
| 					xpath_changed = 1; | ||||
| 	 | ||||
|  | ||||
| 					stx = stat_file (httpd, tmp->xpath, &st, 0); | ||||
| 					if (stx <= -1)  | ||||
| 					{ | ||||
| 						/* stop at the current segment if stating fails.  | ||||
| 						 * if the current semgment can't be stat-ed, it's not likely that | ||||
| 						 * the next segment can be successfully stat-ed */ | ||||
| 						break;  | ||||
| 						/* instead of stopping here, let's give a non-existent  | ||||
| 						 * segment to be a virtual cgi script(function pointer). */ | ||||
| 						st.isdir = 0; | ||||
| 					} | ||||
|  | ||||
| 					if (!st.isdir) | ||||
| @ -2636,9 +2630,16 @@ static int attempt_cgi ( | ||||
| 						QSE_MEMSET (&qinfo, 0, QSE_SIZEOF(qinfo)); | ||||
| 						qinfo.req = req; | ||||
| 						qinfo.xpath = tmp->xpath; | ||||
| 						qinfo.xpath_nx = (stx <= -1); | ||||
|  | ||||
| 						if (server_xtn->query (httpd, client->server, QSE_HTTPD_SERVERSTD_CGI, &qinfo, &cgi) >= 0 && cgi.cgi) | ||||
| 						{ | ||||
| 							if (cgi.fncptr == QSE_NULL && stx <= -1)  | ||||
| 							{ | ||||
| 								/* normal cgi script must exist. */ | ||||
| 								break; | ||||
| 							} | ||||
|  | ||||
| 							/* the script name is composed of the orginal query path. | ||||
| 							 * the pointer held in 'slash' is valid for tmp->qpath as | ||||
| 							 * tmp->qpath_rp is at most the tail part of tmp->qpath. */ | ||||
| @ -2646,23 +2647,57 @@ static int attempt_cgi ( | ||||
| 							suffix = qse_mbsdup (slash, httpd->mmgr); | ||||
| 							if (!script || !suffix) goto oops; | ||||
|  | ||||
| 							if (cgi.shebang) | ||||
| 							{ | ||||
| 								shebang = qse_mbsdup (cgi.shebang, httpd->mmgr); | ||||
| 								if (shebang == QSE_NULL) goto oops; | ||||
| 							} | ||||
|  | ||||
| 							goto bingo; | ||||
| 						} | ||||
| 					} | ||||
|  | ||||
| 					if (stx <= -1)  | ||||
| 					{ | ||||
| 						/* stop at the current segment if stat() fails.  | ||||
| 						 * if the current segment can't be stat-ed, it's not likely that | ||||
| 						 * the next segment can be stat-ed successfully */ | ||||
| 						break; | ||||
| 					} | ||||
| 				} | ||||
|  | ||||
| 				ptr = slash + 1; | ||||
| 			} | ||||
| 			else  | ||||
| 			{ | ||||
| 				/* no more slash is found. the last segement doesn't have to be checked  | ||||
| 				 * here since it's attempted by the caller. */ | ||||
| 				/* no more slash is found. this is the last segment. | ||||
| 				 * the caller has called stat() against the last segment | ||||
| 				 * before having called this function. so it's known | ||||
| 				 * that the path disn't exist. | ||||
| 				 *  | ||||
| 				 * however, a virtual cgi script may not exist. a check | ||||
| 				 * for it is still required here */ | ||||
| 				 | ||||
| 				qse_httpd_serverstd_query_info_t qinfo; | ||||
|  | ||||
| 				if (xpath_changed) | ||||
| 				{ | ||||
| 					/* restore the tmp->xpath to the original value by  | ||||
| 					 * combining the full path with the document root. */ | ||||
| 					merge_paths_to_buf (httpd, tmp->root.u.path.val, tmp->qpath_rp, (qse_size_t)-1, tmp->xpath); | ||||
| 					xpath_changed = 0; | ||||
| 				} | ||||
|  | ||||
| 				QSE_MEMSET (&qinfo, 0, QSE_SIZEOF(qinfo)); | ||||
| 				qinfo.req = req; | ||||
| 				qinfo.xpath = tmp->xpath; | ||||
| 				qinfo.xpath_nx = 1; | ||||
|  | ||||
| 				if (server_xtn->query (httpd, client->server, QSE_HTTPD_SERVERSTD_CGI, &qinfo, &cgi) >= 0 && cgi.cgi && cgi.fncptr) | ||||
| 				{ | ||||
| 					/* virtual cgi script */ | ||||
| 					script = qse_mbsdup (tmp->qpath, httpd->mmgr); | ||||
| 					if (!script) goto oops; | ||||
| 					suffix = QSE_NULL; | ||||
|  | ||||
| 					goto bingo; | ||||
| 				} | ||||
|  | ||||
| 				/* not a virtual cgi script. just break */ | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| @ -2675,12 +2710,32 @@ static int attempt_cgi ( | ||||
|  | ||||
| bingo: | ||||
| 	target->type = QSE_HTTPD_RSRC_CGI; | ||||
| 	target->u.cgi.nph = cgi.nph; | ||||
| 	target->u.cgi.path = tmp->xpath; | ||||
| 	target->u.cgi.flags = 0; | ||||
| 	if (cgi.nph) target->u.cgi.flags |= QSE_HTTPD_RSRC_CGI_NPH; | ||||
|  | ||||
| 	if (cgi.fncptr)  | ||||
| 	{ | ||||
| 		/* the type casting here is guly */ | ||||
| 		target->u.cgi.path = (qse_mchar_t*)cgi.fncptr; | ||||
| 		target->u.cgi.shebang = cgi.shebang; | ||||
| 		target->u.cgi.flags |= QSE_HTTPD_RSRC_CGI_FNC; | ||||
| 	} | ||||
| 	else  | ||||
| 	{ | ||||
| 		if (cgi.shebang) | ||||
| 		{ | ||||
| 			shebang = qse_mbsdup (cgi.shebang, httpd->mmgr); | ||||
| 			if (shebang == QSE_NULL) goto oops; | ||||
| 		} | ||||
|  | ||||
| 		target->u.cgi.path = tmp->xpath; | ||||
| 		target->u.cgi.shebang = shebang; | ||||
| 	} | ||||
|  | ||||
| 	target->u.cgi.script = script; | ||||
| 	target->u.cgi.suffix = suffix; | ||||
| 	target->u.cgi.root = tmp->root.u.path.val; | ||||
| 	target->u.cgi.shebang = shebang; | ||||
|  | ||||
| 	return 1; | ||||
|  | ||||
| oops: | ||||
| @ -2739,6 +2794,13 @@ static int make_resource ( | ||||
| 	/* handle the request locally */ | ||||
| 	QSE_ASSERT (tmp.root.type == QSE_HTTPD_SERVERSTD_ROOT_PATH); | ||||
|  | ||||
| /***************************************************************************** | ||||
|  * BUG BUG BUG !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1 | ||||
|  * TODO: calling the realm query here is wrong especially if the prefix path is resolved to a cgi. | ||||
|  * for example, /abc/def/test.cgi/x/y/z,  | ||||
|  * when this function queries for REALM, it's not known that /abc/def/test.cgi is a cgi script. | ||||
|  | ||||
|  *****************************************************************************/ | ||||
| 	if (server_xtn->query (httpd, client->server, QSE_HTTPD_SERVERSTD_REALM, &qinfo, &tmp.realm) <= -1 || | ||||
| 	    server_xtn->query (httpd, client->server, QSE_HTTPD_SERVERSTD_INDEX, &qinfo, &tmp.index) <= -1) | ||||
| 	{ | ||||
| @ -2877,7 +2939,7 @@ auth_ok: | ||||
| 						tmp.xpath = tpath; | ||||
| 						tmp.idxfile = ptr; | ||||
| 						goto attempt_file; | ||||
| 					}	 | ||||
| 					} | ||||
|  | ||||
| 					QSE_MMGR_FREE (httpd->mmgr, tpath); | ||||
| 				} | ||||
| @ -2898,8 +2960,9 @@ auth_ok: | ||||
| 			{ | ||||
| 				/* the query path doesn't end with a slash. so redirect it  */ | ||||
| 				qse_htre_discardcontent (req); | ||||
| 				target->type = QSE_HTTPD_RSRC_REDIR; | ||||
| 				target->u.redir.dst = tmp.qpath; | ||||
| 				target->type = QSE_HTTPD_RSRC_RELOC; | ||||
| 				target->u.reloc.flags = QSE_HTTPD_RSRC_RELOC_APPENDSLASH | QSE_HTTPD_RSRC_RELOC_PERMANENT; | ||||
| 				target->u.reloc.dst = tmp.qpath; | ||||
| 				/* free xpath since it won't be used */ | ||||
| 				QSE_MMGR_FREE (httpd->mmgr, tmp.xpath); | ||||
| 			} | ||||
| @ -2929,7 +2992,16 @@ auth_ok: | ||||
| 			QSE_MMGR_FREE (httpd->mmgr, tmp.xpath); | ||||
| 			return -1; | ||||
| 		} | ||||
| 		if (n >= 1) return 0; | ||||
| 		if (n >= 1)  | ||||
| 		{ | ||||
| 			if (target->u.cgi.flags & QSE_HTTPD_RSRC_CGI_FNC) | ||||
| 			{ | ||||
| 				/* tmp.xpath is not set to target->u.cgi.path when | ||||
| 				 * this flag is set. it must be deallocated */ | ||||
| 				QSE_MMGR_FREE (httpd->mmgr, tmp.xpath); | ||||
| 			} | ||||
| 			return 0; | ||||
| 		} | ||||
|  | ||||
| 		qinfo.xpath = tmp.xpath; | ||||
|  | ||||
| @ -3015,8 +3087,8 @@ struct cgi_tab_t | ||||
| }; | ||||
| static struct cgi_tab_t cgitab[] = | ||||
| { | ||||
| 	{ QSE_MT(".cgi"), { 1, 0, QSE_NULL } }, | ||||
| 	{ QSE_MT(".nph"), { 1, 1, QSE_NULL } }, | ||||
| 	{ QSE_MT(".cgi"), { 1, 0, QSE_NULL, QSE_NULL } }, | ||||
| 	{ QSE_MT(".nph"), { 1, 1, QSE_NULL, QSE_NULL } }, | ||||
| }; | ||||
|  | ||||
| static int query_server ( | ||||
| @ -3071,12 +3143,18 @@ static int query_server ( | ||||
| 		case QSE_HTTPD_SERVERSTD_CGI: | ||||
| 		{ | ||||
| 			qse_httpd_serverstd_cgi_t* cgi = (qse_httpd_serverstd_cgi_t*)result; | ||||
| 			for (i = 0; i < QSE_COUNTOF(cgitab); i++) | ||||
|  | ||||
| 			if (!qinfo->xpath_nx)  | ||||
| 			{ | ||||
| 				if (qse_mbsend (qinfo->xpath, cgitab[i].suffix)) | ||||
| 				/* this standard implementation supports a normal cgi script only */ | ||||
|  | ||||
| 				for (i = 0; i < QSE_COUNTOF(cgitab); i++) | ||||
| 				{ | ||||
| 					QSE_MEMCPY (cgi, &cgitab[i].cgi, QSE_SIZEOF(*cgi)); | ||||
| 					return 0; | ||||
| 					if (qse_mbsend (qinfo->xpath, cgitab[i].suffix)) | ||||
| 					{ | ||||
| 						QSE_MEMCPY (cgi, &cgitab[i].cgi, QSE_SIZEOF(*cgi)); | ||||
| 						return 0; | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
|  | ||||
| @ -178,14 +178,16 @@ qse_httpd_task_t* qse_httpd_entask_status ( | ||||
| 	msg = qse_httpstatustombs (code); | ||||
| 	switch (code) | ||||
| 	{ | ||||
| 		case 301: | ||||
| 		case 302: | ||||
| 		case 307: | ||||
| 		case 301: /* Moved Permanently */  | ||||
| 		case 302: /* Found */ | ||||
| 		case 303: /* See Other (since HTTP/1.1) */ | ||||
| 		case 307: /* Temporary Redirect (since HTTP/1.1) */ | ||||
| 		case 308: /* Permanent Redirect (Experimental RFC; RFC 7238) */ | ||||
| 		{ | ||||
| 			qse_httpd_status_reloc_t* reloc; | ||||
| 			reloc = (qse_httpd_status_reloc_t*)extra; | ||||
| 			qse_httpd_rsrc_reloc_t* reloc; | ||||
| 			reloc = (qse_httpd_rsrc_reloc_t*)extra; | ||||
| 			extrapre = QSE_MT("Location: "); | ||||
| 			extrapst = reloc->redir? QSE_MT("/\r\n"): QSE_MT("\r\n"); | ||||
| 			extrapst = (reloc->flags & QSE_HTTPD_RSRC_RELOC_APPENDSLASH)? QSE_MT("/\r\n"): QSE_MT("\r\n"); | ||||
| 			extraval = reloc->dst; | ||||
| 			break; | ||||
| 		} | ||||
| @ -276,31 +278,22 @@ qse_httpd_task_t* qse_httpd_entaskauth ( | ||||
|  | ||||
| qse_httpd_task_t* qse_httpd_entaskreloc ( | ||||
| 	qse_httpd_t* httpd, qse_httpd_client_t* client,  | ||||
| 	qse_httpd_task_t* pred, const qse_mchar_t* dst, qse_htre_t* req) | ||||
| 	qse_httpd_task_t* pred, const qse_httpd_rsrc_reloc_t* reloc, qse_htre_t* req) | ||||
| { | ||||
| 	qse_httpd_status_reloc_t reloc; | ||||
| 	int code; | ||||
|  | ||||
| 	reloc.dst = dst; | ||||
| 	reloc.redir = 0; | ||||
| 	if (reloc->flags & QSE_HTTPD_RSRC_RELOC_KEEPMETHOD) | ||||
| 	{ | ||||
| 		code = (reloc->flags & QSE_HTTPD_RSRC_RELOC_PERMANENT)? 308: 307; | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		/* NOTE: 302 can be 303 for HTTP/1.1 */ | ||||
| 		code = (reloc->flags & QSE_HTTPD_RSRC_RELOC_PERMANENT)? 301: 302; | ||||
| 	} | ||||
|  | ||||
| 	return qse_httpd_entask_status ( | ||||
| 		httpd, client, pred, 301, (void*)&reloc, | ||||
| 		qse_htre_getqmethodtype(req),  | ||||
| 		qse_htre_getversion(req),  | ||||
| 		(req->flags & QSE_HTRE_ATTR_KEEPALIVE)); | ||||
| } | ||||
|  | ||||
| qse_httpd_task_t* qse_httpd_entaskredir ( | ||||
| 	qse_httpd_t* httpd, qse_httpd_client_t* client,  | ||||
| 	qse_httpd_task_t* pred, const qse_mchar_t* dst, qse_htre_t* req) | ||||
| { | ||||
| 	qse_httpd_status_reloc_t reloc; | ||||
|  | ||||
| 	reloc.dst = dst; | ||||
| 	reloc.redir = 1; | ||||
|  | ||||
| 	return qse_httpd_entask_status ( | ||||
| 		httpd, client, pred, 301, (void*)&reloc, | ||||
| 		httpd, client, pred, code, (void*)reloc, | ||||
| 		qse_htre_getqmethodtype(req),  | ||||
| 		qse_htre_getversion(req),  | ||||
| 		(req->flags & QSE_HTRE_ATTR_KEEPALIVE)); | ||||
| @ -403,11 +396,7 @@ qse_httpd_task_t* qse_httpd_entaskrsrc ( | ||||
| 			break; | ||||
|  | ||||
| 		case QSE_HTTPD_RSRC_RELOC: | ||||
| 			task = qse_httpd_entaskreloc (httpd, client, pred, rsrc->u.reloc.dst, req); | ||||
| 			break; | ||||
|  | ||||
| 		case QSE_HTTPD_RSRC_REDIR: | ||||
| 			task = qse_httpd_entaskredir (httpd, client, pred, rsrc->u.redir.dst, req); | ||||
| 			task = qse_httpd_entaskreloc (httpd, client, pred, &rsrc->u.reloc, req); | ||||
| 			break; | ||||
|  | ||||
| 		case QSE_HTTPD_RSRC_TEXT: | ||||
|  | ||||
| @ -100,13 +100,6 @@ struct qse_httpd_real_task_t | ||||
| 	qse_httpd_real_task_t* next; | ||||
| }; | ||||
|  | ||||
| typedef struct qse_httpd_status_reloc_t qse_httpd_status_reloc_t; | ||||
| struct qse_httpd_status_reloc_t | ||||
| { | ||||
| 	const qse_mchar_t* dst; | ||||
| 	int redir; | ||||
| }; | ||||
|  | ||||
| #define MAX_SEND_SIZE 4096 | ||||
| #define MAX_RECV_SIZE 4096 | ||||
|  | ||||
|  | ||||
		Reference in New Issue
	
	Block a user