| /* 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. |
| */ |
| |
| #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 "apr_optional.h" |
| #include "apr_lib.h" |
| #include "mod_cgi.h" |
| #include "mpm_common.h" |
| |
| #ifdef NETWARE |
| |
| |
| module AP_MODULE_DECLARE_DATA netware_module; |
| |
| typedef struct { |
| apr_table_t *file_type_handlers; /* CGI map from file types to CGI modules */ |
| apr_table_t *file_handler_mode; /* CGI module mode (spawn in same address space or not) */ |
| apr_table_t *extra_env_vars; /* Environment variables to be added to the CGI environment */ |
| } netware_dir_config; |
| |
| |
| static void *create_netware_dir_config(apr_pool_t *p, char *dir) |
| { |
| netware_dir_config *new = (netware_dir_config*) apr_palloc(p, sizeof(netware_dir_config)); |
| |
| new->file_type_handlers = apr_table_make(p, 10); |
| new->file_handler_mode = apr_table_make(p, 10); |
| new->extra_env_vars = apr_table_make(p, 10); |
| |
| apr_table_setn(new->file_type_handlers, "NLM", "OS"); |
| |
| return new; |
| } |
| |
| static void *merge_netware_dir_configs(apr_pool_t *p, void *basev, void *addv) |
| { |
| netware_dir_config *base = (netware_dir_config *) basev; |
| netware_dir_config *add = (netware_dir_config *) addv; |
| netware_dir_config *new = (netware_dir_config *) apr_palloc(p, sizeof(netware_dir_config)); |
| |
| new->file_type_handlers = apr_table_overlay(p, add->file_type_handlers, base->file_type_handlers); |
| new->file_handler_mode = apr_table_overlay(p, add->file_handler_mode, base->file_handler_mode); |
| new->extra_env_vars = apr_table_overlay(p, add->extra_env_vars, base->extra_env_vars); |
| |
| return new; |
| } |
| |
| static const char *set_extension_map(cmd_parms *cmd, netware_dir_config *m, |
| char *CGIhdlr, char *ext, char *detach) |
| { |
| int i, len; |
| |
| if (*ext == '.') |
| ++ext; |
| |
| if (CGIhdlr != NULL) { |
| len = strlen(CGIhdlr); |
| for (i=0; i<len; i++) { |
| if (CGIhdlr[i] == '\\') { |
| CGIhdlr[i] = '/'; |
| } |
| } |
| } |
| |
| apr_table_set(m->file_type_handlers, ext, CGIhdlr); |
| if (detach) { |
| apr_table_set(m->file_handler_mode, ext, "y"); |
| } |
| |
| return NULL; |
| } |
| |
| 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) |
| { |
| char *ext = NULL; |
| char *cmd_only, *ptr; |
| const char *new_cmd; |
| netware_dir_config *d; |
| const char *args = ""; |
| |
| d = (netware_dir_config *)ap_get_module_config(r->per_dir_config, |
| &netware_module); |
| |
| if (e_info->process_cgi) { |
| /* 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 |
| */ |
| *cmd = r->filename; |
| if (r->args && r->args[0] && !ap_strchr_c(r->args, '=')) { |
| args = r->args; |
| } |
| } |
| |
| cmd_only = apr_pstrdup(p, *cmd); |
| e_info->cmd_type = APR_PROGRAM; |
| |
| /* truncate any arguments from the cmd */ |
| for (ptr = cmd_only; *ptr && (*ptr != ' '); ptr++); |
| *ptr = '\0'; |
| |
| /* Figure out what the extension is so that we can match it. */ |
| ext = strrchr(apr_filepath_name_get(cmd_only), '.'); |
| |
| /* If there isn't an extension then give it an empty string */ |
| if (!ext) { |
| ext = ""; |
| } |
| |
| /* eliminate the '.' if there is one */ |
| if (*ext == '.') { |
| ++ext; |
| } |
| |
| /* check if we have a registered command for the extension*/ |
| new_cmd = apr_table_get(d->file_type_handlers, ext); |
| e_info->detached = 1; |
| if (new_cmd == NULL) { |
| ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02135) |
| "Could not find a command associated with the %s extension", ext); |
| return APR_EBADF; |
| } |
| if (stricmp(new_cmd, "OS")) { |
| /* If we have a registered command then add the file that was passed in as a |
| parameter to the registered command. */ |
| *cmd = apr_pstrcat (p, new_cmd, " ", cmd_only, NULL); |
| |
| /* Run in its own address space if specified */ |
| if (apr_table_get(d->file_handler_mode, ext)) { |
| e_info->addrspace = 1; |
| } |
| } |
| |
| /* Tokenize the full command string into its arguments */ |
| apr_tokenize_to_argv(*cmd, (char***)argv, p); |
| |
| /* The first argument should be the executible */ |
| *cmd = ap_server_root_relative(p, *argv[0]); |
| |
| return APR_SUCCESS; |
| } |
| |
| static int |
| netware_pre_config(apr_pool_t *pconf, apr_pool_t *plog, |
| apr_pool_t *ptemp) |
| { |
| ap_sys_privileges_handlers(1); |
| return OK; |
| } |
| |
| static void register_hooks(apr_pool_t *p) |
| { |
| APR_REGISTER_OPTIONAL_FN(ap_cgi_build_command); |
| ap_hook_pre_config(netware_pre_config, |
| NULL, NULL, APR_HOOK_FIRST); |
| } |
| |
| static const command_rec netware_cmds[] = { |
| AP_INIT_TAKE23("CGIMapExtension", set_extension_map, NULL, OR_FILEINFO, |
| "Full path to the CGI NLM module followed by a file extension. If the " |
| "first parameter is set to \"OS\" then the following file extension is " |
| "treated as NLM. The optional parameter \"detach\" can be specified if " |
| "the NLM should be launched in its own address space."), |
| { NULL } |
| }; |
| |
| AP_DECLARE_MODULE(netware) = { |
| STANDARD20_MODULE_STUFF, |
| create_netware_dir_config, /* create per-dir config */ |
| merge_netware_dir_configs, /* merge per-dir config */ |
| NULL, /* server config */ |
| NULL, /* merge server config */ |
| netware_cmds, /* command apr_table_t */ |
| register_hooks /* register hooks */ |
| }; |
| |
| #endif |