cgi.c

来自「samba-3.0.22.tar.gz 编译smb服务器的源码」· C语言 代码 · 共 651 行 · 第 1/2 页

C
651
字号
/*    some simple CGI helper routines   Copyright (C) Andrew Tridgell 1997-1998      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 2 of the License, 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.*/#include "includes.h"#include "web/swat_proto.h"#define MAX_VARIABLES 10000/* set the expiry on fixed pages */#define EXPIRY_TIME (60*60*24*7)#ifdef DEBUG_COMMENTSextern void print_title(char *fmt, ...);#endifstruct cgi_var {	char *name;	char *value;};static struct cgi_var variables[MAX_VARIABLES];static int num_variables;static int content_length;static int request_post;static char *query_string;static const char *baseurl;static char *pathinfo;static char *C_user;static BOOL inetd_server;static BOOL got_request;static char *grab_line(FILE *f, int *cl){	char *ret = NULL;	int i = 0;	int len = 0;	while ((*cl)) {		int c;			if (i == len) {			char *ret2;			if (len == 0) len = 1024;			else len *= 2;			ret2 = (char *)SMB_REALLOC(ret, len);			if (!ret2) return ret;			ret = ret2;		}			c = fgetc(f);		(*cl)--;		if (c == EOF) {			(*cl) = 0;			break;		}				if (c == '\r') continue;		if (strchr_m("\n&", c)) break;		ret[i++] = c;	}		ret[i] = 0;	return ret;}/** URL encoded strings can have a '+', which should be replaced with a space (This was in rfc1738_unescape(), but that broke the squid helper)**/static void plus_to_space_unescape(char *buf){	char *p=buf;	while ((p=strchr_m(p,'+')))		*p = ' ';}/***************************************************************************  load all the variables passed to the CGI program. May have multiple variables  with the same name and the same or different values. Takes a file parameter  for simulating CGI invocation eg loading saved preferences.  ***************************************************************************/void cgi_load_variables(void){	static char *line;	char *p, *s, *tok;	int len, i;	FILE *f = stdin;#ifdef DEBUG_COMMENTS	char dummy[100]="";	print_title(dummy);	d_printf("<!== Start dump in cgi_load_variables() %s ==>\n",__FILE__);#endif	if (!content_length) {		p = getenv("CONTENT_LENGTH");		len = p?atoi(p):0;	} else {		len = content_length;	}	if (len > 0 && 	    (request_post ||	     ((s=getenv("REQUEST_METHOD")) && 	      strequal(s,"POST")))) {		while (len && (line=grab_line(f, &len))) {			p = strchr_m(line,'=');			if (!p) continue;						*p = 0;						variables[num_variables].name = SMB_STRDUP(line);			variables[num_variables].value = SMB_STRDUP(p+1);			SAFE_FREE(line);						if (!variables[num_variables].name || 			    !variables[num_variables].value)				continue;			plus_to_space_unescape(variables[num_variables].value);			rfc1738_unescape(variables[num_variables].value);			plus_to_space_unescape(variables[num_variables].name);			rfc1738_unescape(variables[num_variables].name);#ifdef DEBUG_COMMENTS			printf("<!== POST var %s has value \"%s\"  ==>\n",			       variables[num_variables].name,			       variables[num_variables].value);#endif						num_variables++;			if (num_variables == MAX_VARIABLES) break;		}	}	fclose(stdin);	open("/dev/null", O_RDWR);	if ((s=query_string) || (s=getenv("QUERY_STRING"))) {		for (tok=strtok(s,"&;");tok;tok=strtok(NULL,"&;")) {			p = strchr_m(tok,'=');			if (!p) continue;						*p = 0;						variables[num_variables].name = SMB_STRDUP(tok);			variables[num_variables].value = SMB_STRDUP(p+1);			if (!variables[num_variables].name || 			    !variables[num_variables].value)				continue;			plus_to_space_unescape(variables[num_variables].value);			rfc1738_unescape(variables[num_variables].value);			plus_to_space_unescape(variables[num_variables].name);			rfc1738_unescape(variables[num_variables].name);#ifdef DEBUG_COMMENTS                        printf("<!== Commandline var %s has value \"%s\"  ==>\n",                               variables[num_variables].name,                               variables[num_variables].value);#endif									num_variables++;			if (num_variables == MAX_VARIABLES) break;		}	}#ifdef DEBUG_COMMENTS        printf("<!== End dump in cgi_load_variables() ==>\n");   #endif	/* variables from the client are in UTF-8 - convert them	   to our internal unix charset before use */	for (i=0;i<num_variables;i++) {		pstring dest;		convert_string(CH_UTF8, CH_UNIX, 			       variables[i].name, -1, 			       dest, sizeof(dest), True);		free(variables[i].name);		variables[i].name = SMB_STRDUP(dest);		convert_string(CH_UTF8, CH_UNIX, 			       variables[i].value, -1,			       dest, sizeof(dest), True);		free(variables[i].value);		variables[i].value = SMB_STRDUP(dest);	}}/***************************************************************************  find a variable passed via CGI  Doesn't quite do what you think in the case of POST text variables, because  if they exist they might have a value of "" or even " ", depending on the   browser. Also doesn't allow for variables[] containing multiple variables  with the same name and the same or different values.  ***************************************************************************/const char *cgi_variable(const char *name){	int i;	for (i=0;i<num_variables;i++)		if (strcmp(variables[i].name, name) == 0)			return variables[i].value;	return NULL;}/***************************************************************************tell a browser about a fatal error in the http processing  ***************************************************************************/static void cgi_setup_error(const char *err, const char *header, const char *info){	if (!got_request) {		/* damn browsers don't like getting cut off before they give a request */		char line[1024];		while (fgets(line, sizeof(line)-1, stdin)) {			if (strnequal(line,"GET ", 4) || 			    strnequal(line,"POST ", 5) ||			    strnequal(line,"PUT ", 4)) {				break;			}		}	}	d_printf("HTTP/1.0 %s\r\n%sConnection: close\r\nContent-Type: text/html\r\n\r\n<HTML><HEAD><TITLE>%s</TITLE></HEAD><BODY><H1>%s</H1>%s<p></BODY></HTML>\r\n\r\n", err, header, err, err, info);	fclose(stdin);	fclose(stdout);	exit(0);}/***************************************************************************tell a browser about a fatal authentication error  ***************************************************************************/static void cgi_auth_error(void){	if (inetd_server) {                cgi_setup_error("401 Authorization Required",                                 "WWW-Authenticate: Basic realm=\"SWAT\"\r\n",                                "You must be authenticated to use this service");	} else {		printf("Content-Type: text/html\r\n");		printf("\r\n<HTML><HEAD><TITLE>SWAT</TITLE></HEAD>\n");		printf("<BODY><H1>Installation Error</H1>\n");		printf("SWAT must be installed via inetd. It cannot be run as a CGI script<p>\n");		printf("</BODY></HTML>\r\n");	}	exit(0);}/***************************************************************************authenticate when we are running as a CGI  ***************************************************************************/static void cgi_web_auth(void){	const char *user = getenv("REMOTE_USER");	struct passwd *pwd;	const char *head = "Content-Type: text/html\r\n\r\n<HTML><BODY><H1>SWAT installation Error</H1>\n";	const char *tail = "</BODY></HTML>\r\n";	if (!user) {		printf("%sREMOTE_USER not set. Not authenticated by web server.<br>%s\n",		       head, tail);		exit(0);	}	pwd = getpwnam_alloc(user);	if (!pwd) {		printf("%sCannot find user %s<br>%s\n", head, user, tail);		exit(0);	}	setuid(0);	setuid(pwd->pw_uid);	if (geteuid() != pwd->pw_uid || getuid() != pwd->pw_uid) {		printf("%sFailed to become user %s - uid=%d/%d<br>%s\n", 		       head, user, (int)geteuid(), (int)getuid(), tail);		exit(0);	}	passwd_free(&pwd);}/***************************************************************************handle a http authentication line  ***************************************************************************/static BOOL cgi_handle_authorization(char *line){	char *p;	fstring user, user_pass;	struct passwd *pass = NULL;	if (!strnequal(line,"Basic ", 6)) {		goto err;	}	line += 6;	while (line[0] == ' ') line++;

⌨️ 快捷键说明

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