summaryrefslogtreecommitdiffstats
path: root/rubbos/app/httpd-2.0.64/modules/arch/win32/mod_win32.c
diff options
context:
space:
mode:
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.c553
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 */