📄 mod_mime.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. *//* * http_mime.c: Sends/gets MIME headers for requests * * Rob McCool * */#define MIME_PRIVATE#include "httpd.h"#include "http_config.h"#include "http_log.h"/* * isascii(c) isn't universal, and even those places where it is * defined it's not always right for our needs. Roll our own that * we can rely on. */#define ap_isascii(c) ((OS_ASC(c) & 0x80) == 0)typedef struct attrib_info { char *name;} attrib_info;typedef struct { table *forced_types; /* Additional AddTyped stuff */ table *encoding_types; /* Added with AddEncoding... */ table *charset_types; /* Added with AddCharset... */ table *language_types; /* Added with AddLanguage... */ table *handlers; /* Added with AddHandler... */ array_header *handlers_remove; /* List of handlers to remove */ array_header *types_remove; /* List of MIME types to remove */ array_header *encodings_remove; /* List of encodings to remove */ char *type; /* Type forced with ForceType */ char *handler; /* Handler forced with SetHandler */ char *default_language; /* Language if no AddLanguage ext found */} mime_dir_config;typedef struct param_s { char *attr; char *val; struct param_s *next;} param;typedef struct { char *type; char *subtype; param *param;} content_type;static char tspecial[] = { '(', ')', '<', '>', '@', ',', ';', ':', '\\', '"', '/', '[', ']', '?', '=', '\0'};module MODULE_VAR_EXPORT mime_module;static void *create_mime_dir_config(pool *p, char *dummy){ mime_dir_config *new = (mime_dir_config *) ap_palloc(p, sizeof(mime_dir_config)); new->forced_types = ap_make_table(p, 4); new->encoding_types = ap_make_table(p, 4); new->charset_types = ap_make_table(p, 4); new->language_types = ap_make_table(p, 4); new->handlers = ap_make_table(p, 4); new->handlers_remove = ap_make_array(p, 4, sizeof(attrib_info)); new->types_remove = ap_make_array(p, 4, sizeof(attrib_info)); new->encodings_remove = ap_make_array(p, 4, sizeof(attrib_info)); new->type = NULL; new->handler = NULL; new->default_language = NULL; return new;}static void *merge_mime_dir_configs(pool *p, void *basev, void *addv){ mime_dir_config *base = (mime_dir_config *) basev; mime_dir_config *add = (mime_dir_config *) addv; mime_dir_config *new = (mime_dir_config *) ap_palloc(p, sizeof(mime_dir_config)); int i; attrib_info *suffix; new->forced_types = ap_overlay_tables(p, add->forced_types, base->forced_types); new->encoding_types = ap_overlay_tables(p, add->encoding_types, base->encoding_types); new->charset_types = ap_overlay_tables(p, add->charset_types, base->charset_types); new->language_types = ap_overlay_tables(p, add->language_types, base->language_types); new->handlers = ap_overlay_tables(p, add->handlers, base->handlers); suffix = (attrib_info *) add->handlers_remove->elts; for (i = 0; i < add->handlers_remove->nelts; i++) { ap_table_unset(new->handlers, suffix[i].name); } suffix = (attrib_info *) add->types_remove->elts; for (i = 0; i < add->types_remove->nelts; i++) { ap_table_unset(new->forced_types, suffix[i].name); } suffix = (attrib_info *) add->encodings_remove->elts; for (i = 0; i < add->encodings_remove->nelts; i++) { ap_table_unset(new->encoding_types, suffix[i].name); } new->type = add->type ? add->type : base->type; new->handler = add->handler ? add->handler : base->handler; new->default_language = add->default_language ? add->default_language : base->default_language; return new;}static const char *add_type(cmd_parms *cmd, mime_dir_config *m, char *ct, char *ext){ if (*ext == '.') ++ext; ap_str_tolower(ct); ap_table_setn(m->forced_types, ext, ct); return NULL;}static const char *add_encoding(cmd_parms *cmd, mime_dir_config *m, char *enc, char *ext){ if (*ext == '.') ++ext; ap_str_tolower(enc); ap_table_setn(m->encoding_types, ext, enc); return NULL;}static const char *add_charset(cmd_parms *cmd, mime_dir_config *m, char *charset, char *ext){ if (*ext == '.') { ++ext; } ap_str_tolower(charset); ap_table_setn(m->charset_types, ext, charset); return NULL;}static const char *add_language(cmd_parms *cmd, mime_dir_config *m, char *lang, char *ext){ if (*ext == '.') { ++ext; } ap_str_tolower(lang); ap_table_setn(m->language_types, ext, lang); return NULL;}static const char *add_handler(cmd_parms *cmd, mime_dir_config *m, char *hdlr, char *ext){ if (*ext == '.') ++ext; ap_str_tolower(hdlr); ap_table_setn(m->handlers, ext, hdlr); return NULL;}/* * Note handler names that should be un-added for this location. This * will keep the association from being inherited, as well, but not * from being re-added at a subordinate level. */static const char *remove_handler(cmd_parms *cmd, void *m, char *ext){ mime_dir_config *mcfg = (mime_dir_config *) m; attrib_info *suffix; if (*ext == '.') { ++ext; } suffix = (attrib_info *) ap_push_array(mcfg->handlers_remove); suffix->name = ap_pstrdup(cmd->pool, ext); return NULL;}/* * Just like the previous function, except that it records encoding * associations to be undone. */static const char *remove_encoding(cmd_parms *cmd, void *m, char *ext){ mime_dir_config *mcfg = (mime_dir_config *) m; attrib_info *suffix; if (*ext == '.') { ++ext; } suffix = (attrib_info *) ap_push_array(mcfg->encodings_remove); suffix->name = ap_pstrdup(cmd->pool, ext); return NULL;}/* * Similar to the previous functions, except that it deals with filename * suffix/MIME-type associations. */static const char *remove_type(cmd_parms *cmd, void *m, char *ext){ mime_dir_config *mcfg = (mime_dir_config *) m; attrib_info *suffix; if (*ext == '.') { ++ext; } suffix = (attrib_info *) ap_push_array(mcfg->types_remove); suffix->name = ap_pstrdup(cmd->pool, ext); return NULL;}/* The sole bit of server configuration that the MIME module has is * the name of its config file, so... */static const char *set_types_config(cmd_parms *cmd, void *dummy, char *arg){ ap_set_module_config(cmd->server->module_config, &mime_module, arg); return NULL;}static const command_rec mime_cmds[] ={ {"AddType", add_type, NULL, OR_FILEINFO, ITERATE2, "a mime type followed by one or more file extensions"}, {"AddEncoding", add_encoding, NULL, OR_FILEINFO, ITERATE2, "an encoding (e.g., gzip), followed by one or more file extensions"}, {"AddCharset", add_charset, NULL, OR_FILEINFO, ITERATE2, "a charset (e.g., iso-2022-jp), followed by one or more file extensions"}, {"AddLanguage", add_language, NULL, OR_FILEINFO, ITERATE2, "a language (e.g., fr), followed by one or more file extensions"}, {"AddHandler", add_handler, NULL, OR_FILEINFO, ITERATE2, "a handler name followed by one or more file extensions"}, {"ForceType", ap_set_string_slot_lower, (void *)XtOffsetOf(mime_dir_config, type), OR_FILEINFO, TAKE1, "a media type"}, {"RemoveHandler", remove_handler, NULL, OR_FILEINFO, ITERATE, "one or more file extensions"}, {"RemoveEncoding", remove_encoding, NULL, OR_FILEINFO, ITERATE, "one or more file extensions"}, {"RemoveType", remove_type, NULL, OR_FILEINFO, ITERATE, "one or more file extensions"}, {"SetHandler", ap_set_string_slot_lower, (void *)XtOffsetOf(mime_dir_config, handler), OR_FILEINFO, TAKE1, "a handler name"}, {"TypesConfig", set_types_config, NULL, RSRC_CONF, TAKE1, "the MIME types config file"}, {"DefaultLanguage", ap_set_string_slot, (void*)XtOffsetOf(mime_dir_config, default_language), OR_FILEINFO, TAKE1, "language to use for documents with no other language file extension" }, {NULL}};/* Hash table --- only one of these per daemon; virtual hosts can * get private versions through AddType... */#define MIME_HASHSIZE (32)#define hash(i) (ap_tolower(i) % MIME_HASHSIZE)static table *hash_buckets[MIME_HASHSIZE];static void init_mime(server_rec *s, pool *p){ configfile_t *f; char l[MAX_STRING_LEN]; int x; char *types_confname = ap_get_module_config(s->module_config, &mime_module); if (!types_confname) types_confname = TYPES_CONFIG_FILE; types_confname = ap_server_root_relative(p, types_confname); if (!(f = ap_pcfg_openfile(p, types_confname))) { ap_log_error(APLOG_MARK, APLOG_ERR, s, "could not open mime types config file %s.", types_confname); exit(1); } for (x = 0; x < MIME_HASHSIZE; x++) hash_buckets[x] = ap_make_table(p, 10); while (!(ap_cfg_getline(l, MAX_STRING_LEN, f))) { const char *ll = l, *ct; if (l[0] == '#') continue; ct = ap_getword_conf(p, &ll); while (ll[0]) { char *ext = ap_getword_conf(p, &ll); ap_str_tolower(ext); /* ??? */ ap_table_setn(hash_buckets[hash(ext[0])], ext, ct); } } ap_cfg_closefile(f);}static char *zap_sp(char *s){ char *tp; if (s == NULL) { return (NULL); } if (*s == '\0') { return (s); } /* delete prefixed white space */ for (; *s == ' ' || *s == '\t' || *s == '\n'; s++); /* delete postfixed white space */ for (tp = s; *tp != '\0'; tp++); for (tp--; tp != s && (*tp == ' ' || *tp == '\t' || *tp == '\n'); tp--) { *tp = '\0'; } return (s);}static int is_token(int c){ int res; res = (ap_isascii(c) && ap_isgraph(c) && (strchr(tspecial, c) == NULL)) ? 1 : -1; return res;}static int is_qtext(int c){ int res; res = (ap_isascii(c) && (c != '"') && (c != '\\') && (c != '\n')) ? 1 : -1; return res;}static int is_quoted_pair(char *s){ int res = -1; int c; if (((s + 1) != NULL) && (*s == '\\')) { c = (int) *(s + 1); if (ap_isascii(c)) { res = 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -