1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
|
/*
** mod_relocate.c -- Log relocation hits
*/
#include "httpd.h"
#include "http_config.h"
#include "http_protocol.h"
#include "http_request.h"
#include "ap_config.h"
#include "http_log.h"
typedef struct {
char *hostname_key;
char *trigger;
} relocate_conf;
static void *create_dir_mconfig(pool *p, char *dir) {
relocate_conf *cfg;
cfg = ap_pcalloc(p, sizeof(relocate_conf));
cfg->hostname_key = ap_pstrdup(p, "_URL");
cfg->trigger = NULL;
return (void *) cfg;
}
module MODULE_VAR_EXPORT relocate_module;
static int include_virtual(request_rec *r, char *uri) {
int status = OK;
request_rec *subr;
/* Better safe then sorry */
ap_table_set(r->headers_in, "Content-Length", "0");
subr = (request_rec *) ap_sub_req_method_uri("GET", uri, r);
ap_table_set(subr->subprocess_env, "RELOCATE_SCRIPT_NAME", r->uri);
ap_table_set(subr->subprocess_env, "RELOCATE_PATH_INFO", r->path_info);
ap_table_set(subr->subprocess_env, "RELOCATE_QUERY_STRING", r->args);
status = ap_run_sub_req(subr);
ap_destroy_sub_req(subr);
return status;
}
const char *url_rebuild (request_rec *r, char *hostname_key) {
const char *data = NULL;
const char *key = NULL;
const char *url = NULL;
const char *returntosender = NULL;
int key_size = strlen(hostname_key);
data = ap_pstrdup(r->pool, r->args);
while(*data && (key = ap_getword(r->pool, &data, '&'))){
if(!strncmp(key, hostname_key, key_size)) {
(void)ap_getword(r->pool, &key, '=');
url = (char *)ap_pstrdup(r->pool, key);
} else {
if (returntosender) {
returntosender = ap_pstrcat(r->pool, returntosender, "&", key, NULL);
} else {
returntosender = ap_pstrdup(r->pool, key);
}
}
}
/* Now lets put her back together */
if(!url) {
return NULL;
}
if(returntosender) {
if(ap_rind(url, '?') != -1) {
return ap_pstrcat(r->pool, url, "&", returntosender, r->path_info, NULL);
}else {
return ap_pstrcat(r->pool, url, "?", returntosender, r->path_info, NULL);
}
} else {
if (r->path_info) {
return ap_pstrcat(r->pool, url, r->path_info, NULL);
} else {
return ap_pstrcat(r->pool, url, NULL);
}
}
}
static int relocate_handler(request_rec *r) {
const char *url;
int rc;
relocate_conf *cfg = (relocate_conf *)ap_get_module_config(r->per_dir_config, &relocate_module);
if (r->header_only)
return OK;
if(!(url = (const char *)url_rebuild(r, cfg->hostname_key))) {
return 404;
}
if (cfg->trigger) {
if((rc = include_virtual(r,cfg->trigger)) != OK) {
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, "The following error occured while processing trigger %s : %d", cfg->trigger, rc);
}
}
ap_table_set(r->headers_out, "Location", url);
return HTTP_MOVED_TEMPORARILY;
}
static const command_rec relocate_cmds[] = {
{"RelocatURLKey", ap_set_string_slot, (void *) XtOffsetOf(relocate_conf, hostname_key), OR_OPTIONS, TAKE1, "Enter a string which will override the default _URL key."},
{"RelocateTrigger", ap_set_string_slot, (void *) XtOffsetOf(relocate_conf, trigger), OR_OPTIONS, TAKE1, "Enter a uri which will be called whenever a relocation occurs."},
{NULL},
};
/* Dispatch list of content handlers */
static const handler_rec relocate_handlers[] = {
{ "relocate", relocate_handler },
{ NULL, NULL }
};
/* Dispatch list for API hooks */
module MODULE_VAR_EXPORT relocate_module = {
STANDARD_MODULE_STUFF,
NULL, /* module initializer */
create_dir_mconfig, /* create per-dir config structures */
NULL, /* merge per-dir config structures */
NULL, /* create per-server config structures */
NULL, /* merge per-server config structures */
relocate_cmds, /* table of config file commands */
relocate_handlers, /* [#8] MIME-typed-dispatched handlers */
NULL, /* [#1] URI to filename translation */
NULL, /* [#4] validate user id from request */
NULL, /* [#5] check if the user is ok _here_ */
NULL, /* [#3] check access by host address */
NULL, /* [#6] determine MIME type */
NULL, /* [#7] pre-run fixups */
NULL, /* [#9] log a transaction */
NULL, /* [#2] header parser */
NULL, /* child_init */
NULL, /* child_exit */
NULL /* [#0] post read-request */
};
|