/** * Fixup routine for request header processing. * * @params r The request record */ static apr_status_t replace_input_fixup(request_rec *r) { replace_server_t *conf = ap_get_module_config(r->server->module_config, &replace_module); replace_filter_t *filter = (replace_filter_t*)apr_hash_get(conf->h, REQUEST_REPLACE_FILTER, APR_HASH_KEY_STRING); header_replace_pattern_t *pattern; /* Exit if there is no filter definition. */ if (filter == NULL) { return DECLINED; } /* Loop the configured patterns */ for (pattern = filter->header_pattern; pattern != NULL; pattern = pattern->next) { apr_table_t *header_table = apr_table_make(r->pool, 2); header_replace_cb_t *hrcb = apr_palloc(r->pool, sizeof(header_replace_cb_t)); hrcb->header_table = header_table; hrcb->pattern = pattern->pattern; hrcb->extra = pattern->extra; hrcb->replacement = pattern->replacement; hrcb->r = r; apr_table_do(replace_header_cb, hrcb, r->headers_in, pattern->header, NULL); if (!apr_is_empty_table(header_table)) { apr_table_unset(r->headers_in, pattern->header); r->headers_in = apr_table_overlay(r->pool, r->headers_in, header_table); } } return OK; }
/** * Read a cookie called name, placing its value in val. * * Both the Cookie and Cookie2 headers are scanned for the cookie. * * If the cookie is duplicated, this function returns APR_EGENERAL. If found, * and if remove is non zero, the cookie will be removed from the headers, and * thus kept private from the backend. */ AP_DECLARE(apr_status_t) ap_cookie_read(request_rec * r, const char *name, const char **val, int remove) { ap_cookie_do v; v.r = r; v.encoded = NULL; v.new_cookies = apr_table_make(r->pool, 10); v.duplicated = 0; v.name = name; apr_table_do((int (*) (void *, const char *, const char *)) extract_cookie_line, (void *) &v, r->headers_in, "Cookie", "Cookie2", NULL); if (v.duplicated) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00011) LOG_PREFIX "client submitted cookie '%s' more than once: %s", v.name, r->uri); return APR_EGENERAL; } /* remove our cookie(s), and replace them */ if (remove) { apr_table_unset(r->headers_in, "Cookie"); apr_table_unset(r->headers_in, "Cookie2"); r->headers_in = apr_table_overlay(r->pool, r->headers_in, v.new_cookies); } *val = v.encoded; return APR_SUCCESS; }
static void *domaintree_merge_srv(apr_pool_t *p, void *old_cfg_ptr, void *new_cfg_ptr) { MDT_CNF *old_cfg = (MDT_CNF *) old_cfg_ptr, *new_cfg = (MDT_CNF *) new_cfg_ptr; MDT_CNF *DT = (MDT_CNF *) apr_palloc(p, sizeof(MDT_CNF)); DT->server = new_cfg->server; DT->enabled = IF_SET_ELSE(new_cfg->enabled, old_cfg->enabled); DT->stripwww = IF_SET_ELSE(new_cfg->stripwww, old_cfg->stripwww); DT->statroot = IF_SET_ELSE(new_cfg->statroot, old_cfg->statroot); DT->maxdepth = IF_SET_ELSE(new_cfg->maxdepth, old_cfg->maxdepth); DT->prefix = EMPTY(new_cfg->prefix) ? EMPTY(old_cfg->prefix) ? "/var/www" : old_cfg->prefix : new_cfg->prefix; DT->suffix = EMPTY(new_cfg->suffix) ? EMPTY(old_cfg->suffix) ? "public_html" : old_cfg->suffix : new_cfg->suffix; DT->ignore = apr_array_append(p, new_cfg->ignore, old_cfg->ignore); DT->forbid = apr_array_append(p, new_cfg->forbid, old_cfg->forbid); #ifdef HAVE_UNIX_SUEXEC DT->suexec = apr_array_append(p, new_cfg->suexec, old_cfg->suexec); #endif DT->aliases.recursion = IF_SET_ELSE(new_cfg->aliases.recursion, old_cfg->aliases.recursion); DT->aliases.faketable = apr_table_overlay(p, new_cfg->aliases.faketable, old_cfg->aliases.faketable); DT->dircache.clim = IF_SET_ELSE(new_cfg->dircache.clim, old_cfg->dircache.clim); DT->dircache.hmap = apr_hash_overlay(p, new_cfg->dircache.hmap, old_cfg->dircache.hmap); apr_global_mutex_create(&new_cfg->dircache.lock, __FILE__, APR_LOCK_DEFAULT, p); #if DBG fprintf(stderr, "MDT: cfg merge %p + %p = %p\n", old_cfg, new_cfg, DT); #endif return DT; }
static void *merge_config_log_state(apr_pool_t *p, void *basev, void *addv) { multi_log_state *base = (multi_log_state *) basev; multi_log_state *add = (multi_log_state *) addv; add->server_config_logs = base->config_logs; if (!add->default_format) { add->default_format_string = base->default_format_string; add->default_format = base->default_format; } add->formats = apr_table_overlay(p, base->formats, add->formats); return add; }
static int fixup_env_module(request_rec *r) { env_dir_config_rec *sconf = ap_get_module_config(r->per_dir_config, &env_module); if (apr_is_empty_table(sconf->vars)) { return DECLINED; } r->subprocess_env = apr_table_overlay(r->pool, r->subprocess_env, sconf->vars); return OK; }
static int fixup_env_module(request_rec *r) { apr_table_t *e = r->subprocess_env; env_dir_config_rec *sconf = ap_get_module_config(r->per_dir_config, &env_module); apr_table_t *vars = sconf->vars; if (!apr_table_elts(sconf->vars)->nelts) return DECLINED; r->subprocess_env = apr_table_overlay(r->pool, e, vars); return OK; }
static void accept_headers(cache_handle_t *h, request_rec *r) { apr_table_t *cookie_table; const char *v; v = apr_table_get(h->resp_hdrs, "Content-Type"); if (v) { ap_set_content_type(r, v); apr_table_unset(h->resp_hdrs, "Content-Type"); } /* If the cache gave us a Last-Modified header, we can't just * pass it on blindly because of restrictions on future values. */ v = apr_table_get(h->resp_hdrs, "Last-Modified"); if (v) { ap_update_mtime(r, apr_date_parse_http(v)); ap_set_last_modified(r); apr_table_unset(h->resp_hdrs, "Last-Modified"); } /* The HTTP specification says that it is legal to merge duplicate * headers into one. Some browsers that support Cookies don't like * merged headers and prefer that each Set-Cookie header is sent * separately. Lets humour those browsers by not merging. * Oh what a pain it is. */ cookie_table = apr_table_make(r->pool, 2); apr_table_do(set_cookie_doo_doo, cookie_table, r->err_headers_out, "Set-Cookie", NULL); apr_table_do(set_cookie_doo_doo, cookie_table, h->resp_hdrs, "Set-Cookie", NULL); apr_table_unset(r->err_headers_out, "Set-Cookie"); apr_table_unset(h->resp_hdrs, "Set-Cookie"); apr_table_overlap(r->headers_out, h->resp_hdrs, APR_OVERLAP_TABLES_SET); apr_table_overlap(r->err_headers_out, h->resp_err_hdrs, APR_OVERLAP_TABLES_SET); if (!apr_is_empty_table(cookie_table)) { r->err_headers_out = apr_table_overlay(r->pool, r->err_headers_out, cookie_table); } }
static int req_add_env_vars (lua_State *L) { request_rec *r = CHECK_REQUEST_OBJECT(1); int mode = luaL_checkoption(L, 2, "all", add_var_modes); if ((mode == 0 || mode == 3) && ap_find_module) { module* env_module = ap_find_module(r->server, "env_module"); if (env_module) { env_dir_config_rec *sconf = ap_get_module_config(r->per_dir_config, env_module); if (sconf && sconf->vars && apr_table_elts(sconf->vars)->nelts) { r->subprocess_env = apr_table_overlay(r->pool, r->subprocess_env, sconf->vars); } } } if (mode == 1 || mode == 3) ap_add_common_vars(r); if (mode == 2 || mode == 3) ap_add_cgi_vars(r); return 0; }
static apr_status_t store_headers(cache_handle_t *h, request_rec *r, cache_info *info) { disk_cache_conf *conf = ap_get_module_config(r->server->module_config, &disk_cache_module); apr_status_t rv; apr_size_t amt; disk_cache_object_t *dobj = (disk_cache_object_t*) h->cache_obj->vobj; disk_cache_info_t disk_info; struct iovec iov[2]; /* This is flaky... we need to manage the cache_info differently */ h->cache_obj->info = *info; if (r->headers_out) { const char *tmp; tmp = apr_table_get(r->headers_out, "Vary"); if (tmp) { apr_array_header_t* varray; apr_uint32_t format = VARY_FORMAT_VERSION; /* If we were initially opened as a vary format, rollback * that internal state for the moment so we can recreate the * vary format hints in the appropriate directory. */ if (dobj->prefix) { dobj->hdrsfile = dobj->prefix; dobj->prefix = NULL; } mkdir_structure(conf, dobj->hdrsfile, r->pool); rv = apr_file_mktemp(&dobj->tfd, dobj->tempfile, APR_CREATE | APR_WRITE | APR_BINARY | APR_EXCL, r->pool); if (rv != APR_SUCCESS) { return rv; } amt = sizeof(format); apr_file_write(dobj->tfd, &format, &amt); amt = sizeof(info->expire); apr_file_write(dobj->tfd, &info->expire, &amt); varray = apr_array_make(r->pool, 6, sizeof(char*)); tokens_to_array(r->pool, tmp, varray); store_array(dobj->tfd, varray); apr_file_close(dobj->tfd); dobj->tfd = NULL; rv = safe_file_rename(conf, dobj->tempfile, dobj->hdrsfile, r->pool); if (rv != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_WARNING, rv, r->server, "disk_cache: rename tempfile to varyfile failed: %s -> %s", dobj->tempfile, dobj->hdrsfile); apr_file_remove(dobj->tempfile, r->pool); return rv; } dobj->tempfile = apr_pstrcat(r->pool, conf->cache_root, AP_TEMPFILE, NULL); tmp = regen_key(r->pool, r->headers_in, varray, dobj->name); dobj->prefix = dobj->hdrsfile; dobj->hashfile = NULL; dobj->datafile = data_file(r->pool, conf, dobj, tmp); dobj->hdrsfile = header_file(r->pool, conf, dobj, tmp); } } rv = apr_file_mktemp(&dobj->hfd, dobj->tempfile, APR_CREATE | APR_WRITE | APR_BINARY | APR_BUFFERED | APR_EXCL, r->pool); if (rv != APR_SUCCESS) { return rv; } disk_info.format = DISK_FORMAT_VERSION; disk_info.date = info->date; disk_info.expire = info->expire; disk_info.entity_version = dobj->disk_info.entity_version++; disk_info.request_time = info->request_time; disk_info.response_time = info->response_time; disk_info.status = info->status; disk_info.name_len = strlen(dobj->name); iov[0].iov_base = (void*)&disk_info; iov[0].iov_len = sizeof(disk_cache_info_t); iov[1].iov_base = (void*)dobj->name; iov[1].iov_len = disk_info.name_len; rv = apr_file_writev(dobj->hfd, (const struct iovec *) &iov, 2, &amt); if (rv != APR_SUCCESS) { return rv; } if (r->headers_out) { apr_table_t *headers_out; headers_out = ap_cache_cacheable_hdrs_out(r->pool, r->headers_out, r->server); if (!apr_table_get(headers_out, "Content-Type") && r->content_type) { apr_table_setn(headers_out, "Content-Type", ap_make_content_type(r, r->content_type)); } headers_out = apr_table_overlay(r->pool, headers_out, r->err_headers_out); rv = store_table(dobj->hfd, headers_out); if (rv != APR_SUCCESS) { return rv; } } /* Parse the vary header and dump those fields from the headers_in. */ /* FIXME: Make call to the same thing cache_select calls to crack Vary. */ if (r->headers_in) { apr_table_t *headers_in; headers_in = ap_cache_cacheable_hdrs_out(r->pool, r->headers_in, r->server); rv = store_table(dobj->hfd, headers_in); if (rv != APR_SUCCESS) { return rv; } } apr_file_close(dobj->hfd); /* flush and close */ /* Remove old file with the same name. If remove fails, then * perhaps we need to create the directory tree where we are * about to write the new headers file. */ rv = apr_file_remove(dobj->hdrsfile, r->pool); if (rv != APR_SUCCESS) { mkdir_structure(conf, dobj->hdrsfile, r->pool); } rv = safe_file_rename(conf, dobj->tempfile, dobj->hdrsfile, r->pool); if (rv != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_WARNING, rv, r->server, "disk_cache: rename tempfile to hdrsfile failed: %s -> %s", dobj->tempfile, dobj->hdrsfile); apr_file_remove(dobj->tempfile, r->pool); return rv; } dobj->tempfile = apr_pstrcat(r->pool, conf->cache_root, AP_TEMPFILE, NULL); ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "disk_cache: Stored headers for URL %s", dobj->name); return APR_SUCCESS; }
static int pgasp_handler (request_rec * r) { char cursor_string[256]; pgasp_config* config = (pgasp_config*) ap_get_module_config(r->server->module_config, &pgasp_module ) ; pgasp_dir_config* dir_config = (pgasp_dir_config*) ap_get_module_config(r->per_dir_config, &pgasp_module ) ; apr_table_t * GET = NULL, *GETargs = NULL; apr_array_header_t * POST; PGconn * pgc; PGresult * pgr; int i, j, allowed_to_serve, filename_length = 0; int field_count, tuple_count; char * requested_file; char *basename; params_t params; /* PQexecParams doesn't seem to like zero-length strings, so we feed it a dummy */ const char * dummy_get = "nothing"; const char * dummy_user = "******"; const char * cursor_values[2] = { r -> args ? apr_pstrdup(r->pool, r -> args) : dummy_get, r->user ? r->user : dummy_user }; int cursor_value_lengths[2] = { strlen(cursor_values[0]), strlen(cursor_values[1]) }; int cursor_value_formats[2] = { 0, 0 }; if (!r -> handler || strcmp (r -> handler, "pgasp-handler") ) return DECLINED; if (!r -> method || (strcmp (r -> method, "GET") && strcmp (r -> method, "POST")) ) return DECLINED; if (config->is_enabled != true) return OK; /* pretending we have responded, may return DECLINED in the future */ requested_file = apr_pstrdup (r -> pool, r -> path_info /*filename*/); i = strlen(requested_file) - 1; while (i > 0) { if (requested_file[i] == '.') filename_length = i; if (requested_file[i] == '/') break; i--; } if (i >= 0) { requested_file += i+1; /* now pointing to foo.pgasp instead of /var/www/.../foo.pgasp */ if (filename_length > i) filename_length -= i+1; } allowed_to_serve = false; for (i = 0; i < config->allowed_count; i++) { if (!strcmp(config->allowed[i], requested_file)) { allowed_to_serve = true; break; } } if (config->allowed_count == 0) allowed_to_serve = true; if (!allowed_to_serve) { ap_set_content_type(r, "text/plain"); ap_rprintf(r, "Hello there\nThis is PGASP\nEnabled: %s\n", config->is_enabled ? "On" : "Off"); ap_rprintf(r, "Requested: %s\n", requested_file); ap_rprintf(r, "Allowed: %s\n", allowed_to_serve ? "Yes" : "No"); return OK; /* pretending we have served the file, may return HTTP_FORDIDDEN in the future */ } if (filename_length == 0) { basename = requested_file; } else { basename = apr_pstrndup(r->pool, requested_file, filename_length); } ap_args_to_table(r, &GETargs); if (OK != ap_parse_form_data(r, NULL, &POST, -1, (~((apr_size_t)0)))) { __(r->server, " ** ap_parse_form_data is NOT OK"); } GET = (NULL == GET) ? GETargs : apr_table_overlay(r->pool, GETargs, GET); // move all POST parameters into GET table { ap_form_pair_t *pair; char *buffer; apr_off_t len; apr_size_t size; while (NULL != (pair = apr_array_pop(POST))) { apr_brigade_length(pair->value, 1, &len); size = (apr_size_t) len; buffer = apr_palloc(r->pool, size + 1); apr_brigade_flatten(pair->value, buffer, &size); buffer[len] = 0; apr_table_setn(GET, apr_pstrdup(r->pool, pair->name), buffer); //should name and value be ap_unescape_url() -ed? // __(r->server, "POST[%s]: %s", pair->name, buffer); } } params.r = r; params.args = NULL; apr_table_do(tab_args, ¶ms, GET, NULL); params.args = apr_pstrcat(r->pool, "&", params.args, "&", NULL); cursor_values[0] = params.args; cursor_value_lengths[0] = strlen(cursor_values[0]); /* set response content type according to configuration or to default value */ ap_set_content_type(r, dir_config->content_type_set ? dir_config->content_type : "text/html"); /* now connecting to Postgres, getting function output, and printing it */ pgc = pgasp_pool_open (r->server); if (PQstatus(pgc) != CONNECTION_OK) { spit_pg_error ("connect"); pgasp_pool_close(r->server, pgc); return OK; } /* removing extention (.pgasp or other) from file name, and adding "f_" for function name, i.e. foo.pgasp becomes psp_foo() */ snprintf(cursor_string, sizeof(cursor_string), "select * from f_%s($1::varchar)", basename); /* passing GET as first (and only) parameter */ if (0 == PQsendQueryParams (pgc, cursor_string, 1, NULL, cursor_values, cursor_value_lengths, cursor_value_formats, 0)) { spit_pg_error ("sending async query with params"); return clean_up_connection(r->server); } if (0 == PQsetSingleRowMode(pgc)) { ap_log_error(APLOG_MARK, APLOG_WARNING, 0, r->server, "can not fall into single raw mode to fetch data"); } while (NULL != (pgr = PQgetResult(pgc))) { if (PQresultStatus(pgr) != PGRES_TUPLES_OK && PQresultStatus(pgr) != PGRES_SINGLE_TUPLE) { spit_pg_error ("fetch data"); return clean_up_connection(r->server); } /* the following counts and for-loop may seem excessive as it's just 1 row/1 field, but might need it in the future */ field_count = PQnfields(pgr); tuple_count = PQntuples(pgr); for (i = 0; i < tuple_count; i++) { for (j = 0; j < field_count; j++) ap_rprintf(r, "%s", PQgetvalue(pgr, i, j)); ap_rprintf(r, "\n"); } PQclear (pgr); } pgasp_pool_close(r->server, pgc); return OK; }
AP_DECLARE(int) ap_scan_script_header_err_core(request_rec *r, char *buffer, int (*getsfunc) (char *, int, void *), void *getsfunc_data) { char x[MAX_STRING_LEN]; char *w, *l; int p; int cgi_status = HTTP_UNSET; apr_table_t *merge; apr_table_t *cookie_table; if (buffer) { *buffer = '\0'; } w = buffer ? buffer : x; /* temporary place to hold headers to merge in later */ merge = apr_table_make(r->pool, 10); /* The HTTP specification says that it is legal to merge duplicate * headers into one. Some browsers that support Cookies don't like * merged headers and prefer that each Set-Cookie header is sent * separately. Lets humour those browsers by not merging. * Oh what a pain it is. */ cookie_table = apr_table_make(r->pool, 2); apr_table_do(set_cookie_doo_doo, cookie_table, r->err_headers_out, "Set-Cookie", NULL); while (1) { int rv = (*getsfunc) (w, MAX_STRING_LEN - 1, getsfunc_data); if (rv == 0) { ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_TOCLIENT, 0, r, "Premature end of script headers: %s", apr_filepath_name_get(r->filename)); return HTTP_INTERNAL_SERVER_ERROR; } else if (rv == -1) { ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_TOCLIENT, 0, r, "Script timed out before returning headers: %s", apr_filepath_name_get(r->filename)); return HTTP_GATEWAY_TIME_OUT; } /* Delete terminal (CR?)LF */ p = strlen(w); /* Indeed, the host's '\n': '\012' for UNIX; '\015' for MacOS; '\025' for OS/390 -- whatever the script generates. */ if (p > 0 && w[p - 1] == '\n') { if (p > 1 && w[p - 2] == CR) { w[p - 2] = '\0'; } else { w[p - 1] = '\0'; } } /* * If we've finished reading the headers, check to make sure any * HTTP/1.1 conditions are met. If so, we're done; normal processing * will handle the script's output. If not, just return the error. * The appropriate thing to do would be to send the script process a * SIGPIPE to let it know we're ignoring it, close the channel to the * script process, and *then* return the failed-to-meet-condition * error. Otherwise we'd be waiting for the script to finish * blithering before telling the client the output was no good. * However, we don't have the information to do that, so we have to * leave it to an upper layer. */ if (w[0] == '\0') { int cond_status = OK; /* PR#38070: This fails because it gets confused when a * CGI Status header overrides ap_meets_conditions. * * We can fix that by dropping ap_meets_conditions when * Status has been set. Since this is the only place * cgi_status gets used, let's test it explicitly. * * The alternative would be to ignore CGI Status when * ap_meets_conditions returns anything interesting. * That would be safer wrt HTTP, but would break CGI. */ if ((cgi_status == HTTP_UNSET) && (r->method_number == M_GET)) { cond_status = ap_meets_conditions(r); } apr_table_overlap(r->err_headers_out, merge, APR_OVERLAP_TABLES_MERGE); if (!apr_is_empty_table(cookie_table)) { /* the cookies have already been copied to the cookie_table */ apr_table_unset(r->err_headers_out, "Set-Cookie"); r->err_headers_out = apr_table_overlay(r->pool, r->err_headers_out, cookie_table); } return cond_status; } /* if we see a bogus header don't ignore it. Shout and scream */ #if APR_CHARSET_EBCDIC /* Chances are that we received an ASCII header text instead of * the expected EBCDIC header lines. Try to auto-detect: */ if (!(l = strchr(w, ':'))) { int maybeASCII = 0, maybeEBCDIC = 0; unsigned char *cp, native; apr_size_t inbytes_left, outbytes_left; for (cp = w; *cp != '\0'; ++cp) { native = apr_xlate_conv_byte(ap_hdrs_from_ascii, *cp); if (apr_isprint(*cp) && !apr_isprint(native)) ++maybeEBCDIC; if (!apr_isprint(*cp) && apr_isprint(native)) ++maybeASCII; } if (maybeASCII > maybeEBCDIC) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, "CGI Interface Error: Script headers apparently ASCII: (CGI = %s)", r->filename); inbytes_left = outbytes_left = cp - w; apr_xlate_conv_buffer(ap_hdrs_from_ascii, w, &inbytes_left, w, &outbytes_left); } } #endif /*APR_CHARSET_EBCDIC*/ if (!(l = strchr(w, ':'))) { char malformed[(sizeof MALFORMED_MESSAGE) + 1 + MALFORMED_HEADER_LENGTH_TO_SHOW]; strcpy(malformed, MALFORMED_MESSAGE); strncat(malformed, w, MALFORMED_HEADER_LENGTH_TO_SHOW); if (!buffer) { /* Soak up all the script output - may save an outright kill */ while ((*getsfunc) (w, MAX_STRING_LEN - 1, getsfunc_data)) { continue; } } ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_TOCLIENT, 0, r, "%s: %s", malformed, apr_filepath_name_get(r->filename)); return HTTP_INTERNAL_SERVER_ERROR; } *l++ = '\0'; while (*l && apr_isspace(*l)) { ++l; } if (!strcasecmp(w, "Content-type")) { char *tmp; /* Nuke trailing whitespace */ char *endp = l + strlen(l) - 1; while (endp > l && apr_isspace(*endp)) { *endp-- = '\0'; } tmp = apr_pstrdup(r->pool, l); ap_content_type_tolower(tmp); ap_set_content_type(r, tmp); } /* * If the script returned a specific status, that's what * we'll use - otherwise we assume 200 OK. */ else if (!strcasecmp(w, "Status")) { r->status = cgi_status = atoi(l); r->status_line = apr_pstrdup(r->pool, l); } else if (!strcasecmp(w, "Location")) { apr_table_set(r->headers_out, w, l); } else if (!strcasecmp(w, "Content-Length")) { apr_table_set(r->headers_out, w, l); } else if (!strcasecmp(w, "Content-Range")) { apr_table_set(r->headers_out, w, l); } else if (!strcasecmp(w, "Transfer-Encoding")) { apr_table_set(r->headers_out, w, l); } /* * If the script gave us a Last-Modified header, we can't just * pass it on blindly because of restrictions on future values. */ else if (!strcasecmp(w, "Last-Modified")) { ap_update_mtime(r, apr_date_parse_http(l)); ap_set_last_modified(r); } else if (!strcasecmp(w, "Set-Cookie")) { apr_table_add(cookie_table, w, l); } else { apr_table_add(merge, w, l); } } return OK; }
static int mod_vhost_ldap_translate_name(request_rec *r) { mod_vhost_ldap_request_t *reqc = NULL; mod_vhost_ldap_config_t *conf = (mod_vhost_ldap_config_t *)ap_get_module_config(r->server->module_config, &vhost_ldap_ng_module); #if (AP_SERVER_MAJORVERSION_NUMBER == 2) && (AP_SERVER_MINORVERSION_NUMBER <= 2) core_server_config *core = (core_server_config *)ap_get_module_config(r->server->module_config, &core_module); #endif LDAP *ld = NULL; char *realfile = NULL; char *myfilter = NULL; alias_t *alias = NULL, *cursor = NULL; int i = 0, ret = 0; apr_table_t *e; LDAPMessage *ldapmsg = NULL, *vhostentry = NULL; if (conf->enabled != MVL_ENABLED || !conf->url || !r->hostname){ ap_log_rerror(APLOG_MARK, APLOG_INFO|APLOG_NOERRNO, 0, r, "[mod_vhost_ldap_ng.c] Module disabled"); return DECLINED; } //Search in cache reqc = (mod_vhost_ldap_request_t *)get_from_requestscache(r); if(!reqc){ ap_log_rerror(APLOG_MARK, APLOG_INFO|APLOG_NOERRNO, 0, r, "[mod_vhost_ldap_ng.c] Cannot resolve data from cache"); reqc = apr_pcalloc(vhost_ldap_pool, sizeof(mod_vhost_ldap_request_t)); } if (reqc->expires < apr_time_now()){ //Search ldap //TODO: Create a function while((ret = ldapconnect(&ld, conf)) != 0 && i<2){ i++; ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r, "[mod_vhost_ldap_ng.c] ldapconnect: %s", ldap_err2string(ret)); } if(i == 2){ conf->enabled = MVL_DISABLED; return HTTP_GATEWAY_TIME_OUT; } myfilter = apr_psprintf(r->pool,"(&(%s)(|(apacheServerName=%s)(apacheServerAlias=%s)))", conf->filter, r->hostname, r->hostname); ret = ldap_search_s (ld, conf->basedn, conf->scope, myfilter, (char **)attributes, 0, &ldapmsg); if(ret != LDAP_SUCCESS){//SIGPIPE? return DECLINED; } if(ldap_count_entries(ld, ldapmsg)!=1){ if(!conf->fallback_name || !conf->fallback_docroot){ reqc->name = apr_pstrdup(vhost_ldap_pool, r->hostname); reqc->decline = 1; reqc->admin = apr_pstrdup(vhost_ldap_pool, r->server->server_admin); add_to_requestscache(reqc, r); if(ldapmsg) ldap_msgfree(ldapmsg); ldapdestroy(&ld); return DECLINED; }else{ reqc->name = conf->fallback_name; reqc->docroot = conf->fallback_docroot; } }else{ reqc->aliases = (apr_array_header_t *)apr_array_make(vhost_ldap_pool, 2, sizeof(alias_t)); reqc->redirects = (apr_array_header_t *)apr_array_make(vhost_ldap_pool, 2, sizeof(alias_t)); reqc->env = apr_table_make(vhost_ldap_pool, 2); vhostentry = ldap_first_entry(ld, ldapmsg); reqc->dn = ldap_get_dn(ld, vhostentry); i=0; while(attributes[i]){ int k = 0, j; char **eValues = ldap_get_values(ld, vhostentry, attributes[i]), *str[3]; if (eValues){ k = ldap_count_values (eValues); if (strcasecmp(attributes[i], "apacheServerName") == 0){ reqc->name = apr_pstrdup(vhost_ldap_pool, eValues[0]); }else if(strcasecmp(attributes[i], "apacheServerAdmin") == 0){ reqc->admin = apr_pstrdup(vhost_ldap_pool, eValues[0]); }else if(strcasecmp(attributes[i], "apacheDocumentRoot") == 0){ reqc->docroot = apr_pstrdup(vhost_ldap_pool, eValues[0]); /* Make it absolute, relative to ServerRoot */ if(conf->rootdir && (strncmp(reqc->docroot, "/", 1) != 0)) reqc->docroot = apr_pstrcat(vhost_ldap_pool, conf->rootdir, reqc->docroot, NULL); reqc->docroot = ap_server_root_relative(vhost_ldap_pool, reqc->docroot); }else if(strcasecmp(attributes[i], "apacheAlias") == 0){ while(k){ k--; for(j = 0; j < 2; j++) str[j] = ap_getword_conf(r->pool, (const char **)&eValues[k]); if(str[--j] == '\0') ap_log_rerror(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r, "[mod_vhost_ldap_ng.c]: Wrong apacheAlias parameter: %s", eValues[k]); else{ alias = apr_array_push(reqc->aliases); alias->src = apr_pstrdup(vhost_ldap_pool, str[0]); alias->dst = apr_pstrdup(vhost_ldap_pool, str[1]); } } }else if(strcasecmp(attributes[i], "apacheScriptAlias") == 0){ while(k){ k--; for(j = 0; j < 2; j++) str[j] = ap_getword_conf(r->pool, (const char **)&eValues[k]); if(str[--j] == '\0') ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, "[mod_vhost_ldap_ng.c]: Wrong apacheScriptAlias parameter: %s", eValues[k]); else{ alias = apr_array_push(reqc->aliases); alias->src = apr_pstrdup(vhost_ldap_pool, str[0]); alias->dst = apr_pstrdup(vhost_ldap_pool, str[1]); } } }else if(strcasecmp (attributes[i], "apacheRedirect") == 0){ while(k){ k--; for(j = 0; j < 3; j++) str[j] = ap_getword_conf(r->pool, (const char **)&eValues[k]); if(str[1] == '\0') ap_log_rerror(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r, "[mod_vhost_ldap_ng.c]: Missing apacheRedirect parameter: %s", eValues[k]); else{ alias = apr_array_push(reqc->redirects); alias->src = apr_pstrdup(vhost_ldap_pool, str[0]); if(str[2] != '\0'){ if(strcasecmp(str[1], "gone") == 0) alias->flags |= REDIR_GONE; else if (strcasecmp(str[1], "permanent") == 0) alias->flags |= REDIR_PERMANENT; else if (strcasecmp(str[1], "temp") == 0) alias->flags |= REDIR_TEMP; else if (strcasecmp(str[1], "seeother") == 0) alias->flags |= REDIR_SEEOTHER; else{ alias->flags |= REDIR_PERMANENT; ap_log_rerror(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r, "[mod_vhost_ldap_ng.c]: Wrong apacheRedirect type: %s", str[2]); } alias->dst = apr_pstrdup(vhost_ldap_pool, str[2]); }else alias->dst = apr_pstrdup(vhost_ldap_pool, str[1]); } } }else if(strcasecmp(attributes[i], "apacheSuexecUid") == 0){ reqc->uid = apr_pstrdup(vhost_ldap_pool, eValues[0]); }else if(strcasecmp(attributes[i], "apacheSuexecGid") == 0){ reqc->gid = apr_pstrdup(vhost_ldap_pool, eValues[0]); }else if(strcasecmp (attributes[i], "apacheErrorLog") == 0){ if(conf->rootdir && (strncmp(eValues[0], "/", 1) != 0)) r->server->error_fname = apr_pstrcat(vhost_ldap_pool, conf->rootdir, eValues[0], NULL); else r->server->error_fname = apr_pstrdup(vhost_ldap_pool, eValues[0]);; apr_file_open(&r->server->error_log, r->server->error_fname, APR_APPEND | APR_WRITE | APR_CREATE | APR_LARGEFILE, APR_OS_DEFAULT, r->pool); } #ifdef HAVEPHP else if(strcasecmp(attributes[i], "phpIncludePath") == 0){ if(conf->php_includepath) reqc->php_includepath = apr_pstrcat(vhost_ldap_pool, conf->php_includepath, ":", eValues[0], NULL); else reqc->php_includepath = apr_pstrdup(vhost_ldap_pool, eValues[0]); }else if(strcasecmp(attributes[i], "phpOpenBasedir") == 0){ if(conf->rootdir && (strncmp(eValues[0], "/", 1) != 0)) reqc->php_openbasedir = apr_pstrcat(vhost_ldap_pool, conf->rootdir, eValues[0], NULL); else reqc->php_openbasedir = apr_pstrdup(vhost_ldap_pool, eValues[0]); } else if(strcasecmp(attributes[i], "php_admin_value") == 0){ } #endif else if(strcasecmp(attributes[i], "SetEnv") == 0){ for(j = 0; j < 2; j++) str[j] = ap_getword_conf(r->pool, (const char **)&eValues[0]); if(str[--j] == '\0') ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, "[mod_vhost_ldap_ng.c]: Wrong apacheScriptAlias parameter: %s", eValues[0]); else{ apr_table_set(reqc->env, str[0], str[1]); } }else if(strcasecmp(attributes[i], "PassEnv") == 0){ } } i++; } } if(ldapmsg) ldap_msgfree(ldapmsg); ldapdestroy(&ld); add_to_requestscache(reqc, r); } if(reqc->decline) return DECLINED; ap_set_module_config(r->request_config, &vhost_ldap_ng_module, reqc); e = r->subprocess_env; if(apr_table_elts(reqc->env)->nelts) r->subprocess_env = apr_table_overlay(r->pool, e, reqc->env); #ifdef HAVEPHP char *openbasedir, *include; if(!reqc->php_includepath) include = apr_pstrcat(r->pool, conf->php_includepath, ":", reqc->docroot, NULL); else include = apr_pstrcat(r->pool, reqc->php_includepath, ":", conf->php_includepath, ":", reqc->docroot, NULL); zend_alter_ini_entry("include_path", strlen("include_path") + 1, (void *)include, strlen(include), PHP_INI_SYSTEM, PHP_INI_STAGE_RUNTIME); if(reqc->php_openbasedir){ openbasedir = apr_pstrcat(r->pool, reqc->php_openbasedir, ":", include, NULL); zend_alter_ini_entry("open_basedir", strlen("open_basedir") + 1, (void *)openbasedir, strlen(openbasedir), PHP_INI_SYSTEM, PHP_INI_STAGE_RUNTIME); } #endif if ((reqc->name == NULL)||(reqc->docroot == NULL)) { ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r, "[mod_vhost_ldap_ng.c] translate: " "translate failed; ServerName %s or DocumentRoot %s not defined", reqc->name, reqc->docroot); return HTTP_INTERNAL_SERVER_ERROR; } cursor = NULL; //From mod_alias: checking for redirects if(reqc->redirects){ cursor = (alias_t *)reqc->redirects->elts; if (r->uri[0] != '/' && r->uri[0] != '\0') return DECLINED; for(i = 0; i < reqc->redirects->nelts; i++){ alias = (alias_t *) &cursor[i]; if(alias_matches(r->uri, alias->src)){ apr_table_setn(r->headers_out, "Location", alias->dst); /* OLD STUFF if(alias->redir_status){ if (strcasecmp(alias->redir_status, "gone") == 0) return HTTP_GONE; else if (strcasecmp(alias->redir_status, "permanent") == 0) return HTTP_MOVED_PERMANENTLY; else if (strcasecmp(alias->redir_status, "temp") == 0) return HTTP_MOVED_TEMPORARILY; else if (strcasecmp(alias->redir_status, "seeother") == 0) return HTTP_SEE_OTHER; } */ if(alias->flags & REDIR_GONE) return HTTP_GONE; else if(alias->flags & REDIR_TEMP) return HTTP_MOVED_TEMPORARILY; else if(alias->flags & REDIR_SEEOTHER) return HTTP_SEE_OTHER; else return HTTP_MOVED_PERMANENTLY; } } } /* Checking for aliases */ if(reqc->aliases){ cursor = (alias_t *)reqc->aliases->elts; for(i = 0; reqc->aliases && i < reqc->aliases->nelts; i++){ alias = (alias_t *) &cursor[i]; if (alias_matches(r->uri, alias->src)) { /* Set exact filename for CGI script */ realfile = apr_pstrcat(r->pool, alias->dst, r->uri + strlen(alias->src), NULL); /* Add apacheRootDir config param IF realfile is a realative path*/ if(conf->rootdir && (strncmp(realfile, "/", 1) != 0)) realfile = apr_pstrcat(r->pool, conf->rootdir, "/", realfile, NULL); /* Let apache normalize the path */ if((realfile = ap_server_root_relative(r->pool, realfile))) { ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, "[mod_vhost_ldap_ng.c]: ap_document_root is: %s", ap_document_root(r)); r->filename = realfile; if(alias->flags & ISCGI){ //r->handler = "cgi-script"; r->handler = "Script"; apr_table_setn(r->notes, "alias-forced-type", r->handler); } return OK; } return OK; } else if (r->uri[0] == '/') { /* we don't set r->filename here, and let other modules do it * this allows other modules (mod_rewrite.c) to work as usual */ /* r->filename = apr_pstrcat (r->pool, reqc->docroot, r->uri, NULL); */ } else { /* We don't handle non-file requests here */ return DECLINED; } } } if ((r->server = apr_pmemdup(r->pool, r->server, sizeof(*r->server))) == NULL) { ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r, "[mod_vhost_ldap_ng.c] translate: " "translate failed; Unable to copy r->server structure"); return HTTP_INTERNAL_SERVER_ERROR; } r->server->server_hostname = apr_pstrdup(r->pool,reqc->name); if (reqc->admin) r->server->server_admin = apr_pstrdup(r->pool, reqc->admin); #if (AP_SERVER_MAJORVERSION_NUMBER == 2) && (AP_SERVER_MINORVERSION_NUMBER <= 2) core->ap_document_root = apr_pstrdup(r->pool, reqc->docroot); if (!ap_is_directory(r->pool, reqc->docroot)) ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "[mod_vhost_ldap_ng.c] set_document_root: Warning: DocumentRoot [%s] does not exist", core->ap_document_root); #else ap_set_document_root(r, reqc->docroot); #endif //ap_set_module_config(r->server->module_config, &core_module, core); /* Hack to allow post-processing by other modules (mod_rewrite, mod_alias) */ return DECLINED; }
static apr_status_t store_headers(cache_handle_t *h, request_rec *r, cache_info *info) { cache_object_t *obj = h->cache_obj; mem_cache_object_t *mobj = (mem_cache_object_t*) obj->vobj; apr_table_t *headers_out; /* * The cache needs to keep track of the following information: * - Date, LastMod, Version, ReqTime, RespTime, ContentLength * - The original request headers (for Vary) * - The original response headers (for returning with a cached response) * - The body of the message */ if (mobj->lock) { apr_thread_mutex_lock(mobj->lock); } mobj->req_hdrs = deep_table_copy(mobj->pool, r->headers_in); if (mobj->lock) { apr_thread_mutex_unlock(mobj->lock); } /* Precompute how much storage we need to hold the headers */ headers_out = apr_table_overlay(r->pool, r->headers_out, r->err_headers_out); headers_out = ap_cache_cacheable_hdrs_out(r->pool, headers_out, r->server); /* If not set in headers_out, set Content-Type */ if (!apr_table_get(headers_out, "Content-Type") && r->content_type) { apr_table_setn(headers_out, "Content-Type", ap_make_content_type(r, r->content_type)); } if (!apr_table_get(headers_out, "Content-Encoding") && r->content_encoding) { apr_table_setn(headers_out, "Content-Encoding", r->content_encoding); } if (mobj->lock) { apr_thread_mutex_lock(mobj->lock); } mobj->header_out = deep_table_copy(mobj->pool, headers_out); if (mobj->lock) { apr_thread_mutex_unlock(mobj->lock); } /* Init the info struct */ obj->info.status = info->status; if (info->date) { obj->info.date = info->date; } if (info->response_time) { obj->info.response_time = info->response_time; } if (info->request_time) { obj->info.request_time = info->request_time; } if (info->expire) { obj->info.expire = info->expire; } return APR_SUCCESS; }
/** * The output filter routine. This one gets called whenever a response is * generated that passes this filter. Returns APR_SUCCESS if everything works * out. * * @param f The filter definition. * @param bb The bucket brigade containing the data. */ static apr_status_t replace_output_filter(ap_filter_t *f, apr_bucket_brigade *bb) { request_rec *r = f->r; conn_rec *c = r->connection; replace_ctx_t *ctx = f->ctx; apr_bucket *b; apr_size_t len; const char *data; const char *header; apr_status_t rv; int re_vector[RE_VECTOR_SIZE]; // 3 elements per matched pattern replace_pattern_t *next; header_replace_pattern_t *next_header; int modified = 0; // flag to determine if a replacement has // occured. if (!ctx) { /* Initialize context */ ctx = apr_pcalloc(f->r->pool, sizeof(replace_ctx_t)); f->ctx = ctx; ctx->bb = apr_brigade_create(r->pool, c->bucket_alloc); } /* parse config settings */ /* look for the user-defined filter */ ctx->filter = find_filter_def(f->r->server, f->frec->name); if (!ctx->filter) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, f->r, "couldn't find definition of filter '%s'", f->frec->name); return APR_EINVAL; } ctx->p = f->r->pool; if (ctx->filter->intype && ctx->filter->intype != INTYPE_ALL) { if (!f->r->content_type) { ctx->noop = 1; } else { const char *ctypes = f->r->content_type; const char *ctype = ap_getword(f->r->pool, &ctypes, ';'); if (strcasecmp(ctx->filter->intype, ctype)) { /* wrong IMT for us; don't mess with the output */ ctx->noop = 1; } } } /* exit immediately if there are indications that the filter shouldn't be * executed. */ if (ctx->noop == 1) { ap_pass_brigade(f->next, bb); return APR_SUCCESS; } /** * Loop through the configured header patterns. */ for (next_header = ctx->filter->header_pattern; next_header != NULL; next_header = next_header->next) { // create a separate table with the requested HTTP header entries and // unset those headers in the original request. apr_table_t *header_table; header_table = apr_table_make(r->pool, 2); // create a data structure for the callback function header_replace_cb_t *hrcb; hrcb = apr_palloc(r->pool, sizeof(header_replace_cb_t)); hrcb->header_table = header_table; hrcb->pattern = next_header->pattern; hrcb->extra = next_header->extra; hrcb->replacement = next_header->replacement; hrcb->r = r; // pass any header that is defined to be processed to the callback // function and unset those headers in the original outgoing record. apr_table_do(replace_header_cb, hrcb, r->headers_out, next_header->header, NULL); // only touch the header if the changed header table is not empty. if (!apr_is_empty_table(header_table)) { apr_table_unset(r->headers_out, next_header->header); // overlay the original header table with the new one to reintegrate // the changed headers. r->headers_out = apr_table_overlay(r->pool, r->headers_out, header_table); } } /* Not nice but neccessary: Unset the ETag , because we cannot adjust the * value correctly, because we do not know how. */ apr_table_unset(f->r->headers_out, "ETag"); int eos = 0; // flag to check if an EOS bucket is in the brigade. apr_bucket *eos_bucket; // Backup for the EOS bucket. /* Interate through the available data. Stop if there is an EOS */ for (b = APR_BRIGADE_FIRST(bb); b != APR_BRIGADE_SENTINEL(bb); b = APR_BUCKET_NEXT(b)) { if (APR_BUCKET_IS_EOS(b)) { eos = 1; ap_save_brigade(f, &ctx->bb, &bb, ctx->p); APR_BUCKET_REMOVE(b); eos_bucket = b; break; } } /* If the iteration over the brigade hasn't found an EOS bucket, just save * the brigade and return. */ if (eos != 1) { ap_save_brigade(f, &ctx->bb, &bb, ctx->p); return APR_SUCCESS; } if ((rv = apr_brigade_pflatten(ctx->bb, (char **)&data, &len, ctx->p)) != APR_SUCCESS) { /* Return if the flattening didn't work. */ return rv; } else { /* Remove the original data from the bucket brigade. Otherwise it would * be passed twice (original data and the processed, flattened copy) to * the next filter. */ apr_brigade_cleanup(ctx->bb); } /* Good cast, we just tested len isn't negative or zero */ if (len > 0) { /* start checking for the regex's. */ for (next = ctx->filter->pattern; next != NULL; next = next->next) { int rc = 0; int offset = 0; /* loop through the configured patterns */ do { rc = pcre_exec(next->pattern, next->extra, data, len, offset, 0, re_vector, RE_VECTOR_SIZE); if (rc < 0 && rc != PCRE_ERROR_NOMATCH) { ap_log_rerror(APLOG_MARK, APLOG_ERR, rc, r, "Matching Error %d", rc); return rc; } /* This shouldn´t happen */ if (rc == 0) { ap_log_rerror(APLOG_MARK, APLOG_ERR, rc, r, "PCRE output vector too small (%d)", RE_VECTOR_SIZE/3-1); } /* If the result count is greater than 0 then there are * matches in the data string. Thus we try to replace those * strings with the user provided string. */ if (rc > 0) { char *prefix; // the string before the matching part. char *postfix; // the string after the matching part. char *newdata; // the concatenated string of prefix, // the replaced string and postfix. char *replacement; // the string with the data to replace // (after the subpattern processing has // been done). char *to_replace[10]; // the string array containing the // strings that are to be replaced. int match_diff; // the difference between the matching // string and its replacement. int x; // a simple counter. char *pos; // the starting position within the // replacement string, where there is a // subpattern to replace. /* start with building the replacement string */ replacement = apr_pstrcat(ctx->p, next->replacement, NULL); /* look for the subpatterns \0 to \9 */ for (x = 0; x < rc && x < 10; x++) { /* extract the x'ths subpattern */ to_replace[x] = substr(data, re_vector[x*2], re_vector[x*2+1] - re_vector[x*2], r); ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "Found match: %s", to_replace[x]); /* the token ( \0 to \9) we are looking for */ char *token = apr_pstrcat(ctx->p, "\\", apr_itoa(ctx->p, x), NULL); /* allocate memory for the replacement operation */ char *tmp; if (!to_replace[x] || strlen(to_replace[x]) < 2) { tmp = malloc(strlen(replacement) + 1); } else { tmp = malloc(strlen(replacement) - 1 + strlen(to_replace[x])); } /* copy the replacement string to the new * location. */ memcpy(tmp, replacement, strlen(replacement) + 1); replacement = tmp; /* try to replace each occurence of the token with * its matched subpattern. */ pos = ap_strstr(replacement, token); while (pos) { if (!to_replace[x]) { break; } substr_replace(pos, to_replace[x], strlen(pos), strlen(to_replace[x])); if (strlen(to_replace[x]) < 2) { tmp = malloc(strlen(replacement) + 1); } else { tmp = malloc(strlen(replacement) - 1 + strlen(to_replace[x])); } memcpy(tmp, replacement, strlen(replacement) + 1); /* clean up. */ free(replacement); replacement = tmp; pos = ap_strstr(replacement, token); } } match_diff = strlen(replacement) - (re_vector[1] - re_vector[0]); /* Allocate memory for a buffer to copy the first part * of the data string up to (but not including) the * the matching pattern. */ prefix = apr_pcalloc(ctx->p, re_vector[0] + 1); if (prefix == NULL) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Unable to allocate memory for prefix", NULL); return -1; } /* Copy the string from the offset (beginning of * pattern matching) to the first occurence of the * pattern and add a trailing \0. */ memcpy(prefix, data, (size_t)re_vector[0]); /* Copy the string from the end of the pattern to the * end of the data string itself. */ postfix = apr_pcalloc(ctx->p, len); if (postfix == NULL) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Unable to allocate memory for postfix", NULL); return -1; } memcpy(postfix, (data + re_vector[1]), len - re_vector[1]); /* Create the new data string, replace the old one * and clean up. */ newdata = apr_pstrcat(ctx->p, prefix, replacement, postfix, NULL); /* update the point of the data and free the allocated * memory for the replacement string. */ data = newdata; free(replacement); /* Calculate the new offset in the data string, where * the new matching round is to begin. */ offset = re_vector[1] + match_diff; len += match_diff; modified = 1; } } while (rc > 0); } /* Adjust the real length of the processed data. */ if (apr_table_get(f->r->headers_out, "Content-Length") != NULL) { apr_table_set(f->r->headers_out, "Content-Length", apr_itoa(ctx->p, len)); } /* If an Entity Tag is set, change the mtime and generate a new ETag.*/ if (apr_table_get(f->r->headers_out, "ETag") != NULL) { r->mtime = time(NULL); ap_set_etag(r); } } /* Create a new bucket with the processed data, insert that one into our * brigade, then insert the saved EOS bucket at the end of the brigade * and pass the brigade to the next filter. */ APR_BRIGADE_INSERT_TAIL(ctx->bb, apr_bucket_transient_create(data, len, apr_bucket_alloc_create(ctx->p))); APR_BRIGADE_INSERT_TAIL(ctx->bb, eos_bucket); ap_pass_brigade(f->next, ctx->bb); return APR_SUCCESS; }