static const char *log_header_out(request_rec *r, char *a) { const char *cp = ap_table_get(r->headers_out, a); if (!strcasecmp(a, "Content-type") && r->content_type) { cp = ap_field_noparam(r->pool, r->content_type); } if (cp) { return cp; } return ap_table_get(r->err_headers_out, a); }
static config_log_state *open_multi_logs(server_rec *s, pool *p) { int i; multi_log_state *mls = ap_get_module_config(s->module_config, &config_log_module); config_log_state *clsarray; const char *dummy; const char *format; if (mls->default_format_string) { format = ap_table_get(mls->formats, mls->default_format_string); if (format) { mls->default_format = parse_log_string(p, format, &dummy); } } if (!mls->default_format) { mls->default_format = parse_log_string(p, DEFAULT_LOG_FORMAT, &dummy); } if (mls->config_logs->nelts) { clsarray = (config_log_state *) mls->config_logs->elts; for (i = 0; i < mls->config_logs->nelts; ++i) { config_log_state *cls = &clsarray[i]; if (cls->format_string) { format = ap_table_get(mls->formats, cls->format_string); if (format) { cls->format = parse_log_string(p, format, &dummy); } } cls = open_config_log(s, p, cls, mls->default_format); } } else if (mls->server_config_logs) { clsarray = (config_log_state *) mls->server_config_logs->elts; for (i = 0; i < mls->server_config_logs->nelts; ++i) { config_log_state *cls = &clsarray[i]; if (cls->format_string) { format = ap_table_get(mls->formats, cls->format_string); if (format) { cls->format = parse_log_string(p, format, &dummy); } } cls = open_config_log(s, p, cls, mls->default_format); } } return NULL; }
static int agent_log_transaction(request_rec *orig) { agent_log_state *cls = ap_get_module_config(orig->server->module_config, &agent_log_module); char str[HUGE_STRING_LEN]; const char *agent; request_rec *r; if (cls->agent_fd < 0) return OK; for (r = orig; r->next; r = r->next) continue; if (*cls->fname == '\0') /* Don't log agent */ return DECLINED; agent = ap_table_get(orig->headers_in, "User-Agent"); if (agent != NULL) { ap_snprintf(str, sizeof(str), "%s\n", agent); write(cls->agent_fd, str, strlen(str)); } return OK; }
/** * Nomalize charset in HTTP request line and HTTP header(s). * Returns 0 on success, -1 (non-zero) on error. * * FIXME: Should handle/consider partial success? * * @param r Apache request object structure * @param cd Conversion descriptor, made by iconv_open(3). */ static int iconv_header(request_rec *r, iconv_t cd) { char *buff; char *keys[] = { "Destination", NULL }; int i; /* Normalize encoding in HTTP request line */ ap_unescape_url(r->unparsed_uri); if ((buff = iconv_string(r, cd, r->unparsed_uri, strlen(r->unparsed_uri))) == NULL) return -1; ap_parse_uri(r, buff); ap_getparents(r->uri); /* normalize given path for security */ /* Normalize encoding in HTTP request header(s) */ for (i = 0 ; keys[i] ; i++) { if ((buff = (char *)ap_table_get(r->headers_in, keys[i])) != NULL) { ap_unescape_url(buff); if ((buff = iconv_string(r, cd, buff, strlen(buff))) == NULL) return -1; ap_table_set(r->headers_in, keys[i], buff); } } return 0; }
int ApacheRequest___parse(ApacheRequest *req) { request_rec *r = req->r; int result; if (r->args) { split_to_parms(req, r->args); } if (r->method_number == M_POST) { const char *ct = ap_table_get(r->headers_in, "Content-type"); if (ct && strncaseEQ(ct, DEFAULT_ENCTYPE, DEFAULT_ENCTYPE_LENGTH)) { result = ApacheRequest_parse_urlencoded(req); } else if (ct && strncaseEQ(ct, MULTIPART_ENCTYPE, MULTIPART_ENCTYPE_LENGTH)) { result = ApacheRequest_parse_multipart(req); } else { ap_log_rerror(REQ_ERROR, "[libapreq] unknown content-type: `%s'", ct); result = HTTP_INTERNAL_SERVER_ERROR; } } else { result = ApacheRequest_parse_urlencoded(req); } req->parsed = 1; return result; }
static PyObject * req_get_all_dirs(requestobject *self, PyObject *args) { table *all; py_dir_config *conf = (py_dir_config *) ap_get_module_config(self->request_rec->per_dir_config, &python_module); all = ap_copy_table(self->request_rec->pool, conf->dirs); if (ap_table_get(self->request_rec->notes, "py_more_directives")) { array_header *ah = ap_table_elts(self->request_rec->notes); table_entry *elts = (table_entry *)ah->elts; int i = ah->nelts; while (i--) { if (elts[i].key) { /* chop off _dir */ char *s = ap_pstrdup(self->request_rec->pool, elts[i].key); if (valid_handler(s)) { s[strlen(s)-4] = 0; ap_table_set(all, s, elts[i].val); } } } } return MpTable_FromTable(all); }
static char *wrap_getenv (void *data, const char *s) { WRAPPER_DATA *wrap = (WRAPPER_DATA *)data; char *v; v = (char *) ap_table_get (wrap->r->subprocess_env, s); if (v) return strdup(v); return NULL; }
static PyObject *server_register_cleanup(serverobject *self, PyObject *args) { cleanup_info *ci; PyObject *handler = NULL; PyObject *data = NULL; PyObject *Req = NULL; requestobject *req = NULL; if (! PyArg_ParseTuple(args, "OO|O", &Req, &handler, &data)) return NULL; if (! PyObject_HasAttrString(Req, "_req")) { PyErr_SetString(PyExc_ValueError, "first argument must be a Request object"); return NULL; } else { req = (requestobject *) PyObject_GetAttrString(Req, "_req"); if (! MpRequest_Check(req)) { PyErr_SetString(PyExc_ValueError, "first argument must be a request object"); return NULL; } else if(!PyCallable_Check(handler)) { PyErr_SetString(PyExc_ValueError, "second argument must be a callable object"); return NULL; } } ci = (cleanup_info *)malloc(sizeof(cleanup_info)); ci->request_rec = NULL; ci->server_rec = self->server; Py_INCREF(handler); ci->handler = handler; ci->interpreter = ap_table_get(req->request_rec->notes, "python_interpreter"); if (data) { Py_INCREF(data); ci->data = data; } else { Py_INCREF(Py_None); ci->data = Py_None; } ap_register_cleanup(child_init_pool, ci, python_cleanup, ap_null_cleanup); Py_INCREF(Py_None); return Py_None; }
static int find_allowdeny(request_rec *r, array_header *a, int method) { allowdeny *ap = (allowdeny *) a->elts; int mmask = (1 << method); int i; int gothost = 0; const char *remotehost = NULL; for (i = 0; i < a->nelts; ++i) { if (!(mmask & ap[i].limited)) continue; switch (ap[i].type) { case T_ENV: if (ap_table_get(r->subprocess_env, ap[i].x.from)) { return 1; } break; case T_ALL: return 1; case T_IP: if (ap[i].x.ip.net.s_addr != INADDR_NONE && (r->connection->remote_addr.sin_addr.s_addr & ap[i].x.ip.mask.s_addr) == ap[i].x.ip.net.s_addr) { return 1; } break; case T_HOST: if (!gothost) { remotehost = ap_get_remote_host(r->connection, r->per_dir_config, REMOTE_DOUBLE_REV); if ((remotehost == NULL) || is_ip(remotehost)) gothost = 1; else gothost = 2; } if ((gothost == 2) && in_domain(ap[i].x.from, remotehost)) return 1; break; case T_FAIL: /* do nothing? */ break; } } return 0; }
static int asis_handler(request_rec *r) { FILE *f; const char *location; r->allowed |= (1 << M_GET); if (r->method_number != M_GET) return DECLINED; if (r->finfo.st_mode == 0) { ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, "File does not exist: %s", r->filename); return NOT_FOUND; } f = ap_pfopen(r->pool, r->filename, "r"); if (f == NULL) { ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "file permissions deny server access: %s", r->filename); return FORBIDDEN; } ap_scan_script_header_err(r, f, NULL); location = ap_table_get(r->headers_out, "Location"); if (location && location[0] == '/' && ((r->status == HTTP_OK) || ap_is_HTTP_REDIRECT(r->status))) { ap_pfclose(r->pool, f); /* Internal redirect -- fake-up a pseudo-request */ r->status = HTTP_OK; /* This redirect needs to be a GET no matter what the original * method was. */ r->method = ap_pstrdup(r->pool, "GET"); r->method_number = M_GET; ap_internal_redirect_handler(location, r); return OK; } ap_send_http_header(r); if (!r->header_only) ap_send_fd(f, r); ap_pfclose(r->pool, f); return OK; }
static PyObject * req_get_all_config(requestobject *self, PyObject *args) { table *all; py_dir_config *conf = (py_dir_config *) ap_get_module_config(self->request_rec->per_dir_config, &python_module); all = ap_copy_table(self->request_rec->pool, conf->directives); if (ap_table_get(self->request_rec->notes, "py_more_directives")) { array_header *ah = ap_table_elts(self->request_rec->notes); table_entry *elts = (table_entry *)ah->elts; int i = ah->nelts; while (i--) { if (elts[i].key) { if (valid_handler(elts[i].key)) { /* if exists - append, otherwise add */ const char *val = ap_table_get(all, elts[i].key); if (val) { ap_table_set(all, elts[i].key, ap_pstrcat(self->request_rec->pool, val, " ", elts[i].val, NULL)); } else { ap_table_set(all, elts[i].key, elts[i].val); } } } } } return MpTable_FromTable(all); }
/** get_params : void -> #list <doc>parse all GET and POST params and return them into a chained list</doc> **/ static value get_params() { mcontext *c = CONTEXT(); const char *args = c->r->args; value p = val_null; // PARSE "GET" PARAMS if( args != NULL ) parse_get(&p,args); // PARSE "POST" PARAMS if( c->post_data != NULL ) { const char *ctype = ap_table_get(c->r->headers_in,"Content-Type"); if( ctype == NULL || strstr(ctype,"urlencoded") != NULL ) parse_get(&p,val_string(c->post_data)); } return p; }
/** * get DSAME Cookie */ static char *get_cookie(request_rec *r, const char *name) { static const char separators[] = { " ;\n\r\t\f" }; char *cookie; char *part; char *marker = NULL; char *value = NULL; char *last_separator; if (!(cookie = (char *)ap_table_get(r->headers_in, "Cookie"))) { am_web_log_warning("in get_cookie: no cookie in ap_table"); return NULL; } part = ap_pstrcat (r->pool, cookie, ";", NULL); am_web_log_debug("in get_cookie: part is %s", part); // get the last IS cookie for (part = strtok_r(part, separators, &last_separator); part != NULL; part = strtok_r(NULL, separators, &last_separator)) { while (part && !(marker = strchr(part, '='))) { part = strtok_r(NULL, separators, &last_separator); } if (++marker) { if (!strcasecmp(ap_getword(r->pool, (const char **)&part, '='), name)) { value = marker; } } } if (value) { am_web_log_debug("in get_cookie: return cookie value of %s", value); } return value; }
static PyObject *req_register_cleanup(requestobject *self, PyObject *args) { cleanup_info *ci; PyObject *handler = NULL; PyObject *data = NULL; if (! PyArg_ParseTuple(args, "O|O", &handler, &data)) return NULL; /* bad args */ ci = (cleanup_info *)malloc(sizeof(cleanup_info)); ci->request_rec = self->request_rec; ci->server_rec = self->request_rec->server; if (PyCallable_Check(handler)) { Py_INCREF(handler); ci->handler = handler; ci->interpreter = ap_table_get(self->request_rec->notes, "python_interpreter"); if (data) { Py_INCREF(data); ci->data = data; } else { Py_INCREF(Py_None); ci->data = Py_None; } } else { PyErr_SetString(PyExc_ValueError, "first argument must be a callable object"); free(ci); return NULL; } ap_register_cleanup(self->request_rec->pool, ci, python_cleanup, ap_null_cleanup); Py_INCREF(Py_None); return Py_None; }
/** get_cookies : void -> #list <doc>Return a cookie list as a (name,value) chained list</doc> **/ static value get_cookies() { const char *k = ap_table_get(CONTEXT()->r->headers_in,"Cookie"); char *start, *end; value p = val_null, tmp; if( k == NULL ) return p; while( (start = strchr(k,'=')) != NULL ) { start++; end = start; while( *end != 0 && *end != '\r' && *end != '\n' && *end != ';' ) end++; tmp = alloc_array(3); val_array_ptr(tmp)[0] = copy_string(k,(int)(start-k-1)); val_array_ptr(tmp)[1] = copy_string(start,(int)(end-start)); val_array_ptr(tmp)[2] = p; p = tmp; if( *end != ';' || end[1] != ' ' ) break; k = end + 2; } return p; }
int ApacheRequest_parse_urlencoded(ApacheRequest *req) { request_rec *r = req->r; int rc = OK; if (r->method_number == M_POST) { const char *data = NULL, *type; type = ap_table_get(r->headers_in, "Content-Type"); if (!strncaseEQ(type, DEFAULT_ENCTYPE, DEFAULT_ENCTYPE_LENGTH)) { return DECLINED; } if ((rc = util_read(req, &data)) != OK) { return rc; } if (data) { split_to_parms(req, data); } } return OK; }
API_EXPORT(char **) ap_create_environment(pool *p, table *t) { array_header *env_arr = ap_table_elts(t); table_entry *elts = (table_entry *) env_arr->elts; char **env = (char **) ap_palloc(p, (env_arr->nelts + 2) * sizeof(char *)); int i, j; char *tz; char *whack; j = 0; if (!ap_table_get(t, "TZ")) { tz = getenv("TZ"); if (tz != NULL) { env[j++] = ap_pstrcat(p, "TZ=", tz, NULL); } } for (i = 0; i < env_arr->nelts; ++i) { if (!elts[i].key) { continue; } env[j] = ap_pstrcat(p, elts[i].key, "=", elts[i].val, NULL); whack = env[j]; if (ap_isdigit(*whack)) { *whack++ = '_'; } while (*whack != '=') { if (!ap_isalnum(*whack) && *whack != '_') { *whack = '_'; } ++whack; } ++j; } env[j] = NULL; return env; }
int ApacheRequest_parse_multipart(ApacheRequest *req) { request_rec *r = req->r; int rc = OK; const char *ct = ap_table_get(r->headers_in, "Content-Type"); long length; char *boundary; multipart_buffer *mbuff; ApacheUpload *upload = NULL; if (!ct) { ap_log_rerror(REQ_ERROR, "[libapreq] no Content-type header!"); return HTTP_INTERNAL_SERVER_ERROR; } if ((rc = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR))) { return rc; } if (!ap_should_client_block(r)) { return rc; } if ((length = r->remaining) > req->post_max && req->post_max > 0) { ap_log_rerror(REQ_ERROR, "[libapreq] entity too large (%d, max=%d)", (int)length, req->post_max); return HTTP_REQUEST_ENTITY_TOO_LARGE; } (void)ap_getword(r->pool, &ct, '='); boundary = ap_getword_conf(r->pool, &ct); if (!(mbuff = multipart_buffer_new(boundary, length, r))) { return DECLINED; } while (!multipart_buffer_eof(mbuff)) { table *header = multipart_buffer_headers(mbuff); const char *cd, *param=NULL, *filename=NULL; char buff[FILLUNIT]; int blen, wlen; if (!header) { #ifdef DEBUG ap_log_rerror(REQ_ERROR, "[libapreq] silently drop remaining '%ld' bytes", r->remaining); #endif ap_hard_timeout("[libapreq] parse_multipart", r); while ( ap_get_client_block(r, buff, sizeof(buff)) > 0 ) /* wait for more input to ignore */ ; ap_kill_timeout(r); return OK; } if ((cd = ap_table_get(header, "Content-Disposition"))) { const char *pair; while (*cd && (pair = ap_getword(r->pool, &cd, ';'))) { const char *key; while (ap_isspace(*cd)) { ++cd; } if (ap_ind(pair, '=')) { key = ap_getword(r->pool, &pair, '='); if(strEQ(key, "name")) { param = ap_getword_conf(r->pool, &pair); } else if(strEQ(key, "filename")) { filename = ap_getword_conf(r->pool, &pair); } } } if (!filename) { char *value = multipart_buffer_read_body(mbuff); ap_table_add(req->parms, param, value); continue; } if (!param) continue; /* shouldn't happen, but just in case. */ if (req->disable_uploads) { ap_log_rerror(REQ_ERROR, "[libapreq] file upload forbidden"); return HTTP_FORBIDDEN; } ap_table_add(req->parms, param, filename); if (upload) { upload->next = ApacheUpload_new(req); upload = upload->next; } else { upload = ApacheUpload_new(req); req->upload = upload; } if (! req->upload_hook && ! ApacheRequest_tmpfile(req, upload) ) { return HTTP_INTERNAL_SERVER_ERROR; } upload->info = header; upload->filename = ap_pstrdup(req->r->pool, filename); upload->name = ap_pstrdup(req->r->pool, param); /* mozilla empty-file (missing CRLF) hack */ fill_buffer(mbuff); if( strEQN(mbuff->buf_begin, mbuff->boundary, strlen(mbuff->boundary)) ) { r->remaining -= 2; continue; } while ((blen = multipart_buffer_read(mbuff, buff, sizeof(buff)))) { if (req->upload_hook != NULL) { wlen = req->upload_hook(req->hook_data, buff, blen, upload); } else { wlen = fwrite(buff, 1, blen, upload->fp); } if (wlen != blen) { return HTTP_INTERNAL_SERVER_ERROR; } upload->size += wlen; } if (upload->size > 0 && (upload->fp != NULL)) { fseek(upload->fp, 0, 0); } } } return OK; }
const char *ApacheRequest_param(ApacheRequest *req, const char *key) { ApacheRequest_parse(req); return ap_table_get(req->parms, key); }
int isapi_handler (request_rec *r) { LPEXTENSION_CONTROL_BLOCK ecb = ap_pcalloc(r->pool, sizeof(struct _EXTENSION_CONTROL_BLOCK)); HSE_VERSION_INFO *pVer = ap_pcalloc(r->pool, sizeof(HSE_VERSION_INFO)); HINSTANCE isapi_handle; BOOL (*isapi_version)(HSE_VERSION_INFO *); /* entry point 1 */ DWORD (*isapi_entry)(LPEXTENSION_CONTROL_BLOCK); /* entry point 2 */ BOOL (*isapi_term)(DWORD); /* optional entry point 3 */ isapi_cid *cid = ap_pcalloc(r->pool, sizeof(isapi_cid)); table *e = r->subprocess_env; DWORD read; char *p; int retval; int res; /* Use similar restrictions as CGIs */ if (!(ap_allow_options(r) & OPT_EXECCGI)) return FORBIDDEN; if (r->finfo.st_mode == 0) return NOT_FOUND; if (S_ISDIR(r->finfo.st_mode)) return FORBIDDEN; if (!(isapi_handle = ap_os_dso_load(r->filename))) { ap_log_rerror(APLOG_MARK, APLOG_ALERT, r, "ISAPI Could not load DLL: %s", r->filename); return SERVER_ERROR; } if (!(isapi_version = (void *)(ap_os_dso_sym(isapi_handle, "GetExtensionVersion")))) { ap_log_rerror(APLOG_MARK, APLOG_ALERT, r, "DLL could not load GetExtensionVersion(): %s", r->filename); ap_os_dso_unload(isapi_handle); return SERVER_ERROR; } if (!(isapi_entry = (void *)(ap_os_dso_sym(isapi_handle, "HttpExtensionProc")))) { ap_log_rerror(APLOG_MARK, APLOG_ALERT, r, "DLL could not load HttpExtensionProc(): %s", r->filename); ap_os_dso_unload(isapi_handle); return SERVER_ERROR; } isapi_term = (void *)(ap_os_dso_sym(isapi_handle, "TerminateExtension")); /* Run GetExtensionVersion() */ if (!(*isapi_version)(pVer)) { ap_log_rerror(APLOG_MARK, APLOG_ALERT, r, "ISAPI GetExtensionVersion() failed: %s", r->filename); ap_os_dso_unload(isapi_handle); return SERVER_ERROR; } /* Set up variables. There are a couple of special cases for ISAPI. * XXX: These were taken verbatim from GetServerVariable, and should * be reviewed carefully. */ ap_add_common_vars(r); ap_add_cgi_vars(r); ap_table_setn(r->subprocess_env, "UNMAPPED_REMOTE_USER", "REMOTE_USER"); ap_table_setn(r->subprocess_env, "SERVER_PORT_SECURE", "0"); ap_table_setn(r->subprocess_env, "URL", r->uri); /* Set up connection ID */ ecb->ConnID = (HCONN)cid; cid->ecb = ecb; cid->r = r; cid->status = 0; ecb->cbSize = sizeof(struct _EXTENSION_CONTROL_BLOCK); ecb->dwVersion = MAKELONG(0, 2); ecb->dwHttpStatusCode = 0; strcpy(ecb->lpszLogData, ""); ecb->lpszMethod = ap_pstrdup(r->pool, r->method); ecb->lpszQueryString = ap_pstrdup(r->pool, ap_table_get(e, "QUERY_STRING")); ecb->lpszPathInfo = ap_pstrdup(r->pool, ap_table_get(e, "PATH_INFO")); ecb->lpszPathTranslated = ap_pstrdup(r->pool, ap_table_get(e, "PATH_TRANSLATED")); ecb->lpszContentType = ap_pstrdup(r->pool, ap_table_get(e, "CONTENT_TYPE")); /* Set up client input */ if ((retval = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR))) { if (isapi_term) (*isapi_term)( 2 /* HSE_TERM_MUST_UNLOAD */); ap_os_dso_unload(isapi_handle); return retval; } if (ap_should_client_block(r)) { /* Time to start reading the appropriate amount of data, * and allow the administrator to tweak the number * TODO: add the httpd.conf option for ReadAheadBuffer. */ if (r->remaining) { ecb->cbTotalBytes = r->remaining; if (ecb->cbTotalBytes > ReadAheadBuffer) ecb->cbAvailable = ReadAheadBuffer; else ecb->cbAvailable = ecb->cbTotalBytes; } else { ecb->cbTotalBytes = 0xffffffff; ecb->cbAvailable = ReadAheadBuffer; } ecb->lpbData = ap_pcalloc(r->pool, ecb->cbAvailable + 1); p = ecb->lpbData; read = 0; while (read < ecb->cbAvailable && ((res = ap_get_client_block(r, ecb->lpbData + read, ecb->cbAvailable - read)) > 0)) { read += res; } if (res < 0) { if (isapi_term) (*isapi_term)(HSE_TERM_MUST_UNLOAD); ap_os_dso_unload(isapi_handle); return SERVER_ERROR; } /* Although its not to spec, IIS seems to null-terminate * its lpdData string. So we will too. * * XXX: This must be an issue... backing out the null * from the count of bytes. */ if (res == 0) ecb->cbAvailable = ecb->cbTotalBytes = read; else ecb->cbAvailable = read; ecb->lpbData[read] = '\0'; } else { ecb->cbTotalBytes = 0; ecb->cbAvailable = 0; ecb->lpbData = NULL; } /* Set up the callbacks */ ecb->GetServerVariable = &GetServerVariable; ecb->WriteClient = &WriteClient; ecb->ReadClient = &ReadClient; ecb->ServerSupportFunction = &ServerSupportFunction; /* All right... try and load the sucker */ retval = (*isapi_entry)(ecb); /* Set the status (for logging) */ if (ecb->dwHttpStatusCode) r->status = ecb->dwHttpStatusCode; /* Check for a log message - and log it */ if (ecb->lpszLogData && strcmp(ecb->lpszLogData, "")) ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, "ISAPI: %s: %s", ecb->lpszLogData, r->filename); /* Soak up any remaining input */ if (r->remaining > 0) { char argsbuffer[HUGE_STRING_LEN]; while (ap_get_client_block(r, argsbuffer, HUGE_STRING_LEN) > 0); } /* All done with the DLL... get rid of it */ if (isapi_term) (*isapi_term)(HSE_TERM_MUST_UNLOAD); ap_os_dso_unload(isapi_handle); switch(retval) { case 0: /* Strange, but MS isapi accepts this as success */ case HSE_STATUS_SUCCESS: case HSE_STATUS_SUCCESS_AND_KEEP_CONN: /* Ignore the keepalive stuff; Apache handles it just fine without * the ISA's "advice". */ if (cid->status) /* We have a special status to return */ return cid->status; return OK; case HSE_STATUS_PENDING: /* We don't support this */ if (LogNotSupported) ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, r, "ISAPI asynchronous I/O not supported: %s", r->filename); case HSE_STATUS_ERROR: default: return SERVER_ERROR; } }
BOOL WINAPI GetServerVariable (HCONN hConn, LPSTR lpszVariableName, LPVOID lpvBuffer, LPDWORD lpdwSizeofBuffer) { request_rec *r = ((isapi_cid *)hConn)->r; const char *result; DWORD len; if (!strcmp(lpszVariableName, "ALL_HTTP")) { /* lf delimited, colon split, comma seperated and * null terminated list of HTTP_ vars */ char **env = (char**) ap_table_elts(r->subprocess_env)->elts; int nelts = 2 * ap_table_elts(r->subprocess_env)->nelts; int i; for (len = 0, i = 0; i < nelts; i += 2) if (!strncmp(env[i], "HTTP_", 5)) len += strlen(env[i]) + strlen(env[i + 1]) + 2; if (*lpdwSizeofBuffer < len + 1) { *lpdwSizeofBuffer = len + 1; SetLastError(ERROR_INSUFFICIENT_BUFFER); return FALSE; } for (i = 0; i < nelts; i += 2) if (!strncmp(env[i], "HTTP_", 5)) { strcpy(lpvBuffer, env[i]); ((char*)lpvBuffer) += strlen(env[i]); *(((char*)lpvBuffer)++) = ':'; strcpy(lpvBuffer, env[i + 1]); ((char*)lpvBuffer) += strlen(env[i + 1]); *(((char*)lpvBuffer)++) = '\n'; } *(((char*)lpvBuffer)++) = '\0'; *lpdwSizeofBuffer = len; return TRUE; } if (!strcmp(lpszVariableName, "ALL_RAW")) { /* lf delimited, colon split, comma seperated and * null terminated list of the raw request header */ char **raw = (char**) ap_table_elts(r->headers_in)->elts; int nelts = 2 * ap_table_elts(r->headers_in)->nelts; int i; for (len = 0, i = 0; i < nelts; i += 2) len += strlen(raw[i]) + strlen(raw[i + 1]) + 2; if (*lpdwSizeofBuffer < len + 1) { *lpdwSizeofBuffer = len + 1; SetLastError(ERROR_INSUFFICIENT_BUFFER); return FALSE; } for (i = 0; i < nelts; i += 2) { strcpy(lpvBuffer, raw[i]); ((char*)lpvBuffer) += strlen(raw[i]); *(((char*)lpvBuffer)++) = ':'; *(((char*)lpvBuffer)++) = ' '; strcpy(lpvBuffer, raw[i + 1]); ((char*)lpvBuffer) += strlen(raw[i + 1]); *(((char*)lpvBuffer)++) = '\n'; i += 2; } *(((char*)lpvBuffer)++) = '\0'; *lpdwSizeofBuffer = len; return TRUE; } /* Not a special case */ result = ap_table_get(r->subprocess_env, lpszVariableName); if (result) { len = strlen(result); if (*lpdwSizeofBuffer < len + 1) { *lpdwSizeofBuffer = len + 1; SetLastError(ERROR_INSUFFICIENT_BUFFER); return FALSE; } strcpy(lpvBuffer, result); *lpdwSizeofBuffer = len; return TRUE; } /* Not Found */ SetLastError(ERROR_INVALID_INDEX); return FALSE; }
static int suphp_handler(request_rec *r) { suphp_conf *sconf; suphp_conf *dconf; #ifdef SUPHP_USE_USERGROUP char *ud_user = NULL; char *ud_group = NULL; int ud_success = 0; #endif struct stat finfo; int rv; char *auth_user = NULL; char *auth_pass = NULL; pool *p; BUFF *script_in, *script_out, *script_err; const char *handler; sconf = ap_get_module_config(r->server->module_config, &suphp_module); dconf = ap_get_module_config(r->per_dir_config, &suphp_module); p = r->main ? r->main->pool : r->pool; /* only handle request if mod_suphp is active for this handler */ /* check only first byte of value (second has to be \0) */ if (r->handler != NULL) { handler = r->handler; } else { handler = r->content_type; } if ((ap_table_get(dconf->handlers, handler) == NULL)) { if ((ap_table_get(sconf->handlers, handler) == NULL) || (*(ap_table_get(sconf->handlers, handler)) == '0')) { return DECLINED; } } else if (*(ap_table_get(dconf->handlers, handler)) == '0') { return DECLINED; } /* check if suPHP is enabled for this request */ if (((sconf->engine != SUPHP_ENGINE_ON) && (dconf->engine != SUPHP_ENGINE_ON)) || ((sconf->engine == SUPHP_ENGINE_ON) && (dconf->engine == SUPHP_ENGINE_OFF))) return DECLINED; /* check if file is existing and accessible */ rv = stat(ap_pstrdup(p, r->filename), &finfo); if (rv == 0) { ; /* do nothing */ } else if (errno == EACCES) { ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "access to %s denied", r->filename); return HTTP_FORBIDDEN; } else if (errno == ENOENT || errno == ENOTDIR) { ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "File does not exist: %s", r->filename); return HTTP_NOT_FOUND; } else { ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "could not get fileinfo: %s", r->filename); return HTTP_NOT_FOUND; } #ifdef SUPHP_USE_USERGROUP if ((sconf->target_user == NULL || sconf->target_group == NULL) && (dconf->target_user == NULL || dconf->target_group == NULL)) { /* Identify mod_userdir request As Apache 1.3 does not yet provide a clean way to see whether a request was handled by mod_userdir, we assume this is true for any request beginning with ~ */ int ud_success = 0; /* set to 1 on success */ if (!strncmp("/~", r->uri, 2)) { char *username = ap_pstrdup(r->pool, r->uri + 2); char *pos = strchr(username, '/'); if (pos) { *pos = 0; if (strlen(username)) { struct passwd *pw; struct group *gr; gid_t gid; char *grpname; if ((pw = getpwnam(username)) != NULL) { gid = pw->pw_gid; if ((gr = getgrgid(gid)) != NULL) { grpname = gr->gr_name; } else { if ((grpname = ap_palloc(r->pool, 16)) == NULL) { return HTTP_INTERNAL_SERVER_ERROR; } ap_snprintf(grpname, 16, "#%ld", (long) gid); } ud_user = username; ud_group = grpname; ud_success = 1; } } } } if (!ud_success) { /* This is not a userdir request and user/group are not set, so log the error and return */ ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "No user or group set - set suPHP_UserGroup"); return HTTP_INTERNAL_SERVER_ERROR; } } #endif /* SUPHP_USE_USERGROUP */ /* prepare environment for new process */ ap_add_common_vars(r); ap_add_cgi_vars(r); ap_table_unset(r->subprocess_env, "SUPHP_PHP_CONFIG"); ap_table_unset(r->subprocess_env, "SUPHP_AUTH_USER"); ap_table_unset(r->subprocess_env, "SUPHP_AUTH_PW"); #ifdef SUPHP_USE_USERGROUP ap_table_unset(r->subprocess_env, "SUPHP_USER"); ap_table_unset(r->subprocess_env, "SUPHP_GROUP"); ap_table_unset(r->subprocess_env, "SUPHP_USERDIR_USER"); ap_table_unset(r->subprocess_env, "SUPHP_USERDIR_GROUP"); #endif /* SUPHP_USE_USERGROUP */ if (dconf->php_config) { ap_table_set(r->subprocess_env, "SUPHP_PHP_CONFIG", dconf->php_config); } ap_table_set(r->subprocess_env, "SUPHP_HANDLER", handler); if (r->headers_in) { const char *auth; auth = ap_table_get(r->headers_in, "Authorization"); if (auth && auth[0] != 0 && strncmp(auth, "Basic ", 6) == 0) { char *user; char *pass; user = ap_pbase64decode(p, auth + 6); if (user) { pass = strchr(user, ':'); if (pass) { *pass++ = '\0'; auth_user = ap_pstrdup(p, user); auth_pass = ap_pstrdup(p, pass); } } } } if (auth_user && auth_pass) { ap_table_setn(r->subprocess_env, "SUPHP_AUTH_USER", auth_user); ap_table_setn(r->subprocess_env, "SUPHP_AUTH_PW", auth_pass); } #ifdef SUPHP_USE_USERGROUP if (dconf->target_user) { ap_table_set(r->subprocess_env, "SUPHP_USER", dconf->target_user); } else if (sconf->target_user) { ap_table_set(r->subprocess_env, "SUPHP_USER", sconf->target_user); } else { ap_table_set(r->subprocess_env, "SUPHP_USER", ud_user); } if (dconf->target_group) { ap_table_set(r->subprocess_env, "SUPHP_GROUP", dconf->target_group); } else if (sconf->target_group) { ap_table_set(r->subprocess_env, "SUPHP_GROUP", sconf->target_group); } else { ap_table_set(r->subprocess_env, "SUPHP_GROUP", ud_group); } if (ud_success) { ap_table_set(r->subprocess_env, "SUPHP_USERDIR_USER", ud_user); ap_table_set(r->subprocess_env, "SUPHP_USERDIR_GROUP", ud_group); } #endif /* SUPHP_USE_USERGROUP */ /* Fork child process */ if (!ap_bspawn_child(p, suphp_child, (void *) r, kill_after_timeout, &script_in, &script_out, &script_err)) { ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "couldn't spawn child process for: %s", r->filename); return HTTP_INTERNAL_SERVER_ERROR; } /* Transfer request body to script */ if ((rv = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR)) != OK) { /* Call failed, return status */ return rv; } if (ap_should_client_block(r)) { char buffer[HUGE_STRING_LEN]; int len_read; ap_hard_timeout("reading request body", r); while ((len_read = ap_get_client_block(r, buffer, HUGE_STRING_LEN)) > 0) { ap_reset_timeout(r); if (ap_bwrite(script_in, buffer, len_read) < len_read) { /* silly script stopped reading, soak up remaining message */ while (ap_get_client_block(r, buffer, HUGE_STRING_LEN) > 0) { /* dump it */ } break; } } ap_bflush(script_in); ap_kill_timeout(r); } ap_bclose(script_in); /* Transfer output from script to client */ if (script_out) { const char *location; char hbuffer[MAX_STRING_LEN]; char buffer[HUGE_STRING_LEN]; rv = ap_scan_script_header_err_buff(r, script_out, hbuffer); if (rv == HTTP_NOT_MODIFIED) { return rv; } else if (rv) { return HTTP_INTERNAL_SERVER_ERROR; } location = ap_table_get(r->headers_out, "Location"); if (location && r->status == 200) { /* Soak up all the script output */ ap_hard_timeout("reading from script", r); while (ap_bgets(buffer, HUGE_STRING_LEN, script_out) > 0) { continue; } ap_kill_timeout(r); ap_bclose(script_out); ap_bclose(script_err); if (location[0] == '/') { /* Redirect has always GET method */ r->method = ap_pstrdup(p, "GET"); r->method_number = M_GET; /* Remove Content-Length - redirect should not read * * request body */ ap_table_unset(r->headers_in, "Content-Length"); /* Do the redirect */ ap_internal_redirect_handler(location, r); return OK; } else { /* Script did not set status 302 - so it does not want * * to send its own body. Simply set redirect status */ return REDIRECT; } } /* Output headers and body */ ap_send_http_header(r); if (!r->header_only) { ap_send_fb(script_out, r); } ap_bclose(script_out); /* Errors have already been logged by child */ ap_bclose(script_err); } return OK; }
static int tora_handler( request_rec *r ) { mcontext ctx, *c = &ctx; if( strcmp(r->handler,"tora-handler") != 0) return DECLINED; // init context c->need_discard = false; c->is_multipart = false; c->headers_sent = false; c->is_form_post = false; c->r = r; c->post_data = NULL; c->xff = NULL; c->client_ip = NULL; c->p = NULL; c->r->content_type = "text/html"; config.hits++; // read post data { const char *ctype = ap_table_get(r->headers_in,"Content-Type"); ap_setup_client_block(r,REQUEST_CHUNKED_ERROR); if( ctype && strstr(ctype,"multipart/form-data") ) c->is_multipart = true; else if( ap_should_client_block(r) ) { int tlen = 0; c->post_data = (char*)malloc(config.max_post_size); while( true ) { int len = ap_get_client_block(r,c->post_data + tlen,config.max_post_size - tlen); if( len <= 0 ) break; tlen += len; } if( tlen >= config.max_post_size ) { discard_body(c); free(c->post_data); log_error(c,"Maximum POST data exceeded. Try using multipart encoding"); return OK; } c->post_data[tlen] = 0; c->post_data_size = tlen; c->is_form_post = ctype == NULL || (strstr(ctype,"urlencoded") != NULL); } } // init protocol { protocol_infos infos; request_rec *first = r; while( first->prev != NULL ) first = first->prev; infos.custom = c; infos.script = r->filename; infos.uri = first->uri; infos.hostname = r->hostname ? r->hostname : ""; if( config.proxy_mode ) { const char *xff = ap_table_get(r->headers_in,"X-Forwarded-For"); if( xff == NULL ) infos.client_ip = r->connection->remote_ip; else { char tmp; char *xend = (char*)xff + strlen(xff) - 1; while( xend > xff && *xend != ' ' && *xend != ',' ) xend--; c->client_ip = strdup(xend); infos.client_ip = c->client_ip; if( xend > xff && *xend == ' ' && xend[-1] == ',' ) xend--; tmp = *xend; *xend = 0; c->xff = strdup(xff); *xend = tmp; } } else infos.client_ip = inet_ntoa(REMOTE_ADDR(r->connection)); infos.http_method = r->method; infos.get_data = r->args; infos.post_data = c->post_data; infos.post_data_size = c->post_data_size; infos.content_type = ap_table_get(r->headers_in,"Content-Type"); infos.do_get_headers = do_get_headers; infos.do_get_params = do_get_params; infos.do_set_header = do_set_header; infos.do_set_return_code = do_set_return_code; infos.do_print = do_print; infos.do_flush = do_flush; infos.do_log = do_log; infos.do_stream_data = c->is_multipart ? do_stream_data : NULL; c->p = protocol_init(&infos); } // run protocol { int port = config.port_min + (config.hits % (1 + config.port_max - config.port_min)); if( !protocol_connect(c->p,config.host,port) || !protocol_send_request(c->p) || !protocol_read_answer(c->p) ) log_error(c,protocol_get_error(c->p)); } // cleanup protocol_free(c->p); free(c->xff); free(c->client_ip); free(c->post_data); send_headers(c); // in case... if( c->need_discard ) discard_body(c); return OK; }
static const char *log_env_var(request_rec *r, char *a) { return ap_table_get(r->subprocess_env, a); }
static int config_log_transaction(request_rec *r, config_log_state *cls, array_header *default_format) { log_format_item *items; char *str, *s; const char **strs; int *strl; request_rec *orig; int i; int len = 0; array_header *format; char *envar; if (cls->fname == NULL) { return DECLINED; } /* * See if we've got any conditional envariable-controlled logging decisions * to make. */ if (cls->condition_var != NULL) { envar = cls->condition_var; if (*envar != '!') { if (ap_table_get(r->subprocess_env, envar) == NULL) { return DECLINED; } } else { if (ap_table_get(r->subprocess_env, &envar[1]) != NULL) { return DECLINED; } } } format = cls->format ? cls->format : default_format; strs = ap_palloc(r->pool, sizeof(char *) * (format->nelts)); strl = ap_palloc(r->pool, sizeof(int) * (format->nelts)); items = (log_format_item *) format->elts; orig = r; while (orig->prev) { orig = orig->prev; } while (r->next) { r = r->next; } for (i = 0; i < format->nelts; ++i) { strs[i] = process_item(r, orig, &items[i]); } for (i = 0; i < format->nelts; ++i) { len += strl[i] = strlen(strs[i]); } #ifdef BUFFERED_LOGS if (len + cls->outcnt > LOG_BUFSIZE) { flush_log(cls); } if (len >= LOG_BUFSIZE) { str = ap_palloc(r->pool, len + 1); for (i = 0, s = str; i < format->nelts; ++i) { memcpy(s, strs[i], strl[i]); s += strl[i]; } write(cls->log_fd, str, len); } else { for (i = 0, s = &cls->outbuf[cls->outcnt]; i < format->nelts; ++i) { memcpy(s, strs[i], strl[i]); s += strl[i]; } cls->outcnt += len; } #else str = ap_palloc(r->pool, len + 1); for (i = 0, s = str; i < format->nelts; ++i) { memcpy(s, strs[i], strl[i]); s += strl[i]; } write(cls->log_fd, str, len); #endif return OK; }
static const char *log_note(request_rec *r, char *a) { return ap_table_get(r->notes, a); }
/* ==================================================================== * Here's the real content handler. * ==================================================================== */ static int content_handler(request_rec *r) { long length; wkcfg *cfg; WFILE* env_dict = NULL; int i; char msgbuf[MAX_STRING_LEN]; int conn_attempt = 0; WFILE* whole_dict = NULL; WFILE* int_dict = NULL; const char *value; const char *key; array_header *hdr_arr; table_entry *elts; cfg = ap_get_module_config(r->per_dir_config, &webkit_module); if (cfg == NULL) { log_debug("No cfg", r); cfg = (wkcfg*)wk_create_dir_config(r->pool, "/"); } env_dict = setup_WFILE(r); whole_dict = setup_WFILE(r); int_dict = setup_WFILE(r); if (env_dict == NULL || whole_dict == NULL) { log_error("Couldn't allocate Python data structures", r->server); return HTTP_INTERNAL_SERVER_ERROR; } ap_add_common_vars(r); ap_add_cgi_vars(r); /* not included in the common_vars above */ /* Build the environment dictionary */ hdr_arr = ap_table_elts(r->subprocess_env); elts = (table_entry *)hdr_arr->elts; /* start dictionary */ w_byte(TYPE_DICT, env_dict); for (i = 0; i < hdr_arr->nelts; ++i) { if (!elts[i].key) continue; key = elts[i].key; value = ap_table_get(r->subprocess_env, elts[i].key); write_string(key, env_dict); if (value != NULL) write_string(value, env_dict); else w_byte(TYPE_NONE, env_dict); } hdr_arr = cfg->passheaders; if (hdr_arr) { char **headers = (char **)hdr_arr->elts; for (i = 0; i < hdr_arr->nelts; i++) { key = headers[i]; value = ap_table_get(r->headers_in, key); if (value && *value) { write_string(key, env_dict); write_string(value, env_dict); } } } #ifdef SECURITY_HOLE_PASS_AUTHORIZATION /* Ordinarily Apache only makes the username available to CGI scripts, keeping the password secret. It can be configured to make the complete credential details available, but only by completely rebuilding the server with SECURITY_HOLE_PASS_AUTHORIZATION set (enabling this feature is considered a security risk). By setting the same constant, you can have mod_webkit pass the authorization information to WebKit instead. (suggested by Maximillian Dornseif 2003-10-27) */ key = "Authorization"; value = ap_table_get(r->headers_in, key); if (value && *value) { write_string("X-HTTP_AUTHORIZATION", env_dict); write_string(value, env_dict); } #endif w_byte(TYPE_NULL, env_dict); /* end dictionary */ log_debug("Built env dictionary", r); /* We can start building the full dictionary now */ w_byte(TYPE_DICT, whole_dict); write_string("format", whole_dict); /* key */ write_string("CGI", whole_dict); /* value */ write_string("time", whole_dict); /* key */ w_byte(TYPE_INT, whole_dict); /* value */ /* patch from Ken Lalonde to make the time entry useful */ w_long((long)r->request_time, whole_dict); /* value */ write_string("environ", whole_dict); /* key */ /* copy env_dict into whole_dict */ insert_data(whole_dict, env_dict); /* that should be it */ /* end dictionary */ w_byte(TYPE_NULL, whole_dict); length = whole_dict->ptr - whole_dict->str; write_integer((int)length, int_dict); /* now we try to send it */ for (conn_attempt = 1; conn_attempt <= cfg->retryattempts; conn_attempt++) { int result = transact_with_app_server(r, cfg, whole_dict, int_dict, length); if (result == 0) { return OK; } else if (result == 2) { log_error("error transacting with app server -- giving up.", r->server); return HTTP_INTERNAL_SERVER_ERROR; } sprintf(msgbuf, "Couldn't connect to AppServer, attempt %i of %i", conn_attempt, cfg->retryattempts); log_error(msgbuf, r->server); sleep(cfg->retrydelay); } log_error("error transacting with app server -- giving up.", r->server); return HTTP_INTERNAL_SERVER_ERROR; }
static const char *log_header_in(request_rec *r, char *a) { return ap_escape_logitem(r->pool, ap_table_get(r->headers_in, a)); }
/** get_client_header : name:string -> string? <doc>Get a HTTP header sent by the client</doc> **/ static value get_client_header( value s ) { mcontext *c = CONTEXT(); val_check(s,string); return alloc_string( ap_table_get(c->r->headers_in,val_string(s)) ); }
/** parse_multipart_data : onpart:function:2 -> ondata:function:3 -> void <doc> Incrementally parse the multipart data. call [onpart(name,filename)] for each part found and [ondata(buf,pos,len)] when some data is available </doc> **/ static value parse_multipart_data( value onpart, value ondata ) { value buf; int len = 0; mcontext *c = CONTEXT(); const char *ctype = ap_table_get(c->r->headers_in,"Content-Type"); value boundstr; val_check_function(onpart,2); val_check_function(ondata,3); buf = alloc_empty_string(BUFSIZE); if( !ctype || strstr(ctype,"multipart/form-data") == NULL ) return val_null; // extract boundary value { const char *boundary, *bend; if( (boundary = strstr(ctype,"boundary=")) == NULL ) neko_error(); boundary += 9; PARSE_HEADER(boundary,bend); len = (int)(bend - boundary); boundstr = alloc_empty_string(len+2); if( val_strlen(boundstr) > BUFSIZE / 2 ) neko_error(); val_string(boundstr)[0] = '-'; val_string(boundstr)[1] = '-'; memcpy(val_string(boundstr)+2,boundary,len); } len = 0; if( !ap_should_client_block(c->r) ) neko_error(); while( true ) { char *name, *end_name, *filename, *end_file_name, *data; int pos; // refill buffer // we assume here that the the whole multipart header can fit in the buffer fill_buffer(c,buf,&len); // is boundary at the beginning of buffer ? if( len < val_strlen(boundstr) || memcmp(val_string(buf),val_string(boundstr),val_strlen(boundstr)) != 0 ) return discard_body(c); name = memfind(val_string(buf),len,"Content-Disposition:"); if( name == NULL ) break; name = memfind(name,len - (int)(name - val_string(buf)),"name="); if( name == NULL ) return discard_body(c); name += 5; PARSE_HEADER(name,end_name); data = memfind(end_name,len - (int)(end_name - val_string(buf)),"\r\n\r\n"); if( data == NULL ) return discard_body(c); filename = memfind(name,(int)(data - name),"filename="); if( filename != NULL ) { filename += 9; PARSE_HEADER(filename,end_file_name); } data += 4; pos = (int)(data - val_string(buf)); // send part name val_call2(onpart,copy_string(name,(int)(end_name - name)),filename?copy_string(filename,(int)(end_file_name - filename)):val_null); // read data while( true ) { const char *boundary; // recall buffer memmove(val_string(buf),val_string(buf)+pos,len - pos); len -= pos; pos = 0; fill_buffer(c,buf,&len); // lookup bounds boundary = memfind(val_string(buf),len,val_string(boundstr)); if( boundary == NULL ) { if( len == 0 ) return discard_body(c); // send as much buffer as possible to client if( len < BUFSIZE ) pos = len; else pos = len - val_strlen(boundstr) + 1; val_call3(ondata,buf,alloc_int(0),alloc_int(pos)); } else { // send remaining data pos = (int)(boundary - val_string(buf)); val_call3(ondata,buf,alloc_int(0),alloc_int(pos-2)); // recall memmove(val_string(buf),val_string(buf)+pos,len - pos); len -= pos; break; } } } return val_null; }