util_script.c revision 3e520e9f095fbbcaa3c216c8ea56e89bd6fd58b4
842ae4bd224140319ae7feec1872b93dfd491143fielding/* Licensed to the Apache Software Foundation (ASF) under one or more
842ae4bd224140319ae7feec1872b93dfd491143fielding * contributor license agreements. See the NOTICE file distributed with
842ae4bd224140319ae7feec1872b93dfd491143fielding * this work for additional information regarding copyright ownership.
842ae4bd224140319ae7feec1872b93dfd491143fielding * The ASF licenses this file to You under the Apache License, Version 2.0
842ae4bd224140319ae7feec1872b93dfd491143fielding * (the "License"); you may not use this file except in compliance with
842ae4bd224140319ae7feec1872b93dfd491143fielding * the License. You may obtain a copy of the License at
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * Unless required by applicable law or agreed to in writing, software
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * distributed under the License is distributed on an "AS IS" BASIS,
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * See the License for the specific language governing permissions and
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * limitations under the License.
7d37dff338a52aa8836d78e4f1a67b76911da66caaron#include "http_request.h" /* for sub_req_lookup_uri() */
49f77954252489cd8f9037e1e2d79d16a7d6897fchrisd * Various utility functions which are common to a whole lot of
4567cfc6a65328bd3e8dd2b758ca926b389c7058brianp * script-type extensions mechanisms, and might as well be gathered
4567cfc6a65328bd3e8dd2b758ca926b389c7058brianp * in one place (if only to avoid creating inter-module dependancies
4567cfc6a65328bd3e8dd2b758ca926b389c7058brianp * where there don't have to be).
7d37dff338a52aa8836d78e4f1a67b76911da66caaron/* we know core's module_index is 0 */
7d37dff338a52aa8836d78e4f1a67b76911da66caaron char *res = (char *)apr_palloc(r->pool, sizeof("HTTP_") + strlen(w));
7d37dff338a52aa8836d78e4f1a67b76911da66caaron while ((c = *w++) != 0) {
4567cfc6a65328bd3e8dd2b758ca926b389c7058brianp else if (c == '-') {
7d37dff338a52aa8836d78e4f1a67b76911da66caaron "Not exporting header with invalid name as envvar: %s",
4567cfc6a65328bd3e8dd2b758ca926b389c7058brianpstatic void add_unless_null(apr_table_t *table, const char *name, const char *val)
4567cfc6a65328bd3e8dd2b758ca926b389c7058brianpstatic void env2env(apr_table_t *table, const char *name)
2abb2c210f1ddd7312ee86dd1d9e8486f4fff29cniqAP_DECLARE(char **) ap_create_environment(apr_pool_t *p, apr_table_t *t)
49f77954252489cd8f9037e1e2d79d16a7d6897fchrisd const apr_table_entry_t *elts = (const apr_table_entry_t *) env_arr->elts;
51ef69890746f3cb512c7b867d43425af928a816rpluem char **env = (char **) apr_palloc(p, (env_arr->nelts + 2) * sizeof(char *));
4567cfc6a65328bd3e8dd2b758ca926b389c7058brianp env[j] = apr_pstrcat(p, elts[i].key, "=", elts[i].val, NULL);
4567cfc6a65328bd3e8dd2b758ca926b389c7058brianp const char *env_temp;
377225a335b5bb47e12c2739cb902f53fd869a09brianp const apr_array_header_t *hdrs_arr = apr_table_elts(r->headers_in);
377225a335b5bb47e12c2739cb902f53fd869a09brianp const apr_table_entry_t *hdrs = (const apr_table_entry_t *) hdrs_arr->elts;
b44a707ac289d826620a65769db8074c96cb6a7erpluem /* use a temporary apr_table_t which we'll overlap onto
b44a707ac289d826620a65769db8074c96cb6a7erpluem * r->subprocess_env later
b44a707ac289d826620a65769db8074c96cb6a7erpluem * (exception: if r->subprocess_env is empty at the start,
b44a707ac289d826620a65769db8074c96cb6a7erpluem * write directly into it)
377225a335b5bb47e12c2739cb902f53fd869a09brianp /* First, add environment vars from headers... this is as per
377225a335b5bb47e12c2739cb902f53fd869a09brianp * CGI specs, though other sorts of scripting interfaces see
377225a335b5bb47e12c2739cb902f53fd869a09brianp * the same vars...
4567cfc6a65328bd3e8dd2b758ca926b389c7058brianp /* A few headers are special cased --- Authorization to prevent
4567cfc6a65328bd3e8dd2b758ca926b389c7058brianp * rogue scripts from capturing passwords; content-type and -length
4567cfc6a65328bd3e8dd2b758ca926b389c7058brianp * for no particular reason.
4567cfc6a65328bd3e8dd2b758ca926b389c7058brianp else if (!strcasecmp(hdrs[i].key, "Content-length")) {
7d37dff338a52aa8836d78e4f1a67b76911da66caaron * You really don't want to disable this check, since it leaves you
7d37dff338a52aa8836d78e4f1a67b76911da66caaron * wide open to CGIs stealing passwords and people viewing them
4567cfc6a65328bd3e8dd2b758ca926b389c7058brianp * in the environment with "ps -e". But, if you must...
4567cfc6a65328bd3e8dd2b758ca926b389c7058brianp || !strcasecmp(hdrs[i].key, "Proxy-Authorization")) {
c96beebb3d04691bf199a3b311d281a31f34c767chrisd add_unless_null(e, http2env(r, hdrs[i].key), hdrs[i].val);
4567cfc6a65328bd3e8dd2b758ca926b389c7058brianp apr_table_addn(e, "PATH", apr_pstrdup(r->pool, env_temp));
4567cfc6a65328bd3e8dd2b758ca926b389c7058brianp#if defined(WIN32)
7d37dff338a52aa8836d78e4f1a67b76911da66caaron /* HPUX PARISC 2.0W knows both, otherwise redundancy is harmless */
7d37dff338a52aa8836d78e4f1a67b76911da66caaron#else /* Some Unix */
e00ae6859667e293a4c40108f524408ae1289f2frbb apr_table_addn(e, "SERVER_SIGNATURE", ap_psignature("", r));
e00ae6859667e293a4c40108f524408ae1289f2frbb apr_table_addn(e, "SERVER_SOFTWARE", ap_get_server_banner());
e00ae6859667e293a4c40108f524408ae1289f2frbb ap_escape_html(r->pool, ap_get_server_name_for_url(r)));
e7c42c26f9d1f8bfdc703028801bb3daff2f982aaaron apr_table_addn(e, "SERVER_ADDR", r->connection->local_ip); /* Apache */
e00ae6859667e293a4c40108f524408ae1289f2frbb ap_get_remote_host(c, r->per_dir_config, REMOTE_HOST, NULL));
e7c42c26f9d1f8bfdc703028801bb3daff2f982aaaron apr_table_addn(e, "DOCUMENT_ROOT", ap_document_root(r)); /* Apache */
e00ae6859667e293a4c40108f524408ae1289f2frbb apr_table_addn(e, "CONTEXT_PREFIX", ap_context_prefix(r));
e00ae6859667e293a4c40108f524408ae1289f2frbb apr_table_addn(e, "CONTEXT_DOCUMENT_ROOT", ap_context_document_root(r));
d311f077fd868fef41b768dc2fbc0d31140c531ftrawick apr_table_addn(e, "SERVER_ADMIN", s->server_admin); /* Apache */
e00ae6859667e293a4c40108f524408ae1289f2frbb apr_table_addn(e, "SCRIPT_FILENAME", r->filename); /* Apache */
e00ae6859667e293a4c40108f524408ae1289f2frbb apr_table_addn(e, "REMOTE_PORT", apr_itoa(r->pool, rport));
64ff1949093e64474a00badd61a3495e35fa192daaron else if (r->prev) {
a322a82f79b790fb7ddcd7df4459d20725450fa7trawick apr_table_addn(e, "REMOTE_IDENT", apr_pstrdup(r->pool, env_temp));
a322a82f79b790fb7ddcd7df4459d20725450fa7trawick /* Apache custom error responses. If we have redirected set two new vars */
a322a82f79b790fb7ddcd7df4459d20725450fa7trawick add_unless_null(e, "REDIRECT_QUERY_STRING", r->prev->args);
e7c42c26f9d1f8bfdc703028801bb3daff2f982aaaron if (e != r->subprocess_env) {
8639a789ef8a4adec121d5b26b4d66c5cf8989ccjim apr_table_overlap(r->subprocess_env, e, APR_OVERLAP_TABLES_SET);
62775acdbd932f60b1fc4ceb306c4dfeabdb92a4rbb/* This "cute" little function comes about because the path info on
b1627fe7e2cb3809dcdfdf1fcbbb6dbccaf788c6rbb * filenames and URLs aren't always the same. So we take the two,
e00ae6859667e293a4c40108f524408ae1289f2frbb * and find as much of the two that match as possible.
a322a82f79b790fb7ddcd7df4459d20725450fa7trawickAP_DECLARE(int) ap_find_path_info(const char *uri, const char *path_info)
8639a789ef8a4adec121d5b26b4d66c5cf8989ccjim/* Obtain the Request-URI from the original request-line, returning
8639a789ef8a4adec121d5b26b4d66c5cf8989ccjim * a new string from the request pool containing the URI or "".
6a5bdbbacf4a62adecde52b8f23ebcc4fa2a08b8trawick apr_table_setn(e, "QUERY_STRING", r->args ? r->args : "");
e00ae6859667e293a4c40108f524408ae1289f2frbb /* Note that the code below special-cases scripts run from includes,
28c8f68d24d3511c87f7b3bd2841caa8c5621ee1brianp * because it "knows" that the sub_request has been hacked to have the
28c8f68d24d3511c87f7b3bd2841caa8c5621ee1brianp * args and path_info of the original request, and not any that may have
28c8f68d24d3511c87f7b3bd2841caa8c5621ee1brianp * come with the script URI in the include command. Ugh.
8639a789ef8a4adec121d5b26b4d66c5cf8989ccjim int path_info_start = ap_find_path_info(r->uri, r->path_info);
28c8f68d24d3511c87f7b3bd2841caa8c5621ee1brianp * To get PATH_TRANSLATED, treat PATH_INFO as a URI path.
28c8f68d24d3511c87f7b3bd2841caa8c5621ee1brianp * Need to re-escape it for this, since the entire URI was
39ec0caa195570eff38f6c2b0d022e7f45d56310rbb * un-escaped before we determined where the PATH_INFO began.
a322a82f79b790fb7ddcd7df4459d20725450fa7trawick pa_req = ap_sub_req_lookup_uri(ap_escape_uri(r->pool, r->path_info), r,
39ec0caa195570eff38f6c2b0d022e7f45d56310rbb char *pt = apr_pstrcat(r->pool, pa_req->filename, pa_req->path_info,
39ec0caa195570eff38f6c2b0d022e7f45d56310rbb /* We need to make this a real Windows path name */
39ec0caa195570eff38f6c2b0d022e7f45d56310rbb apr_filepath_merge(&pt, "", pt, APR_FILEPATH_NATIVE, r->pool);
e8f95a682820a599fe41b22977010636be5c2717jimstatic int set_cookie_doo_doo(void *v, const char *key, const char *val)
6a5bdbbacf4a62adecde52b8f23ebcc4fa2a08b8trawick#define SCRIPT_LOG_MARK __FILE__,__LINE__,module_index
int (*getsfunc) (char *, int, void *),
void *getsfunc_data,
int module_index)
char x[MAX_STRING_LEN];
if (buffer) {
if (rv == 0) {
if (first_header)
return HTTP_INTERNAL_SERVER_ERROR;
return HTTP_GATEWAY_TIME_OUT;
p = strlen(w);
return cond_status;
if (trace_log) {
if (first_header)
++maybeEBCDIC;
++maybeASCII;
r->filename);
if (!buffer) {
return HTTP_INTERNAL_SERVER_ERROR;
while (*l && apr_isspace(*l)) {
char *tmp;
first_header = 0;
return OK;
int (*getsfunc) (char *, int, void *),
void *getsfunc_data)
char *buffer)
int done = 0;
const char *bucket_data;
const char *src;
const char *src_end;
src++;
e = next;
*dst = 0;
char *buffer)
char *buffer,
int module_index)
struct vastrs {
int arg;
const char *curpos;
if (t > len)
t = len;
char *buffer,
int module_index,
const char **termch,
int *termarg, ...)
int res;
if (termch)
if (termarg)
return res;
char *buffer,
const char **termch,
int *termarg, ...)
int res;
if (termch)
if (termarg)
return res;
char *key;
char *value;
char *strtok_state;
while (key) {
if (value) {
*table = t;