📄 mod_autoindex.c
字号:
pool *scratch = ap_make_sub_pool(r->pool); int name_width; int desc_width; char *name_scratch; char *pad_scratch; if (name[0] == '\0') { name = "/"; } desc_width = d->desc_width; if (d->desc_adjust == K_ADJUST) { for (x = 0; x < n; x++) { if (ar[x]->desc != NULL) { int t = strlen(ar[x]->desc); if (t > desc_width) { desc_width = t; } } } } name_width = d->name_width; if (d->name_adjust == K_ADJUST) { for (x = 0; x < n; x++) { int t = strlen(ar[x]->name); if (t > name_width) { name_width = t; } } } name_scratch = ap_palloc(r->pool, name_width + 1); pad_scratch = ap_palloc(r->pool, name_width + 1); memset(pad_scratch, ' ', name_width); pad_scratch[name_width] = '\0'; if (autoindex_opts & FANCY_INDEXING) { ap_rputs("<PRE>", r); if ((tp = find_default_icon(d, "^^BLANKICON^^"))) { ap_rvputs(r, "<IMG SRC=\"", ap_escape_html(scratch, tp), "\" ALT=\" \"", NULL); if (d->icon_width && d->icon_height) { ap_rprintf ( r, " HEIGHT=\"%d\" WIDTH=\"%d\"", d->icon_height, d->icon_width ); } ap_rputs("> ", r); } emit_link(r, "Name", K_NAME, keyid, direction, static_columns); ap_rputs(pad_scratch + 4, r); /* * Emit the guaranteed-at-least-one-space-between-columns byte. */ ap_rputs(" ", r); if (!(autoindex_opts & SUPPRESS_LAST_MOD)) { emit_link(r, "Last modified", K_LAST_MOD, keyid, direction, static_columns); ap_rputs(" ", r); } if (!(autoindex_opts & SUPPRESS_SIZE)) { emit_link(r, "Size", K_SIZE, keyid, direction, static_columns); ap_rputs(" ", r); } if (!(autoindex_opts & SUPPRESS_DESC)) { emit_link(r, "Description", K_DESC, keyid, direction, static_columns); } ap_rputs("\n<HR>\n", r); } else { ap_rputs("<UL>", r); } for (x = 0; x < n; x++) { char *anchor, *t, *t2; int nwidth; ap_clear_pool(scratch); if (is_parent(ar[x]->name)) { t = ap_make_full_path(scratch, name, "../"); ap_getparents(t); if (t[0] == '\0') { t = "/"; } t2 = "Parent Directory"; anchor = ap_escape_html(scratch, ap_os_escape_path(scratch, t, 0)); } else { t = ar[x]->name; t2 = t; anchor = ap_escape_html(scratch, ap_os_escape_path(scratch, t, 0)); } if (autoindex_opts & FANCY_INDEXING) { if (autoindex_opts & ICONS_ARE_LINKS) { ap_rvputs(r, "<A HREF=\"", anchor, "\">", NULL); } if ((ar[x]->icon) || d->default_icon) { ap_rvputs(r, "<IMG SRC=\"", ap_escape_html(scratch, ar[x]->icon ? ar[x]->icon : d->default_icon), "\" ALT=\"[", (ar[x]->alt ? ar[x]->alt : " "), "]\"", NULL); if (d->icon_width && d->icon_height) { ap_rprintf(r, " HEIGHT=\"%d\" WIDTH=\"%d\"", d->icon_height, d->icon_width); } ap_rputs(">", r); } if (autoindex_opts & ICONS_ARE_LINKS) { ap_rputs("</A>", r); } nwidth = strlen(t2); if (nwidth > name_width) { memcpy(name_scratch, t2, name_width - 3); name_scratch[name_width - 3] = '.'; name_scratch[name_width - 2] = '.'; name_scratch[name_width - 1] = '>'; name_scratch[name_width] = 0; t2 = name_scratch; nwidth = name_width; } ap_rvputs(r, " <A HREF=\"", anchor, "\">", ap_escape_html(scratch, t2), "</A>", pad_scratch + nwidth, NULL); /* * The blank before the storm.. er, before the next field. */ ap_rputs(" ", r); if (!(autoindex_opts & SUPPRESS_LAST_MOD)) { if (ar[x]->lm != -1) { char time_str[MAX_STRING_LEN]; struct tm *ts = localtime(&ar[x]->lm); strftime(time_str, MAX_STRING_LEN, "%d-%b-%Y %H:%M ", ts); ap_rputs(time_str, r); } else { /*Length="22-Feb-1998 23:42 " (see 4 lines above) */ ap_rputs(" ", r); } } if (!(autoindex_opts & SUPPRESS_SIZE)) { ap_send_size(ar[x]->size, r); ap_rputs(" ", r); } if (!(autoindex_opts & SUPPRESS_DESC)) { if (ar[x]->desc) { ap_rputs(terminate_description(d, ar[x]->desc, autoindex_opts, desc_width), r); } } } else { ap_rvputs(r, "<LI><A HREF=\"", anchor, "\"> ", t2, "</A>", NULL); } ap_rputc('\n', r); } if (autoindex_opts & FANCY_INDEXING) { ap_rputs("</PRE>", r); } else { ap_rputs("</UL>", r); }}/* * Compare two file entries according to the sort criteria. The return * is essentially a signum function value. */static int dsortf(struct ent **e1, struct ent **e2){ struct ent *c1; struct ent *c2; int result = 0; int ignorecase; /* * First, see if either of the entries is for the parent directory. * If so, that *always* sorts lower than anything else. */ if (is_parent((*e1)->name)) { return -1; } if (is_parent((*e2)->name)) { return 1; } /* * Now see if one's a directory and one isn't, AND we're listing * directories first. */ if ((*e1)->checkdir) { if ((*e1)->isdir != (*e2)->isdir) { return (*e1)->isdir ? -1 : 1; } } /* * All of our comparisons will be of the c1 entry against the c2 one, * so assign them appropriately to take care of the ordering. */ if ((*e1)->ascending) { c1 = *e1; c2 = *e2; } else { c1 = *e2; c2 = *e1; } switch (c1->key) { case K_LAST_MOD: if (c1->lm > c2->lm) { return 1; } else if (c1->lm < c2->lm) { return -1; } break; case K_SIZE: if (c1->size > c2->size) { return 1; } else if (c1->size < c2->size) { return -1; } break; case K_DESC: result = strcmp(c1->desc ? c1->desc : "", c2->desc ? c2->desc : ""); if (result) { return result; } break; } ignorecase = c1->ignorecase; if (ignorecase) { result = strcasecmp(c1->name, c2->name); if (result == 0) { /* * They're identical when treated case-insensitively, so * pretend they weren't and let strcmp() put them in a * deterministic order. This means that 'ABC' and 'abc' * will always appear in the same order, rather than * unpredictably 'ABC abc' or 'abc ABC'. */ ignorecase = 0; } } if (! ignorecase) { result = strcmp(c1->name, c2->name); } return result;}static int index_directory(request_rec *r, autoindex_config_rec *autoindex_conf){ char *title_name = ap_escape_html(r->pool, r->uri); char *title_endp; char *name = r->filename; DIR *d; struct DIR_TYPE *dstruct; int num_ent = 0, x; struct ent *head, *p; struct ent **ar = NULL; const char *qstring; int autoindex_opts = autoindex_conf->opts; char keyid; char direction; if (!(d = ap_popendir(r->pool, name))) { ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "Can't open directory for index: %s", r->filename); return HTTP_FORBIDDEN; } r->content_type = "text/html"; if (autoindex_opts & TRACK_MODIFIED) { ap_update_mtime(r, r->finfo.st_mtime); ap_set_last_modified(r); ap_set_etag(r); } ap_send_http_header(r);#ifdef CHARSET_EBCDIC /* Server-generated response, converted */ ap_bsetflag(r->connection->client, B_EBCDIC2ASCII, r->ebcdic.conv_out = 1);#endif if (r->header_only) { ap_pclosedir(r->pool, d); return 0; } ap_hard_timeout("send directory", r); /* Spew HTML preamble */ title_endp = title_name + strlen(title_name) - 1; while (title_endp > title_name && *title_endp == '/') { *title_endp-- = '\0'; } emit_head(r, find_header(autoindex_conf, r), autoindex_opts & SUPPRESS_PREAMBLE, title_name); /* * Figure out what sort of indexing (if any) we're supposed to use. * * If no QUERY_STRING was specified or column sorting has been * explicitly disabled, we use the default specified by the * IndexOrderDefault directive (if there is one); otherwise, * we fall back to ascending by name. */ qstring = r->args; if ((autoindex_opts & SUPPRESS_COLSORT) || ((qstring == NULL) || (*qstring == '\0'))) { qstring = autoindex_conf->default_order; } /* * If there is no specific ordering defined for this directory, * default to ascending by filename. */ if ((qstring == NULL) || (*qstring == '\0')) { keyid = K_NAME; direction = D_ASCENDING; } else { keyid = *qstring; ap_getword(r->pool, &qstring, '='); if (*qstring == D_DESCENDING) { direction = D_DESCENDING; } else { direction = D_ASCENDING; } } /* * Since we don't know how many dir. entries there are, put them into a * linked list and then arrayificate them so qsort can use them. */ head = NULL; while ((dstruct = readdir(d))) { p = make_autoindex_entry(dstruct->d_name, autoindex_opts, autoindex_conf, r, keyid, direction); if (p != NULL) { p->next = head; head = p; num_ent++; } } if (num_ent > 0) { ar = (struct ent **) ap_palloc(r->pool, num_ent * sizeof(struct ent *)); p = head; x = 0; while (p) { ar[x++] = p; p = p->next; } qsort((void *) ar, num_ent, sizeof(struct ent *), (int (*)(const void *, const void *)) dsortf); } output_directories(ar, num_ent, autoindex_conf, r, autoindex_opts, keyid, direction); ap_pclosedir(r->pool, d); if (autoindex_opts & FANCY_INDEXING) { ap_rputs("<HR>\n", r); } emit_tail(r, find_readme(autoindex_conf, r), autoindex_opts & SUPPRESS_PREAMBLE); ap_kill_timeout(r); return 0;}/* The formal handler... */static int handle_autoindex(request_rec *r){ autoindex_config_rec *d; int allow_opts = ap_allow_options(r); d = (autoindex_config_rec *) ap_get_module_config(r->per_dir_config, &autoindex_module); r->allowed |= (1 << M_GET); if (r->method_number != M_GET) { return DECLINED; } /* OK, nothing easy. Trot out the heavy artillery... */ if (allow_opts & OPT_INDEXES) { /* KLUDGE --- make the sub_req lookups happen in the right directory. * Fixing this in the sub_req_lookup functions themselves is difficult, * and would probably break virtual includes... */ if (r->filename[strlen(r->filename) - 1] != '/') { r->filename = ap_pstrcat(r->pool, r->filename, "/", NULL); } return index_directory(r, d); } else { ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, "Directory index forbidden by rule: %s", r->filename); return HTTP_FORBIDDEN; }}static const handler_rec autoindex_handlers[] ={ {DIR_MAGIC_TYPE, handle_autoindex}, {NULL}};module MODULE_VAR_EXPORT autoindex_module ={ STANDARD_MODULE_STUFF, NULL, /* initializer */ create_autoindex_config, /* dir config creater */ merge_autoindex_configs, /* dir merger --- default is to override */ NULL, /* server config */ NULL, /* merge server config */ autoindex_cmds, /* command table */ autoindex_handlers, /* handlers */ NULL, /* filename translation */ NULL, /* check_user_id */ NULL, /* check auth */ NULL, /* check access */ NULL, /* type_checker */ NULL, /* fixups */ NULL, /* logger */ NULL, /* header parser */ NULL, /* child_init */ NULL, /* child_exit */ NULL /* post read-request */};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -