⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 get.c

📁 linux平台上的开放源代码的网络摄像机程序.实现视频捕捉,传输以及云台控制等.非常具有参考价值.
💻 C
字号:
/* *  Boa, an http server *  Copyright (C) 1995 Paul Phillips <psp@well.com> *  Some changes Copyright (C) 1996 Larry Doolittle <ldoolitt@cebaf.gov> *  Some changes Copyright (C) 1996 Jon Nelson <nels0988@tc.umn.edu> * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 1, or (at your option) *  any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * *//* boa: get.c */#include "boa.h"#define D(x) x/* * Name: init_get * Description: Initializes a non-script GET or HEAD request. * * Return values: *   0: finished or error, request will be freed *   1: successfully initialized, added to ready queue */int init_get(request * req){	int data_fd;	struct stat statbuf;	clean_pathname(req->path_translated);	/* remove double slashes etc. */	data_fd = open(req->path_translated, O_RDONLY);		if(data_fd == -1) {				/* cannot open */		log_error_doc(req);		perror("document open");		if(errno == ENOENT)			send_r_not_found(req);		else if(errno == EACCES)			send_r_forbidden(req);		else			send_r_bad_request(req);		return 0;	}		fstat(data_fd, &statbuf);		if (auth_check(req,0) != 0) {		return 0;	}	#ifdef CREATE_INDEX_IN_MEM	if(S_ISDIR(statbuf.st_mode)) {		/* directory */				if(req->path_translated[strlen(req->path_translated) - 1] != '/') {			static char buffer[3*MAX_PATH_LENGTH + 128];			char* new_path = (char*) malloc(strlen(req->path_translated)+2);			new_path[0] = '\0';			strcpy(new_path, req->path_translated);			strcat(new_path, "/");			free(req->path_translated);			req->path_translated = new_path;			sprintf(buffer, "http://%s:%d%s/", server_name, server_port,				escape_uri(req->request_uri));			req->ret_content_type = strdup("text/html");			send_redirect(req, buffer);			return 0;		}				close(data_fd);				/* close dir */		data_fd = get_dir_file(req,&statbuf);   /* updates statbuf */				if(data_fd == -1) {           /* couldn't do it */			return 0;             /* errors reported by get_dir_file */		}	}		if (!(req->req_status & REQ_STAT_DATA_IN_MEM)) {		D(printf("get.c:st_mtime=%lx\r\n",(long ) (statbuf.st_mtime))); 		if (req->if_modified_since && 		    !modified_since(&(statbuf.st_mtime), req->if_modified_since)) {			send_r_not_modified(req);			close(data_fd);			return 0;		}				D(printf("get.c:st_size=%lx\r\n",statbuf.st_size));		D(printf("get.c:st_mode=%lx\r\n",(long) statbuf.st_mode));		D(printf("get.c:st_dev=%lx\r\n", (long) statbuf.st_dev));		D(printf("get.c:S_ISCHR(st_dev)=%lx\r\n", (long) S_ISCHR(statbuf.st_dev) ));		req->filesize = statbuf.st_size;		req->last_modified = statbuf.st_mtime;				if(req->method == M_HEAD) {			send_r_request_ok(req);			close(data_fd);			return 0;		}				/* MAP_OPTIONS: see compat.h */		req->data_mem = mmap(0, statbuf.st_size, PROT_READ, MAP_OPTIONS,				     data_fd, 0);		close(data_fd);				/* close data file */				if((int)req->data_mem == -1) {			boa_perror(req,"mmap-1");			exit(1);   /* or should this be "return 0;" ? */		}	}#else	if(S_ISDIR(statbuf.st_mode)) {		/* directory */				if(req->path_translated[strlen(req->path_translated) - 1] != '/') {			static char buffer[3*MAX_PATH_LENGTH + 128];			char* tmp_path = (char*) malloc(strlen(req->path_translated)+2);			tmp_path[0] = '\0';			strcpy( tmp_path, req->path_translated );			strcat( tmp_path, "/");			free(req->path_translated);			req->path_translated = tmp_path; 			sprintf(buffer, "http://%s:%d%s/", server_name, server_port, 				escape_uri(req->request_uri));			req->ret_content_type = strdup("text/html");			send_redirect(req, buffer);			return 0;		}				close(data_fd);				/* close dir */		data_fd = get_dir_file(req,&statbuf);   /* updates statbuf */				if(data_fd == -1) {           /* couldn't do it */			return 0;             /* errors reported by get_dir_file */		}	}		if (req->if_modified_since &&	    !modified_since(&(statbuf.st_mtime), req->if_modified_since)) {		send_r_not_modified(req);		close(data_fd);		return 0;	}		req->filesize = statbuf.st_size;	req->last_modified = statbuf.st_mtime;		if(req->method == M_HEAD) {		send_r_request_ok(req);		close(data_fd);		return 0;	}		/* MAP_OPTIONS: see compat.h */	req->data_mem = mmap(0, statbuf.st_size, PROT_READ, MAP_OPTIONS,			     data_fd, 0);	close(data_fd);				/* close data file */		if((int)req->data_mem == -1) {		boa_perror(req,"mmap-2");		exit(1);   /* or should this be "return 0;" ? */	}#endif	send_r_request_ok(req);			/* All's well */	/* We lose statbuf here, so make sure response has been sent */	return 1;}/* * Name: process_get * Description: Writes a chunk of data to the socket. * * Return values: *  -1: request blocked, move to blocked queue *   0: EOF or error, close it down *   1: successful write, recycle in ready queue */int process_get(request * req){    int bytes_written, bytes_to_write;    bytes_to_write = req->filesize - req->filepos;    if(bytes_to_write > SOCKETBUF_SIZE)	bytes_to_write = SOCKETBUF_SIZE;    bytes_written = write(req->fd, req->data_mem + req->filepos,       bytes_to_write);    if(bytes_written == -1) {	if(errno == EAGAIN || errno == EWOULDBLOCK) {  /* no room in pipe */	    return -1;	} else {		/* something wrong, includes EPIPE possibility */#if 1	    log_error_doc(req);  /* Can generate lots of log entries, */	    perror("write");     /* OK to disable if your logs get too big */#endif	    SQUASH_KA(req);      /* force close fd */	    return 0;	}    }    req->filepos += bytes_written;    req->time_last = time(NULL);    if(req->filepos == req->filesize) {		/* EOF */	return 0;    }    else {    	return 1;				/* more to do */    }}#ifdef CREATE_INDEX_IN_MEM int get_dir_file( request * req, struct stat *statbuf) {	static char pathname_with_index[MAX_PATH_LENGTH];	int data_fd;	/* time_t real_dir_mtime; */		sprintf(pathname_with_index, "%s%s", req->path_translated, 		directory_index);D(printf("get.c:1:pathname_with_index=%s\n",pathname_with_index));		data_fd = open(pathname_with_index, O_RDONLY);		if(data_fd != -1) {                        /* user's index file */		strcpy(req->request_uri, directory_index);      /* for mimetype */		fstat(data_fd, statbuf);		return data_fd;	}		if (index_directory(req, pathname_with_index) == 0) {		/* OK */		return 0;	}	return -1;    /* Nothing worked. */}/* * Name: index_directory * Description: Called from get_dir_mapping if a directory html * has to be generated on the fly * If no_slash is true, prepend slashes to hrefs * returns -1 for problem, else 0 */int index_directory(request * req, char * dest_filename){	DIR * request_dir;	struct stat statbuf;	struct dirent * dirbuf;	char line_buffer[256];	char *page_buffer = NULL;	int buf_size = 0;	int used_size = 0;	int line_size = 0;	if(chdir(req->path_translated) == -1) {		if(errno == EACCES || errno == EPERM) {			send_r_forbidden(req);		} else {			log_error_doc(req);			perror("chdir");			send_r_bad_request(req);		}		return -1;	}		request_dir = opendir(".");	if (request_dir == NULL) {		int errno_save=errno;//		send_r_error(req);		send_r_error_debug(req,"get.c - 1");		log_error_time();		fprintf(stderr, "directory \"%s\": ", req->path_translated);		errno=errno_save;		perror("opendir");		return -1;	}			buf_size = 20 * 1024;	page_buffer = (char*) malloc( buf_size );	if (page_buffer == NULL) return -1;	        strcpy(req->request_uri, directory_index);      /* for mimetype */	sprintf( line_buffer, 		 "<HTML><HEAD>\n<TITLE>Index of %s</TITLE>\n</HEAD>\n\n", 		 req->request_uri);	memcpy( page_buffer + used_size, line_buffer, strlen( line_buffer ));	used_size += strlen( line_buffer );	sprintf( line_buffer, 		 "<BODY>\n\n<H2>Index of %s</H2>\n",		 req->request_uri);	memcpy( page_buffer + used_size, line_buffer, line_size = strlen( line_buffer ));	used_size += line_size;		while((dirbuf = readdir(request_dir))) {		if(!strcmp(dirbuf->d_name, "."))			continue;				if(!strcmp(dirbuf->d_name, "..")) {			sprintf( line_buffer, 				 " [DIR] <A HREF=\"../\">Parent Directory</A><BR>\n");			memcpy( page_buffer + used_size, line_buffer, line_size = strlen( line_buffer ));			used_size += line_size;			if ( buf_size < (used_size + 200)) break;			continue;		}				if(stat(dirbuf->d_name, &statbuf) == -1)			continue;				if(S_ISDIR(statbuf.st_mode)) {			sprintf( line_buffer, 				 " [DIR] <A HREF=\"%s/\">%s</A><BR>\n",				 escape_uri(dirbuf->d_name), dirbuf->d_name);		}		else {			sprintf( line_buffer, 				 "[FILE] <A HREF=\"%s\">%s</A> (%ld bytes)<BR>\n", 				 escape_uri(dirbuf->d_name), dirbuf->d_name, 				 (long)statbuf.st_size);		}		memcpy( page_buffer + used_size, line_buffer, line_size = strlen( line_buffer ));		used_size += line_size;		if ( buf_size < (used_size + 200)) break;	}		closedir(request_dir);	if ( buf_size < (used_size + 200)) {		sprintf( line_buffer, "</PRE>\n\n To many files in directory!<BR>\n List trucated!\n</BODY>\n</HTML>\n");	}	else {		sprintf( line_buffer, "</PRE>\n\n</BODY>\n</HTML>\n");	}	memcpy( page_buffer + used_size, line_buffer, line_size = strlen( line_buffer ));	used_size += line_size;		chdir(server_root);		req->req_status |= REQ_STAT_DATA_IN_MEM;	req->data_mem = page_buffer;	req->last_modified = 0;	req->filesize = used_size;     	/* for logging transfer size */	return 0;                       /* success */}#else/* * Name: get_dir_file * Description: Called from process_get if the request is a directory. * statbuf must describe directory on input, since we may need its *   device, inode, and mtime. * statbuf is updated, since we may need to check mtimes of a cache. * returns file descriptor, or -1 on error. * Sequence of places to look: *  1. User generated index.html *  2. Previously generated cachedir file *  3. cachedir file we generate now * Cases 2 and 3 only work if cachedir is enabled, otherwise * issue a 403 Forbidden. */int get_dir_file( request * req, struct stat *statbuf) {    static char pathname_with_index[MAX_PATH_LENGTH];    int data_fd;    time_t real_dir_mtime;    sprintf(pathname_with_index, "%s%s", req->path_translated,             directory_index);    data_fd = open(pathname_with_index, O_RDONLY); D(printf("get.c:2:pathname_with_index=%s\n",pathname_with_index));    if(data_fd != -1) {                        /* user's index file */	strcpy(req->request_uri, directory_index);      /* for mimetype */	fstat(data_fd, statbuf);	return data_fd;    } else if (cachedir == NULL) {        send_r_forbidden(req);        return -1;    }    real_dir_mtime = statbuf->st_mtime;    sprintf(pathname_with_index, "%s/dir.%lld.%ld",                       cachedir, statbuf->st_dev, statbuf->st_ino);    data_fd = open(pathname_with_index, O_RDONLY);    if (data_fd != -1) {                 /* index cache */	fstat(data_fd, statbuf);	if (statbuf->st_mtime > real_dir_mtime) {		statbuf->st_mtime = real_dir_mtime;         /* lie */		strcpy(req->request_uri, directory_index);  /* for mimetype */ 		return data_fd;	}	close(data_fd);	unlink(pathname_with_index);      /* cache is stale, delete it */    }    if (index_directory(req, pathname_with_index) == -1) return -1;    data_fd = open(pathname_with_index, O_RDONLY);      /* Last chance */    if (data_fd != -1) {        strcpy(req->request_uri, directory_index);      /* for mimetype */	fstat(data_fd, statbuf);	statbuf->st_mtime = real_dir_mtime;         /* lie */	return data_fd;    }    boa_perror(req,"re-opening dircache");    return -1;    /* Nothing worked. */}/* * Name: index_directory * Description: Called from get_dir_mapping if a directory html * has to be generated on the fly * If no_slash is true, prepend slashes to hrefs * returns -1 for problem, else 0 */int index_directory(request * req, char * dest_filename){    DIR * request_dir;    FILE * fdstream;    struct stat statbuf;    struct dirent * dirbuf;    int bytes = 0;    if(chdir(req->path_translated) == -1) {	if(errno == EACCES || errno == EPERM) {	    send_r_forbidden(req);	} else {	    log_error_doc(req);	    perror("chdir");	    send_r_bad_request(req);	}	return -1;    }    request_dir = opendir(".");    if (request_dir == NULL) {	int errno_save=errno;//	send_r_error(req);	send_r_error_debug(req,"get.c - 2");        log_error_time();        fprintf(stderr, "directory \"%s\": ", req->path_translated);	errno=errno_save;        perror("opendir");        return -1;    }    fdstream = fopen(dest_filename, "w");    if (fdstream == NULL) {	boa_perror(req,"dircache fopen");        return -1;    }        bytes += fprintf(fdstream,       "<HTML><HEAD>\n<TITLE>Index of %s</TITLE>\n</HEAD>\n\n",      req->request_uri);    bytes += fprintf(fdstream, "<BODY>\n\n<H2>Index of %s</H2>\n\n<PRE>\n",      req->request_uri);    while((dirbuf = readdir(request_dir))) {	if(!strcmp(dirbuf->d_name, "."))	    continue;	if(!strcmp(dirbuf->d_name, "..")) {	    bytes += fprintf(fdstream, 	      " [DIR] <A HREF=\"../\">Parent Directory</A>\n");	    continue;	}        if(stat(dirbuf->d_name, &statbuf) == -1)	    continue;	if(S_ISDIR(statbuf.st_mode)) {	    bytes += fprintf(fdstream, " [DIR] <A HREF=\"%s/\">%s</A>\n",	      escape_uri(dirbuf->d_name), dirbuf->d_name);	}	else {	    bytes += fprintf(fdstream, 	      "[FILE] <A HREF=\"%s\">%s</A> (%ld bytes)\n", 	      escape_uri(dirbuf->d_name), dirbuf->d_name, 	      (long)statbuf.st_size);	}    }    closedir(request_dir);    bytes += fprintf(fdstream, "</PRE>\n\n</BODY>\n</HTML>\n");    fclose(fdstream);    chdir(server_root);    req->filesize = bytes;		/* for logging transfer size */    return 0;                           /* success */}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -