mod_mime.c revision 1585c2979d749ee71edb6a1d57bc9ff6db12a426
f743002678eb67b99bbc29fee116b65d9530fec0wrowe/* ====================================================================
80833bb9a1bf25dcf19e814438a4b311d2e1f4cffuankg * The Apache Software License, Version 1.1
efe780dcf13b2b95effabf897d694d8f23feac74trawick *
fe83f60b41477b14a37edcfcd1f7f5c5a1ebfe44minfrin * Copyright (c) 2000-2002 The Apache Software Foundation. All rights
fe83f60b41477b14a37edcfcd1f7f5c5a1ebfe44minfrin * reserved.
fe83f60b41477b14a37edcfcd1f7f5c5a1ebfe44minfrin *
bb2ec4bda29720d914838486ad0bbfba9ac75d5dtrawick * Redistribution and use in source and binary forms, with or without
bb2ec4bda29720d914838486ad0bbfba9ac75d5dtrawick * modification, are permitted provided that the following conditions
bb2ec4bda29720d914838486ad0bbfba9ac75d5dtrawick * are met:
7f6bfe455bd605a6401d2fcc9423972a24266b16jim *
7f6bfe455bd605a6401d2fcc9423972a24266b16jim * 1. Redistributions of source code must retain the above copyright
7f6bfe455bd605a6401d2fcc9423972a24266b16jim * notice, this list of conditions and the following disclaimer.
993d1261a278d7322bccef219101220b7b4fb8c5jkaluza *
993d1261a278d7322bccef219101220b7b4fb8c5jkaluza * 2. Redistributions in binary form must reproduce the above copyright
993d1261a278d7322bccef219101220b7b4fb8c5jkaluza * notice, this list of conditions and the following disclaimer in
3b995de5609b15115a0764e6979ba43071a2988fjim * the documentation and/or other materials provided with the
3b995de5609b15115a0764e6979ba43071a2988fjim * distribution.
3b995de5609b15115a0764e6979ba43071a2988fjim *
ba050a6f942b9fa0e81ed73437588005c569655ccovener * 3. The end-user documentation included with the redistribution,
ba050a6f942b9fa0e81ed73437588005c569655ccovener * if any, must include the following acknowledgment:
ba050a6f942b9fa0e81ed73437588005c569655ccovener * "This product includes software developed by the
ba050a6f942b9fa0e81ed73437588005c569655ccovener * Apache Software Foundation (http://www.apache.org/)."
ba050a6f942b9fa0e81ed73437588005c569655ccovener * Alternately, this acknowledgment may appear in the software itself,
ba050a6f942b9fa0e81ed73437588005c569655ccovener * if and wherever such third-party acknowledgments normally appear.
ba050a6f942b9fa0e81ed73437588005c569655ccovener *
135ddda3a989215d2bedbcf1529bfb269c3eda23niq * 4. The names "Apache" and "Apache Software Foundation" must
135ddda3a989215d2bedbcf1529bfb269c3eda23niq * not be used to endorse or promote products derived from this
135ddda3a989215d2bedbcf1529bfb269c3eda23niq * software without prior written permission. For written
166b66614fb67e1b95c200433925787457657a0ajim * permission, please contact apache@apache.org.
166b66614fb67e1b95c200433925787457657a0ajim *
166b66614fb67e1b95c200433925787457657a0ajim * 5. Products derived from this software may not be called "Apache",
166b66614fb67e1b95c200433925787457657a0ajim * nor may "Apache" appear in their name, without prior written
3f414998b6d7e96a9f699621352fc61516b1a316chrisd * permission of the Apache Software Foundation.
3f414998b6d7e96a9f699621352fc61516b1a316chrisd *
3f414998b6d7e96a9f699621352fc61516b1a316chrisd * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
9d766f93eefb9358f9a24bb99ff424ad399b9b39minfrin * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
9d766f93eefb9358f9a24bb99ff424ad399b9b39minfrin * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
9d766f93eefb9358f9a24bb99ff424ad399b9b39minfrin * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
5725c3eb0c6c572049ba61dedd92b4e5da078081minfrin * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
5725c3eb0c6c572049ba61dedd92b4e5da078081minfrin * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
5725c3eb0c6c572049ba61dedd92b4e5da078081minfrin * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
5725c3eb0c6c572049ba61dedd92b4e5da078081minfrin * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
1122585e1e00bb81e9d0f054bf5c318cec23aa7dminfrin * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
1122585e1e00bb81e9d0f054bf5c318cec23aa7dminfrin * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
1122585e1e00bb81e9d0f054bf5c318cec23aa7dminfrin * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
b4e664baba9a4be0457c31f84b3dcc4c31f2cb07kbrand * SUCH DAMAGE.
b4e664baba9a4be0457c31f84b3dcc4c31f2cb07kbrand * ====================================================================
b4e664baba9a4be0457c31f84b3dcc4c31f2cb07kbrand *
b4e664baba9a4be0457c31f84b3dcc4c31f2cb07kbrand * This software consists of voluntary contributions made by many
a52dab9b245d2bc88feacc380eb94bd6abcd5dd0kbrand * individuals on behalf of the Apache Software Foundation. For more
b4e664baba9a4be0457c31f84b3dcc4c31f2cb07kbrand * information on the Apache Software Foundation, please see
ac0c8366f49659958162b4bfb3d625a77343eda3kbrand * <http://www.apache.org/>.
ac0c8366f49659958162b4bfb3d625a77343eda3kbrand *
001a44c352f89c9ec332ffd3e0a6927dcd19432chumbedooh * Portions of this software are based upon public domain software
001a44c352f89c9ec332ffd3e0a6927dcd19432chumbedooh * originally written at the National Center for Supercomputing Applications,
001a44c352f89c9ec332ffd3e0a6927dcd19432chumbedooh * University of Illinois, Urbana-Champaign.
efe780dcf13b2b95effabf897d694d8f23feac74trawick */
793214f67dede32edfd9ee96c664ead04d175cbbjfclere
cc5a4a08dc9783fcbc52ce86f11e01c281a43810minfrin/*
33124689065ade0dfc8c54d8ebb734f9439cb89btrawick * http_mime.c: Sends/gets MIME headers for requests
33124689065ade0dfc8c54d8ebb734f9439cb89btrawick *
33124689065ade0dfc8c54d8ebb734f9439cb89btrawick * Rob McCool
3ccfc257819b3bad063cd3ac9dd1670d5d2ae4d2kbrand *
3ccfc257819b3bad063cd3ac9dd1670d5d2ae4d2kbrand */
3ccfc257819b3bad063cd3ac9dd1670d5d2ae4d2kbrand
3ccfc257819b3bad063cd3ac9dd1670d5d2ae4d2kbrand#include "apr.h"
9b0076ddd1103e5fa9c1f9bafde4b06ce244fbaecovener#include "apr_strings.h"
9b0076ddd1103e5fa9c1f9bafde4b06ce244fbaecovener#include "apr_lib.h"
9b0076ddd1103e5fa9c1f9bafde4b06ce244fbaecovener#include "apr_hash.h"
249d09d51808cb7981af99762c3b3736ca126cd5jkaluza
249d09d51808cb7981af99762c3b3736ca126cd5jkaluza#define APR_WANT_STRFUNC
249d09d51808cb7981af99762c3b3736ca126cd5jkaluza#include "apr_want.h"
249d09d51808cb7981af99762c3b3736ca126cd5jkaluza
56589be3d7a3e9343370df240010c6928cc78b39jkaluza#include "ap_config.h"
56589be3d7a3e9343370df240010c6928cc78b39jkaluza#include "httpd.h"
56589be3d7a3e9343370df240010c6928cc78b39jkaluza#include "http_config.h"
8c4967445b49a1612b3f98c1dada65e597ecfe26trawick#include "http_log.h"
8c4967445b49a1612b3f98c1dada65e597ecfe26trawick#include "http_request.h"
8c4967445b49a1612b3f98c1dada65e597ecfe26trawick#include "http_protocol.h"
61fefed8ce5211c31b44f3a38a6e76ca055e5780trawick
61fefed8ce5211c31b44f3a38a6e76ca055e5780trawick/* XXXX - fix me / EBCDIC
61fefed8ce5211c31b44f3a38a6e76ca055e5780trawick * there was a cludge here which would use its
61fefed8ce5211c31b44f3a38a6e76ca055e5780trawick * own version apr_isascii(). Indicating that
6001d914962deabb83a46251001612e969bdf67ajim * on some platforms that might be needed.
6001d914962deabb83a46251001612e969bdf67ajim *
6001d914962deabb83a46251001612e969bdf67ajim * #define OS_ASC(c) (c) -- for mere mortals
c4e8006db0cf457c68876d7d4c30dcc451d8cba7jkaluza * or
c4e8006db0cf457c68876d7d4c30dcc451d8cba7jkaluza * #define OS_ASC(c) (ebcdic2ascii[c]) -- for dino's
c4e8006db0cf457c68876d7d4c30dcc451d8cba7jkaluza *
652bacc79dd7f980249784cc8c4838e8f1de7e8acovener * #define apr_isascii(c) ((OS_ASC(c) & 0x80) == 0)
652bacc79dd7f980249784cc8c4838e8f1de7e8acovener */
652bacc79dd7f980249784cc8c4838e8f1de7e8acovener
652bacc79dd7f980249784cc8c4838e8f1de7e8acovener/* XXXXX - fix me - See note with NOT_PROXY
f4db898517ccc6ef1a403630de56918286d3a47eminfrin */
f4db898517ccc6ef1a403630de56918286d3a47eminfrin
f4db898517ccc6ef1a403630de56918286d3a47eminfrintypedef struct attrib_info {
28a723b775c7666281298eab813c63ac42270f95humbedooh char *name;
28a723b775c7666281298eab813c63ac42270f95humbedooh int offset;
28a723b775c7666281298eab813c63ac42270f95humbedooh} attrib_info;
067698ad30941e38ef5d7f95f1c2736c2ebc5cb9humbedooh
067698ad30941e38ef5d7f95f1c2736c2ebc5cb9humbedooh/* Information to which an extension can be mapped
067698ad30941e38ef5d7f95f1c2736c2ebc5cb9humbedooh */
d8a6de5eec06d4136839c8f7a56a6ab5acd2d3behumbedoohtypedef struct extension_info {
6e1e45624d6f32110383bb0bd06c254c1dba8123humbedooh char *forced_type; /* Additional AddTyped stuff */
77ca16c5676da23155311e13cee61e7eaba9fa3ejailletc char *encoding_type; /* Added with AddEncoding... */
77ca16c5676da23155311e13cee61e7eaba9fa3ejailletc char *language_type; /* Added with AddLanguage... */
77ca16c5676da23155311e13cee61e7eaba9fa3ejailletc char *handler; /* Added with AddHandler... */
77ca16c5676da23155311e13cee61e7eaba9fa3ejailletc char *charset_type; /* Added with AddCharset... */
921d32d80d8271da08f12fc374a69cb36d1d63b3covener char *input_filters; /* Added with AddInputFilter... */
921d32d80d8271da08f12fc374a69cb36d1d63b3covener char *output_filters; /* Added with AddOutputFilter... */
921d32d80d8271da08f12fc374a69cb36d1d63b3covener} extension_info;
3e097af23e40c45aa32602545155f0964ab5c69dcovener
3e097af23e40c45aa32602545155f0964ab5c69dcovener#define MULTIMATCH_UNSET 0
3e097af23e40c45aa32602545155f0964ab5c69dcovener#define MULTIMATCH_ANY 1
faea99bb676ec50ece38da6b1879aa37546483a2covener#define MULTIMATCH_NEGOTIATED 2
faea99bb676ec50ece38da6b1879aa37546483a2covener#define MULTIMATCH_HANDLERS 4
faea99bb676ec50ece38da6b1879aa37546483a2covener#define MULTIMATCH_FILTERS 8
86a5604df726638a2b8085e993b4b79c4b3a5262covener
faea99bb676ec50ece38da6b1879aa37546483a2covenertypedef struct {
344f755169e100ea8ce51e847a0bf30a13b46917covener apr_hash_t *extension_mappings; /* Map from extension name to
344f755169e100ea8ce51e847a0bf30a13b46917covener * extension_info structure */
344f755169e100ea8ce51e847a0bf30a13b46917covener
50cfe8bbbaf4279375802531268e2bf0155215fetrawick apr_array_header_t *remove_mappings; /* A simple list, walked once */
50cfe8bbbaf4279375802531268e2bf0155215fetrawick
50cfe8bbbaf4279375802531268e2bf0155215fetrawick char *default_language; /* Language if no AddLanguage ext found */
50cfe8bbbaf4279375802531268e2bf0155215fetrawick
ffaa9771884a8664f0e6267efbe9d26b40000461trawick int multimatch; /* Extensions to include in multiview matching
ffaa9771884a8664f0e6267efbe9d26b40000461trawick * for filenames, e.g. Filters and Handlers
ffaa9771884a8664f0e6267efbe9d26b40000461trawick */
ffaa9771884a8664f0e6267efbe9d26b40000461trawick} mime_dir_config;
f87299dab99bc04b51a6b8cad51b6795db862c0atrawick
f87299dab99bc04b51a6b8cad51b6795db862c0atrawicktypedef struct param_s {
f87299dab99bc04b51a6b8cad51b6795db862c0atrawick char *attr;
4d12805e6c18253040223ea637acd6b3b3c18f60jorton char *val;
4d12805e6c18253040223ea637acd6b3b3c18f60jorton struct param_s *next;
4d12805e6c18253040223ea637acd6b3b3c18f60jorton} param;
4d12805e6c18253040223ea637acd6b3b3c18f60jorton
4d12805e6c18253040223ea637acd6b3b3c18f60jortontypedef struct {
e5d909f2b06bd880fb3675cd49363df981caa631trawick char *type;
a4df2cd1e1391575a327c2a90ba4315f805a0a78covener char *subtype;
a4df2cd1e1391575a327c2a90ba4315f805a0a78covener param *param;
a4df2cd1e1391575a327c2a90ba4315f805a0a78covener} content_type;
cb666b29f81df1d11d65002250153353568021fccovener
cb666b29f81df1d11d65002250153353568021fccovenerstatic char tspecial[] = {
cb666b29f81df1d11d65002250153353568021fccovener '(', ')', '<', '>', '@', ',', ';', ':',
6a80c3c6f4b8ea7ba5e89402b8b779b09ce020e0covener '\\', '"', '/', '[', ']', '?', '=',
1c2cab00d988fc48cbe59032cf76cc0bab20d6f7covener '\0'
6a80c3c6f4b8ea7ba5e89402b8b779b09ce020e0covener};
75a230a728338d84dcfe81edd375352f34de22d0covener
75a230a728338d84dcfe81edd375352f34de22d0covenermodule AP_MODULE_DECLARE_DATA mime_module;
75a230a728338d84dcfe81edd375352f34de22d0covener
1f50dc34ae069adeed20b2986e5ffdefa5c410e0covenerstatic void *create_mime_dir_config(apr_pool_t *p, char *dummy)
1f50dc34ae069adeed20b2986e5ffdefa5c410e0covener{
1f50dc34ae069adeed20b2986e5ffdefa5c410e0covener mime_dir_config *new =
63a5ea80bddcc84a462e40f402b4f330e0e05411covener (mime_dir_config *) apr_palloc(p, sizeof(mime_dir_config));
63a5ea80bddcc84a462e40f402b4f330e0e05411covener
63a5ea80bddcc84a462e40f402b4f330e0e05411covener new->extension_mappings = NULL;
63a5ea80bddcc84a462e40f402b4f330e0e05411covener new->remove_mappings = NULL;
986f3ea2c314d4d4b3b937149853a0f23f6119aaminfrin
986f3ea2c314d4d4b3b937149853a0f23f6119aaminfrin new->default_language = NULL;
986f3ea2c314d4d4b3b937149853a0f23f6119aaminfrin
65a4e663b82f8bce28ac22ab2edfd7502de36998sf new->multimatch = MULTIMATCH_UNSET;
65a4e663b82f8bce28ac22ab2edfd7502de36998sf
65a4e663b82f8bce28ac22ab2edfd7502de36998sf return new;
65a4e663b82f8bce28ac22ab2edfd7502de36998sf}
c7de1955eb0eaeabf7042902476397692672d549sf/*
74e7f6c55fd67b10cb400b3f6d1dc718a303d944minfrin * Overlay one hash table of extension_mappings onto another
74e7f6c55fd67b10cb400b3f6d1dc718a303d944minfrin */
74e7f6c55fd67b10cb400b3f6d1dc718a303d944minfrinstatic void *overlay_extension_mappings(apr_pool_t *p,
74e7f6c55fd67b10cb400b3f6d1dc718a303d944minfrin const void *key,
a511a29faf2ff7ead3b67680154a624effb31aafminfrin apr_ssize_t klen,
a511a29faf2ff7ead3b67680154a624effb31aafminfrin const void *overlay_val,
a511a29faf2ff7ead3b67680154a624effb31aafminfrin const void *base_val,
a511a29faf2ff7ead3b67680154a624effb31aafminfrin const void *data)
a511a29faf2ff7ead3b67680154a624effb31aafminfrin{
63921358ef93fcb41bc71d9894221ba3d7fbb87bminfrin extension_info *new_info = apr_palloc(p, sizeof(extension_info));
63921358ef93fcb41bc71d9894221ba3d7fbb87bminfrin const extension_info *overlay_info = (const extension_info *)overlay_val;
63921358ef93fcb41bc71d9894221ba3d7fbb87bminfrin const extension_info *base_info = (const extension_info *)base_val;
deec48c67d4786bc77112ffbf3a4e70b931097edminfrin
6d601599d3d65df0410eae6e573e75b2dbfb1fb4minfrin memcpy(new_info, base_info, sizeof(extension_info));
6d601599d3d65df0410eae6e573e75b2dbfb1fb4minfrin if (overlay_info->forced_type) {
6d601599d3d65df0410eae6e573e75b2dbfb1fb4minfrin new_info->forced_type = overlay_info->forced_type;
6d601599d3d65df0410eae6e573e75b2dbfb1fb4minfrin }
4c02bab56a528a180bbe394d8b6e6fd9c1a3ac1esf if (overlay_info->encoding_type) {
4c02bab56a528a180bbe394d8b6e6fd9c1a3ac1esf new_info->encoding_type = overlay_info->encoding_type;
4c02bab56a528a180bbe394d8b6e6fd9c1a3ac1esf }
4c02bab56a528a180bbe394d8b6e6fd9c1a3ac1esf if (overlay_info->language_type) {
2c487ac43b583db869e743772a7a10b278aa2bcfminfrin new_info->language_type = overlay_info->language_type;
684e0cfc200f66287a93bbd1708d1dd8a92a7eefcovener }
684e0cfc200f66287a93bbd1708d1dd8a92a7eefcovener if (overlay_info->handler) {
5c43d2fb853f84497b5ece2d414ef9484aa87e5fsf new_info->handler = overlay_info->handler;
05a5a9c3e16f21566e1b61f4bd68025ce1b741ccjoes }
05a5a9c3e16f21566e1b61f4bd68025ce1b741ccjoes if (overlay_info->charset_type) {
ef82e8fa164e0a1f8b813f7deb6b7ead96018c94niq new_info->charset_type = overlay_info->charset_type;
26c5829347f6a355c00f1ba0301d575056b69536niq }
ef82e8fa164e0a1f8b813f7deb6b7ead96018c94niq if (overlay_info->input_filters) {
ef82e8fa164e0a1f8b813f7deb6b7ead96018c94niq new_info->input_filters = overlay_info->input_filters;
ef82e8fa164e0a1f8b813f7deb6b7ead96018c94niq }
ef82e8fa164e0a1f8b813f7deb6b7ead96018c94niq if (overlay_info->output_filters) {
ef82e8fa164e0a1f8b813f7deb6b7ead96018c94niq new_info->output_filters = overlay_info->output_filters;
ef82e8fa164e0a1f8b813f7deb6b7ead96018c94niq }
413ee814748f37be168ff12407fa6dba0ceeabe6trawick
c12917da693bae4028a1d5a5e8224bceed8c739dsf return new_info;
c12917da693bae4028a1d5a5e8224bceed8c739dsf}
eafcc0ebf263d0ba69855b6e10958c4c1a2361bdsf
eafcc0ebf263d0ba69855b6e10958c4c1a2361bdsf/* Member is the offset within an extension_info of the pointer to reset
eafcc0ebf263d0ba69855b6e10958c4c1a2361bdsf */
eafcc0ebf263d0ba69855b6e10958c4c1a2361bdsfstatic void remove_items(apr_pool_t *p, apr_array_header_t *remove,
eafcc0ebf263d0ba69855b6e10958c4c1a2361bdsf apr_hash_t *mappings)
d7ffd2da16d58b1a0de212e4d56f7aebb72bef26sf{
d7ffd2da16d58b1a0de212e4d56f7aebb72bef26sf attrib_info *suffix = (attrib_info *) remove->elts;
d7ffd2da16d58b1a0de212e4d56f7aebb72bef26sf int i;
4576c1a9ef54cd1e5555ee07d016a7f559f80338sf for (i = 0; i < remove->nelts; i++) {
4576c1a9ef54cd1e5555ee07d016a7f559f80338sf extension_info *exinfo =
4576c1a9ef54cd1e5555ee07d016a7f559f80338sf (extension_info*)apr_hash_get(mappings,
9811aed12bbc71783d2e544ccb5fecd193843eadsf suffix[i].name,
9811aed12bbc71783d2e544ccb5fecd193843eadsf APR_HASH_KEY_STRING);
9811aed12bbc71783d2e544ccb5fecd193843eadsf if (exinfo && *(const char**)((char *)exinfo + suffix[i].offset)) {
1366443dc565c33e7b449ae428bbfc4c86f33935drh extension_info *copyinfo = exinfo;
1366443dc565c33e7b449ae428bbfc4c86f33935drh exinfo = (extension_info*)apr_palloc(p, sizeof(*exinfo));
88fac54d9d64f85bbdab5d7010816f4377f95bd7rjung apr_hash_set(mappings, suffix[i].name,
88fac54d9d64f85bbdab5d7010816f4377f95bd7rjung APR_HASH_KEY_STRING, exinfo);
bd3f5647b96d378d9c75c954e3f13582af32c643sf memcpy(exinfo, copyinfo, sizeof(*exinfo));
bd3f5647b96d378d9c75c954e3f13582af32c643sf *(const char**)((char *)exinfo + suffix[i].offset) = NULL;
bd3f5647b96d378d9c75c954e3f13582af32c643sf }
bd3f5647b96d378d9c75c954e3f13582af32c643sf }
bd3f5647b96d378d9c75c954e3f13582af32c643sf}
2a7beea91d46beb41f043a84eaad060047ee04aafabien
2a7beea91d46beb41f043a84eaad060047ee04aafabienstatic void *merge_mime_dir_configs(apr_pool_t *p, void *basev, void *addv)
2a7beea91d46beb41f043a84eaad060047ee04aafabien{
2a7beea91d46beb41f043a84eaad060047ee04aafabien mime_dir_config *base = (mime_dir_config *) basev;
584a85dd4047e38d3ed3a29b6662fcc9d100ae4csf mime_dir_config *add = (mime_dir_config *) addv;
584a85dd4047e38d3ed3a29b6662fcc9d100ae4csf mime_dir_config *new = apr_palloc(p, sizeof(mime_dir_config));
584a85dd4047e38d3ed3a29b6662fcc9d100ae4csf
f21e9e3d0bfb7a507ecc5bc963f2159d693503d1sf if (base->extension_mappings && add->extension_mappings) {
f21e9e3d0bfb7a507ecc5bc963f2159d693503d1sf new->extension_mappings = apr_hash_merge(p, add->extension_mappings,
f21e9e3d0bfb7a507ecc5bc963f2159d693503d1sf base->extension_mappings,
f6b9c755a0b793e8a3a3aebd327ca20a86478117sf overlay_extension_mappings,
f6b9c755a0b793e8a3a3aebd327ca20a86478117sf NULL);
f6b9c755a0b793e8a3a3aebd327ca20a86478117sf }
132ee6ac1c26d6e8953836316ba50734eefab47bsf else {
132ee6ac1c26d6e8953836316ba50734eefab47bsf if (base->extension_mappings == NULL) {
132ee6ac1c26d6e8953836316ba50734eefab47bsf new->extension_mappings = add->extension_mappings;
85eacfc96a04547ef25aabbc06440039715084c2jorton }
85eacfc96a04547ef25aabbc06440039715084c2jorton else {
85eacfc96a04547ef25aabbc06440039715084c2jorton new->extension_mappings = base->extension_mappings;
536d2e7cd1fdec1255b8c3bdf41fdc714c506a54trawick }
536d2e7cd1fdec1255b8c3bdf41fdc714c506a54trawick /* We may not be merging the tables, but if we potentially will change
536d2e7cd1fdec1255b8c3bdf41fdc714c506a54trawick * an exinfo member, then we are about to trounce it anyways.
536d2e7cd1fdec1255b8c3bdf41fdc714c506a54trawick * We must have a copy for safety.
79c5787b92ac5f0e1cc82393816c77a006399316trawick */
79c5787b92ac5f0e1cc82393816c77a006399316trawick if (new->extension_mappings && add->remove_mappings) {
79c5787b92ac5f0e1cc82393816c77a006399316trawick new->extension_mappings =
79c5787b92ac5f0e1cc82393816c77a006399316trawick apr_hash_copy(p, new->extension_mappings);
c967bf3bc89e8aa60dbd30d9da388e448ddc1cc4trawick }
79c5787b92ac5f0e1cc82393816c77a006399316trawick }
79c5787b92ac5f0e1cc82393816c77a006399316trawick
79c5787b92ac5f0e1cc82393816c77a006399316trawick if (new->extension_mappings) {
79c5787b92ac5f0e1cc82393816c77a006399316trawick if (add->remove_mappings)
79c5787b92ac5f0e1cc82393816c77a006399316trawick remove_items(p, add->remove_mappings, new->extension_mappings);
7b395e4e878c28a4784919cfd2e704ddd14a3390jorton }
7b395e4e878c28a4784919cfd2e704ddd14a3390jorton new->remove_mappings = NULL;
7b395e4e878c28a4784919cfd2e704ddd14a3390jorton
7b395e4e878c28a4784919cfd2e704ddd14a3390jorton new->default_language = add->default_language ?
536e48c08d674acac5d44929318f2ad928edc361jorton add->default_language : base->default_language;
536e48c08d674acac5d44929318f2ad928edc361jorton
e81785da447b469da66f218b3f0244aab507958djorton new->multimatch = (add->multimatch != MULTIMATCH_UNSET) ?
e81785da447b469da66f218b3f0244aab507958djorton add->multimatch : base->multimatch;
3e4e54d4e3fc0123c63d57aa84ac7ad7a8c73ff8jorton
3e4e54d4e3fc0123c63d57aa84ac7ad7a8c73ff8jorton return new;
3e4e54d4e3fc0123c63d57aa84ac7ad7a8c73ff8jorton}
53e9b27aba029b18be814df40bcf6f0428771d1efuankg
53e9b27aba029b18be814df40bcf6f0428771d1efuankgstatic const char *add_extension_info(cmd_parms *cmd, void *m_,
53e9b27aba029b18be814df40bcf6f0428771d1efuankg const char *value_, const char* ext)
53e9b27aba029b18be814df40bcf6f0428771d1efuankg{
53e9b27aba029b18be814df40bcf6f0428771d1efuankg mime_dir_config *m=m_;
6bb524f1895f30265a1431afc460977d391cb36bsf extension_info *exinfo;
6bb524f1895f30265a1431afc460977d391cb36bsf int offset = (int) (long) cmd->info;
ca61ccd0c306c2c72df153688ba1b49f3eceed80sf char *key = apr_pstrdup(cmd->temp_pool, ext);
6bb524f1895f30265a1431afc460977d391cb36bsf char *value = apr_pstrdup(cmd->pool, value_);
e6dd71992459d05a676b98b7963423dc5dc1e24aminfrin ap_str_tolower(value);
e6dd71992459d05a676b98b7963423dc5dc1e24aminfrin ap_str_tolower(key);
e6dd71992459d05a676b98b7963423dc5dc1e24aminfrin
e6dd71992459d05a676b98b7963423dc5dc1e24aminfrin if (*key == '.')
23f1535d6a60817d2846bac0aea230ea475d7dccminfrin ++key;
23f1535d6a60817d2846bac0aea230ea475d7dccminfrin if (!m->extension_mappings) {
23f1535d6a60817d2846bac0aea230ea475d7dccminfrin m->extension_mappings = apr_hash_make(cmd->pool);
23f1535d6a60817d2846bac0aea230ea475d7dccminfrin exinfo = NULL;
ec7520b24cd80d34d82bbcaca153cbb23cc04bc0rjung }
ec7520b24cd80d34d82bbcaca153cbb23cc04bc0rjung else
ec7520b24cd80d34d82bbcaca153cbb23cc04bc0rjung exinfo = (extension_info*)apr_hash_get(m->extension_mappings, key,
ec7520b24cd80d34d82bbcaca153cbb23cc04bc0rjung APR_HASH_KEY_STRING);
ec7520b24cd80d34d82bbcaca153cbb23cc04bc0rjung if (!exinfo) {
ec7520b24cd80d34d82bbcaca153cbb23cc04bc0rjung exinfo = apr_pcalloc(cmd->pool, sizeof(extension_info));
ec7520b24cd80d34d82bbcaca153cbb23cc04bc0rjung key = apr_pstrdup(cmd->pool, key);
ec7520b24cd80d34d82bbcaca153cbb23cc04bc0rjung apr_hash_set(m->extension_mappings, key,
6249dfa569d3b4f1f539665b979a80c6e335d93etrawick APR_HASH_KEY_STRING, exinfo);
6249dfa569d3b4f1f539665b979a80c6e335d93etrawick }
0827cb14e550f6f65018431c22c2c913631c8f25kbrand *(const char**)((char *)exinfo + offset) = value;
6249dfa569d3b4f1f539665b979a80c6e335d93etrawick return NULL;
ae600ca541efc686b34f8b1f21bd3d0741d37674covener}
6249dfa569d3b4f1f539665b979a80c6e335d93etrawick
cfa64348224b66dd1c9979b809406c4d15b1c137fielding/*
74499a117b3b2cd9666715a14f90c0e5d1a4ee8ajim * Note handler names are un-added with each per_dir_config merge.
cfa64348224b66dd1c9979b809406c4d15b1c137fielding * This keeps the association from being inherited, but not
74499a117b3b2cd9666715a14f90c0e5d1a4ee8ajim * from being re-added at a subordinate level.
cfa64348224b66dd1c9979b809406c4d15b1c137fielding */
74499a117b3b2cd9666715a14f90c0e5d1a4ee8ajimstatic const char *remove_extension_info(cmd_parms *cmd, void *m_,
cfa64348224b66dd1c9979b809406c4d15b1c137fielding const char *ext)
74499a117b3b2cd9666715a14f90c0e5d1a4ee8ajim{
cfa64348224b66dd1c9979b809406c4d15b1c137fielding 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 "Any is incompatible with NegotiatedOnly, "
"Filters and Handlers";
m->multimatch |= MULTIMATCH_NEGOTIATED;
}
else if (strcasecmp(include, "Filters") == 0) {
if (m->multimatch && (m->multimatch & (MULTIMATCH_NEGOTIATED
| MULTIMATCH_ANY)))
return "Filters is incompatible with Any and NegotiatedOnly";
m->multimatch |= MULTIMATCH_FILTERS;
}
else if (strcasecmp(include, "Handlers") == 0) {
if (m->multimatch && (m->multimatch & (MULTIMATCH_NEGOTIATED
| MULTIMATCH_ANY)))
return "Handlers is incompatible with Any and NegotiatedOnly";
m->multimatch |= MULTIMATCH_HANDLERS;
}
else
return "Unrecognized option";
return NULL;
}
static const command_rec mime_cmds[] =
{
AP_INIT_ITERATE2("AddCharset", add_extension_info,
(void *)APR_XtOffsetOf(extension_info, charset_type), OR_FILEINFO,
"a charset (e.g., iso-2022-jp), followed by one or more file extensions"),
AP_INIT_ITERATE2("AddEncoding", add_extension_info,
(void *)APR_XtOffsetOf(extension_info, encoding_type), OR_FILEINFO,
"an encoding (e.g., gzip), followed by one or more file extensions"),
AP_INIT_ITERATE2("AddHandler", add_extension_info,
(void *)APR_XtOffsetOf(extension_info, handler), OR_FILEINFO,
"a handler name followed by one or more file extensions"),
AP_INIT_ITERATE2("AddInputFilter", add_extension_info,
(void *)APR_XtOffsetOf(extension_info, input_filters), OR_FILEINFO,
"input filter name (or ; delimited names) followed by one or more file extensions"),
AP_INIT_ITERATE2("AddLanguage", add_extension_info,
(void *)APR_XtOffsetOf(extension_info, language_type), OR_FILEINFO,
"a language (e.g., fr), followed by one or more file extensions"),
AP_INIT_ITERATE2("AddOutputFilter", add_extension_info,
(void *)APR_XtOffsetOf(extension_info, output_filters), OR_FILEINFO,
"output filter name (or ; delimited names) followed by one or more file extensions"),
AP_INIT_ITERATE2("AddType", add_extension_info,
(void *)APR_XtOffsetOf(extension_info, forced_type), OR_FILEINFO,
"a mime type followed by one or more file extensions"),
AP_INIT_TAKE1("DefaultLanguage", ap_set_string_slot,
(void*)APR_XtOffsetOf(mime_dir_config, default_language), OR_FILEINFO,
"language to use for documents with no other language file extension"),
AP_INIT_ITERATE("MultiviewsMatch", multiviews_match, NULL, OR_FILEINFO,
"NegotiatedOnly (default), Handlers and/or Filters, or Any"),
AP_INIT_ITERATE("RemoveCharset", remove_extension_info,
(void *)APR_XtOffsetOf(extension_info, charset_type), OR_FILEINFO,
"one or more file extensions"),
AP_INIT_ITERATE("RemoveEncoding", remove_extension_info,
(void *)APR_XtOffsetOf(extension_info, encoding_type), OR_FILEINFO,
"one or more file extensions"),
AP_INIT_ITERATE("RemoveHandler", remove_extension_info,
(void *)APR_XtOffsetOf(extension_info, handler), OR_FILEINFO,
"one or more file extensions"),
AP_INIT_ITERATE("RemoveInputFilter", remove_extension_info,
(void *)APR_XtOffsetOf(extension_info, input_filters), OR_FILEINFO,
"one or more file extensions"),
AP_INIT_ITERATE("RemoveLanguage", remove_extension_info,
(void *)APR_XtOffsetOf(extension_info, language_type), OR_FILEINFO,
"one or more file extensions"),
AP_INIT_ITERATE("RemoveOutputFilter", remove_extension_info,
(void *)APR_XtOffsetOf(extension_info, output_filters), OR_FILEINFO,
"one or more file extensions"),
AP_INIT_ITERATE("RemoveType", remove_extension_info,
(void *)APR_XtOffsetOf(extension_info, forced_type), OR_FILEINFO,
"one or more file extensions"),
AP_INIT_TAKE1("TypesConfig", set_types_config, NULL, RSRC_CONF,
"the MIME types config file"),
{NULL}
};
static apr_hash_t *mime_type_extensions;
static int mime_post_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
{
ap_configfile_t *f;
char l[MAX_STRING_LEN];
const char *types_confname = ap_get_module_config(s->module_config, &mime_module);
apr_status_t status;
if (!types_confname)
types_confname = AP_TYPES_CONFIG_FILE;
types_confname = ap_server_root_relative(p, types_confname);
if (!types_confname) {
ap_log_error(APLOG_MARK, APLOG_ERR, APR_EBADPATH, s,
"Invalid mime types config path %s",
(const char *)ap_get_module_config(s->module_config, &mime_module));
return HTTP_INTERNAL_SERVER_ERROR;
}
if ((status = ap_pcfg_openfile(&f, ptemp, types_confname))
!= APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_ERR, status, s,
"could not open mime types config file %s.",
types_confname);
return HTTP_INTERNAL_SERVER_ERROR;
}
mime_type_extensions = apr_hash_make(p);
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);
apr_hash_set(mime_type_extensions, ext, APR_HASH_KEY_STRING, ct);
}
}
ap_cfg_closefile(f);
return OK;
}
static const char *zap_sp(const char *s)
{
if (s == NULL) {
return (NULL);
}
if (*s == '\0') {
return (s);
}
/* skip prefixed white space */
for (; *s == ' ' || *s == '\t' || *s == '\n'; s++);
return (s);
}
static char *zap_sp_and_dup(apr_pool_t *p, const char *start,
const char *end, apr_size_t *len)
{
while ((start < end) && apr_isspace(*start)) {
start++;
}
while ((end > start) && apr_isspace(*(end - 1))) {
end--;
}
if (len) {
*len = end - start;
}
return apr_pstrmemdup(p, start, end - start);
}
static int is_token(char c)
{
int res;
res = (apr_isascii(c) && apr_isgraph(c)
&& (strchr(tspecial, c) == NULL)) ? 1 : -1;
return res;
}
static int is_qtext(char c)
{
int res;
res = (apr_isascii(c) && (c != '"') && (c != '\\') && (c != '\n'))
? 1 : -1;
return res;
}
static int is_quoted_pair(const char *s)
{
int res = -1;
int c;
if (((s + 1) != NULL) && (*s == '\\')) {
c = (int) *(s + 1);
if (apr_isascii(c)) {
res = 1;
}
}
return (res);
}
static content_type *analyze_ct(request_rec *r, const char *s)
{
const char *cp, *mp, *tmp;
char *attribute, *value;
int quoted = 0;
server_rec * ss = r->server;
apr_pool_t * p = r->pool;
content_type *ctp;
param *pp, *npp;
/* initialize ctp */
ctp = (content_type *) apr_palloc(p, sizeof(content_type));
ctp->type = NULL;
ctp->subtype = NULL;
ctp->param = NULL;
mp = s;
/* getting a type */
if (!(cp = ap_strchr_c(mp, '/'))) {
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ss,
"mod_mime: analyze_ct: cannot get media type from '%s'",
(const char *) mp);
return (NULL);
}
ctp->type = zap_sp_and_dup(p, mp, cp, NULL);
if (ctp->type == NULL || *(ctp->type) == '\0') {
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ss,
"Cannot get media subtype.");
return (NULL);
}
for (tmp = ctp->type; *tmp; tmp++) {
if ((*tmp == ';') || (*tmp == ' ') || (*tmp == '\t')) {
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ss,
"Cannot get media subtype.");
return (NULL);
}
}
/* getting a subtype */
cp++;
mp = cp;
for (; *cp != ';' && *cp != '\0'; cp++)
continue;
ctp->subtype = zap_sp_and_dup(p, mp, cp, NULL);
if ((ctp->subtype == NULL) || (*(ctp->subtype) == '\0')) {
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ss,
"Cannot get media subtype.");
return (NULL);
}
for (tmp = ctp->subtype; *tmp; tmp++) {
if ((*tmp == ' ') || (*tmp == '\t')) {
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ss,
"Cannot get media subtype.");
return (NULL);
}
}
if (*cp == '\0') {
return (ctp);
}
/* getting parameters */
cp++;
cp = zap_sp(cp);
if (cp == NULL || *cp == '\0') {
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ss,
"Cannot get media parameter.");
return (NULL);
}
mp = cp;
attribute = NULL;
value = NULL;
while (cp != NULL && *cp != '\0') {
if (attribute == NULL) {
if (is_token(*cp) > 0) {
cp++;
continue;
}
else if (*cp == ' ' || *cp == '\t' || *cp == '\n') {
cp++;
continue;
}
else if (*cp == '=') {
attribute = zap_sp_and_dup(p, mp, cp, NULL);
if (attribute == NULL || *attribute == '\0') {
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ss,
"Cannot get media parameter.");
return (NULL);
}
cp++;
cp = zap_sp(cp);
if (cp == NULL || *cp == '\0') {
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ss,
"Cannot get media parameter.");
return (NULL);
}
mp = cp;
continue;
}
else {
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ss,
"Cannot get media parameter.");
return (NULL);
}
}
else {
if (mp == cp) {
if (*cp == '"') {
quoted = 1;
cp++;
}
else {
quoted = 0;
}
}
if (quoted > 0) {
while (quoted && *cp != '\0') {
if (is_qtext(*cp) > 0) {
cp++;
}
else if (is_quoted_pair(cp) > 0) {
cp += 2;
}
else if (*cp == '"') {
cp++;
while (*cp == ' ' || *cp == '\t' || *cp == '\n') {
cp++;
}
if (*cp != ';' && *cp != '\0') {
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ss,
"Cannot get media parameter.");
return(NULL);
}
quoted = 0;
}
else {
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ss,
"Cannot get media parameter.");
return (NULL);
}
}
}
else {
while (1) {
if (is_token(*cp) > 0) {
cp++;
}
else if (*cp == '\0' || *cp == ';') {
break;
}
else {
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ss,
"Cannot get media parameter.");
return (NULL);
}
}
}
value = zap_sp_and_dup(p, mp, cp, NULL);
if (value == NULL || *value == '\0') {
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ss,
"Cannot get media parameter.");
return (NULL);
}
pp = apr_palloc(p, sizeof(param));
pp->attr = attribute;
pp->val = value;
pp->next = NULL;
if (ctp->param == NULL) {
ctp->param = pp;
}
else {
npp = ctp->param;
while (npp->next) {
npp = npp->next;
}
npp->next = pp;
}
quoted = 0;
attribute = NULL;
value = NULL;
if (*cp == '\0') {
break;
}
cp++;
mp = cp;
}
}
return (ctp);
}
/*
* find_ct is the hook routine for determining content-type and other
* MIME-related metadata. It assumes that r->filename has already been
* set and stat has been called for r->finfo. It also assumes that the
* non-path base file name is not the empty string unless it is a dir.
*/
static int find_ct(request_rec *r)
{
mime_dir_config *conf;
apr_array_header_t *exception_list;
char *ext;
const char *fn, *type, *charset = NULL;
int found_metadata = 0;
if (r->finfo.filetype == APR_DIR) {
ap_set_content_type(r, DIR_MAGIC_TYPE);
return OK;
}
conf = (mime_dir_config *) ap_get_module_config(r->per_dir_config,
&mime_module);
exception_list = apr_array_make(r->pool, 2, sizeof(char *));
/* Always drop the path leading up to the file name.
*/
if ((fn = strrchr(r->filename, '/')) == NULL)
fn = r->filename;
else
++fn;
/* The exception list keeps track of those filename components that
* are not associated with extensions indicating metadata.
* The base name is always the first exception (i.e., "txt.html" has
* a basename of "txt" even though it might look like an extension).
*/
ext = ap_getword(r->pool, &fn, '.');
*((const char **) apr_array_push(exception_list)) = ext;
/* Parse filename extensions which can be in any order
*/
while (*fn && (ext = ap_getword(r->pool, &fn, '.'))) {
const extension_info *exinfo = NULL;
int found;
if (*ext == '\0') /* ignore empty extensions "bad..html" */
continue;
found = 0;
ap_str_tolower(ext);
if (conf->extension_mappings != NULL) {
exinfo = (extension_info*)apr_hash_get(conf->extension_mappings,
ext, APR_HASH_KEY_STRING);
}
if (exinfo == NULL || !exinfo->forced_type) {
if ((type = apr_hash_get(mime_type_extensions, ext,
APR_HASH_KEY_STRING)) != NULL) {
ap_set_content_type(r, (char*) type);
found = 1;
}
}
if (exinfo != NULL) {
if (exinfo->forced_type) {
ap_set_content_type(r, exinfo->forced_type);
found = 1;
}
if (exinfo->charset_type) {
charset = exinfo->charset_type;
found = 1;
}
if (exinfo->language_type) {
if (!r->content_languages)
r->content_languages = apr_array_make(r->pool, 2,
sizeof(char *));
*((const char **) apr_array_push(r->content_languages))
= exinfo->language_type;
found = 1;
}
if (exinfo->encoding_type) {
if (!r->content_encoding)
r->content_encoding = exinfo->encoding_type;
else {
/* XXX should eliminate duplicate entities */
r->content_encoding = apr_pstrcat(r->pool,
r->content_encoding,
", ",
exinfo->encoding_type,
NULL);
}
found = 1;
}
/* The following extensions are not 'Found'. That is, they don't
* make any contribution to metadata negotation, so they must have
* been explicitly requested by name.
*/
if (exinfo->handler && r->proxyreq == PROXYREQ_NONE) {
r->handler = exinfo->handler;
if (conf->multimatch & MULTIMATCH_HANDLERS)
found = 1;
}
/* XXX Two significant problems; 1, we don't check to see if we are
* setting redundant filters. 2, we insert these in the types config
* hook, which may be too early (dunno.)
*/
if (exinfo->input_filters && r->proxyreq == PROXYREQ_NONE) {
const char *filter, *filters = exinfo->input_filters;
while (*filters
&& (filter = ap_getword(r->pool, &filters, ';'))) {
ap_add_input_filter(filter, NULL, r, r->connection);
}
if (conf->multimatch & MULTIMATCH_FILTERS)
found = 1;
}
if (exinfo->output_filters && r->proxyreq == PROXYREQ_NONE) {
const char *filter, *filters = exinfo->output_filters;
while (*filters
&& (filter = ap_getword(r->pool, &filters, ';'))) {
ap_add_output_filter(filter, NULL, r, r->connection);
}
if (conf->multimatch & MULTIMATCH_FILTERS)
found = 1;
}
}
if (found || (conf->multimatch & MULTIMATCH_ANY))
found_metadata = 1;
else
*((const char **) apr_array_push(exception_list)) = ext;
}
/*
* Need to set a notes entry on r for unrecognized elements.
* Somebody better claim them! If we did absolutely nothing,
* skip the notes to alert mod_negotiation we are clueless.
*/
if (found_metadata) {
apr_table_setn(r->notes, "ap-mime-exceptions-list",
(void *)exception_list);
}
if (r->content_type) {
content_type *ctp;
int override = 0;
if ((ctp = analyze_ct(r, r->content_type))) {
param *pp = ctp->param;
ap_set_content_type(r, apr_pstrcat(r->pool, ctp->type, "/",
ctp->subtype, NULL));
while (pp != NULL) {
if (charset && !strcmp(pp->attr, "charset")) {
if (!override) {
ap_set_content_type(r, apr_pstrcat(r->pool, r->content_type,
"; charset=", charset,
NULL));
override = 1;
}
}
else {
ap_set_content_type(r, apr_pstrcat(r->pool, r->content_type,
"; ", pp->attr,
"=", pp->val,
NULL));
}
pp = pp->next;
}
if (charset && !override) {
ap_set_content_type(r, apr_pstrcat(r->pool, r->content_type,
"; charset=", charset,
NULL));
}
}
}
/* Set default language, if none was specified by the extensions
* and we have a DefaultLanguage setting in force
*/
if (!r->content_languages && conf->default_language) {
const char **new;
if (!r->content_languages)
r->content_languages = apr_array_make(r->pool, 2, sizeof(char *));
new = (const char **) apr_array_push(r->content_languages);
*new = conf->default_language;
}
if (!r->content_type)
return DECLINED;
return OK;
}
static void register_hooks(apr_pool_t *p)
{
ap_hook_post_config(mime_post_config,NULL,NULL,APR_HOOK_MIDDLE);
ap_hook_type_checker(find_ct,NULL,NULL,APR_HOOK_MIDDLE);
/*
* this hook seems redundant ... is there any reason a type checker isn't
* allowed to do this already? I'd think that fixups in general would be
* the last opportunity to get the filters right.
* ap_hook_insert_filter(mime_insert_filters,NULL,NULL,APR_HOOK_MIDDLE);
*/
}
module AP_MODULE_DECLARE_DATA mime_module = {
STANDARD20_MODULE_STUFF,
create_mime_dir_config, /* create per-directory config structure */
merge_mime_dir_configs, /* merge per-directory config structures */
NULL, /* create per-server config structure */
NULL, /* merge per-server config structures */
mime_cmds, /* command apr_table_t */
register_hooks /* register hooks */
};