#include "apr_buckets.h" #include "apr_strings.h" #include "ap_config.h" #include "util_filter.h" #include "httpd.h" #include "http_config.h" #include "http_request.h" #include "http_core.h" #include "http_protocol.h" #include "http_log.h" #include "http_main.h" #include "util_script.h" #include "http_core.h" module AP_MODULE_DECLARE_DATA hf_module; typedef struct header_footer_rec { const char *headerf; const char *headert; const char *footerf; const char *footert; } header_footer_rec; static const char *add_header_file(cmd_parms *cmd, void *dummy, const char *arg) { header_footer_rec *d = dummy; d->headerf = apr_pstrdup(cmd->pool, arg); return NULL; } static const char *add_footer_file(cmd_parms *cmd, void *dummy, const char *arg) { header_footer_rec *d = dummy; d->footerf = apr_pstrdup(cmd->pool, arg); return NULL; } static const char *add_header_text(cmd_parms *cmd, void *dummy, const char *arg) { header_footer_rec *d = dummy; d->headert = apr_pstrdup(cmd->pool, arg); return NULL; } static const char *add_footer_text(cmd_parms *cmd, void *dummy, const char *arg) { header_footer_rec *d = dummy; d->footert = apr_pstrdup(cmd->pool, arg); return NULL; } static const command_rec dir_cmds[] = { AP_INIT_TAKE1("FooterFile", add_footer_file, NULL, ACCESS_CONF || OR_FILEINFO, "a file name"), AP_INIT_TAKE1("HeaderFile", add_header_file, NULL, ACCESS_CONF || OR_FILEINFO, "a file name"), AP_INIT_TAKE1("FooterText", add_footer_text, NULL, ACCESS_CONF || OR_FILEINFO, "a file name"), AP_INIT_TAKE1("HeaderText", add_header_text, NULL, ACCESS_CONF || OR_FILEINFO, "a file name"), {NULL} }; static void *create_hf_config(apr_pool_t *p, char *dummy) { header_footer_rec *new = (header_footer_rec *) apr_pcalloc(p, sizeof(header_footer_rec)); new->headerf = NULL; new->headert = NULL; new->footerf = NULL; new->footert = NULL; return (void *) new; } typedef struct hf_struct { int state; } hf_struct; static int hf_filter(ap_filter_t *f, apr_bucket_brigade *bb) { hf_struct *ctx = f->ctx; header_footer_rec *conf; apr_bucket *e; conf = (header_footer_rec *) ap_get_module_config(f->r->per_dir_config, &hf_module); if (ctx == NULL) { f->ctx = ctx = apr_pcalloc(f->r->pool, sizeof(*ctx)); } if (ctx->state == 0) { ctx->state = 1; if (conf->headerf) { request_rec *rr; rr = ap_sub_req_lookup_uri(conf->headerf, f->r, f->next); if (rr->status == HTTP_OK) { ap_run_sub_req(rr); } } if (conf->headert) { e = apr_bucket_immortal_create(conf->headert, strlen(conf->headert)); APR_BRIGADE_INSERT_HEAD(bb, e); } } e = APR_BRIGADE_LAST(bb); if (APR_BUCKET_IS_EOS(e)) { apr_bucket_brigade *end; end = apr_brigade_split(bb, e); if (!APR_BRIGADE_EMPTY(bb)) { ap_pass_brigade(f->next, bb); } apr_brigade_destroy(bb); bb = end; if (conf->footerf) { request_rec *rr; rr = ap_sub_req_lookup_uri(conf->footerf, f->r, f->next); if (rr->status == HTTP_OK) { ap_run_sub_req(rr); } } if (conf->footert) { apr_bucket *foot; foot = apr_bucket_immortal_create(conf->footert, strlen(conf->footert)); APR_BUCKET_INSERT_BEFORE(e, foot); } } ap_pass_brigade(f->next, bb); return APR_SUCCESS; } static void hf_register_hook(apr_pool_t *p) { ap_register_output_filter("HEADERFOOTER", hf_filter, AP_FTYPE_CONTENT); } module AP_MODULE_DECLARE_DATA hf_module = { STANDARD20_MODULE_STUFF, create_hf_config, /* create per-directory config structure */ NULL, /* merge per-directory config structures */ NULL, /* create per-server config structure */ NULL, /* merge per-server config structures */ dir_cmds, /* command apr_table_t */ hf_register_hook /* register hooks */ };