📄 cgi.c
字号:
/* * Boa, an http server * Copyright (C) 1995 Paul Phillips <paulp@go2net.com> * Some changes Copyright (C) 1996,97 Larry Doolittle <ldoolitt@boa.org> * Some changes Copyright (C) 1996 Charles F. Randall <crandall@goldsys.com> * Some changes Copyright (C) 1997-2002 Jon Nelson <jnelson@boa.org> * * 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. * *//* $Id: cgi.c,v 1.83.2.3 2002/07/23 15:49:54 jnelson Exp $ */#include "boa.h"static char *env_gen_extra(const char *key, const char *value, int extra);int verbose_cgi_logs = 0;/* The +1 is for the the NULL in complete_env */static char *common_cgi_env[COMMON_CGI_COUNT + 1];/* * Name: create_common_env * * Description: Set up the environment variables that are common to * all CGI scripts */void create_common_env(){ int index = 0, i; /* NOTE NOTE NOTE: If you (the reader) someday modify this chunk of code to handle more "common" CGI environment variables, then bump the value COMMON_CGI_COUNT in defines.h UP Also, in the case of document_root and server_admin, two variables that may or may not be defined depending on the way the server is configured, we check for null values and use an empty string to denote a NULL value to the environment, as per the specification. The quote for which follows: "In all cases, a missing environment variable is equivalent to a zero-length (NULL) value, and vice versa." */ common_cgi_env[index++] = env_gen_extra("PATH", ((cgi_path != NULL) ? cgi_path : DEFAULT_PATH), 0); common_cgi_env[index++] = env_gen_extra("SERVER_SOFTWARE", SERVER_VERSION, 0); common_cgi_env[index++] = env_gen_extra("SERVER_NAME", server_name, 0); common_cgi_env[index++] = env_gen_extra("GATEWAY_INTERFACE", CGI_VERSION, 0); common_cgi_env[index++] = env_gen_extra("SERVER_PORT", simple_itoa(server_port), 0); /* NCSA and APACHE added -- not in CGI spec */ /* common_cgi_env[index++] = env_gen_extra("DOCUMENT_ROOT", document_root); */ /* NCSA added */ /* common_cgi_env[index++] = env_gen_extra("SERVER_ROOT", server_root); */ /* APACHE added */ common_cgi_env[index++] = env_gen_extra("SERVER_ADMIN", server_admin, 0); common_cgi_env[index] = NULL; /* Sanity checking -- make *sure* the memory got allocated */ if (index > COMMON_CGI_COUNT) { log_error_time(); fprintf(stderr, "COMMON_CGI_COUNT not high enough.\n"); exit(1); } for(i = 0;i < index;++i) { if (common_cgi_env[i] == NULL) { log_error_time(); fprintf(stderr, "Unable to allocate a component of common_cgi_env - out of memory.\n"); exit(1); } }}void clear_common_env(void){ int i; for(i = 0;i <= COMMON_CGI_COUNT;++i) { if (common_cgi_env[i] != NULL) { free(common_cgi_env[i]); common_cgi_env[i] = NULL; } }}/* * Name: env_gen_extra * (and via a not-so-tricky #define, env_gen) * This routine calls malloc: please free the memory when you are done */static char *env_gen_extra(const char *key, const char *value, int extra){ char *result; int key_len, value_len; if (value == NULL) /* ServerAdmin may not be defined, eg */ value = ""; key_len = strlen(key); value_len = strlen(value); /* leave room for '=' sign and null terminator */ result = malloc(extra + key_len + value_len + 2); if (result) { memcpy(result + extra, key, key_len); *(result + extra + key_len) = '='; memcpy(result + extra + key_len + 1, value, value_len); *(result + extra + key_len + value_len + 1) = '\0'; } else { log_error_time(); perror("malloc"); log_error_time(); fprintf(stderr, "tried to allocate (key=value) extra=%d: %s=%s\n", extra, key, value); } return result;}/* * Name: add_cgi_env * * Description: adds a variable to CGI's environment * Used for HTTP_ headers */int add_cgi_env(request * req, char *key, char *value, int http_prefix){ char *p; int prefix_len; if (http_prefix) { prefix_len = 5; } else { prefix_len = 0; } if (req->cgi_env_index < CGI_ENV_MAX) { p = env_gen_extra(key, value, prefix_len); if (!p) { log_error_time(); fprintf(stderr, "Unable to generate additional CGI Environment" "variable -- ran out of memory!\n"); } if (prefix_len) memcpy(p, "HTTP_", 5); req->cgi_env[req->cgi_env_index++] = p; return 1; } else { log_error_time(); fprintf(stderr, "Unable to generate additional CGI Environment" "variable -- not enough space!\n"); } return 0;}#define my_add_cgi_env(req, key, value) { \ int ok = add_cgi_env(req, key, value, 0); \ if (!ok) return 0; \ }/* * Name: complete_env * * Description: adds the known client header env variables * and terminates the environment array */int complete_env(request * req){ int i; for (i = 0; common_cgi_env[i]; i++) req->cgi_env[i] = common_cgi_env[i]; { char *w; switch (req->method) { case M_POST: w = "POST"; break; case M_HEAD: w = "HEAD"; break; case M_GET: w = "GET"; break; default: w = "UNKNOWN"; break; } my_add_cgi_env(req, "REQUEST_METHOD", w); } my_add_cgi_env(req, "SERVER_ADDR", req->local_ip_addr); my_add_cgi_env(req, "SERVER_PROTOCOL", req->http_version); my_add_cgi_env(req, "REQUEST_URI", req->request_uri); if (req->path_info) my_add_cgi_env(req, "PATH_INFO", req->path_info); if (req->path_translated) /* while path_translated depends on path_info, * there are cases when path_translated might * not exist when path_info does */ my_add_cgi_env(req, "PATH_TRANSLATED", req->path_translated); my_add_cgi_env(req, "SCRIPT_NAME", req->script_name); if (req->query_string) my_add_cgi_env(req, "QUERY_STRING", req->query_string); my_add_cgi_env(req, "REMOTE_ADDR", req->remote_ip_addr); my_add_cgi_env(req, "REMOTE_PORT", simple_itoa(req->remote_port)); if (req->method == M_POST) { if (req->content_type) { my_add_cgi_env(req, "CONTENT_TYPE", req->content_type); } else { my_add_cgi_env(req, "CONTENT_TYPE", default_type); } if (req->content_length) { my_add_cgi_env(req, "CONTENT_LENGTH", req->content_length); } }#ifdef ACCEPT_ON if (req->accept[0]) my_add_cgi_env(req, "HTTP_ACCEPT", req->accept);#endif if (req->cgi_env_index < CGI_ENV_MAX + 1) { req->cgi_env[req->cgi_env_index] = NULL; /* terminate */ return 1; } log_error_time(); fprintf(stderr, "Not enough space in CGI environment for remainder"\ " of variables.\n"); return 0;}/* * Name: make_args_cgi * * Build argv list for a CGI script according to spec * */void create_argv(request * req, char **aargv){ char *p, *q, *r; int aargc; q = req->query_string; aargv[0] = req->pathname; /* here, we handle a special "indexed" query string. * Taken from the CGI/1.1 SPEC: * This is identified by a GET or HEAD request with a query string * with no *unencoded* '=' in it. * For such a request, I'm supposed to parse the search string
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -