home *** CD-ROM | disk | FTP | other *** search
/ PC Online 1999 April / PCO0499.ISO / filesbbs / os2 / apach134.arj / APACH134.ZIP / src / modules / standard / mod_mime.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-01-01  |  14.0 KB  |  408 lines

  1. /* ====================================================================
  2.  * Copyright (c) 1995-1999 The Apache Group.  All rights reserved.
  3.  *
  4.  * Redistribution and use in source and binary forms, with or without
  5.  * modification, are permitted provided that the following conditions
  6.  * are met:
  7.  *
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer. 
  10.  *
  11.  * 2. Redistributions in binary form must reproduce the above copyright
  12.  *    notice, this list of conditions and the following disclaimer in
  13.  *    the documentation and/or other materials provided with the
  14.  *    distribution.
  15.  *
  16.  * 3. All advertising materials mentioning features or use of this
  17.  *    software must display the following acknowledgment:
  18.  *    "This product includes software developed by the Apache Group
  19.  *    for use in the Apache HTTP server project (http://www.apache.org/)."
  20.  *
  21.  * 4. The names "Apache Server" and "Apache Group" must not be used to
  22.  *    endorse or promote products derived from this software without
  23.  *    prior written permission. For written permission, please contact
  24.  *    apache@apache.org.
  25.  *
  26.  * 5. Products derived from this software may not be called "Apache"
  27.  *    nor may "Apache" appear in their names without prior written
  28.  *    permission of the Apache Group.
  29.  *
  30.  * 6. Redistributions of any form whatsoever must retain the following
  31.  *    acknowledgment:
  32.  *    "This product includes software developed by the Apache Group
  33.  *    for use in the Apache HTTP server project (http://www.apache.org/)."
  34.  *
  35.  * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
  36.  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  37.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  38.  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE APACHE GROUP OR
  39.  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  40.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  41.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  42.  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  43.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  44.  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  45.  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  46.  * OF THE POSSIBILITY OF SUCH DAMAGE.
  47.  * ====================================================================
  48.  *
  49.  * This software consists of voluntary contributions made by many
  50.  * individuals on behalf of the Apache Group and was originally based
  51.  * on public domain software written at the National Center for
  52.  * Supercomputing Applications, University of Illinois, Urbana-Champaign.
  53.  * For more information on the Apache Group and the Apache HTTP server
  54.  * project, please see <http://www.apache.org/>.
  55.  *
  56.  */
  57.  
  58. /*
  59.  * http_mime.c: Sends/gets MIME headers for requests
  60.  * 
  61.  * Rob McCool
  62.  * 
  63.  */
  64.  
  65. #define MIME_PRIVATE
  66.  
  67. #include "httpd.h"
  68. #include "http_config.h"
  69. #include "http_log.h"
  70.  
  71. typedef struct handlers_info {
  72.     char *name;
  73. } handlers_info;
  74.  
  75. typedef struct {
  76.     table *forced_types;        /* Additional AddTyped stuff */
  77.     table *encoding_types;      /* Added with AddEncoding... */
  78.     table *language_types;      /* Added with AddLanguage... */
  79.     table *handlers;            /* Added with AddHandler...  */
  80.     array_header *handlers_remove;     /* List of handlers to remove */
  81.  
  82.     char *type;                 /* Type forced with ForceType  */
  83.     char *handler;              /* Handler forced with SetHandler */
  84.     char *default_language;     /* Language if no AddLanguage ext found */
  85. } mime_dir_config;
  86.  
  87. module MODULE_VAR_EXPORT mime_module;
  88.  
  89. static void *create_mime_dir_config(pool *p, char *dummy)
  90. {
  91.     mime_dir_config *new =
  92.     (mime_dir_config *) ap_palloc(p, sizeof(mime_dir_config));
  93.  
  94.     new->forced_types = ap_make_table(p, 4);
  95.     new->encoding_types = ap_make_table(p, 4);
  96.     new->language_types = ap_make_table(p, 4);
  97.     new->handlers = ap_make_table(p, 4);
  98.     new->handlers_remove = ap_make_array(p, 4, sizeof(handlers_info));
  99.  
  100.     new->type = NULL;
  101.     new->handler = NULL;
  102.     new->default_language = NULL;
  103.  
  104.     return new;
  105. }
  106.  
  107. static void *merge_mime_dir_configs(pool *p, void *basev, void *addv)
  108. {
  109.     mime_dir_config *base = (mime_dir_config *) basev;
  110.     mime_dir_config *add = (mime_dir_config *) addv;
  111.     mime_dir_config *new =
  112.         (mime_dir_config *) ap_palloc(p, sizeof(mime_dir_config));
  113.     int i;
  114.     handlers_info *hand;
  115.  
  116.     hand = (handlers_info *) add->handlers_remove->elts;
  117.     for (i = 0; i < add->handlers_remove->nelts; i++) {
  118.         ap_table_unset(base->handlers, hand[i].name);
  119.     }
  120.  
  121.     new->forced_types = ap_overlay_tables(p, add->forced_types,
  122.                                        base->forced_types);
  123.     new->encoding_types = ap_overlay_tables(p, add->encoding_types,
  124.                                          base->encoding_types);
  125.     new->language_types = ap_overlay_tables(p, add->language_types,
  126.                                          base->language_types);
  127.     new->handlers = ap_overlay_tables(p, add->handlers,
  128.                                    base->handlers);
  129.  
  130.     new->type = add->type ? add->type : base->type;
  131.     new->handler = add->handler ? add->handler : base->handler;
  132.     new->default_language = add->default_language ?
  133.         add->default_language : base->default_language;
  134.  
  135.     return new;
  136. }
  137.  
  138. static const char *add_type(cmd_parms *cmd, mime_dir_config * m, char *ct,
  139.                             char *ext)
  140. {
  141.     if (*ext == '.')
  142.         ++ext;
  143.     ap_str_tolower(ct);
  144.     ap_table_setn(m->forced_types, ext, ct);
  145.     return NULL;
  146. }
  147.  
  148. static const char *add_encoding(cmd_parms *cmd, mime_dir_config * m, char *enc,
  149.                                 char *ext)
  150. {
  151.     if (*ext == '.')
  152.         ++ext;
  153.     ap_str_tolower(enc);
  154.     ap_table_setn(m->encoding_types, ext, enc);
  155.     return NULL;
  156. }
  157.  
  158. static const char *add_language(cmd_parms *cmd, mime_dir_config * m, char *lang,
  159.                                 char *ext)
  160. {
  161.     if (*ext == '.')
  162.         ++ext;
  163.     ap_str_tolower(lang);
  164.     ap_table_setn(m->language_types, ext, lang);
  165.     return NULL;
  166. }
  167.  
  168. static const char *add_handler(cmd_parms *cmd, mime_dir_config * m, char *hdlr,
  169.                                char *ext)
  170. {
  171.     if (*ext == '.')
  172.         ++ext;
  173.     ap_str_tolower(hdlr);
  174.     ap_table_setn(m->handlers, ext, hdlr);
  175.     return NULL;
  176. }
  177.  
  178. /*
  179.  * Note handler names that should be un-added for this location.  This
  180.  * will keep the association from being inherited, as well, but not
  181.  * from being re-added at a subordinate level.
  182.  */
  183. static const char *remove_handler(cmd_parms *cmd, void *m, char *ext)
  184. {
  185.     mime_dir_config *mcfg = (mime_dir_config *) m;
  186.     handlers_info *hand;
  187.  
  188.     if (*ext == '.') {
  189.         ++ext;
  190.     }
  191.     hand = (handlers_info *) ap_push_array(mcfg->handlers_remove);
  192.     hand->name = ap_pstrdup(cmd->pool, ext);
  193.     return NULL;
  194. }
  195.  
  196. /* The sole bit of server configuration that the MIME module has is
  197.  * the name of its config file, so...
  198.  */
  199.  
  200. static const char *set_types_config(cmd_parms *cmd, void *dummy, char *arg)
  201. {
  202.     ap_set_module_config(cmd->server->module_config, &mime_module, arg);
  203.     return NULL;
  204. }
  205.  
  206. static const command_rec mime_cmds[] =
  207. {
  208.     {"AddType", add_type, NULL, OR_FILEINFO, ITERATE2,
  209.      "a mime type followed by one or more file extensions"},
  210.     {"AddEncoding", add_encoding, NULL, OR_FILEINFO, ITERATE2,
  211.      "an encoding (e.g., gzip), followed by one or more file extensions"},
  212.     {"AddLanguage", add_language, NULL, OR_FILEINFO, ITERATE2,
  213.      "a language (e.g., fr), followed by one or more file extensions"},
  214.     {"AddHandler", add_handler, NULL, OR_FILEINFO, ITERATE2,
  215.      "a handler name followed by one or more file extensions"},
  216.     {"ForceType", ap_set_string_slot_lower, 
  217.      (void *)XtOffsetOf(mime_dir_config, type), OR_FILEINFO, TAKE1, 
  218.      "a media type"},
  219.     {"RemoveHandler", remove_handler, NULL, OR_FILEINFO, ITERATE,
  220.      "one or more file extensions"},
  221.     {"SetHandler", ap_set_string_slot_lower, 
  222.      (void *)XtOffsetOf(mime_dir_config, handler), OR_FILEINFO, TAKE1, 
  223.      "a handler name"},
  224.     {"TypesConfig", set_types_config, NULL, RSRC_CONF, TAKE1,
  225.      "the MIME types config file"},
  226.     {"DefaultLanguage", ap_set_string_slot,
  227.      (void*)XtOffsetOf(mime_dir_config, default_language), OR_FILEINFO, TAKE1,
  228.      "language to use for documents with no other language file extension" },
  229.     {NULL}
  230. };
  231.  
  232. /* Hash table  --- only one of these per daemon; virtual hosts can
  233.  * get private versions through AddType...
  234.  */
  235.  
  236. /* MIME_HASHSIZE used to be 27 (26 chars and one "non-alpha" slot), but
  237.  * with character sets like EBCDIC, this is insufficient because the
  238.  * range 'a'...'z' is not contigous. Defining it as ('z'-'a'+2) is
  239.  * equivalent to 27 in ASCII, and makes it work in EBCDIC.
  240.  */
  241. #define MIME_HASHSIZE ('z'-'a'+2)
  242. #define hash(i) (ap_isalpha(i) ? (ap_tolower(i)) - 'a' : (MIME_HASHSIZE-1))
  243.  
  244. static table *hash_buckets[MIME_HASHSIZE];
  245.  
  246. static void init_mime(server_rec *s, pool *p)
  247. {
  248.     configfile_t *f;
  249.     char l[MAX_STRING_LEN];
  250.     int x;
  251.     char *types_confname = ap_get_module_config(s->module_config, &mime_module);
  252.  
  253.     if (!types_confname)
  254.         types_confname = TYPES_CONFIG_FILE;
  255.  
  256.     types_confname = ap_server_root_relative(p, types_confname);
  257.  
  258.     if (!(f = ap_pcfg_openfile(p, types_confname))) {
  259.         ap_log_error(APLOG_MARK, APLOG_ERR, s,
  260.              "could not open mime types log file %s.", types_confname);
  261.         exit(1);
  262.     }
  263.  
  264.     for (x = 0; x < MIME_HASHSIZE; x++)
  265.         hash_buckets[x] = ap_make_table(p, 10);
  266.  
  267.     while (!(ap_cfg_getline(l, MAX_STRING_LEN, f))) {
  268.         const char *ll = l, *ct;
  269.  
  270.         if (l[0] == '#')
  271.             continue;
  272.         ct = ap_getword_conf(p, &ll);
  273.  
  274.         while (ll[0]) {
  275.             char *ext = ap_getword_conf(p, &ll);
  276.             ap_str_tolower(ext);   /* ??? */
  277.             ap_table_setn(hash_buckets[hash(ext[0])], ext, ct);
  278.         }
  279.     }
  280.     ap_cfg_closefile(f);
  281. }
  282.  
  283. static int find_ct(request_rec *r)
  284. {
  285.     const char *fn = strrchr(r->filename, '/');
  286.     mime_dir_config *conf =
  287.     (mime_dir_config *) ap_get_module_config(r->per_dir_config, &mime_module);
  288.     char *ext;
  289.     const char *orighandler = r->handler;
  290.     const char *type;
  291.  
  292.     if (S_ISDIR(r->finfo.st_mode)) {
  293.         r->content_type = DIR_MAGIC_TYPE;
  294.         return OK;
  295.     }
  296.  
  297.     /* TM -- FIXME
  298.      * if r->filename does not contain a '/', the following passes a null
  299.      * pointer to getword, causing a SEGV ..
  300.      */
  301.  
  302.     if (fn == NULL)
  303.         fn = r->filename;
  304.  
  305.     /* Parse filename extensions, which can be in any order */
  306.     while ((ext = ap_getword(r->pool, &fn, '.')) && *ext) {
  307.         int found = 0;
  308.  
  309.         /* Check for Content-Type */
  310.         if ((type = ap_table_get(conf->forced_types, ext))
  311.             || (type = ap_table_get(hash_buckets[hash(*ext)], ext))) {
  312.             r->content_type = type;
  313.             found = 1;
  314.         }
  315.  
  316.         /* Check for Content-Language */
  317.         if ((type = ap_table_get(conf->language_types, ext))) {
  318.             const char **new;
  319.  
  320.             r->content_language = type;         /* back compat. only */
  321.             if (!r->content_languages)
  322.                 r->content_languages = ap_make_array(r->pool, 2, sizeof(char *));
  323.             new = (const char **) ap_push_array(r->content_languages);
  324.             *new = type;
  325.             found = 1;
  326.         }
  327.  
  328.         /* Check for Content-Encoding */
  329.         if ((type = ap_table_get(conf->encoding_types, ext))) {
  330.             if (!r->content_encoding)
  331.                 r->content_encoding = type;
  332.             else
  333.                 r->content_encoding = ap_pstrcat(r->pool, r->content_encoding,
  334.                                               ", ", type, NULL);
  335.             found = 1;
  336.         }
  337.  
  338.         /* Check for a special handler, but not for proxy request */
  339.         if ((type = ap_table_get(conf->handlers, ext)) && !r->proxyreq) {
  340.             r->handler = type;
  341.             found = 1;
  342.         }
  343.  
  344.         /* This is to deal with cases such as foo.gif.bak, which we want
  345.          * to not have a type. So if we find an unknown extension, we
  346.          * zap the type/language/encoding and reset the handler
  347.          */
  348.  
  349.         if (!found) {
  350.             r->content_type = NULL;
  351.             r->content_language = NULL;
  352.             r->content_languages = NULL;
  353.             r->content_encoding = NULL;
  354.             r->handler = orighandler;
  355.         }
  356.  
  357.     }
  358.  
  359.     /* Set default language, if none was specified by the extensions
  360.      * and we have a DefaultLanguage setting in force
  361.      */
  362.  
  363.     if (!r->content_languages && conf->default_language) {
  364.         const char **new;
  365.  
  366.         r->content_language = conf->default_language; /* back compat. only */
  367.         if (!r->content_languages)
  368.             r->content_languages = ap_make_array(r->pool, 2, sizeof(char *));
  369.         new = (const char **) ap_push_array(r->content_languages);
  370.         *new = conf->default_language;
  371.     }
  372.  
  373.     /* Check for overrides with ForceType/SetHandler */
  374.  
  375.     if (conf->type && strcmp(conf->type, "none"))
  376.         r->content_type = conf->type;
  377.     if (conf->handler && strcmp(conf->handler, "none"))
  378.         r->handler = conf->handler;
  379.  
  380.     if (!r->content_type)
  381.         return DECLINED;
  382.  
  383.     return OK;
  384. }
  385.  
  386. module MODULE_VAR_EXPORT mime_module =
  387. {
  388.     STANDARD_MODULE_STUFF,
  389.     init_mime,                  /* initializer */
  390.     create_mime_dir_config,     /* dir config creator */
  391.     merge_mime_dir_configs,     /* dir config merger */
  392.     NULL,                       /* server config */
  393.     NULL,                       /* merge server config */
  394.     mime_cmds,                  /* command table */
  395.     NULL,                       /* handlers */
  396.     NULL,                       /* filename translation */
  397.     NULL,                       /* check_user_id */
  398.     NULL,                       /* check auth */
  399.     NULL,                       /* check access */
  400.     find_ct,                    /* type_checker */
  401.     NULL,                       /* fixups */
  402.     NULL,                       /* logger */
  403.     NULL,                       /* header parser */
  404.     NULL,                       /* child_init */
  405.     NULL,                       /* child_exit */
  406.     NULL                        /* post read-request */
  407. };
  408.