📄 mod_autoindex.c
字号:
static char *find_default_item(char *bogus_name, apr_array_header_t *list){ request_rec r; /* Bleah. I tried to clean up find_item, and it lead to this bit * of ugliness. Note that the fields initialized are precisely * those that find_item looks at... */ r.filename = bogus_name; r.content_type = r.content_encoding = NULL; return find_item(&r, list, 1);}#define find_default_icon(d,n) find_default_item(n, d->icon_list)#define find_default_alt(d,n) find_default_item(n, d->alt_list)/* * Look through the list of pattern/description pairs and return the first one * if any) that matches the filename in the request. If multiple patterns * match, only the first one is used; since the order in the array is the * same as the order in which directives were processed, earlier matching * directives will dominate. */#ifdef CASE_BLIND_FILESYSTEM#define MATCH_FLAGS APR_FNM_CASE_BLIND#else#define MATCH_FLAGS 0#endifstatic char *find_desc(autoindex_config_rec *dcfg, const char *filename_full){ int i; ai_desc_t *list = (ai_desc_t *) dcfg->desc_list->elts; const char *filename_only; const char *filename; /* * If the filename includes a path, extract just the name itself * for the simple matches. */ if ((filename_only = ap_strrchr_c(filename_full, '/')) == NULL) { filename_only = filename_full; } else { filename_only++; } for (i = 0; i < dcfg->desc_list->nelts; ++i) { ai_desc_t *tuple = &list[i]; int found; /* * Only use the full-path filename if the pattern contains '/'s. */ filename = (tuple->full_path) ? filename_full : filename_only; /* * Make the comparison using the cheapest method; only do * wildcard checking if we must. */ if (tuple->wildcards) { found = (apr_fnmatch(tuple->pattern, filename, MATCH_FLAGS) == 0); } else { found = (ap_strstr_c(filename, tuple->pattern) != NULL); } if (found) { return tuple->description; } } return NULL;}static int ignore_entry(autoindex_config_rec *d, char *path){ apr_array_header_t *list = d->ign_list; struct item *items = (struct item *) list->elts; char *tt; int i; if ((tt = strrchr(path, '/')) == NULL) { tt = path; } else { tt++; } for (i = 0; i < list->nelts; ++i) { struct item *p = &items[i]; char *ap; if ((ap = strrchr(p->apply_to, '/')) == NULL) { ap = p->apply_to; } else { ap++; }#ifndef CASE_BLIND_FILESYSTEM if (!ap_strcmp_match(path, p->apply_path) && !ap_strcmp_match(tt, ap)) { return 1; }#else /* !CASE_BLIND_FILESYSTEM */ /* * On some platforms, the match must be case-blind. This is really * a factor of the filesystem involved, but we can't detect that * reliably - so we have to granularise at the OS level. */ if (!ap_strcasecmp_match(path, p->apply_path) && !ap_strcasecmp_match(tt, ap)) { return 1; }#endif /* !CASE_BLIND_FILESYSTEM */ } return 0;}/***************************************************************** * * Actually generating output *//* * Elements of the emitted document: * Preamble * Emitted unless SUPPRESS_PREAMBLE is set AND ap_run_sub_req * succeeds for the (content_type == text/html) header file. * Header file * Emitted if found (and able). * H1 tag line * Emitted if a header file is NOT emitted. * Directory stuff * Always emitted. * HR * Emitted if FANCY_INDEXING is set. * Readme file * Emitted if found (and able). * ServerSig * Emitted if ServerSignature is not Off AND a readme file * is NOT emitted. * Postamble * Emitted unless SUPPRESS_PREAMBLE is set AND ap_run_sub_req * succeeds for the (content_type == text/html) readme file. *//* * emit a plain text file */static void do_emit_plain(request_rec *r, apr_file_t *f){ char buf[AP_IOBUFSIZE + 1]; int ch; apr_size_t i, c, n; apr_status_t rv; ap_rputs("<pre>\n", r); while (!apr_file_eof(f)) { do { n = sizeof(char) * AP_IOBUFSIZE; rv = apr_file_read(f, buf, &n); } while (APR_STATUS_IS_EINTR(rv)); if (n == 0 || rv != APR_SUCCESS) { /* ###: better error here? */ break; } buf[n] = '\0'; c = 0; while (c < n) { for (i = c; i < n; i++) { if (buf[i] == '<' || buf[i] == '>' || buf[i] == '&') { break; } } ch = buf[i]; buf[i] = '\0'; ap_rputs(&buf[c], r); if (ch == '<') { ap_rputs("<", r); } else if (ch == '>') { ap_rputs(">", r); } else if (ch == '&') { ap_rputs("&", r); } c = i + 1; } } ap_rputs("</pre>\n", r);}/* * Handle the preamble through the H1 tag line, inclusive. Locate * the file with a subrequests. Process text/html documents by actually * running the subrequest; text/xxx documents get copied verbatim, * and any other content type is ignored. This means that a non-text * document (such as HEADER.gif) might get multiviewed as the result * instead of a text document, meaning nothing will be displayed, but * oh well. */static void emit_head(request_rec *r, char *header_fname, int suppress_amble, int emit_xhtml, char *title){ apr_table_t *hdrs = r->headers_in; apr_file_t *f = NULL; request_rec *rr = NULL; int emit_amble = 1; int emit_H1 = 1; const char *r_accept; const char *r_accept_enc; /* * If there's a header file, send a subrequest to look for it. If it's * found and html do the subrequest, otherwise handle it */ r_accept = apr_table_get(hdrs, "Accept"); r_accept_enc = apr_table_get(hdrs, "Accept-Encoding"); apr_table_setn(hdrs, "Accept", "text/html, text/plain"); apr_table_unset(hdrs, "Accept-Encoding"); if ((header_fname != NULL) && r->args) { header_fname = apr_pstrcat(r->pool, header_fname, "?", r->args, NULL); } if ((header_fname != NULL) && (rr = ap_sub_req_lookup_uri(header_fname, r, r->output_filters)) && (rr->status == HTTP_OK) && (rr->filename != NULL) && (rr->finfo.filetype == APR_REG)) { /* * Check for the two specific cases we allow: text/html and * text/anything-else. The former is allowed to be processed for * SSIs. */ if (rr->content_type != NULL) { if (!strcasecmp(ap_field_noparam(r->pool, rr->content_type), "text/html")) { ap_filter_t *f; /* Hope everything will work... */ emit_amble = 0; emit_H1 = 0; if (! suppress_amble) { emit_preamble(r, emit_xhtml, title); } /* This is a hack, but I can't find any better way to do this. * The problem is that we have already created the sub-request, * but we just inserted the OLD_WRITE filter, and the * sub-request needs to pass its data through the OLD_WRITE * filter, or things go horribly wrong (missing data, data in * the wrong order, etc). To fix it, if you create a * sub-request and then insert the OLD_WRITE filter before you * run the request, you need to make sure that the sub-request * data goes through the OLD_WRITE filter. Just steal this * code. The long-term solution is to remove the ap_r* * functions. */ for (f=rr->output_filters; f->frec != ap_subreq_core_filter_handle; f = f->next); f->next = r->output_filters; /* * If there's a problem running the subrequest, display the * preamble if we didn't do it before -- the header file * didn't get displayed. */ if (ap_run_sub_req(rr) != OK) { /* It didn't work */ emit_amble = suppress_amble; emit_H1 = 1; } } else if (!strncasecmp("text/", rr->content_type, 5)) { /* * If we can open the file, prefix it with the preamble * regardless; since we'll be sending a <pre> block around * the file's contents, any HTML header it had won't end up * where it belongs. */ if (apr_file_open(&f, rr->filename, APR_READ, APR_OS_DEFAULT, r->pool) == APR_SUCCESS) { emit_preamble(r, emit_xhtml, title); emit_amble = 0; do_emit_plain(r, f); apr_file_close(f); emit_H1 = 0; } } } } if (r_accept) { apr_table_setn(hdrs, "Accept", r_accept); } else { apr_table_unset(hdrs, "Accept"); } if (r_accept_enc) { apr_table_setn(hdrs, "Accept-Encoding", r_accept_enc); } if (emit_amble) { emit_preamble(r, emit_xhtml, title); } if (emit_H1) { ap_rvputs(r, "<h1>Index of ", title, "</h1>\n", NULL); } if (rr != NULL) { ap_destroy_sub_req(rr); }}/* * Handle the Readme file through the postamble, inclusive. Locate * the file with a subrequests. Process text/html documents by actually * running the subrequest; text/xxx documents get copied verbatim, * and any other content type is ignored. This means that a non-text * document (such as FOOTER.gif) might get multiviewed as the result * instead of a text document, meaning nothing will be displayed, but * oh well. */static void emit_tail(request_rec *r, char *readme_fname, int suppress_amble){ apr_file_t *f = NULL; request_rec *rr = NULL; int suppress_post = 0; int suppress_sig = 0; /* * If there's a readme file, send a subrequest to look for it. If it's * found and a text file, handle it -- otherwise fall through and * pretend there's nothing there. */ if ((readme_fname != NULL) && (rr = ap_sub_req_lookup_uri(readme_fname, r, r->output_filters)) && (rr->status == HTTP_OK) && (rr->filename != NULL) && rr->finfo.filetype == APR_REG) { /* * Check for the two specific cases we allow: text/html and * text/anything-else. The former is allowed to be processed for * SSIs. */ if (rr->content_type != NULL) { if (!strcasecmp(ap_field_noparam(r->pool, rr->content_type), "text/html")) { ap_filter_t *f; for (f=rr->output_filters; f->frec != ap_subreq_core_filter_handle; f = f->next); f->next = r->output_filters; if (ap_run_sub_req(rr) == OK) { /* worked... */ suppress_sig = 1; suppress_post = suppress_amble; } } else if (!strncasecmp("text/", rr->content_type, 5)) { /* * If we can open the file, suppress the signature. */ if (apr_file_open(&f, rr->filename, APR_READ, APR_OS_DEFAULT, r->pool) == APR_SUCCESS) { do_emit_plain(r, f); apr_file_close(f); suppress_sig = 1; } } } } if (!suppress_sig) { ap_rputs(ap_psignature("", r), r); } if (!suppress_post) { ap_rputs("</body></html>\n", r); } if (rr != NULL) { ap_destroy_sub_req(rr); }}static char *find_title(request_rec *r){ char titlebuf[MAX_STRING_LEN], *find = "<title>"; apr_file_t *thefile = NULL; int x, y, p; apr_size_t n; if (r->status != HTTP_OK) { return NULL; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -