home *** CD-ROM | disk | FTP | other *** search
/ PC Online 1999 April / PCO0499.ISO / filesbbs / os2 / apach134.arj / APACH134.ZIP / src / modules / standard / mod_cern_meta.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-01-01  |  12.3 KB  |  396 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.  * IT'S 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.  * mod_cern_meta.c
  60.  * version 0.1.0
  61.  * status beta
  62.  * 
  63.  * Andrew Wilson <Andrew.Wilson@cm.cf.ac.uk> 25.Jan.96
  64.  *
  65.  * *** IMPORTANT ***
  66.  * This version of mod_cern_meta.c controls Meta File behaviour on a
  67.  * per-directory basis.  Previous versions of the module defined behaviour
  68.  * on a per-server basis.  The upshot is that you'll need to revisit your 
  69.  * configuration files in order to make use of the new module.
  70.  * ***
  71.  *
  72.  * Emulate the CERN HTTPD Meta file semantics.  Meta files are HTTP
  73.  * headers that can be output in addition to the normal range of
  74.  * headers for each file accessed.  They appear rather like the Apache
  75.  * .asis files, and are able to provide a crude way of influencing
  76.  * the Expires: header, as well as providing other curiosities.
  77.  * There are many ways to manage meta information, this one was
  78.  * chosen because there is already a large number of CERN users
  79.  * who can exploit this module.  It should be noted that there are probably
  80.  * more sensitive ways of managing the Expires: header specifically.
  81.  *
  82.  * The module obeys the following directives, which can appear 
  83.  * in the server's .conf files and in .htaccess files.
  84.  *
  85.  *  MetaFiles <on|off> 
  86.  *
  87.  *    turns on|off meta file processing for any directory.  
  88.  *    Default value is off
  89.  *
  90.  *        # turn on MetaFiles in this directory
  91.  *        MetaFiles on
  92.  *
  93.  *  MetaDir <directory name>
  94.  *      
  95.  *    specifies the name of the directory in which Apache can find
  96.  *    meta information files.  The directory is usually a 'hidden'
  97.  *    subdirectory of the directory that contains the file being
  98.  *    accessed.  eg:
  99.  *
  100.  *        # .meta files are in the *same* directory as the 
  101.  *        # file being accessed
  102.  *        MetaDir .
  103.  *
  104.  *    the default is to look in a '.web' subdirectory. This is the
  105.  *    same as for CERN 3.+ webservers and behaviour is the same as 
  106.  *    for the directive:
  107.  *
  108.  *        MetaDir .web
  109.  *
  110.  *  MetaSuffix <meta file suffix>
  111.  *
  112.  *    specifies the file name suffix for the file containing the
  113.  *    meta information.  eg:
  114.  *
  115.  *       # our meta files are suffixed with '.cern_meta'
  116.  *       MetaSuffix .cern_meta
  117.  *
  118.  *    the default is to look for files with the suffix '.meta'.  This
  119.  *    behaviour is the same as for the directive:
  120.  *
  121.  *       MetaSuffix .meta
  122.  *
  123.  * When accessing the file
  124.  *
  125.  *   DOCUMENT_ROOT/somedir/index.html
  126.  *
  127.  * this module will look for the file
  128.  *
  129.  *   DOCUMENT_ROOT/somedir/.web/index.html.meta
  130.  *
  131.  * and will use its contents to generate additional MIME header 
  132.  * information.
  133.  *
  134.  * For more information on the CERN Meta file semantics see:
  135.  *
  136.  *   http://www.w3.org/hypertext/WWW/Daemon/User/Config/General.html#MetaDir
  137.  *
  138.  * Change-log:
  139.  * 29.Jan.96 pfopen/pfclose instead of fopen/fclose
  140.  *           DECLINE when real file not found, we may be checking each
  141.  *           of the index.html/index.shtml/index.htm variants and don't
  142.  *           need to report missing ones as spurious errors. 
  143.  * 31.Jan.96 log_error reports about a malformed .meta file, rather
  144.  *           than a script error.
  145.  * 20.Jun.96 MetaFiles <on|off> default off, added, so that module
  146.  *           can be configured per-directory.  Prior to this the module
  147.  *           was running for each request anywhere on the server, naughty..
  148.  * 29.Jun.96 All directives made per-directory.
  149.  */
  150.  
  151. #include "httpd.h"
  152. #include "http_config.h"
  153. #include <sys/types.h>
  154. #include <sys/stat.h>
  155. #include "util_script.h"
  156. #include "http_log.h"
  157. #include "http_request.h"
  158.  
  159. #define DIR_CMD_PERMS OR_INDEXES
  160.  
  161. #define DEFAULT_METADIR        ".web"
  162. #define DEFAULT_METASUFFIX    ".meta"
  163. #define DEFAULT_METAFILES    0
  164.  
  165. module MODULE_VAR_EXPORT cern_meta_module;
  166.  
  167. typedef struct {
  168.     char *metadir;
  169.     char *metasuffix;
  170.     char *metafiles;
  171. } cern_meta_dir_config;
  172.  
  173. static void *create_cern_meta_dir_config(pool *p, char *dummy)
  174. {
  175.     cern_meta_dir_config *new =
  176.     (cern_meta_dir_config *) ap_palloc(p, sizeof(cern_meta_dir_config));
  177.  
  178.     new->metadir = NULL;
  179.     new->metasuffix = NULL;
  180.     new->metafiles = DEFAULT_METAFILES;
  181.  
  182.     return new;
  183. }
  184.  
  185. static void *merge_cern_meta_dir_configs(pool *p, void *basev, void *addv)
  186. {
  187.     cern_meta_dir_config *base = (cern_meta_dir_config *) basev;
  188.     cern_meta_dir_config *add = (cern_meta_dir_config *) addv;
  189.     cern_meta_dir_config *new =
  190.     (cern_meta_dir_config *) ap_palloc(p, sizeof(cern_meta_dir_config));
  191.  
  192.     new->metadir = add->metadir ? add->metadir : base->metadir;
  193.     new->metasuffix = add->metasuffix ? add->metasuffix : base->metasuffix;
  194.     new->metafiles = add->metafiles;
  195.  
  196.     return new;
  197. }
  198.  
  199. static const char *set_metadir(cmd_parms *parms, cern_meta_dir_config * dconf, char *arg)
  200. {
  201.     dconf->metadir = arg;
  202.     return NULL;
  203. }
  204.  
  205. static const char *set_metasuffix(cmd_parms *parms, cern_meta_dir_config * dconf, char *arg)
  206. {
  207.     dconf->metasuffix = arg;
  208.     return NULL;
  209. }
  210.  
  211. static const char *set_metafiles(cmd_parms *parms, cern_meta_dir_config * dconf, char *arg)
  212. {
  213.     dconf->metafiles = arg;
  214.     return NULL;
  215. }
  216.  
  217.  
  218. static const command_rec cern_meta_cmds[] =
  219. {
  220.     {"MetaFiles", set_metafiles, NULL, DIR_CMD_PERMS, FLAG,
  221.     "Limited to 'on' or 'off'"},
  222.     {"MetaDir", set_metadir, NULL, DIR_CMD_PERMS, TAKE1,
  223.      "the name of the directory containing meta files"},
  224.     {"MetaSuffix", set_metasuffix, NULL, DIR_CMD_PERMS, TAKE1,
  225.      "the filename suffix for meta files"},
  226.     {NULL}
  227. };
  228.  
  229. /* XXX: this is very similar to ap_scan_script_header_err_core...
  230.  * are the differences deliberate, or just a result of bit rot?
  231.  */
  232. static int scan_meta_file(request_rec *r, FILE *f)
  233. {
  234.     char w[MAX_STRING_LEN];
  235.     char *l;
  236.     int p;
  237.     table *tmp_headers;
  238.  
  239.     tmp_headers = ap_make_table(r->pool, 5);
  240.     while (fgets(w, MAX_STRING_LEN - 1, f) != NULL) {
  241.  
  242.     /* Delete terminal (CR?)LF */
  243.  
  244.     p = strlen(w);
  245.     if (p > 0 && w[p - 1] == '\n') {
  246.         if (p > 1 && w[p - 2] == '\015')
  247.         w[p - 2] = '\0';
  248.         else
  249.         w[p - 1] = '\0';
  250.     }
  251.  
  252.     if (w[0] == '\0') {
  253.         return OK;
  254.     }
  255.  
  256.     /* if we see a bogus header don't ignore it. Shout and scream */
  257.  
  258.     if (!(l = strchr(w, ':'))) {
  259.         ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
  260.             "malformed header in meta file: %s", r->filename);
  261.         return SERVER_ERROR;
  262.     }
  263.  
  264.     *l++ = '\0';
  265.     while (*l && ap_isspace(*l))
  266.         ++l;
  267.  
  268.     if (!strcasecmp(w, "Content-type")) {
  269.         char *tmp;
  270.         /* Nuke trailing whitespace */
  271.  
  272.         char *endp = l + strlen(l) - 1;
  273.         while (endp > l && ap_isspace(*endp))
  274.         *endp-- = '\0';
  275.  
  276.         tmp = ap_pstrdup(r->pool, l);
  277.         ap_content_type_tolower(tmp);
  278.         r->content_type = tmp;
  279.     }
  280.     else if (!strcasecmp(w, "Status")) {
  281.         sscanf(l, "%d", &r->status);
  282.         r->status_line = ap_pstrdup(r->pool, l);
  283.     }
  284.     else {
  285.         ap_table_set(tmp_headers, w, l);
  286.     }
  287.     }
  288.     ap_overlap_tables(r->headers_out, tmp_headers, AP_OVERLAP_TABLES_SET);
  289.     return OK;
  290. }
  291.  
  292. static int add_cern_meta_data(request_rec *r)
  293. {
  294.     char *metafilename;
  295.     char *last_slash;
  296.     char *real_file;
  297.     char *scrap_book;
  298.     FILE *f;
  299.     cern_meta_dir_config *dconf;
  300.     int rv;
  301.     request_rec *rr;
  302.  
  303.     dconf = ap_get_module_config(r->per_dir_config, &cern_meta_module);
  304.  
  305.     if (!dconf->metafiles) {
  306.     return DECLINED;
  307.     };
  308.  
  309.     /* if ./.web/$1.meta exists then output 'asis' */
  310.  
  311.     if (r->finfo.st_mode == 0) {
  312.     return DECLINED;
  313.     };
  314.  
  315.     /* is this a directory? */
  316.     if (S_ISDIR(r->finfo.st_mode) || r->uri[strlen(r->uri) - 1] == '/') {
  317.     return DECLINED;
  318.     };
  319.  
  320.     /* what directory is this file in? */
  321.     scrap_book = ap_pstrdup(r->pool, r->filename);
  322.     /* skip leading slash, recovered in later processing */
  323.     scrap_book++;
  324.     last_slash = strrchr(scrap_book, '/');
  325.     if (last_slash != NULL) {
  326.     /* skip over last slash */
  327.     real_file = last_slash;
  328.     real_file++;
  329.     *last_slash = '\0';
  330.     }
  331.     else {
  332.     /* no last slash, buh?! */
  333.     ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
  334.             "internal error in mod_cern_meta: %s", r->filename);
  335.     /* should really barf, but hey, let's be friends... */
  336.     return DECLINED;
  337.     };
  338.  
  339.     metafilename = ap_pstrcat(r->pool, "/", scrap_book, "/",
  340.                dconf->metadir ? dconf->metadir : DEFAULT_METADIR,
  341.                "/", real_file,
  342.          dconf->metasuffix ? dconf->metasuffix : DEFAULT_METASUFFIX,
  343.                NULL);
  344.  
  345.     /* XXX: it sucks to require this subrequest to complete, because this
  346.      * means people must leave their meta files accessible to the world.
  347.      * A better solution might be a "safe open" feature of pfopen to avoid
  348.      * pipes, symlinks, and crap like that.
  349.      */
  350.     rr = ap_sub_req_lookup_file(metafilename, r);
  351.     if (rr->status != HTTP_OK) {
  352.     ap_destroy_sub_req(rr);
  353.     return DECLINED;
  354.     }
  355.     ap_destroy_sub_req(rr);
  356.  
  357.     f = ap_pfopen(r->pool, metafilename, "r");
  358.     if (f == NULL) {
  359.     if (errno == ENOENT) {
  360.         return DECLINED;
  361.     }
  362.     ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
  363.           "meta file permissions deny server access: %s", metafilename);
  364.     return FORBIDDEN;
  365.     };
  366.  
  367.     /* read the headers in */
  368.     rv = scan_meta_file(r, f);
  369.     ap_pfclose(r->pool, f);
  370.  
  371.     return rv;
  372. }
  373.  
  374. module MODULE_VAR_EXPORT cern_meta_module =
  375. {
  376.     STANDARD_MODULE_STUFF,
  377.     NULL,            /* initializer */
  378.     create_cern_meta_dir_config,    /* dir config creater */
  379.     merge_cern_meta_dir_configs,    /* dir merger --- default is to override */
  380.     NULL,            /* server config */
  381.     NULL,            /* merge server configs */
  382.     cern_meta_cmds,        /* command table */
  383.     NULL,            /* handlers */
  384.     NULL,            /* filename translation */
  385.     NULL,            /* check_user_id */
  386.     NULL,            /* check auth */
  387.     NULL,            /* check access */
  388.     NULL,            /* type_checker */
  389.     add_cern_meta_data,        /* fixups */
  390.     NULL,            /* logger */
  391.     NULL,            /* header parser */
  392.     NULL,            /* child_init */
  393.     NULL,            /* child_exit */
  394.     NULL            /* post read-request */
  395. };
  396.