/* ** mod_layout.c -- Apache layout module ** $Revision: 1.143 $ */ #include "mod_layout.h" #include "directives.h" static void *create_dir_mconfig(pool *p, char *dir) { /* So why -1, 0, and 1? You see, C lacks an arithmatic if. We need to know three states at any point. We need to know if something is unset, off or on. Hence we use these values. Apache already understands Off as 0 and 1 as on. */ layout_conf *cfg; cfg = ap_pcalloc(p, sizeof(layout_conf)); cfg->dir = ap_pstrdup(p, dir); cfg->replace_tags = UNSET; cfg->merge = UNSET; cfg->notes = UNSET; cfg->proxy = UNSET; cfg->comment = UNSET; cfg->append_header = UNSET; cfg->append_footer = UNSET; cfg->cache_needed = UNSET; cfg->display_origin = ON; cfg->header_enabled = UNSET; cfg->footer_enabled = UNSET; cfg->pattern_enabled = UNSET; cfg->http_header_enabled = UNSET; cfg->http_header = NULL; cfg->async_cache = LAYOUT_CACHE; cfg->begin_tag = LAYOUT_BEGINTAG; cfg->end_tag = LAYOUT_ENDTAG; cfg->async_post = OFF; cfg->time_format = LAYOUT_TIMEFORMAT; cfg->types = ap_make_table(p, 9); /* Doing default types was probably a bad idea */ cfg->uris_ignore = NULL; cfg->uris_ignore_header = NULL; cfg->uris_ignore_http_header = NULL; cfg->uris_ignore_footer = NULL; cfg->tag_ignore = NULL; cfg->tag_ignore_footer = NULL; cfg->tag_ignore_header = NULL; cfg->layouts = NULL; cfg->layout_html_handler = ON; ap_table_setn(cfg->types, INCLUDES_MAGIC_TYPE, "1"); ap_table_setn(cfg->types, INCLUDES_MAGIC_TYPE3, "1"); ap_table_setn(cfg->types, "server-parsed", "1"); ap_table_setn(cfg->types, "text/html", "1"); ap_table_setn(cfg->types, "text/plain", "1"); ap_table_setn(cfg->types, "perl-script", "1"); ap_table_setn(cfg->types, "cgi-script", "1"); ap_table_setn(cfg->types, "application/x-httpd-cgi", "1"); ap_table_setn(cfg->types, "application/x-httpd-php", "1"); ap_table_setn(cfg->types, "LayoutHandler application/x-httpd-php3", "1"); ap_table_setn(cfg->types, "LayoutHandler application/x-httpd-php3-source", "1"); return (void *) cfg; } static void *merge_dir_mconfig(pool *p, void *origin, void *new) { layout_conf *cfg = ap_pcalloc(p, sizeof(layout_conf)); layout_conf *cfg_origin = (layout_conf *)origin; layout_conf *cfg_new = (layout_conf *)new; cfg->dir = ap_pstrdup(p, cfg_new->dir); cfg->replace_tags = UNSET; cfg->merge = UNSET; cfg->notes = UNSET; cfg->proxy = UNSET; cfg->comment = UNSET; cfg->append_header = UNSET; cfg->append_footer = UNSET; cfg->cache_needed = UNSET; cfg->display_origin = ON; cfg->header_enabled = UNSET; cfg->footer_enabled = UNSET; cfg->pattern_enabled = UNSET; cfg->http_header_enabled = UNSET; cfg->http_header = NULL; cfg->time_format = LAYOUT_TIMEFORMAT; cfg->async_post = OFF; cfg->async_cache = LAYOUT_CACHE; cfg->begin_tag = LAYOUT_BEGINTAG; cfg->end_tag = LAYOUT_ENDTAG; cfg->uris_ignore_header = NULL; cfg->uris_ignore_http_header = NULL; cfg->uris_ignore_footer = NULL; cfg->tag_ignore = NULL; cfg->tag_ignore_footer = NULL; cfg->tag_ignore_header = NULL; cfg->layouts = NULL; cfg->layout_html_handler = ON; if (strcmp(cfg_new->async_cache, LAYOUT_CACHE)){ cfg->async_cache = ap_pstrdup(p, cfg_new->async_cache); } else if (strcmp(cfg_origin->async_cache, LAYOUT_CACHE)){ cfg->async_cache = ap_pstrdup(p, cfg_origin->async_cache); } if (strcmp(cfg_new->time_format, LAYOUT_TIMEFORMAT)){ cfg->time_format = ap_pstrdup(p, cfg_new->time_format); } else if (strcmp(cfg_origin->time_format, LAYOUT_TIMEFORMAT)){ cfg->time_format = ap_pstrdup(p, cfg_origin->time_format); } if (strcmp(cfg_new->begin_tag, LAYOUT_BEGINTAG)){ cfg->begin_tag = ap_pstrdup(p, cfg_new->begin_tag); } else if (strcmp(cfg_origin->begin_tag, LAYOUT_BEGINTAG)){ cfg->begin_tag = ap_pstrdup(p, cfg_origin->begin_tag); } if (strcmp(cfg_new->end_tag, LAYOUT_ENDTAG)){ cfg->end_tag = ap_pstrdup(p, cfg_new->end_tag); } else if (strcmp(cfg_origin->end_tag, LAYOUT_ENDTAG)){ cfg->end_tag = ap_pstrdup(p, cfg_origin->end_tag); } cfg->layout_html_handler = (cfg_new->layout_html_handler == OFF) ? OFF : cfg_origin->layout_html_handler; cfg->cache_needed = (cfg_new->cache_needed == UNSET) ? cfg_origin->cache_needed : cfg_new->cache_needed; cfg->proxy = (cfg_new->proxy == UNSET) ? cfg_origin->proxy : cfg_new->proxy; cfg->merge = (cfg_new->merge == UNSET) ? cfg_origin->merge : cfg_new->merge; cfg->notes = (cfg_new->notes == UNSET) ? cfg_origin->notes : cfg_new->notes; cfg->replace_tags = (cfg_new->replace_tags == UNSET) ? cfg_origin->replace_tags : cfg_new->replace_tags; cfg->comment = (cfg_new->comment == UNSET) ? cfg_origin->comment : cfg_new->comment; cfg->async_post = (cfg_new->async_post == UNSET) ? cfg_origin->async_post : cfg_new->async_post; cfg->display_origin = cfg_new->display_origin; cfg->append_header = (cfg_new->append_header == UNSET) ? cfg_origin->append_header : cfg_new->append_header; cfg->append_footer = (cfg_new->append_footer == UNSET) ? cfg_origin->append_footer : cfg_new->append_footer; if (isOn(cfg->append_header) || isOn(cfg->append_footer)) { if (isOn(cfg->append_header) && isOn(cfg->append_footer)) { if (cfg_origin->layouts) cfg->layouts = ap_append_arrays(p, cfg_origin->layouts, cfg_new->layouts); else cfg->layouts = cfg_new->layouts; cfg->header_enabled = cfg_new->header_enabled ? cfg_new->header_enabled : cfg_origin->header_enabled; cfg->footer_enabled = cfg_new->footer_enabled ? cfg_new->footer_enabled : cfg_origin->header_enabled; } else if (isOn(cfg->append_header)) { cfg->header_enabled = cfg_new->header_enabled ? cfg_new->header_enabled : cfg_origin->header_enabled; cfg->footer_enabled = cfg_new->footer_enabled; cfg->layouts = layout_array_push_kind(p, cfg_origin->layouts, cfg_new->layouts, HEADER); /* We now assume just append_footer */ } else { cfg->header_enabled = cfg_new->header_enabled; cfg->footer_enabled = cfg_new->footer_enabled ? cfg_new->footer_enabled : cfg_origin->header_enabled; cfg->layouts = layout_array_push_kind(p, cfg_origin->layouts, cfg_new->layouts, FOOTER); } } else { if (cfg_new->layouts){ cfg->layouts = cfg_new->layouts; cfg->header_enabled = cfg_new->header_enabled; cfg->footer_enabled = cfg_new->footer_enabled; cfg->pattern_enabled = cfg_new->pattern_enabled; } else { cfg->layouts = cfg_origin->layouts; cfg->header_enabled = cfg_origin->header_enabled; cfg->footer_enabled = cfg_origin->footer_enabled; cfg->pattern_enabled = cfg_origin->pattern_enabled; } } if (cfg_new->http_header_enabled == UNSET){ cfg->http_header = ap_pstrdup(p, cfg_origin->http_header); cfg->http_header_enabled = cfg_origin->http_header_enabled; } else if (isOn(cfg_new->http_header_enabled)){ cfg->http_header = ap_pstrdup(p, cfg_new->http_header); cfg->http_header_enabled = cfg_new->http_header_enabled; } else { cfg->http_header_enabled = OFF; } /* This is pretty simple */ cfg->types = cfg_new->types; if (cfg_origin->uris_ignore) { if (cfg_new->uris_ignore) { cfg->uris_ignore = ap_overlay_tables(p, cfg_new->uris_ignore, cfg_origin->uris_ignore); } else { cfg->uris_ignore = cfg_origin->uris_ignore; } } else { cfg->uris_ignore = cfg_new->uris_ignore; } if (cfg_origin->uris_ignore_header) { if (cfg_new->uris_ignore_header) { cfg->uris_ignore_header = ap_overlay_tables(p, cfg_new->uris_ignore_header, cfg_origin->uris_ignore_header); } else { cfg->uris_ignore_header = cfg_origin->uris_ignore_header; } } else { cfg->uris_ignore_header = cfg_new->uris_ignore_header; } if (cfg_origin->uris_ignore_http_header) { if (cfg_new->uris_ignore_http_header) { cfg->uris_ignore_http_header = ap_overlay_tables(p, cfg_new->uris_ignore_http_header, cfg_origin->uris_ignore_http_header); } else { cfg->uris_ignore_http_header = cfg_origin->uris_ignore_http_header; } } else { cfg->uris_ignore_http_header = cfg_new->uris_ignore_http_header; } if (cfg_origin->uris_ignore_footer) { if (cfg_new->uris_ignore_footer) { cfg->uris_ignore_footer = ap_overlay_tables(p, cfg_new->uris_ignore_footer, cfg_origin->uris_ignore_footer); } else { cfg->uris_ignore_footer = cfg_origin->uris_ignore_footer; } } else { cfg->uris_ignore_footer = cfg_new->uris_ignore_footer; } if (cfg_origin->tag_ignore) { if (cfg_new->tag_ignore) { cfg->tag_ignore = ap_overlay_tables(p, cfg_new->tag_ignore, cfg_origin->tag_ignore); } else { cfg->tag_ignore = cfg_origin->tag_ignore; } } else { cfg->tag_ignore = cfg_new->tag_ignore; } if (cfg_origin->tag_ignore_footer) { if (cfg_new->tag_ignore_footer) { cfg->tag_ignore_footer = ap_overlay_tables(p, cfg_new->tag_ignore_footer, cfg_origin->tag_ignore_footer); } else { cfg->tag_ignore_footer = cfg_origin->tag_ignore_footer; } } else { cfg->tag_ignore_footer = cfg_new->tag_ignore_footer; } if (cfg_origin->tag_ignore_header) { if (cfg_new->tag_ignore_header) { cfg->tag_ignore_header = ap_overlay_tables(p, cfg_new->tag_ignore_header, cfg_origin->tag_ignore_header); } else { cfg->tag_ignore_header = cfg_origin->tag_ignore_header; } } else { cfg->tag_ignore_header = cfg_new->tag_ignore_header; } #ifdef DEBUG printf("MERGED %d were from origin, %d were new, and %d came out the backend\n", cfg_origin->layouts->nelts, cfg_new->layouts->nelts, cfg->layouts->nelts); #endif return (void *) cfg; } static void layout_child_init(server_rec *s, pool *p) { if (s->keep_alive) { s->keep_alive = 0; } } static int layout_handler (request_rec * r) { int status; int pid = 0; layout_conf *cfg; char *filename_post = NULL; char *filename_body = NULL; struct stat sbuf; int start_position = 0; int text_handler = 0; int temp_fd = -1; BUFF *buff = NULL; BUFF *obuff = NULL; char *body = NULL; layout_request *info = NULL; mmap_data *map_data = NULL; if (r->main) { return DECLINED; } /* Since I keep finding that people want me to help debug, yet have their server only listing Apache. This of course came from the nice folks at PHP over a night of beers at a conference. */ ap_table_setn(r->headers_out, "X-Powered-By", "ModLayout/"VERSION); cfg = ap_get_module_config(r->per_dir_config, &layout_module); info = ap_get_module_config(r->request_config, &layout_module); #ifdef DEBUG printf("Handler Header:%d: Footer:%d: HTTPHeader:%d:\n", info->header, info->footer, info->http_header); #endif /* We used to do pid, but why bother when child_num works? */ pid = r->connection->child_num; /********************************************************************/ if (isOn(cfg->async_post) && info->length) { filename_post = ap_psprintf(r->pool, "%s/.mod_layout.post.%d",cfg->async_cache, pid); /* Now lets suck up some content */ if ((status = read_content(r, filename_post, info->length)) != OK) { ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, "mod_layout got an error while doing async post : %d", status); } /* Let us be paranoid about content length */ /* Should try to cut this out (one less stat) */ if (stat(filename_post, &sbuf)) { /* This would be very bad */ status = HTTP_INTERNAL_SERVER_ERROR; ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, r, "fstat blew chunks in mod_layout for file: %s", filename_post); } if ((status = get_fd_in(r, filename_post)) != OK) { ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, "mod_layout couldn't open a file descriptor for the post"); return status; } } /********************************************************************/ /* First, we get the original document */ if (isOn(info->origin)) { ap_rflush(r); if (isOn(cfg->layout_html_handler) && check_type(info)) { filename_body = r->filename; text_handler++; if ((temp_fd = ap_popenf(r->pool, filename_body,O_RDONLY,S_IRWXU)) < 0) { ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, "mod_layout couldn't open a file descriptor for : %s", filename_body); return HTTP_NOT_FOUND; } } else { buff = ap_bcreate(r->pool, B_RDWR); obuff = r->connection->client; buff->fd_in = dup(r->connection->client->fd_in); buff->incnt = r->connection->client->incnt; buff->inptr = r->connection->client->inptr; filename_body = ap_psprintf(r->pool, "%s/.mod_layout.body.%d",cfg->async_cache, getpid()); if ((status = get_fd_out(r, filename_body, buff)) != OK) { return status; } r->connection->client = buff; status = layout_origin(r, cfg, info); ap_bflush(buff); temp_fd = dup(buff->fd); //temp_fd = buff->fd; fsync(temp_fd); //buff->fd = -1; //buff->fd_in = -1; ap_bclose(buff); lseek(temp_fd, 0, SEEK_SET); r->connection->client = obuff; if (status != OK) { layout_send_file(r, filename_body); close(temp_fd); return status; } } ap_rflush(r); map_data = ap_pcalloc (r->pool, sizeof (mmap_data)); /* Dump the HTTP crap */ /* if (text_handler) { map_data->size = r->finfo.st_size; } else { */ (void)fstat(temp_fd, &sbuf); map_data->size = sbuf.st_size; // } body = mmap(NULL, map_data->size, PROT_READ, MAP_PRIVATE, temp_fd, 0); map_data->file = body; ap_register_cleanup(r->pool, map_data, cleanup_mmap, ap_null_cleanup); /********************************************************************/ /* Now, if someone has a CGI that is printing out HTTP header stuff for their entire site enter it here. This will always override a merge. If no http header has been created, we just send our own. */ /* No reason to not enable this for all types of connections */ /* We should check this before we scan headers */ if (is_ignored(r, cfg, info, body)) { //ap_send_mmap(map_data->file, r, 0, map_data->size); ap_rputs(body, r); close(temp_fd); return DONE; } if (!text_handler) { start_position = find_headers(r, body); if (start_position < 0) { start_position = 0; } } } #ifdef DEBUG printf("Start position is %d\n", start_position); #endif if (isOn(cfg->notes)) update_info(r->notes, info); if (info->http_header){ if ((status = call_container(r, cfg->http_header, cfg, info, 0)) != OK){ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, r, "The following error occured while processing the Layout HTTP Header : %d", status); } ap_rflush(r); } else { print_layout_headers(r, cfg); } ap_rflush(r); if (isOn(cfg->notes)) update_info(r->notes, info); /********************************************************************/ /* Welcome to the problem, lets patch this all back up */ if (isOn(info->merge) && info->origin) { #ifdef DEBUG printf("Merge Header:%d: Footer:%d: HTTPHeader:%d:\n", info->header, info->footer, info->http_header); #endif /* Look into using ap_send_mmap() -Brian */ if (isOn(info->origin)) { /* This code right here could be replaced and this would all be faster */ /* We have to make two passes through to make sure the headers always happen */ if (info->header && (string_search(r, body, cfg->begin_tag, start_position, 0) == -1)) { layout_kind(r, cfg, info, HEADER); } parser_put(r, cfg, info, body, start_position); if (info->footer && (string_search(r, body, cfg->end_tag, start_position, 0) == -1)) { layout_kind(r, cfg, info, FOOTER); } } else { layout_kind(r, cfg, info, HEADER); if (isOn(cfg->notes)) update_info(r->notes, info); layout_kind(r, cfg, info, LAYOUT); if (isOn(cfg->notes)) update_info(r->notes, info); layout_kind(r, cfg, info, FOOTER); } } else { /********************************************************************/ /* This is the original stream method */ /* Now we do headers if they exist */ if (info->header) { layout_kind(r, cfg, info, HEADER); } ap_rflush(r); if (isOn(cfg->notes)) update_info(r->notes, info); /********************************************************************/ /* Now we handle the orignal request. */ if (isOn(info->origin)) { //ap_send_mmap(map_data->file, r, start_position, map_data->size); ap_rputs(body + start_position, r); } ap_rflush(r); if (isOn(cfg->notes)) update_info(r->notes, info); /********************************************************************/ /* Now lets do the footer */ if (info->footer) { layout_kind(r, cfg, info, FOOTER); } ap_rflush(r); } close(temp_fd); return DONE; } static int layout_fixup(request_rec *r) { layout_conf *cfg = ap_get_module_config(r->per_dir_config, &layout_module); request_rec *subr; const char *type = NULL; int length; layout_request *info = NULL; /* Bug here, what about random layouts? */ if (isOff(cfg->footer_enabled) && isOff(cfg->header_enabled) && isOff(cfg->http_header_enabled) && isOff(cfg->pattern_enabled)) { return DECLINED; } if (r->main) { return DECLINED; } /* If this is a HEAD only, we really don't need to involve ourselves. */ if (r->header_only) { return DECLINED; } if (r->status == AUTH_REQUIRED) { return DECLINED; } /* Now, lets fix it if some goof has called a URL that should have had a / in it */ if (ap_is_directory(r->filename)) { if (r->uri[0] == '\0' || r->uri[strlen(r->uri) - 1] != '/') { /* Now at this point we know things are not going to go over well, so lets just let it all die in some module designed to take care of this sort of thing */ return DECLINED; } } /* So why switch to doing this? Somewhere since 1.3.6 something has changed about the way that CGI's are done. Not sure what it is, but this is now needed */ /* First, we check to see if this is SSI, mod_perl or cgi */ if (r->handler) { type = ap_pstrdup(r->pool, r->handler); } else { type = ap_pstrdup(r->pool, r->content_type); } #ifdef DEBUG printf("fixup Type %s: Handler %s: Content-Type %s\n", type, r->handler, r->content_type); #endif if (isOn(cfg->proxy) && r->proxyreq) { length = strlen(r->uri); /* Damn! Ok, here is the problem. If the request is for something which is and index how do we determine its mime type? Currently we just assume that it is a NULL and wrap it. This is far from perfect and is still pretty much a shot in the dark. More research needed. */ if (r->uri[length - 1] == '/' ) { type = "text/html"; } else { subr = (request_rec *) ap_sub_req_lookup_file(r->uri, r); type = ap_pstrdup(r->pool, subr->content_type); } } if (!table_find(cfg->types, type)) return DECLINED; /* Now lets look at the ignore logic */ /* This is where we finally decide what is going to happen */ if (cfg->uris_ignore) { if (table_find(cfg->uris_ignore, r->uri)) return DECLINED; } info = create_layout_request(r, cfg, type); if (isOff(info->header) && isOff(info->footer) && isOff(info->http_header)) { return DECLINED; } #ifdef DEBUG printf("Fixup Header:%d: Footer:%d: HTTPHeader:%d:\n", info->header, info->footer, info->http_header); #endif r->handler = "layout"; layout_headers(r, cfg, info); ap_set_module_config(r->request_config, &layout_module, info); return DECLINED; } /* Dispatch list of content handlers */ static const handler_rec layout_handlers[] = { {"layout", layout_handler}, {NULL} }; static void layout_init(server_rec * s, pool * p) { /* Tell apache we're here */ ap_add_version_component("mod_layout/"VERSION); } static const char *add_http_header(cmd_parms * cmd, void *mconfig, char *uri) { layout_conf *cfg = (layout_conf *) mconfig; cfg->http_header = ap_pstrdup(cmd->pool, uri); cfg->http_header_enabled = ON; return NULL; } static const char *add_layout_pattern(cmd_parms * cmd, void *mconfig, char *pattern, char *layout, char *mode) { layout_conf *cfg = (layout_conf *) mconfig; struct stat sbuf; const char *temp; layout_string *directive; #ifdef DEBUG printf("Trying to insert %s\n", pattern); #endif directive = ap_pcalloc (cmd->pool, sizeof (layout_string)); if (ap_ind(layout, ' ') != -1) { directive->comment = ap_pstrdup (cmd->pool, "Static Content"); directive->string = ap_pstrdup (cmd->pool, layout); directive->type = 1; } else if (stat(layout, &sbuf) == 0){ unless((temp = add_file(cmd, cfg, layout))) { return NULL; }; directive->comment = ap_pstrdup (cmd->pool, layout); directive->string = ap_pstrdup (cmd->pool, temp); directive->type = 1; } else { directive->comment = ap_pstrdup (cmd->pool, layout); directive->string = ap_pstrdup (cmd->pool, layout); directive->type = 0; if (cfg->cache_needed == UNSET) cfg->cache_needed = ON; } directive->pattern = ap_pstrdup (cmd->pool, pattern); unless(cfg->layouts) { cfg->layouts = ap_make_array (cmd->pool, 1, sizeof (layout_string *)); } unless(strcasecmp(cmd->cmd->name, "LayoutHeader")) { cfg->header_enabled = ON; directive->kind = HEADER; } else unless(strcasecmp(cmd->cmd->name, "LayoutFooter")) { cfg->footer_enabled = ON; directive->kind = FOOTER; } else { cfg->pattern_enabled = ON; directive->kind = LAYOUT; } if (mode) { unless(strcasecmp(mode, "append")) { directive->append = APPEND; } else unless(strcasecmp(mode, "prepend")) { directive->append = PREPEND; } else unless(strcasecmp(mode, "replace")) { directive->append = REPLACE; } else { ap_log_error (APLOG_MARK, APLOG_ERR, cmd->server, "The type %s is not valid for %s ",mode, cmd->cmd->name); directive->append = REPLACE; } } else { directive->append = REPLACE; } *(layout_string **) ap_push_array (cfg->layouts) = (layout_string *) directive; #ifdef DEBUG printf("ADDING LAYOUT:%s (%d) (%d)(%d)\n", directive->pattern, directive->append, directive->kind, cfg->layouts->nelts); #endif return NULL; } static const char *add_layout(cmd_parms * cmd, void *mconfig, char *layout) { layout_conf *cfg = (layout_conf *) mconfig; unless(strcasecmp(cmd->cmd->name, "LayoutHeader")) { (void)add_layout_pattern(cmd, mconfig, (char *)cfg->begin_tag, layout, "append"); } else unless(strcasecmp(cmd->cmd->name, "LayoutFooter")) { (void)add_layout_pattern(cmd, mconfig, (char *)cfg->end_tag, layout, "prepend"); } return NULL; } static const char *ignore_uri(cmd_parms * cmd, void *mconfig, char *uri) { layout_conf *cfg = (layout_conf *) mconfig; unless(cfg->uris_ignore) cfg->uris_ignore = ap_make_table(cmd->pool, 1); ap_table_setn(cfg->uris_ignore, uri, "1"); return NULL; } static const char *ignore_header_uri(cmd_parms * cmd, void *mconfig, char *uri) { layout_conf *cfg = (layout_conf *) mconfig; unless(cfg->uris_ignore_header) cfg->uris_ignore_header = ap_make_table(cmd->pool, 1); ap_table_setn(cfg->uris_ignore_header, uri, "1"); return NULL; } static const char *ignore_http_header_uri(cmd_parms * cmd, void *mconfig, char *uri) { layout_conf *cfg = (layout_conf *) mconfig; unless(cfg->uris_ignore_http_header) cfg->uris_ignore_http_header = ap_make_table(cmd->pool, 1); ap_table_setn(cfg->uris_ignore_http_header, uri, "1"); return NULL; } static const char *ignore_footer_uri(cmd_parms * cmd, void *mconfig, char *uri) { layout_conf *cfg = (layout_conf *) mconfig; unless(cfg->uris_ignore_footer) cfg->uris_ignore_footer = ap_make_table(cmd->pool, 1); ap_table_setn(cfg->uris_ignore_footer, uri, "1"); return NULL; } static const char *add_type(cmd_parms * cmd, void *mconfig, char *type) { layout_conf *cfg = (layout_conf *) mconfig; ap_table_setn(cfg->types, type, "1"); return NULL; } static const char *tag_ignore_add(cmd_parms * cmd, void *mconfig, char *type) { layout_conf *cfg = (layout_conf *) mconfig; unless(cfg->tag_ignore) cfg->tag_ignore = ap_make_table(cmd->pool, 1); ap_table_setn(cfg->tag_ignore, type, "1"); return NULL; } static const char *tag_ignore_footer_add(cmd_parms * cmd, void *mconfig, char *type) { layout_conf *cfg = (layout_conf *) mconfig; unless(cfg->tag_ignore_footer) cfg->tag_ignore_footer = ap_make_table(cmd->pool, 1); ap_table_setn(cfg->tag_ignore_footer, type, "1"); return NULL; } static const char *tag_ignore_header_add(cmd_parms * cmd, void *mconfig, char *type) { layout_conf *cfg = (layout_conf *) mconfig; unless(cfg->tag_ignore_header) cfg->tag_ignore_header = ap_make_table(cmd->pool, 1); ap_table_setn(cfg->tag_ignore_header, type, "1"); return NULL; } static const char *merge_add(cmd_parms * cmd, void *mconfig, int flag) { layout_conf *cfg = (layout_conf *) mconfig; cfg->merge = flag; cfg->display_origin = ON; return NULL; } static const char *footer_off(cmd_parms * cmd, void *mconfig) { layout_conf *cfg = (layout_conf *) mconfig; cfg->footer_enabled = OFF; return NULL; } static const char *header_off(cmd_parms * cmd, void *mconfig) { layout_conf *cfg = (layout_conf *) mconfig; cfg->header_enabled = OFF; return NULL; } static const char *http_header_off(cmd_parms * cmd, void *mconfig) { layout_conf *cfg = (layout_conf *) mconfig; cfg->http_header = NULL; cfg->http_header_enabled = OFF; return NULL; } static const char *append_layouts(cmd_parms * cmd, void *mconfig, int flag) { layout_conf *cfg = (layout_conf *) mconfig; cfg->append_header = flag; cfg->append_footer = flag; return NULL; } static const char *remove_default_types(cmd_parms * cmd, void *mconfig, int flag) { layout_conf *cfg = (layout_conf *) mconfig; if (flag) return NULL; ap_table_setn(cfg->types, INCLUDES_MAGIC_TYPE, "0"); ap_table_setn(cfg->types, INCLUDES_MAGIC_TYPE3, "0"); ap_table_setn(cfg->types, "server-parsed", "0"); ap_table_setn(cfg->types, "text/html", "0"); ap_table_setn(cfg->types, "text/plain", "0"); ap_table_setn(cfg->types, "perl-script", "0"); ap_table_setn(cfg->types, "application/x-httpd-php", "0"); ap_table_setn(cfg->types, "application/x-httpd-php3", "0"); ap_table_setn(cfg->types, "application/x-httpd-php-source", "0"); ap_table_setn(cfg->types, "cgi-script", "0"); ap_table_setn(cfg->types, "application/x-httpd-cgi", "0"); return NULL; } static const command_rec layout_cmds[] = { {"Layout", add_layout_pattern, NULL, OR_ALL, TAKE23, Layout}, {"LayoutHeader", add_layout, NULL, OR_ALL, TAKE1, LayoutHeader}, {"LayoutFooter", add_layout, NULL, OR_ALL, TAKE1, LayoutFooter}, {"LayoutAppend", append_layouts, NULL, OR_ALL, FLAG, LayoutAppend}, {"LayoutAppendHeader", ap_set_flag_slot, (void *) XtOffsetOf(layout_conf, append_header), OR_ALL, FLAG, LayoutHeaderAppend}, {"LayoutAppendFooter", ap_set_flag_slot, (void *) XtOffsetOf(layout_conf, append_header), OR_ALL, FLAG, LayoutFooterAppend}, {"LayoutHandler", add_type, NULL, OR_ALL, TAKE1, LayoutHandler}, {"LayoutIgnoreURI", ignore_uri, NULL, OR_ALL, TAKE1, LayoutIgnoreURI}, {"LayoutIgnoreHeaderURI", ignore_header_uri, NULL, OR_ALL, TAKE1, LayoutIgnoreHeaderURI}, {"LayoutIgnoreHTTPHeaderURI", ignore_http_header_uri, NULL, OR_ALL, TAKE1, LayoutIgnoreHTTPHeaderURI}, {"LayoutIgnoreFooterURI", ignore_footer_uri, NULL, OR_ALL, TAKE1, LayoutIgnoreFooterURI}, {"LayoutComment", ap_set_flag_slot, (void *) XtOffsetOf(layout_conf, comment), OR_ALL, FLAG, LayoutComment}, {"LayoutProxy", ap_set_flag_slot, (void *) XtOffsetOf(layout_conf, proxy), OR_ALL, FLAG, LayoutProxy}, {"LayoutDisplayOriginal", ap_set_flag_slot, (void *) XtOffsetOf(layout_conf, display_origin), OR_ALL, FLAG, LayoutDisplayOriginal}, {"LayoutDefaultHandlers", remove_default_types, NULL, OR_ALL, FLAG, LayoutDefaultHandlers}, {"LayoutTimeFormat", ap_set_string_slot, (void *) XtOffsetOf(layout_conf, time_format), OR_ALL, TAKE1, LayoutTimeFormat}, {"LayoutHTTPHeader", add_http_header, NULL, OR_ALL, TAKE1, LayoutHTTPHeader}, {"LayoutIgnoreTag", tag_ignore_add, NULL, OR_ALL, TAKE1, LayoutIgnoreTag}, {"LayoutIgnoreTagFooter", tag_ignore_footer_add, NULL, OR_ALL, TAKE1, LayoutIgnoreTagFooter}, {"LayoutIgnoreTagHeader", tag_ignore_header_add, NULL, OR_ALL, TAKE1, LayoutIgnoreTagHeader}, {"LayoutFooterOff", footer_off, NULL , OR_ALL, NO_ARGS, LayoutFooterOff}, {"LayoutHeaderOff", header_off, NULL, OR_ALL, NO_ARGS, LayoutHeaderOff}, {"LayoutHTTPHeaderOff", http_header_off, NULL, OR_ALL, NO_ARGS, LayoutHTTPHeaderOff}, {"LayoutPostAsync", ap_set_flag_slot, (void *) XtOffsetOf(layout_conf, async_post), OR_ALL, FLAG, LayoutPostAsync}, {"LayoutCacheNeeded", ap_set_flag_slot, (void *) XtOffsetOf(layout_conf, cache_needed), OR_ALL, FLAG, LayoutCacheNeeded}, {"LayoutCache", ap_set_string_slot, (void *) XtOffsetOf(layout_conf, async_cache), OR_ALL, TAKE1, LayoutCache}, {"LayoutMerge", merge_add, NULL, OR_ALL, FLAG, LayoutMerge}, {"LayoutMergeBeginTag", ap_set_string_slot, (void *) XtOffsetOf(layout_conf, begin_tag), OR_ALL, TAKE1, LayoutMergeBeginTag}, {"LayoutMergeEndTag", ap_set_string_slot, (void *) XtOffsetOf(layout_conf, end_tag), OR_ALL, TAKE1, LayoutMergeEndTag}, {"LayoutHTMLHandler", ap_set_flag_slot, (void *) XtOffsetOf(layout_conf, layout_html_handler), OR_ALL, FLAG, LayoutHTMLHandler}, {"LayoutReplaceTags", ap_set_flag_slot, (void *) XtOffsetOf(layout_conf, replace_tags), OR_ALL, FLAG, LayoutReplaceTags}, {"LayoutNotes", ap_set_flag_slot, (void *) XtOffsetOf(layout_conf, notes), OR_ALL, FLAG, LayoutNotes}, {NULL}, }; /* Dispatch list for API hooks */ module MODULE_VAR_EXPORT layout_module = { STANDARD_MODULE_STUFF, layout_init, /* module initializer */ create_dir_mconfig, /* create per-dir config structures */ merge_dir_mconfig, /* merge per-dir config structures */ NULL, /* create per-server config structures */ NULL, /* merge per-server config structures */ layout_cmds, /* table of config file commands */ layout_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 */ layout_fixup, /* [#7] pre-run fixups */ NULL, /* [#9] log a transaction */ NULL, /* [#2] header parser */ layout_child_init, /* child_init */ NULL, /* child_exit */ NULL /* [#0] post read-request */ #ifdef EAPI ,NULL, /* EAPI: add_module */ NULL, /* EAPI: remove_module */ NULL, /* EAPI: rewrite_command */ NULL /* EAPI: new_connection */ #endif };