/* ** utility.c -- Apache layout module ** $Revision: 1.2 $ */ #include "mod_layout.h" LAYOUT_EXPORT(apr_array_header_t *) layout_array_push_kind(apr_pool_t *p, apr_array_header_t *origin, apr_array_header_t *new, int kind) { apr_array_header_t *returnable = NULL; int x = 0; layout_string **new_layouts; layout_string **origin_layouts; new_layouts = (layout_string **) new->elts; origin_layouts = (layout_string **) origin->elts; if (!origin && !new) { return NULL; } else if (!origin) { return new; } else if (!new) { return origin; } /* Size of new plus some padding */ returnable = ap_make_array (p, new->nelts + 2 + origin->nelts, sizeof (layout_string *)); /* Copy in the origin pieces */ for (x = 0; x < origin->nelts; x++) { if (origin_layouts[x]->kind == kind) { *(layout_string **) ap_push_array (returnable) = (layout_string *) origin_layouts[x]; } } /* Copy in the new pieces */ for (x = 0; x < new->nelts; x++) { if (new_layouts[x]->kind == kind) { *(layout_string **) ap_push_array (returnable) = (layout_string *) new_layouts[x]; } } return returnable; } LAYOUT_EXPORT(int) check_type(layout_request *request) { #ifdef DEBUG printf("check_type: %s \n", request->type); #endif if(request->http == ORIGIN) { return 0; } unless(request->type) return 0; unless(strcmp(request->type, "text/plain")) return 1; unless(strcmp(request->type, "text/html")) return 1; return 0; } LAYOUT_EXPORT(layout_request *) create_layout_request(request_rec *r, layout_conf *cfg) { layout_request *info = NULL; const char *content_length = NULL; info = ap_pcalloc(r->pool, sizeof(layout_request)); info->origin = cfg->display_origin; info->merge = cfg->merge; info->http_header = OFF; info->header = OFF; info->footer = OFF; if((content_length = ap_table_get(r->headers_in, "Content-Length"))) { info->length = (content_length ? atoi(content_length) : 0); } info->pid = getpid(); info->type = NULL; info->http = LAYOUT; #ifdef DEBUG //printf("IGNORES HTTP %d Header %d Footer %d\n", cfg->uris_ignore_http_header, cfg->uris_ignore_header, cfg->footer_enabled); #endif if(isOn(cfg->header_enabled)) { info->header = ON; if(cfg->uris_ignore_header) { if (table_find(cfg->uris_ignore_header, r->uri)) info->header = OFF; } } if(isOn(cfg->http_header_enabled)) { info->http_header = ON; if(cfg->uris_ignore_http_header) { if (table_find(cfg->uris_ignore_http_header, r->uri)) info->http_header = OFF; } } if(isOn(cfg->footer_enabled)) { info->footer = ON; if(cfg->uris_ignore_footer) { if (table_find(cfg->uris_ignore_footer, r->uri)) info->footer = OFF; } } return info; } LAYOUT_EXPORT(int) table_search(request_rec *r, const apr_table_t *t, const char *string) { const apr_array_header_t *hdrs_arr = NULL; const apr_table_entry_t *elts = NULL; int i = 0; if (string == NULL) return 0; if (t == NULL) return 0; hdrs_arr = ap_table_elts(t); elts = (const apr_table_entry_t *) hdrs_arr->elts; for (i = 0; i < hdrs_arr->nelts; ++i) { if(string_search(r, string, elts[i].key, 0, 0) == -1) return 0; } return 1; } LAYOUT_EXPORT(void) table_cat(apr_table_t *src, apr_table_t *dest, char *string) { const apr_array_header_t *hdrs_arr = NULL; const apr_table_entry_t *elts = NULL; int x = 0; if (src == NULL) return; if (dest == NULL) return; hdrs_arr = ap_table_elts(src); elts = (const apr_table_entry_t *) hdrs_arr->elts; if(string) { for (x = 0; x < hdrs_arr->nelts; ++x) { unless(strcasecmp(string,elts[x].key)) ap_table_add(dest, elts[x].key, elts[x].val); } } else { for (x = 0; x < hdrs_arr->nelts; ++x) { ap_table_add(dest, elts[x].key, elts[x].val); } } } void table_list(char *string, const apr_table_t * t) { const apr_array_header_t *hdrs_arr = NULL; const apr_table_entry_t *elts = NULL; int i = 0; if (t == NULL) return; if (string == NULL) string = "table_list: "; hdrs_arr = ap_table_elts(t); elts = (const apr_table_entry_t *) hdrs_arr->elts; for (i = 0; i < hdrs_arr->nelts; ++i) { printf("%s:Key %s:%s:\n", string, elts[i].key, elts[i].val); } } LAYOUT_EXPORT(int) string_search(request_rec *r, const char *string, const char *delim, int init_pos, int flag) { char *temp = NULL; char *sub_temp = NULL; char *lower = NULL; char *substring = NULL; int position = 0; int end = 0; int delim_size; int complete_position = 0; if(delim == NULL || string == NULL) return -1; /* length = strlen(string); */ delim_size = strlen(delim); temp = (char *)string + init_pos; complete_position = init_pos; while((position = ap_ind(temp, delim[0])) != -1) { sub_temp = temp + position; if((end = ap_ind(sub_temp, delim[delim_size - 1])) != -1) { substring = ap_pstrndup(r->pool, sub_temp , end + 1); lower = ap_pstrdup(r->pool, substring); ap_str_tolower(lower); unless(ap_fnmatch(delim, lower, FNM_CASE_BLIND)) { if(flag) { complete_position += position; } else { complete_position += position + end + 1; } return complete_position; } } else { return -1; } temp += end + 1; complete_position += end + 1; } return -1; } LAYOUT_EXPORT(int) parser_put(request_rec *r, layout_conf *cfg, layout_request *info, const char *string, int init_pos) { char *temp = NULL; char *sub_temp = NULL; char *lower = NULL; char *substring = NULL; int length = 0; int end = 0; int x = 0; int j = 0; int match = 0; int complete_position = 0; int run = 0; layout_string **layouts; layouts = (layout_string **) cfg->layouts->elts; if(string == NULL) return -1; length = strlen(string); temp = (char *)string + init_pos; complete_position = init_pos; x = init_pos; while ( x < length ) { if( string[x] == '<') { sub_temp = (char *)string + x; if((end = ap_ind(sub_temp, '>')) != -1) { substring = ap_pstrndup(r->pool, sub_temp , end + 1); lower = ap_pstrdup(r->pool, substring); ap_str_tolower(lower); #ifdef DEBUG printf("MATCH: %s (%d)\n", lower, cfg->layouts->nelts); #endif for (j = 0; j < cfg->layouts->nelts; j++) { #ifdef DEBUG printf("\tWITH: %s\n", layouts[j]->pattern); #endif /* The next few lines should be reduced */ run = 1; if (layouts[j]->kind == HEADER && !info->header) { run = 0; } if (layouts[j]->kind == FOOTER && !info->footer) { run = 0; } if (run) { unless(ap_fnmatch(layouts[j]->pattern, lower, FNM_CASE_BLIND)) { if(layouts[j]->append == APPEND) { ap_fputs(info->f, info->b, substring); layout_print(r, cfg, info, j); if(isOn(cfg->notes)) update_info(r->notes, info); } else if(layouts[j]->append == PREPEND) { layout_print(r, cfg, info, j); if(isOn(cfg->notes)) update_info(r->notes, info); ap_fputs(info->f, info->b, substring); } else { /* We replace! */ layout_print(r, cfg, info, j); if(isOn(cfg->notes)) update_info(r->notes, info); } match++; } } } unless (match) { ap_fputs(info->f, info->b, substring); } match = 0; x += strlen(substring); } else { /* If we never match just write out the substring and keep going */ ap_fputc(info->f, info->b, string[x]); x++; } } else { ap_fputc(info->f, info->b, string[x]); x++; } } return -1; } LAYOUT_EXPORT(int) find_headers(request_rec *r, char *body) { int position = 0; char *temp = NULL; int end = 0; temp = body; if(body==NULL) { return -1; } while((position = ap_ind(temp, '\n')) != -1) { if(temp[position + 1] == '\n') { end = end + position + 1; return (end); } if(temp[position + 1] == '\r') { end += position + 2; return (end); } temp = temp + position + 1; end = end + position + 1; } return -1; } int check_table(const char *a) { if (a == NULL) return 0; if('1' == a[0]) return 1; return 0; } /* This method is borrowed from alloc.c in the main apache distribution. */ LAYOUT_EXPORT(int) table_find(const apr_table_t *t, const char *key) { const apr_array_header_t *hdrs_arr = NULL; const apr_table_entry_t *elts = NULL; int i = 0; if (t == NULL) return 0; hdrs_arr = ap_table_elts(t); elts = (const apr_table_entry_t *) hdrs_arr->elts; if (key == NULL) return 0; for (i = 0; i < hdrs_arr->nelts; ++i) { if (!ap_fnmatch(elts[i].key, key, FNM_CASE_BLIND)) if(check_table(elts[i].val)) return 1; } return 0; } LAYOUT_EXPORT(void) update_info(const apr_table_t *t, layout_request *info) { const apr_array_header_t *hdrs_arr = NULL; const apr_table_entry_t *elts = NULL; int i = 0; if (t == NULL) return; hdrs_arr = ap_table_elts(t); elts = (const apr_table_entry_t *) hdrs_arr->elts; for (i = 0; i < hdrs_arr->nelts; ++i) { if (!ap_fnmatch(elts[i].key, "LAYOUT", FNM_CASE_BLIND)) { if (!ap_fnmatch(elts[i].val, "originoff", FNM_CASE_BLIND)) info->origin = OFF; else if (!ap_fnmatch(elts[i].val, "originon", FNM_CASE_BLIND)) info->origin = ON; else if (!ap_fnmatch(elts[i].val, "footeroff", FNM_CASE_BLIND)) info->footer = OFF; else if (!ap_fnmatch(elts[i].val, "footeron", FNM_CASE_BLIND)) info->footer = ON; else if (!ap_fnmatch(elts[i].val, "headeroff", FNM_CASE_BLIND)) info->header = OFF; else if (!ap_fnmatch(elts[i].val, "headeron", FNM_CASE_BLIND)) info->header = ON; else if (!ap_fnmatch(elts[i].val, "mergeoff", FNM_CASE_BLIND)) info->merge = OFF; else if (!ap_fnmatch(elts[i].val, "mergeon", FNM_CASE_BLIND)) info->merge = ON; } } } LAYOUT_EXPORT(int) is_ignored(request_rec *r, layout_conf *cfg, layout_request *info, char *body) { if(cfg->tag_ignore) { if(table_search(r, cfg->tag_ignore, body)){ info->header = OFF; info->footer = OFF; return 1; } } if(cfg->tag_ignore_footer) { if(table_search(r, cfg->tag_ignore_footer, body)){ info->footer = OFF; } } if(cfg->tag_ignore_header) { if(table_search(r, cfg->tag_ignore_header, body)){ info->header = OFF; } } return 0; } LAYOUT_EXPORT(void) layout_headers(request_rec *r, layout_conf *cfg, layout_request *info) { int status = LAYOUT; #ifdef old_code layout_string **current_header; #endif /* HTTP always overrule all headers */ if(info->http_header) { info->http = HTTP; return; } info->http = status; } LAYOUT_EXPORT(int) call_container(request_rec *r, const char *uri, layout_conf *cfg, layout_request *info, int assbackwards) { int status = OK; request_rec *subr; const char *temp = NULL; #ifdef LAYOUT_FILEOWNER_NAME struct passwd * uidpasswd = NULL; #endif subr = (request_rec *) ap_sub_req_lookup_uri(uri, r, info->f); ap_table_setn(subr->headers_in, "Content-Length", "0"); ap_table_setn(subr->subprocess_env, "LAYOUT_SCRIPT_NAME", r->uri); ap_table_setn(subr->subprocess_env, "LAYOUT_PATH_INFO", r->path_info); ap_table_setn(subr->subprocess_env, "LAYOUT_QUERY_STRING", r->args); ap_table_setn(subr->subprocess_env, "LAYOUT_FILENAME", r->filename); // ap_table_setn(subr->subprocess_env, "LAYOUT_LAST_MODIFIED", // ap_ht_time(r->pool, r->finfo.st_mtime, cfg->time_format, 0)); #ifdef LAYOUT_FILEOWNER_NAME uidpasswd=getpwuid(r->finfo.st_uid); if (uidpasswd) ap_table_setn(subr->subprocess_env, "LAYOUT_FILEOWNER_NAME", uidpasswd->pw_name); #endif subr->args = r->args; subr->path_info = r->path_info; subr->assbackwards = assbackwards; temp = ap_table_get(r->headers_in, "Referer"); if(temp) ap_table_setn(subr->subprocess_env, "HTTP_REFERER", temp); status = ap_run_sub_req(subr); table_cat(subr->notes, r->notes, NULL); ap_destroy_sub_req(subr); return status; } LAYOUT_EXPORT(char *) layout_add_file(cmd_parms *cmd, const char *file) { apr_file_t *file_ptr; char buf[HUGE_STRING_LEN]; char *content = NULL; apr_status_t rc; rc = apr_file_open(&file_ptr, file, APR_READ | APR_BINARY | APR_XTHREAD, APR_OS_DEFAULT, cmd->pool); if (rc != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_WARNING, rc, cmd->server, "mod_layout: unable to open file(%s, O_RDONLY), skipping", file); return NULL; } while ((rc = apr_file_gets(buf, HUGE_STRING_LEN, file_ptr)) == APR_SUCCESS) { if(content) { content = (char *)apr_pstrcat(cmd->temp_pool, content, buf, NULL); } else { content = (char *)apr_pstrcat(cmd->temp_pool, buf, NULL); } } apr_file_close(file_ptr); return content; } LAYOUT_EXPORT(void) layout_kind(request_rec *r, layout_conf *cfg, layout_request *info, int kind) { int x = 0; layout_string **layouts; layouts = (layout_string **) cfg->layouts->elts; for(x = 0; x < cfg->layouts->nelts; x++) { if (layouts[x]->kind == kind) { layout_print(r, cfg, info, x); } } }