Example #1
0
int cgiHandler(struct worker_ctl *wctl)
{
	struct conn_request *req = &wctl->conn.con_req;
	struct conn_response *res = &wctl->conn.con_res;
	char *command = strstr(req->uri, CGISTR) + strlen(CGISTR);
	char *arg[ARGNUM];
	int num = 0;
	char *rpath = wctl->conn.con_req.rpath;
	stat *fs = &wctl->conn.con_res.fsate;

	int retval = -1;
	/*查找CGI的命令*/
	char *pos = command;
	for(;*pos != '?' && *pos !='\0';pos++)
		;
	*pos = '\0';
	sprintf(rpath, "%s%s",conf_para.CGIRoot,command);

	/*CGI的参数*/
	pos++;
	for(;*pos != '\0' && num < ARGNUM;)
	{
		arg[num] = pos;
		for(;*pos != '+' && *pos!='\0';pos++)
			;
		if(*pos == '+')
		{
			*pos = '\0';
			pos++;
			num++;
		}
	}
	arg[num] = NULL;

	/*命令的属性*/
	if(stat(rpath,fs)<0)
	{
		/*错误*/
		res->status = 403;
		retval = -1;
		goto EXITcgiHandler;
	}
	else if((fs->st_mode & S_IFDIR) == S_IFDIR)
	{
		/*是一个目录,列出目录下的文件*/
		GenerateDirFile(wctl);
		retval = 0;
		goto EXITcgiHandler;
	} 
	else if((fs->st_mode & S_IXUSR) != S_IXUSR)
	{
		/*所指文件不能执行*/
		res->status = 403;
		retval = -1;
		goto EXITcgiHandler;
	}
	
	/*创建进程间通信的管道*/	
	int pipe_in[2];
	int pipe_out[2];

	if(pipe[pipe_in] < 0)
	{
		res->status = 500;
		retval = -1;
		goto EXITcgiHandler;
	}

	if(pipe[pipe_out] < 0)
	{
		res->status = 500;
		retval = -1;
		goto EXITcgiHandler;
	}

	/*进程分叉*/
	int pid = 0;
	pid = fork();
	if(pid < 0)/*错误*/
	{
		res->status = 500;
		retval = -1;
		goto EXITcgiHandler;
	}
	else if(pid > 0)/*父进程*/
	{
		close(pipe_out[WRITEOUT]);
		close(pipe_in[READIN]);

		{
			memset(path, 0, URI_MAX);

			size_t		n;
			unsigned long	r1, r2;
			char	*fmt = "%a, %d %b %Y %H:%M:%S GMT";

			/*需要确定的参数*/
			size_t status = 200;		/*状态值,已确定*/
			char *msg = "OK";	/*状态信息,已确定*/
			char  date[64] = "";		/*时间*/
			char  lm[64] = "";			/*请求文件最后修改信息*/
			char  etag[64] = "";		/*etag信息*/
			big_int_t cl;				/*内容长度*/
			char  range[64] = "";		/*范围*/	
			struct mine_type *mine = NULL;

			/*当前时间*/
			time_t t = time(NULL);	
			(void) strftime(date, 
						sizeof(date), 
						fmt, 
						localtime(&t));

			/*最后修改时间*/
			(void) strftime(lm, 
						sizeof(lm), 
						fmt, 
						localtime(&res->fsate.st_mtime));

			/*ETAG*/
			(void) snprintf(etag, 
						sizeof(etag), 
						"%lx.%lx",
						(unsigned long) res->fsate.st_mtime,
						(unsigned long) res->fsate.st_size);
			
			/*发送的MIME类型*/
			mine = Mine_Type(req->uri, strlen(req->uri), wctl);

			memset(res->res.ptr, 0, sizeof(wctl->conn.dres));
			snprintf(
				res->res.ptr,
				sizeof(wctl->conn.dres),
				"HTTP/1.1 %d %s\r\n" 
				"Date: %s\r\n"
				"Last-Modified: %s\r\n"
				"Etag: \"%s\"\r\n"
				"Content-Type: %s\r\n"
				"Accept-Ranges: bytes\r\n"		
				"%s\r\n",
				status,
				msg,
				date,
				lm,
				etag,
				"html",
				range);
			res->status = status;

			send(wctl->conn.cs, res->res.ptr, strlen(res->res.ptr));
		}

		int size = 0;
		int end = 0;
		while(size > 0 && !end)
		{
			size = read(pipe_out[READIN], res->res.ptr, sizeof(wctl->conn.dres));
			if(size > 0)
			{
				send(wctl->conn.cs, res->res.ptr, strlen(res->res.ptr));
			}
			else
			{
				end = 1;
			}
		}
		wait(&end);
		close(pipe_out[READIN]);
		close(pipe_in[WRITEOUT]);

		retval = 0;
	}
	else/*子进程*/
	{
		char cmdarg[2048];
		char onearg[2048];
		char *pos = NULL;
		int i = 0;

		/*形成执行命令*/
		memset(onearg, 0, 2048];
		for(i = 0;i<num;i++)
			sprintf(cmdarg,"%s %s", onearg, arg[i]);

		/*将写入的管道绑定到标注输出*/
		close(pipe_out[READIN]);    /* 关闭无用的读管道*/
		dup2(pipe_out[WRITEOUT], 1); /* 将写管道绑定到标注输出 */
		close(pipe_out[WRITEOUT]);   /* 关闭写管道 */

		close(pipe_in[WRITEOUT]);    
		dup2(pipe_in[READIN], 0);   
		close(pipe_in[READIN]);   

		/*执行命令,命令的输出需要为标准输出*/
		execlp(rpath,  arg);
       	  
	}
EXITcgiHandler:
	return retval;
}
Example #2
0
int GenerateDirFile(struct worker_ctl *wctl)
{
	struct conn_request *req = &wctl->conn.con_req;
	struct conn_response *res = &wctl->conn.con_res;
	char *command = strstr(req->uri, CGISTR) + strlen(CGISTR);
	char *arg[ARGNUM];
	int num = 0;
	char *rpath = wctl->conn.con_req.rpath;
	stat *fs = &wctl->conn.con_res.fsate;

	/*打开目录*/
	DIR *dir = opendir(rpath);
	if(dir == NULL)
	{
		/*错误*/
		res->status = 500;
		retval = -1;
		goto EXITgenerateIndex;
	}

	/*建立临时文件保存目录列表*/
	File *tmpfile;
	char tmpbuff[2048];
	int filesize = 0;
	char *uri = wctl->conn.con_req.uri;
	tmpfile = tmpfile();

	/*标题部分*/
	sprintf(tmpbuff,
		"%s%s%s",
		"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\n<HTML><HEAD><TITLE>",
		uri,
		"</TITLE></HEAD>\n"	);
	fprintf(tmpfile, "%s", tmpbuff);
	filesize += strlen(tmpbuff);

	/*标识部分*/
	sprintf(tmpbuff, 
		"%s %s %s",
		"<BODY><H1>Index of:",
		uri,
		" </H1> <HR><P><I>Date: </I> <I>Size: </I></P><HR>");
	fprintf(tmpfile, "%s", tmpbuff);
	filesize += strlen(tmpbuff);	
	

	/* 读取目录中的文件列表 */
	struct dirent *de;
#define PATHLENGTH 2048
	char path[PATHLENGTH];
	char tmpath[PATHLENGTH];
	char linkname[PATHLENGTH];
	struct stat fs;
	strcpy(path, rpath);
	if(rpath[strlen(rpath)]!='/')
	{
		rpath[strlen(rpath)]='/';
	}
	while ((de = readdir(dir)) != NULL)/*读取一个文件*/
	{
		menset(tmpath, 0, sizeof(tmpath));
		menset(linkname, 0, sizeof(linkname));
		if(strcmp(de->d_name, "."))/*不是当前目录*/
		{
			if(strcmp(de->d_name, ".."))/*不是父目录*/			
			{
				strcpy(linkname,de->d_name);/*将目录名称作为链接名称*/
			}
			else/*是父目录*/
			{
				strcpy(linkname, "Parent Directory");/*将父目录作为链接名称*/
			}

			sprintf(tmpath, "%s%s",path, de->d_name);/*构建当前文件的全路径*/
			stat(tmpath, &fs);/*获得文件信息*/
			if(S_ISDIR(fs.st_mode))/*是一个目录*/
			{
				/*打印目录的连接为目录名称*/
				sprintf(tmpbuff, "<A HREF=\"%s/\">%s/</A><BR>\n", de->d_name,tmpath);
			}
			else/*正常文件*/
			{
				char size_str[32];
				off_t size_int;

				size_int = fs.st_size;/*文件大小*/
				if (size_int < 1024)/*不到1K*/
					sprintf(size_str, "%d bytes", (int) size_int);
				else if (size_int < 1024*1024)/*不到1M*/
					sprintf(size_str, "%1.2f Kbytes", (float) size_int / 1024);
				else/*其他*/
					sprintf(size_str, "%1.2f Mbytes", (float) size_int / (1024*1024));

				/*输出文件大小*/
				sprintf(tmpbuff, "<A HREF=\"%s\">%s</A> (%s)<BR>\n", de->d_name, linkname, size_int);
			}
			/*将形成的字符串写入临时文件*/
			fprintf(tmpfile, "%s", tmpbuff);
			filesize += strlen(tmpbuff);				
		}
	}

	/*生成临时的文件信息,主要是文件大小*/
	fs.st_ctime = time(NULL);
	fs.st_mtime = time(NULL);
	fs.st_size = filesize;
	fseek(tmpfile, (long) 0, SEEK_SET);/*移动文件指针到头部*/

	{
		DBGPRINT("==>Method_DoGet\n");
		struct conn_response *res = &wctl->conn.con_res;
		struct conn_request *req = &wctl->conn.con_req;
		char path[URI_MAX];
		memset(path, 0, URI_MAX);

		size_t		n;
		unsigned long	r1, r2;
		char	*fmt = "%a, %d %b %Y %H:%M:%S GMT";

		/*需要确定的参数*/
		size_t status = 200;		/*状态值,已确定*/
		char *msg = "OK";	/*状态信息,已确定*/
		char  date[64] = "";		/*时间*/
		char  lm[64] = "";			/*请求文件最后修改信息*/
		char  etag[64] = "";		/*etag信息*/
		big_int_t cl;				/*内容长度*/
		char  range[64] = "";		/*范围*/	
		struct mine_type *mine = NULL;

		/*当前时间*/
		time_t t = time(NULL);	
		(void) strftime(date, 
					sizeof(date), 
					fmt, 
					localtime(&t));

		/*最后修改时间*/
		(void) strftime(lm, 
					sizeof(lm), 
					fmt, 
					localtime(&res->fsate.st_mtime));

		/*ETAG*/
		(void) snprintf(etag, 
					sizeof(etag), 
					"%lx.%lx",
					(unsigned long) res->fsate.st_mtime,
					(unsigned long) res->fsate.st_size);
		
		/*发送的MIME类型*/
		mine = Mine_Type(req->uri, strlen(req->uri), wctl);

		/*内容长度*/
		cl = (big_int_t) res->fsate.st_size;

		/*范围range*/
		memset(range, 0, sizeof(range));
		n = -1;
		if (req->ch.range.v_vec.len > 0 )/*取出请求范围*/
		{
			printf("request range:%d\n",req->ch.range.v_vec.len);
			n = sscanf(req->ch.range.v_vec.ptr,"bytes=%lu-%lu",&r1, &r2);
		}

		printf("n:%d\n",n);
		if(n   > 0) 
		{
			status = 206;
			(void) sseek(res->fd, r1, SEEK_SET);
			cl = n == 2 ? r2 - r1 + 1: cl - r1;
			(void) snprintf(range, 
						sizeof(range),
						"Content-Range: bytes %lu-%lu/%lu\r\n",
						r1, 
						r1 + cl - 1, 
						(unsigned long) res->fsate.st_size);
			msg = "Partial Content";
		}

		memset(res->res.ptr, 0, sizeof(wctl->conn.dres));
		snprintf(
			res->res.ptr,
			sizeof(wctl->conn.dres),
			"HTTP/1.1 %d %s\r\n" 
			"Date: %s\r\n"
			"Last-Modified: %s\r\n"
			"Etag: \"%s\"\r\n"
			"Content-Type: %.*s\r\n"
			"Content-Length: %lu\r\n"
			//"Connection:close\r\n"
			"Accept-Ranges: bytes\r\n"		
			"%s\r\n",
			status,
			msg,
			date,
			lm,
			etag,
			strlen(mine->mime_type),
			mine->mime_type,
			cl,
			range);
		res->cl = cl;
		res->status = status;
	}

EXITgenerateIndex:
	return 0;
}
Example #3
0
/*
[HTTP/1.1 200 OK
Date: Thu, 11 Dec 2008 11:25:33 GMT
Last-Modified: Wed, 12 Nov 2008 09:00:01 GMT
Etag: "491a2a91.2afe"
Content-Type: text/plain
Content-Length: 11006
Accept-Ranges: bytes
]
*/
static int Method_DoGet(struct worker_ctl *wctl)
{
	DBGPRINT("==>Method_DoGet\n");
	struct conn_response *res = &wctl->conn.con_res;
	struct conn_request *req = &wctl->conn.con_req;
	char path[URI_MAX];
	memset(path, 0, URI_MAX);

	size_t		n;
	unsigned long	r1, r2;
	char	*fmt = "%a, %d %b %Y %H:%M:%S GMT";

	/*靠*/
	size_t status = 200;		/*状态值,已确定*/
	char *msg = "OK";	/*状态信息,已确定*/
	char  date[64] = "";		/*时间*/
	char  lm[64] = "";			/*请求文件最后修改信息*/
	char  etag[64] = "";		/*etag信息*/
	big_int_t cl;				/*内容长度*/
	char  range[64] = "";		/*范围*/	
	struct mine_type *mine = NULL;

	/*当前时间*/
	time_t t = time(NULL);	
	(void) strftime(date, 
				sizeof(date), 
				fmt, 
				localtime(&t));

	/*最后修改时间*/
	(void) strftime(lm, 
				sizeof(lm), 
				fmt, 
				localtime(&res->fsate.st_mtime));

	/*ETAG*/
	(void) snprintf(etag, 
				sizeof(etag), 
				"%lx.%lx",
				(unsigned long) res->fsate.st_mtime,
				(unsigned long) res->fsate.st_size);
	
	/*发送的MIME类型*/
	mine = Mine_Type(req->uri, strlen(req->uri), wctl);

	/*内容长度*/
	cl = (big_int_t) res->fsate.st_size;

	/*范围range*/
	memset(range, 0, sizeof(range));
	n = -1;
	if (req->ch.range.v_vec.len > 0 )/*取出请求范围*/
	{
		printf("request range:%d\n",req->ch.range.v_vec.len);
		n = sscanf(req->ch.range.v_vec.ptr,"bytes=%lu-%lu",&r1, &r2);
	}

	printf("n:%d\n",n);
	if(n   > 0) 
	{
		status = 206;
		lseek(res->fd, r1, SEEK_SET);
		cl = n == 2 ? r2 - r1 + 1: cl - r1;
		(void) snprintf(range, 
					sizeof(range),
					"Content-Range: bytes %lu-%lu/%lu\r\n",
					r1, 
					r1 + cl - 1, 
					(unsigned long) res->fsate.st_size);
		msg = "Partial Content";
	}

	memset(res->res.ptr, 0, sizeof(wctl->conn.dres));
	snprintf(
		res->res.ptr,
		sizeof(wctl->conn.dres),
		"HTTP/1.1 %d %s\r\n" 
		"Date: %s\r\n"
		"Last-Modified: %s\r\n"
		"Etag: \"%s\"\r\n"
		"Content-Type: %.*s\r\n"
		"Content-Length: %lu\r\n"
		//"Connection:close\r\n"
		"Accept-Ranges: bytes\r\n"		
		"%s\r\n",
		status,
		msg,
		date,
		lm,
		etag,
		strlen(mine->mime_type),
		mine->mime_type,
		cl,
		range);
	res->cl = cl;
	res->status = status;
	printf("content length:%d, status:%d\n",res->cl, res->status);
	DBGPRINT("<==Method_DoGet\n");
	return 0;
}