📄 mod_autoindex.c
字号:
while (n == -1 && ferror(f) && errno == EINTR); if (n == -1 || n == 0) { 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);}/* See mod_include */#define SUB_REQ_STRING "Sub request to mod_include"#define PARENT_STRING "Parent request to mod_include"/* * 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, char *title){ FILE *f; request_rec *rr = NULL; int emit_amble = 1; int emit_H1 = 1; const char *r_accept; const char *r_accept_enc; table *hdrs = r->headers_in; /* * 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 = ap_table_get(hdrs, "Accept"); r_accept_enc = ap_table_get(hdrs, "Accept-Encoding"); ap_table_setn(hdrs, "Accept", "text/html, text/plain;q=.5, text/*;q=.1"); ap_table_unset(hdrs, "Accept-Encoding"); /* * If there's a header 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 ((header_fname != NULL) && (rr = ap_sub_req_lookup_uri(header_fname, r)) && (rr->status == HTTP_OK) && (rr->filename != NULL) && S_ISREG(rr->finfo.st_mode)) { /* * 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")) { /* Hope everything will work... */ emit_amble = 0; emit_H1 = 0; if (! suppress_amble) { emit_preamble(r, title); } /* See mod_include */ ap_table_add(r->notes, PARENT_STRING, ""); ap_table_add(rr->notes, SUB_REQ_STRING, ""); /* * 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; } ap_table_unset(r->notes, PARENT_STRING); /* cleanup */ } 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 ((f = ap_pfopen(r->pool, rr->filename, "r")) != 0) { emit_preamble(r, title); emit_amble = 0; do_emit_plain(r, f); ap_pfclose(r->pool, f); emit_H1 = 0; } } } } if (r_accept) { ap_table_setn(hdrs, "Accept", r_accept); } else { ap_table_unset(hdrs, "Accept"); } if (r_accept_enc) { ap_table_setn(hdrs, "Accept-Encoding", r_accept_enc); } if (emit_amble) { emit_preamble(r, 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){ FILE *f; request_rec *rr = NULL; int suppress_post = 0; int suppress_sig = 0; const char *r_accept; const char *r_accept_enc; table *hdrs = r->headers_in; /* * If there's a readme file, send a subrequest to look for it. If it's * found and html do the subrequest, otherwise handle it */ r_accept = ap_table_get(hdrs, "Accept"); r_accept_enc = ap_table_get(hdrs, "Accept-Encoding"); ap_table_setn(hdrs, "Accept", "text/html, text/plain;q=.5, text/*;q=.1"); ap_table_unset(hdrs, "Accept-Encoding"); /* * 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)) && (rr->status == HTTP_OK) && (rr->filename != NULL) && S_ISREG(rr->finfo.st_mode)) { /* * 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")) { /* See mod_include */ ap_table_add(r->notes, PARENT_STRING, ""); ap_table_add(rr->notes, SUB_REQ_STRING, ""); if (ap_run_sub_req(rr) == OK) { /* worked... */ suppress_sig = 1; suppress_post = suppress_amble; } ap_table_unset(r->notes, PARENT_STRING); /* cleanup */ } else if (!strncasecmp("text/", rr->content_type, 5)) { /* * If we can open the file, suppress the signature. */ if ((f = ap_pfopen(r->pool, rr->filename, "r")) != 0) { do_emit_plain(r, f); ap_pfclose(r->pool, f); suppress_sig = 1; } } } } if (r_accept) { ap_table_setn(hdrs, "Accept", r_accept); } else { ap_table_unset(hdrs, "Accept"); } if (r_accept_enc) { ap_table_setn(hdrs, "Accept-Encoding", r_accept_enc); } 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>"; FILE *thefile = NULL; int x, y, n, p; if (r->status != HTTP_OK) { return NULL; } if ((r->content_type != NULL) && (!strcasecmp(ap_field_noparam(r->pool, r->content_type), "text/html") || !strcmp(r->content_type, INCLUDES_MAGIC_TYPE)) && !r->content_encoding) { if (!(thefile = ap_pfopen(r->pool, r->filename, "r"))) { return NULL; } n = fread(titlebuf, sizeof(char), MAX_STRING_LEN - 1, thefile); if (n <= 0) { ap_pfclose(r->pool, thefile); return NULL; } titlebuf[n] = '\0'; for (x = 0, p = 0; titlebuf[x]; x++) { if (ap_toupper(titlebuf[x]) == find[p]) { if (!find[++p]) { if ((p = ap_ind(&titlebuf[++x], '<')) != -1) { titlebuf[x + p] = '\0'; } /* Scan for line breaks for Tanmoy's secretary */ for (y = x; titlebuf[y]; y++) { if ((titlebuf[y] == CR) || (titlebuf[y] == LF)) { if (y == x) { x++; } else { titlebuf[y] = ' '; } } } ap_pfclose(r->pool, thefile); return ap_pstrdup(r->pool, &titlebuf[x]); } } else { p = 0; } } ap_pfclose(r->pool, thefile); } return NULL;}static struct ent *make_autoindex_entry(char *name, int autoindex_opts, autoindex_config_rec *d, request_rec *r, char keyid, char direction){ struct ent *p; if ((name[0] == '.') && (!name[1])) { return (NULL); } if (ignore_entry(d, ap_make_full_path(r->pool, r->filename, name))) { return (NULL); } p = (struct ent *) ap_pcalloc(r->pool, sizeof(struct ent)); p->name = ap_pstrdup(r->pool, name); p->size = -1; p->icon = NULL; p->alt = NULL; p->desc = NULL; p->lm = -1; p->isdir = 0; /* * It's obnoxious to have to include this in every entry, but the qsort() * comparison routine only takes two arguments.. The alternative would * add another function call to each invocation. Let's use memory * rather than CPU. */ p->checkdir = ((d->opts & FOLDERS_FIRST) != 0); p->ignorecase = ((d->opts & SORT_NOCASE) != 0); p->key = ap_toupper(keyid); p->ascending = (ap_toupper(direction) == D_ASCENDING); if (autoindex_opts & FANCY_INDEXING) { request_rec *rr = ap_sub_req_lookup_file(name, r); if (rr->finfo.st_mode != 0) { p->lm = rr->finfo.st_mtime; if (S_ISDIR(rr->finfo.st_mode)) { p->isdir = 1; if (!(p->icon = find_icon(d, rr, 1))) { p->icon = find_default_icon(d, "^^DIRECTORY^^"); } if (!(p->alt = find_alt(d, rr, 1))) { p->alt = "DIR"; } p->size = -1; p->name = ap_pstrcat(r->pool, name, "/", NULL); } else { p->icon = find_icon(d, rr, 0); p->alt = find_alt(d, rr, 0); p->size = rr->finfo.st_size; } } p->desc = find_desc(d, rr); if ((!p->desc) && (autoindex_opts & SCAN_HTML_TITLES)) { p->desc = ap_pstrdup(r->pool, find_title(rr)); } ap_destroy_sub_req(rr); } /* * We don't need to take any special action for the file size key. If * we did, it would go here. */ if (keyid == K_LAST_MOD) { if (p->lm < 0) { p->lm = 0; } } return (p);}static char *terminate_description(autoindex_config_rec *d, char *desc, int autoindex_opts, int desc_width){ int maxsize = desc_width; register int x; /* * If there's no DescriptionWidth in effect, default to the old * behaviour of adjusting the description size depending upon * what else is being displayed. Otherwise, stick with the * setting. */ if (d->desc_adjust == K_UNSET) { if (autoindex_opts & SUPPRESS_LAST_MOD) { maxsize += 19; } if (autoindex_opts & SUPPRESS_SIZE) { maxsize += 7; } } for (x = 0; desc[x] && ((maxsize > 0) || (desc[x] == '<')); x++) { if (desc[x] == '<') { while (desc[x] != '>') { if (!desc[x]) { maxsize = 0; break; } ++x; } } else if (desc[x] == '&') { /* entities like ä count as one character */ --maxsize; for ( ; desc[x] != ';'; ++x) { if (desc[x] == '\0') { maxsize = 0; break; } } } else { --maxsize; } } if (!maxsize && desc[x] != '\0') { desc[x - 1] = '>'; /* Grump. */ desc[x] = '\0'; /* Double Grump! */ } return desc;}/* * Emit the anchor for the specified field. If a field is the key for the * current request, the link changes its meaning to reverse the order when * selected again. Non-active fields always start in ascending order. */static void emit_link(request_rec *r, char *anchor, char fname, char curkey, char curdirection, int nosort){ char qvalue[5]; int reverse; if (!nosort) { qvalue[0] = '?'; qvalue[1] = fname; qvalue[2] = '='; qvalue[4] = '\0'; reverse = ((curkey == fname) && (curdirection == D_ASCENDING)); qvalue[3] = reverse ? D_DESCENDING : D_ASCENDING; ap_rvputs(r, "<A HREF=\"", qvalue, "\">", anchor, "</A>", NULL); } else { ap_rputs(anchor, r); }}static void output_directories(struct ent **ar, int n, autoindex_config_rec *d, request_rec *r, int autoindex_opts, char keyid, char direction){ int x; char *name = r->uri; char *tp; int static_columns = (autoindex_opts & SUPPRESS_COLSORT);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -