1/* Licensed to the Apache Software Foundation (ASF) under one or more 2 * contributor license agreements. See the NOTICE file distributed with 3 * this work for additional information regarding copyright ownership. 4 * The ASF licenses this file to You under the Apache License, Version 2.0 5 * (the "License"); you may not use this file except in compliance with 6 * the License. You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "apr_strings.h" 18#include "apr_portable.h" 19#include "apr_buckets.h" 20#include "ap_config.h" 21#include "httpd.h" 22#include "http_config.h" 23#include "http_core.h" 24#include "http_protocol.h" 25#include "http_request.h" 26#include "http_log.h" 27#include "util_script.h" 28#include "mod_core.h" 29#include "apr_optional.h" 30#include "apr_lib.h" 31#include "mod_cgi.h" 32#include "mpm_common.h" 33 34#ifdef NETWARE 35 36 37module AP_MODULE_DECLARE_DATA netware_module; 38 39typedef struct { 40 apr_table_t *file_type_handlers; /* CGI map from file types to CGI modules */ 41 apr_table_t *file_handler_mode; /* CGI module mode (spawn in same address space or not) */ 42 apr_table_t *extra_env_vars; /* Environment variables to be added to the CGI environment */ 43} netware_dir_config; 44 45 46static void *create_netware_dir_config(apr_pool_t *p, char *dir) 47{ 48 netware_dir_config *new = (netware_dir_config*) apr_palloc(p, sizeof(netware_dir_config)); 49 50 new->file_type_handlers = apr_table_make(p, 10); 51 new->file_handler_mode = apr_table_make(p, 10); 52 new->extra_env_vars = apr_table_make(p, 10); 53 54 apr_table_setn(new->file_type_handlers, "NLM", "OS"); 55 56 return new; 57} 58 59static void *merge_netware_dir_configs(apr_pool_t *p, void *basev, void *addv) 60{ 61 netware_dir_config *base = (netware_dir_config *) basev; 62 netware_dir_config *add = (netware_dir_config *) addv; 63 netware_dir_config *new = (netware_dir_config *) apr_palloc(p, sizeof(netware_dir_config)); 64 65 new->file_type_handlers = apr_table_overlay(p, add->file_type_handlers, base->file_type_handlers); 66 new->file_handler_mode = apr_table_overlay(p, add->file_handler_mode, base->file_handler_mode); 67 new->extra_env_vars = apr_table_overlay(p, add->extra_env_vars, base->extra_env_vars); 68 69 return new; 70} 71 72static const char *set_extension_map(cmd_parms *cmd, netware_dir_config *m, 73 char *CGIhdlr, char *ext, char *detach) 74{ 75 int i, len; 76 77 if (*ext == '.') 78 ++ext; 79 80 if (CGIhdlr != NULL) { 81 len = strlen(CGIhdlr); 82 for (i=0; i<len; i++) { 83 if (CGIhdlr[i] == '\\') { 84 CGIhdlr[i] = '/'; 85 } 86 } 87 } 88 89 apr_table_set(m->file_type_handlers, ext, CGIhdlr); 90 if (detach) { 91 apr_table_set(m->file_handler_mode, ext, "y"); 92 } 93 94 return NULL; 95} 96 97static apr_status_t ap_cgi_build_command(const char **cmd, const char ***argv, 98 request_rec *r, apr_pool_t *p, 99 cgi_exec_info_t *e_info) 100{ 101 char *ext = NULL; 102 char *cmd_only, *ptr; 103 const char *new_cmd; 104 netware_dir_config *d; 105 const char *args = ""; 106 107 d = (netware_dir_config *)ap_get_module_config(r->per_dir_config, 108 &netware_module); 109 110 if (e_info->process_cgi) { 111 /* Handle the complete file name, we DON'T want to follow suexec, since 112 * an unrooted command is as predictable as shooting craps in Win32. 113 * 114 * Notice that unlike most mime extension parsing, we have to use the 115 * win32 parsing here, therefore the final extension is the only one 116 * we will consider 117 */ 118 *cmd = r->filename; 119 if (r->args && r->args[0] && !ap_strchr_c(r->args, '=')) { 120 args = r->args; 121 } 122 } 123 124 cmd_only = apr_pstrdup(p, *cmd); 125 e_info->cmd_type = APR_PROGRAM; 126 127 /* truncate any arguments from the cmd */ 128 for (ptr = cmd_only; *ptr && (*ptr != ' '); ptr++); 129 *ptr = '\0'; 130 131 /* Figure out what the extension is so that we can match it. */ 132 ext = strrchr(apr_filepath_name_get(cmd_only), '.'); 133 134 /* If there isn't an extension then give it an empty string */ 135 if (!ext) { 136 ext = ""; 137 } 138 139 /* eliminate the '.' if there is one */ 140 if (*ext == '.') 141 ++ext; 142 143 /* check if we have a registered command for the extension*/ 144 new_cmd = apr_table_get(d->file_type_handlers, ext); 145 e_info->detached = 1; 146 if (new_cmd == NULL) { 147 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02135) 148 "Could not find a command associated with the %s extension", ext); 149 return APR_EBADF; 150 } 151 if (stricmp(new_cmd, "OS")) { 152 /* If we have a registered command then add the file that was passed in as a 153 parameter to the registered command. */ 154 *cmd = apr_pstrcat (p, new_cmd, " ", cmd_only, NULL); 155 156 /* Run in its own address space if specified */ 157 if(apr_table_get(d->file_handler_mode, ext)) 158 e_info->addrspace = 1; 159 } 160 161 /* Tokenize the full command string into its arguments */ 162 apr_tokenize_to_argv(*cmd, (char***)argv, p); 163 164 /* The first argument should be the executible */ 165 *cmd = ap_server_root_relative(p, *argv[0]); 166 167 return APR_SUCCESS; 168} 169 170static int 171netware_pre_config(apr_pool_t *pconf, apr_pool_t *plog, 172 apr_pool_t *ptemp) 173{ 174 ap_sys_privileges_handlers(1); 175 return OK; 176} 177 178static void register_hooks(apr_pool_t *p) 179{ 180 APR_REGISTER_OPTIONAL_FN(ap_cgi_build_command); 181 ap_hook_pre_config(netware_pre_config, 182 NULL, NULL, APR_HOOK_FIRST); 183} 184 185static const command_rec netware_cmds[] = { 186AP_INIT_TAKE23("CGIMapExtension", set_extension_map, NULL, OR_FILEINFO, 187 "Full path to the CGI NLM module followed by a file extension. If the " 188 "first parameter is set to \"OS\" then the following file extension is " 189 "treated as NLM. The optional parameter \"detach\" can be specified if " 190 "the NLM should be launched in its own address space."), 191{ NULL } 192}; 193 194AP_DECLARE_MODULE(netware) = { 195 STANDARD20_MODULE_STUFF, 196 create_netware_dir_config, /* create per-dir config */ 197 merge_netware_dir_configs, /* merge per-dir config */ 198 NULL, /* server config */ 199 NULL, /* merge server config */ 200 netware_cmds, /* command apr_table_t */ 201 register_hooks /* register hooks */ 202}; 203 204#endif 205