📄 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 * */#include "apr.h"#include "apr_strings.h"#include "apr_lib.h"#include "apr_hash.h"#define APR_WANT_STRFUNC#include "apr_want.h"#include "ap_config.h"#include "httpd.h"#include "http_config.h"#include "http_log.h"#include "http_request.h"#include "http_protocol.h"/* XXXX - fix me / EBCDIC * there was a cludge here which would use its * own version apr_isascii(). Indicating that * on some platforms that might be needed. * * #define OS_ASC(c) (c) -- for mere mortals * or * #define OS_ASC(c) (ebcdic2ascii[c]) -- for dino's * * #define apr_isascii(c) ((OS_ASC(c) & 0x80) == 0) *//* XXXXX - fix me - See note with NOT_PROXY */typedef struct attrib_info { char *name; int offset;} attrib_info;/* Information to which an extension can be mapped */typedef struct extension_info { char *forced_type; /* Additional AddTyped stuff */ char *encoding_type; /* Added with AddEncoding... */ char *language_type; /* Added with AddLanguage... */ char *handler; /* Added with AddHandler... */ char *charset_type; /* Added with AddCharset... */ char *input_filters; /* Added with AddInputFilter... */ char *output_filters; /* Added with AddOutputFilter... */} extension_info;#define MULTIMATCH_UNSET 0#define MULTIMATCH_ANY 1#define MULTIMATCH_NEGOTIATED 2#define MULTIMATCH_HANDLERS 4#define MULTIMATCH_FILTERS 8typedef struct { apr_hash_t *extension_mappings; /* Map from extension name to * extension_info structure */ apr_array_header_t *remove_mappings; /* A simple list, walked once */ char *default_language; /* Language if no AddLanguage ext found */ int multimatch; /* Extensions to include in multiview matching * for filenames, e.g. Filters and Handlers */ int use_path_info; /* If set to 0, only use filename. * If set to 1, append PATH_INFO to filename for * lookups. * If set to 2, this value is unset and is * effectively 0. */} mime_dir_config;typedef struct param_s { char *attr; char *val; struct param_s *next;} param;typedef struct { const char *type; apr_size_t type_len; const char *subtype; apr_size_t subtype_len; param *param;} content_type;static char tspecial[] = { '(', ')', '<', '>', '@', ',', ';', ':', '\\', '"', '/', '[', ']', '?', '=', '\0'};module AP_MODULE_DECLARE_DATA mime_module;static void *create_mime_dir_config(apr_pool_t *p, char *dummy){ mime_dir_config *new = apr_palloc(p, sizeof(mime_dir_config)); new->extension_mappings = NULL; new->remove_mappings = NULL; new->default_language = NULL; new->multimatch = MULTIMATCH_UNSET; new->use_path_info = 2; return new;}/* * Overlay one hash table of extension_mappings onto another */static void *overlay_extension_mappings(apr_pool_t *p, const void *key, apr_ssize_t klen, const void *overlay_val, const void *base_val, const void *data){ const extension_info *overlay_info = (const extension_info *)overlay_val; const extension_info *base_info = (const extension_info *)base_val; extension_info *new_info = apr_pmemdup(p, base_info, sizeof(extension_info)); if (overlay_info->forced_type) { new_info->forced_type = overlay_info->forced_type; } if (overlay_info->encoding_type) { new_info->encoding_type = overlay_info->encoding_type; } if (overlay_info->language_type) { new_info->language_type = overlay_info->language_type; } if (overlay_info->handler) { new_info->handler = overlay_info->handler; } if (overlay_info->charset_type) { new_info->charset_type = overlay_info->charset_type; } if (overlay_info->input_filters) { new_info->input_filters = overlay_info->input_filters; } if (overlay_info->output_filters) { new_info->output_filters = overlay_info->output_filters; } return new_info;}/* Member is the offset within an extension_info of the pointer to reset */static void remove_items(apr_pool_t *p, apr_array_header_t *remove, apr_hash_t *mappings){ attrib_info *suffix = (attrib_info *) remove->elts; int i; for (i = 0; i < remove->nelts; i++) { extension_info *exinfo = apr_hash_get(mappings, suffix[i].name, APR_HASH_KEY_STRING); if (exinfo && *(const char**)((char *)exinfo + suffix[i].offset)) { extension_info *copyinfo = exinfo; exinfo = (extension_info*)apr_palloc(p, sizeof(*exinfo)); apr_hash_set(mappings, suffix[i].name, APR_HASH_KEY_STRING, exinfo); memcpy(exinfo, copyinfo, sizeof(*exinfo)); *(const char**)((char *)exinfo + suffix[i].offset) = NULL; } }}static void *merge_mime_dir_configs(apr_pool_t *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 = apr_palloc(p, sizeof(mime_dir_config)); if (base->extension_mappings && add->extension_mappings) { new->extension_mappings = apr_hash_merge(p, add->extension_mappings, base->extension_mappings, overlay_extension_mappings, NULL); } else { if (base->extension_mappings == NULL) { new->extension_mappings = add->extension_mappings; } else { new->extension_mappings = base->extension_mappings; } /* We may not be merging the tables, but if we potentially will change * an exinfo member, then we are about to trounce it anyways. * We must have a copy for safety. */ if (new->extension_mappings && add->remove_mappings) { new->extension_mappings = apr_hash_copy(p, new->extension_mappings); } } if (new->extension_mappings) { if (add->remove_mappings) remove_items(p, add->remove_mappings, new->extension_mappings); } new->remove_mappings = NULL; new->default_language = add->default_language ? add->default_language : base->default_language; new->multimatch = (add->multimatch != MULTIMATCH_UNSET) ? add->multimatch : base->multimatch; if ((add->use_path_info & 2) == 0) { new->use_path_info = add->use_path_info; } else { new->use_path_info = base->use_path_info; } return new;}static const char *add_extension_info(cmd_parms *cmd, void *m_, const char *value_, const char* ext){ mime_dir_config *m=m_; extension_info *exinfo; int offset = (int) (long) cmd->info; char *key = apr_pstrdup(cmd->temp_pool, ext); char *value = apr_pstrdup(cmd->pool, value_); ap_str_tolower(value); ap_str_tolower(key); if (*key == '.') { ++key; } if (!m->extension_mappings) { m->extension_mappings = apr_hash_make(cmd->pool); exinfo = NULL; } else { exinfo = (extension_info*)apr_hash_get(m->extension_mappings, key, APR_HASH_KEY_STRING); } if (!exinfo) { exinfo = apr_pcalloc(cmd->pool, sizeof(extension_info)); key = apr_pstrdup(cmd->pool, key); apr_hash_set(m->extension_mappings, key, APR_HASH_KEY_STRING, exinfo); } *(const char**)((char *)exinfo + offset) = value; return NULL;}/* * Note handler names are un-added with each per_dir_config merge. * This keeps the association from being inherited, but not * from being re-added at a subordinate level. */static const char *remove_extension_info(cmd_parms *cmd, void *m_, const char *ext){ mime_dir_config *m = (mime_dir_config *) m_; attrib_info *suffix; if (*ext == '.') { ++ext; } if (!m->remove_mappings) { m->remove_mappings = apr_array_make(cmd->pool, 4, sizeof(*suffix)); } suffix = (attrib_info *)apr_array_push(m->remove_mappings); suffix->name = apr_pstrdup(cmd->pool, ext); ap_str_tolower(suffix->name); suffix->offset = (int) (long) cmd->info; 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, const char *arg){ ap_set_module_config(cmd->server->module_config, &mime_module, (void *)arg); return NULL;}static const char *multiviews_match(cmd_parms *cmd, void *m_, const char *include){ mime_dir_config *m = (mime_dir_config *) m_; if (strcasecmp(include, "Any") == 0) { if (m->multimatch && (m->multimatch & ~MULTIMATCH_ANY)) { return "Any is incompatible with NegotiatedOnly, " "Filters and Handlers"; } m->multimatch |= MULTIMATCH_ANY; } else if (strcasecmp(include, "NegotiatedOnly") == 0) { if (m->multimatch && (m->multimatch & ~MULTIMATCH_NEGOTIATED)) { return "NegotiatedOnly is incompatible with Any, " "Filters and Handlers"; } m->multimatch |= MULTIMATCH_NEGOTIATED; } else if (strcasecmp(include, "Filters") == 0) { if (m->multimatch && (m->multimatch & (MULTIMATCH_NEGOTIATED
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -