📄 mod_autoindex.c
字号:
/* Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *//* * mod_autoindex.c: Handles the on-the-fly html index generation * * Rob McCool * 3/23/93 * * Adapted to Apache by rst. */#include "httpd.h"#include "http_config.h"#include "http_core.h"#include "http_request.h"#include "http_protocol.h"#include "http_log.h"#include "http_main.h"#include "util_script.h"#include "fnmatch.h"module MODULE_VAR_EXPORT autoindex_module;/**************************************************************** * * Handling configuration directives... */#define HRULE 1#define NO_HRULE 0#define FRONT_MATTER 1#define END_MATTER 0#define FANCY_INDEXING 1 /* Indexing options */#define ICONS_ARE_LINKS 2#define SCAN_HTML_TITLES 4#define SUPPRESS_LAST_MOD 8#define SUPPRESS_SIZE 16#define SUPPRESS_DESC 32#define SUPPRESS_PREAMBLE 64#define SUPPRESS_COLSORT 128#define NO_OPTIONS 256#define FOLDERS_FIRST 512#define TRACK_MODIFIED 1024#define SORT_NOCASE 2048#define K_PAD 1#define K_NOPAD 0#define K_NOADJUST 0#define K_ADJUST 1#define K_UNSET 2/* * Define keys for sorting. */#define K_NAME 'N' /* Sort by file name (default) */#define K_LAST_MOD 'M' /* Last modification date */#define K_SIZE 'S' /* Size (absolute, not as displayed) */#define K_DESC 'D' /* Description */#define D_ASCENDING 'A'#define D_DESCENDING 'D'/* * These are the dimensions of the default icons supplied with Apache. */#define DEFAULT_ICON_WIDTH 20#define DEFAULT_ICON_HEIGHT 22/* * Other default dimensions. */#define DEFAULT_NAME_WIDTH 23#define DEFAULT_DESC_WIDTH 23struct item { char *type; char *apply_to; char *apply_path; char *data;};typedef struct ai_desc_t { char *pattern; char *description; int full_path; int wildcards;} ai_desc_t;typedef struct autoindex_config_struct { char *default_icon; int opts; int incremented_opts; int decremented_opts; int name_width; int name_adjust; int desc_width; int desc_adjust; int icon_width; int icon_height; char *default_order; array_header *icon_list; array_header *alt_list; array_header *desc_list; array_header *ign_list; array_header *hdr_list; array_header *rdme_list;} autoindex_config_rec;static char c_by_encoding, c_by_type, c_by_path;#define BY_ENCODING &c_by_encoding#define BY_TYPE &c_by_type#define BY_PATH &c_by_path/* * Return true if the specified string refers to the parent directory (i.e., * matches ".." or "../"). Hopefully this one call is significantly less * expensive than multiple strcmp() calls. */static ap_inline int is_parent(const char *name){ /* * Now, IFF the first two bytes are dots, and the third byte is either * EOS (\0) or a slash followed by EOS, we have a match. */ if (((name[0] == '.') && (name[1] == '.')) && ((name[2] == '\0') || ((name[2] == '/') && (name[3] == '\0')))) { return 1; } return 0;}/* * This routine puts the standard HTML header at the top of the index page. * We include the DOCTYPE because we may be using features therefrom (i.e., * HEIGHT and WIDTH attributes on the icons if we're FancyIndexing). */static void emit_preamble(request_rec *r, char *title){ ap_rvputs(r, DOCTYPE_HTML_3_2, "<HTML>\n <HEAD>\n <TITLE>Index of ", title, "</TITLE>\n </HEAD>\n <BODY>\n", NULL);}static void push_item(array_header *arr, char *type, char *to, char *path, char *data){ struct item *p = (struct item *) ap_push_array(arr); if (!to) { to = ""; } if (!path) { path = ""; } p->type = type; p->data = data ? ap_pstrdup(arr->pool, data) : NULL; p->apply_path = ap_pstrcat(arr->pool, path, "*", NULL); if ((type == BY_PATH) && (!ap_is_matchexp(to))) { p->apply_to = ap_pstrcat(arr->pool, "*", to, NULL); } else if (to) { p->apply_to = ap_pstrdup(arr->pool, to); } else { p->apply_to = NULL; }}static const char *add_alt(cmd_parms *cmd, void *d, char *alt, char *to){ if (cmd->info == BY_PATH) { if (!strcmp(to, "**DIRECTORY**")) { to = "^^DIRECTORY^^"; } } if (cmd->info == BY_ENCODING) { ap_str_tolower(to); } push_item(((autoindex_config_rec *) d)->alt_list, cmd->info, to, cmd->path, alt); return NULL;}static const char *add_icon(cmd_parms *cmd, void *d, char *icon, char *to){ char *iconbak = ap_pstrdup(cmd->pool, icon); if (icon[0] == '(') { char *alt; char *cl = strchr(iconbak, ')'); if (cl == NULL) { return "missing closing paren"; } alt = ap_getword_nc(cmd->pool, &iconbak, ','); *cl = '\0'; /* Lose closing paren */ add_alt(cmd, d, &alt[1], to); } if (cmd->info == BY_PATH) { if (!strcmp(to, "**DIRECTORY**")) { to = "^^DIRECTORY^^"; } } if (cmd->info == BY_ENCODING) { ap_str_tolower(to); } push_item(((autoindex_config_rec *) d)->icon_list, cmd->info, to, cmd->path, iconbak); return NULL;}/* * Add description text for a filename pattern. If the pattern has * wildcards already (or we need to add them), add leading and * trailing wildcards to it to ensure substring processing. If the * pattern contains a '/' anywhere, force wildcard matching mode, * add a slash to the prefix so that "bar/bletch" won't be matched * by "foobar/bletch", and make a note that there's a delimiter; * the matching routine simplifies to just the actual filename * whenever it can. This allows definitions in parent directories * to be made for files in subordinate ones using relative paths. *//* * Absent a strcasestr() function, we have to force wildcards on * systems for which "AAA" and "aaa" mean the same file. */#ifdef CASE_BLIND_FILESYSTEM#define WILDCARDS_REQUIRED 1#else#define WILDCARDS_REQUIRED 0#endifstatic const char *add_desc(cmd_parms *cmd, void *d, char *desc, char *to){ autoindex_config_rec *dcfg = (autoindex_config_rec *) d; ai_desc_t *desc_entry; char *prefix = ""; desc_entry = (ai_desc_t *) ap_push_array(dcfg->desc_list); desc_entry->full_path = (strchr(to, '/') == NULL) ? 0 : 1; desc_entry->wildcards = (WILDCARDS_REQUIRED || desc_entry->full_path || ap_is_fnmatch(to)); if (desc_entry->wildcards) { prefix = desc_entry->full_path ? "*/" : "*"; desc_entry->pattern = ap_pstrcat(dcfg->desc_list->pool, prefix, to, "*", NULL); } else { desc_entry->pattern = ap_pstrdup(dcfg->desc_list->pool, to); } desc_entry->description = ap_pstrdup(dcfg->desc_list->pool, desc); return NULL;}static const char *add_ignore(cmd_parms *cmd, void *d, char *ext){ push_item(((autoindex_config_rec *) d)->ign_list, 0, ext, cmd->path, NULL); return NULL;}static const char *add_header(cmd_parms *cmd, void *d, char *name){ push_item(((autoindex_config_rec *) d)->hdr_list, 0, NULL, cmd->path, name); return NULL;}static const char *add_readme(cmd_parms *cmd, void *d, char *name){ push_item(((autoindex_config_rec *) d)->rdme_list, 0, NULL, cmd->path, name); return NULL;}/* A legacy directive, FancyIndexing is superseded by the IndexOptions * keyword. But for compatibility.. */static const char *fancy_indexing(cmd_parms *cmd, void *d, int arg){ int curopts; int newopts; autoindex_config_rec *cfg; cfg = (autoindex_config_rec *) d; curopts = cfg->opts; if (curopts & NO_OPTIONS) { return "FancyIndexing directive conflicts with existing " "IndexOptions None"; } newopts = (arg ? (curopts | FANCY_INDEXING) : (curopts & ~FANCY_INDEXING)); cfg->opts = newopts; return NULL;}static const char *add_opts(cmd_parms *cmd, void *d, const char *optstr){ char *w; int opts; int opts_add; int opts_remove; char action; autoindex_config_rec *d_cfg = (autoindex_config_rec *) d; opts = d_cfg->opts; opts_add = d_cfg->incremented_opts; opts_remove = d_cfg->decremented_opts; while (optstr[0]) { int option = 0; w = ap_getword_conf(cmd->pool, &optstr); if ((*w == '+') || (*w == '-')) { action = *(w++); } else { action = '\0'; } if (!strcasecmp(w, "FancyIndexing")) { option = FANCY_INDEXING; } else if (!strcasecmp(w, "IconsAreLinks")) { option = ICONS_ARE_LINKS; } else if (!strcasecmp(w, "ScanHTMLTitles")) { option = SCAN_HTML_TITLES; } else if (!strcasecmp(w, "SuppressLastModified")) { option = SUPPRESS_LAST_MOD; } else if (!strcasecmp(w, "SuppressSize")) { option = SUPPRESS_SIZE; } else if (!strcasecmp(w, "SuppressDescription")) { option = SUPPRESS_DESC; } else if (!strcasecmp(w, "SuppressHTMLPreamble")) { option = SUPPRESS_PREAMBLE; } else if (!strcasecmp(w, "SuppressColumnSorting")) { option = SUPPRESS_COLSORT; } else if (!strcasecmp(w, "FoldersFirst")) { option = FOLDERS_FIRST; } else if (!strcasecmp(w, "TrackModified")) { option = TRACK_MODIFIED; } else if (!strcasecmp(w, "IgnoreCase")) { option = SORT_NOCASE; } else if (!strcasecmp(w, "None")) { if (action != '\0') { return "Cannot combine '+' or '-' with 'None' keyword"; } opts = NO_OPTIONS; opts_add = 0; opts_remove = 0; } else if (!strcasecmp(w, "IconWidth")) { if (action != '-') { d_cfg->icon_width = DEFAULT_ICON_WIDTH; } else { d_cfg->icon_width = 0; } } else if (!strncasecmp(w, "IconWidth=", 10)) { if (action == '-') { return "Cannot combine '-' with IconWidth=n"; } d_cfg->icon_width = atoi(&w[10]); } else if (!strcasecmp(w, "IconHeight")) { if (action != '-') { d_cfg->icon_height = DEFAULT_ICON_HEIGHT; } else { d_cfg->icon_height = 0; } } else if (!strncasecmp(w, "IconHeight=", 11)) { if (action == '-') { return "Cannot combine '-' with IconHeight=n"; } d_cfg->icon_height = atoi(&w[11]); } else if (!strcasecmp(w, "NameWidth")) { if (action != '-') { return "NameWidth with no value may only appear as " "'-NameWidth'"; } d_cfg->name_width = DEFAULT_NAME_WIDTH; d_cfg->name_adjust = K_NOADJUST; } else if (!strncasecmp(w, "NameWidth=", 10)) { if (action == '-') { return "Cannot combine '-' with NameWidth=n"; } if (w[10] == '*') { d_cfg->name_adjust = K_ADJUST; } else { int width = atoi(&w[10]); if (width < 5) { return "NameWidth value must be greater than 5"; } d_cfg->name_width = width; d_cfg->name_adjust = K_NOADJUST; } } else if (!strcasecmp(w, "DescriptionWidth")) { if (action != '-') { return "DescriptionWidth with no value may only appear as " "'-DescriptionWidth'"; } d_cfg->desc_width = DEFAULT_DESC_WIDTH; d_cfg->desc_adjust = K_NOADJUST; } else if (!strncasecmp(w, "DescriptionWidth=", 17)) { if (action == '-') { return "Cannot combine '-' with DescriptionWidth=n"; } if (w[17] == '*') { d_cfg->desc_adjust = K_ADJUST; } else { int width = atoi(&w[17]); if (width < 12) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -