diff options
Diffstat (limited to 'rubbos/app/httpd-2.0.64/modules/arch/win32/mod_win32.c')
-rw-r--r-- | rubbos/app/httpd-2.0.64/modules/arch/win32/mod_win32.c | 553 |
1 files changed, 0 insertions, 553 deletions
diff --git a/rubbos/app/httpd-2.0.64/modules/arch/win32/mod_win32.c b/rubbos/app/httpd-2.0.64/modules/arch/win32/mod_win32.c deleted file mode 100644 index 38b7b3b0..00000000 --- a/rubbos/app/httpd-2.0.64/modules/arch/win32/mod_win32.c +++ /dev/null @@ -1,553 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifdef WIN32 - -#include "apr_strings.h" -#include "apr_portable.h" -#include "apr_buckets.h" -#include "ap_config.h" -#include "httpd.h" -#include "http_config.h" -#include "http_core.h" -#include "http_protocol.h" -#include "http_request.h" -#include "http_log.h" -#include "util_script.h" -#include "mod_core.h" -#include "mod_cgi.h" -#include "apr_lib.h" -#include "ap_regkey.h" - -extern OSVERSIONINFO osver; /* hiding in mpm_winnt.c */ -static int win_nt; - -/* - * CGI Script stuff for Win32... - */ -typedef enum { eFileTypeUNKNOWN, eFileTypeBIN, eFileTypeEXE16, eFileTypeEXE32, - eFileTypeSCRIPT } file_type_e; -typedef enum { INTERPRETER_SOURCE_UNSET, INTERPRETER_SOURCE_REGISTRY_STRICT, - INTERPRETER_SOURCE_REGISTRY, INTERPRETER_SOURCE_SHEBANG - } interpreter_source_e; -AP_DECLARE(file_type_e) ap_get_win32_interpreter(const request_rec *, - char **interpreter, - char **arguments); - -module AP_MODULE_DECLARE_DATA win32_module; - -typedef struct { - /* Where to find interpreter to run scripts */ - interpreter_source_e script_interpreter_source; -} win32_dir_conf; - -static void *create_win32_dir_config(apr_pool_t *p, char *dir) -{ - win32_dir_conf *conf; - conf = (win32_dir_conf*)apr_palloc(p, sizeof(win32_dir_conf)); - conf->script_interpreter_source = INTERPRETER_SOURCE_UNSET; - return conf; -} - -static void *merge_win32_dir_configs(apr_pool_t *p, void *basev, void *addv) -{ - win32_dir_conf *new; - win32_dir_conf *base = (win32_dir_conf *) basev; - win32_dir_conf *add = (win32_dir_conf *) addv; - - new = (win32_dir_conf *) apr_pcalloc(p, sizeof(win32_dir_conf)); - new->script_interpreter_source = (add->script_interpreter_source - != INTERPRETER_SOURCE_UNSET) - ? add->script_interpreter_source - : base->script_interpreter_source; - return new; -} - -static const char *set_interpreter_source(cmd_parms *cmd, void *dv, - char *arg) -{ - win32_dir_conf *d = (win32_dir_conf *)dv; - if (!strcasecmp(arg, "registry")) { - d->script_interpreter_source = INTERPRETER_SOURCE_REGISTRY; - } - else if (!strcasecmp(arg, "registry-strict")) { - d->script_interpreter_source = INTERPRETER_SOURCE_REGISTRY_STRICT; - } - else if (!strcasecmp(arg, "script")) { - d->script_interpreter_source = INTERPRETER_SOURCE_SHEBANG; - } - else { - return apr_pstrcat(cmd->temp_pool, "ScriptInterpreterSource \"", arg, - "\" must be \"registry\", \"registry-strict\" or " - "\"script\"", NULL); - } - return NULL; -} - -/* XXX: prep_string should translate the string into unicode, - * such that it is compatible with whatever codepage the client - * will read characters 80-ff. For the moment, use the unicode - * values 0080-00ff. This isn't trivial, since the code page - * varies between msdos and Windows applications. - * For subsystem 2 [GUI] the default is the system Ansi CP. - * For subsystem 3 [CLI] the default is the system OEM CP. - */ -static void prep_string(const char ** str, apr_pool_t *p) -{ - const char *ch = *str; - char *ch2; - int widen = 0; - - if (!ch) { - return; - } - while (*ch) { - if (*(ch++) & 0x80) { - ++widen; - } - } - if (!widen) { - return; - } - widen += (ch - *str) + 1; - ch = *str; - *str = ch2 = apr_palloc(p, widen); - while (*ch) { - if (*ch & 0x80) { - /* sign extension won't hurt us here */ - *(ch2++) = 0xC0 | ((*ch >> 6) & 0x03); - *(ch2++) = 0x80 | (*(ch++) & 0x3f); - } - else { - *(ch2++) = *(ch++); - } - } - *(ch2++) = '\0'; -} - -/* Somewhat more exciting ... figure out where the registry has stashed the - * ExecCGI or Open command - it may be nested one level deep (or more???) - */ -static char* get_interpreter_from_win32_registry(apr_pool_t *p, - const char* ext, - int strict) -{ - apr_status_t rv; - ap_regkey_t *name_key = NULL; - ap_regkey_t *type_key; - ap_regkey_t *key; - char execcgi_path[] = "SHELL\\EXECCGI\\COMMAND"; - char execopen_path[] = "SHELL\\OPEN\\COMMAND"; - char *type_name; - char *buffer; - - if (!ext) { - return NULL; - } - /* - * Future optimization: - * When the registry is successfully searched, store the strings for - * interpreter and arguments in an ext hash to speed up subsequent look-ups - */ - - /* Open the key associated with the script filetype extension */ - rv = ap_regkey_open(&type_key, AP_REGKEY_CLASSES_ROOT, ext, APR_READ, p); - - if (rv != APR_SUCCESS) { - return NULL; - } - - /* Retrieve the name of the script filetype extension */ - rv = ap_regkey_value_get(&type_name, type_key, "", p); - - if (rv == APR_SUCCESS && type_name[0]) { - /* Open the key associated with the script filetype extension */ - rv = ap_regkey_open(&name_key, AP_REGKEY_CLASSES_ROOT, type_name, - APR_READ, p); - } - - /* Open the key for the script command path by: - * - * 1) the 'named' filetype key for ExecCGI/Command - * 2) the extension's type key for ExecCGI/Command - * - * and if the strict arg is false, then continue trying: - * - * 3) the 'named' filetype key for Open/Command - * 4) the extension's type key for Open/Command - */ - - if (name_key) { - if ((rv = ap_regkey_open(&key, name_key, execcgi_path, APR_READ, p)) - == APR_SUCCESS) { - rv = ap_regkey_value_get(&buffer, key, "", p); - ap_regkey_close(name_key); - } - } - - if (!name_key || (rv != APR_SUCCESS)) { - if ((rv = ap_regkey_open(&key, type_key, execcgi_path, APR_READ, p)) - == APR_SUCCESS) { - rv = ap_regkey_value_get(&buffer, key, "", p); - ap_regkey_close(type_key); - } - } - - if (!strict && name_key && (rv != APR_SUCCESS)) { - if ((rv = ap_regkey_open(&key, name_key, execopen_path, APR_READ, p)) - == APR_SUCCESS) { - rv = ap_regkey_value_get(&buffer, key, "", p); - ap_regkey_close(name_key); - } - } - - if (!strict && (rv != APR_SUCCESS)) { - if ((rv = ap_regkey_open(&key, type_key, execopen_path, APR_READ, p)) - == APR_SUCCESS) { - rv = ap_regkey_value_get(&buffer, key, "", p); - ap_regkey_close(type_key); - } - } - - if (name_key) { - ap_regkey_close(name_key); - } - - ap_regkey_close(type_key); - - if (rv != APR_SUCCESS || !buffer[0]) { - return NULL; - } - - return buffer; -} - - -static apr_array_header_t *split_argv(apr_pool_t *p, const char *interp, - const char *cgiprg, const char *cgiargs) -{ - apr_array_header_t *args = apr_array_make(p, 8, sizeof(char*)); - char *d = apr_palloc(p, strlen(interp)+1); - const char *ch = interp; - const char **arg; - int prgtaken = 0; - int argtaken = 0; - int inquo; - int sl; - - while (*ch) { - /* Skip on through Deep Space */ - if (apr_isspace(*ch)) { - ++ch; continue; - } - /* One Arg */ - if (((*ch == '$') || (*ch == '%')) && (*(ch + 1) == '*')) { - const char *cgiarg = cgiargs; - argtaken = 1; - for (;;) { - char *w = ap_getword_nulls(p, &cgiarg, '+'); - if (!*w) { - break; - } - ap_unescape_url(w); - if (win_nt) { - prep_string(&w, p); - } - arg = (const char**)apr_array_push(args); - *arg = ap_escape_shell_cmd(p, w); - } - ch += 2; - continue; - } - if (((*ch == '$') || (*ch == '%')) && (*(ch + 1) == '1')) { - /* Todo: Make short name!!! */ - prgtaken = 1; - arg = (const char**)apr_array_push(args); - if (*ch == '%') { - char *repl = apr_pstrdup(p, cgiprg); - *arg = repl; - while ((repl = strchr(repl, '/'))) { - *repl++ = '\\'; - } - } - else { - *arg = cgiprg; - } - ch += 2; - continue; - } - if ((*ch == '\"') && ((*(ch + 1) == '$') - || (*(ch + 1) == '%')) && (*(ch + 2) == '1') - && (*(ch + 3) == '\"')) { - prgtaken = 1; - arg = (const char**)apr_array_push(args); - if (*(ch + 1) == '%') { - char *repl = apr_pstrdup(p, cgiprg); - *arg = repl; - while ((repl = strchr(repl, '/'))) { - *repl++ = '\\'; - } - } - else { - *arg = cgiprg; - } - ch += 4; - continue; - } - arg = (const char**)apr_array_push(args); - *arg = d; - inquo = 0; - while (*ch) { - if (apr_isspace(*ch) && !inquo) { - ++ch; break; - } - /* Get 'em backslashes */ - for (sl = 0; *ch == '\\'; ++sl) { - *d++ = *ch++; - } - if (sl & 1) { - /* last unmatched '\' + '"' sequence is a '"' */ - if (*ch == '\"') { - *(d - 1) = *ch++; - } - continue; - } - if (*ch == '\"') { - /* '""' sequence within quotes is a '"' */ - if (*++ch == '\"' && inquo) { - *d++ = *ch++; continue; - } - /* Flip quote state */ - inquo = !inquo; - if (apr_isspace(*ch) && !inquo) { - ++ch; break; - } - /* All other '"'s are Munched */ - continue; - } - /* Anything else is, well, something else */ - *d++ = *ch++; - } - /* Term that arg, already pushed on args */ - *d++ = '\0'; - } - - if (!prgtaken) { - arg = (const char**)apr_array_push(args); - *arg = cgiprg; - } - - if (!argtaken) { - const char *cgiarg = cgiargs; - for (;;) { - char *w = ap_getword_nulls(p, &cgiarg, '+'); - if (!*w) { - break; - } - ap_unescape_url(w); - if (win_nt) { - prep_string(&w, p); - } - arg = (const char**)apr_array_push(args); - *arg = ap_escape_shell_cmd(p, w); - } - } - - arg = (const char**)apr_array_push(args); - *arg = NULL; - - return args; -} - - -static apr_status_t ap_cgi_build_command(const char **cmd, const char ***argv, - request_rec *r, apr_pool_t *p, - cgi_exec_info_t *e_info) -{ - const apr_array_header_t *elts_arr = apr_table_elts(r->subprocess_env); - const apr_table_entry_t *elts = (apr_table_entry_t *) elts_arr->elts; - const char *ext = NULL; - const char *interpreter = NULL; - win32_dir_conf *d; - apr_file_t *fh; - const char *args = ""; - int i; - - d = (win32_dir_conf *)ap_get_module_config(r->per_dir_config, - &win32_module); - - if (e_info->cmd_type) { - /* We have to consider that the client gets any QUERY_ARGS - * without any charset interpretation, use prep_string to - * create a string of the literal QUERY_ARGS bytes. - */ - *cmd = r->filename; - if (r->args && r->args[0] && !ap_strchr_c(r->args, '=')) { - args = r->args; - } - } - /* Handle the complete file name, we DON'T want to follow suexec, since - * an unrooted command is as predictable as shooting craps in Win32. - * Notice that unlike most mime extension parsing, we have to use the - * win32 parsing here, therefore the final extension is the only one - * we will consider. - */ - ext = strrchr(apr_filename_of_pathname(*cmd), '.'); - - /* If the file has an extension and it is not .com and not .exe and - * we've been instructed to search the registry, then do so. - * Let apr_proc_create do all of the .bat/.cmd dirty work. - */ - if (ext && (!strcasecmp(ext,".exe") || !strcasecmp(ext,".com") - || !strcasecmp(ext,".bat") || !strcasecmp(ext,".cmd"))) { - interpreter = ""; - } - if (!interpreter && ext - && (d->script_interpreter_source - == INTERPRETER_SOURCE_REGISTRY - || d->script_interpreter_source - == INTERPRETER_SOURCE_REGISTRY_STRICT)) { - /* Check the registry */ - int strict = (d->script_interpreter_source - == INTERPRETER_SOURCE_REGISTRY_STRICT); - interpreter = get_interpreter_from_win32_registry(r->pool, ext, - strict); - if (interpreter && e_info->cmd_type != APR_SHELLCMD) { - e_info->cmd_type = APR_PROGRAM_PATH; - } - else { - ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server, - strict ? "No ExecCGI verb found for files of type '%s'." - : "No ExecCGI or Open verb found for files of type '%s'.", - ext); - } - } - if (!interpreter) { - apr_status_t rv; - char buffer[1024]; - apr_size_t bytes = sizeof(buffer); - int i; - - /* Need to peek into the file figure out what it really is... - * ### aught to go back and build a cache for this one of these days. - */ - if (((rv = apr_file_open(&fh, *cmd, APR_READ | APR_BUFFERED, - APR_OS_DEFAULT, r->pool)) != APR_SUCCESS) - || ((rv = apr_file_read(fh, buffer, &bytes)) != APR_SUCCESS)) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, - "Failed to read cgi file %s for testing", *cmd); - return rv; - } - apr_file_close(fh); - - /* Script or executable, that is the question... */ - if ((buffer[0] == '#') && (buffer[1] == '!')) { - /* Assuming file is a script since it starts with a shebang */ - for (i = 2; i < sizeof(buffer); i++) { - if ((buffer[i] == '\r') || (buffer[i] == '\n')) { - buffer[i] = '\0'; - break; - } - } - if (i < sizeof(buffer)) { - interpreter = buffer + 2; - while (apr_isspace(*interpreter)) { - ++interpreter; - } - if (e_info->cmd_type != APR_SHELLCMD) { - e_info->cmd_type = APR_PROGRAM_PATH; - } - } - } - else { - /* Not a script, is it an executable? */ - IMAGE_DOS_HEADER *hdr = (IMAGE_DOS_HEADER*)buffer; - if ((bytes >= sizeof(IMAGE_DOS_HEADER)) - && (hdr->e_magic == IMAGE_DOS_SIGNATURE)) { - if (hdr->e_lfarlc < 0x40) { - /* Ought to invoke this 16 bit exe by a stub, (cmd /c?) */ - interpreter = ""; - } - else { - interpreter = ""; - } - } - } - } - if (!interpreter) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, - "%s is not executable; ensure interpreted scripts have " - "\"#!\" first line", *cmd); - return APR_EBADF; - } - - *argv = (const char **)(split_argv(p, interpreter, *cmd, - args)->elts); - *cmd = (*argv)[0]; - - e_info->detached = 1; - - /* XXX: Must fix r->subprocess_env to follow utf-8 conventions from - * the client's octets so that win32 apr_proc_create is happy. - * The -best- way is to determine if the .exe is unicode aware - * (using 0x0080-0x00ff) or is linked as a command or windows - * application (following the OEM or Ansi code page in effect.) - */ - for (i = 0; i < elts_arr->nelts; ++i) { - if (win_nt && elts[i].key && *elts[i].key - && (strncmp(elts[i].key, "HTTP_", 5) == 0 - || strncmp(elts[i].key, "SERVER_", 7) == 0 - || strncmp(elts[i].key, "REQUEST_", 8) == 0 - || strcmp(elts[i].key, "QUERY_STRING") == 0 - || strcmp(elts[i].key, "PATH_INFO") == 0 - || strcmp(elts[i].key, "PATH_TRANSLATED") == 0)) { - prep_string((const char**) &elts[i].val, r->pool); - } - } - return APR_SUCCESS; -} - -static int win32_pre_config(apr_pool_t *pconf_, apr_pool_t *plog, apr_pool_t *ptemp) -{ - win_nt = (osver.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS); - return OK; -} - -static void register_hooks(apr_pool_t *p) -{ - APR_REGISTER_OPTIONAL_FN(ap_cgi_build_command); - ap_hook_pre_config(win32_pre_config, NULL, NULL, APR_HOOK_MIDDLE); -} - -static const command_rec win32_cmds[] = { -AP_INIT_TAKE1("ScriptInterpreterSource", set_interpreter_source, NULL, - OR_FILEINFO, - "Where to find interpreter to run Win32 scripts " - "(Registry or script shebang line)"), -{ NULL } -}; - -module AP_MODULE_DECLARE_DATA win32_module = { - STANDARD20_MODULE_STUFF, - create_win32_dir_config, /* create per-dir config */ - merge_win32_dir_configs, /* merge per-dir config */ - NULL, /* server config */ - NULL, /* merge server config */ - win32_cmds, /* command apr_table_t */ - register_hooks /* register hooks */ -}; - -#endif /* defined WIN32 */ |