home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 25 / CDROM25.iso / Share / linux / apache / contrib / modules / mod_cern_meta.c.0.1.0 < prev    next >
Encoding:
Text File  |  1998-06-11  |  11.6 KB  |  376 lines

  1. /* ====================================================================
  2.  * Copyright (c) 1995 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.
  24.  *
  25.  * 5. Redistributions of any form whatsoever must retain the following
  26.  *    acknowledgment:
  27.  *    "This product includes software developed by the Apache Group
  28.  *    for use in the Apache HTTP server project (http://www.apache.org/)."
  29.  *
  30.  * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
  31.  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  32.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  33.  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE APACHE GROUP OR
  34.  * IT'S CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  35.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  36.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  37.  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  38.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  39.  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  40.  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  41.  * OF THE POSSIBILITY OF SUCH DAMAGE.
  42.  * ====================================================================
  43.  *
  44.  * This software consists of voluntary contributions made by many
  45.  * individuals on behalf of the Apache Group and was originally based
  46.  * on public domain software written at the National Center for
  47.  * Supercomputing Applications, University of Illinois, Urbana-Champaign.
  48.  * For more information on the Apache Group and the Apache HTTP server
  49.  * project, please see <http://www.apache.org/>.
  50.  *
  51.  */
  52.  
  53. /*
  54.  * mod_cern_meta.c
  55.  * version 0.1.0
  56.  * status beta
  57.  * 
  58.  * Andrew Wilson <Andrew.Wilson@cm.cf.ac.uk> 25.Jan.96
  59.  *
  60.  * *** IMPORTANT ***
  61.  * This version of mod_cern_meta.c controls Meta File behaviour on a
  62.  * per-directory basis.  Previous versions of the module defined behaviour
  63.  * on a per-server basis.  The upshot is that you'll need to revisit your 
  64.  * configuration files in order to make use of the new module.
  65.  * ***
  66.  *
  67.  * Emulate the CERN HTTPD Meta file semantics.  Meta files are HTTP
  68.  * headers that can be output in addition to the normal range of
  69.  * headers for each file accessed.  They appear rather like the Apache
  70.  * .asis files, and are able to provide a crude way of influencing
  71.  * the Expires: header, as well as providing other curiosities.
  72.  * There are many ways to manage meta information, this one was
  73.  * chosen because there is already a large number of CERN users
  74.  * who can exploit this module.  It should be noted that there are probably
  75.  * more sensitive ways of managing the Expires: header specifically.
  76.  *
  77.  * The module obeys the following directives, which can appear 
  78.  * in the server's .conf files and in .htaccess files.
  79.  *
  80.  *  MetaFiles <on|off> 
  81.  *
  82.  *    turns on|off meta file processing for any directory.  
  83.  *    Default value is off
  84.  *
  85.  *        # turn on MetaFiles in this directory
  86.  *        MetaFiles on
  87.  *
  88.  *  MetaDir <directory name>
  89.  *      
  90.  *    specifies the name of the directory in which Apache can find
  91.  *    meta information files.  The directory is usually a 'hidden'
  92.  *    subdirectory of the directory that contains the file being
  93.  *    accessed.  eg:
  94.  *
  95.  *        # .meta files are in the *same* directory as the 
  96.  *        # file being accessed
  97.  *        MetaDir .
  98.  *
  99.  *    the default is to look in a '.web' subdirectory. This is the
  100.  *    same as for CERN 3.+ webservers and behaviour is the same as 
  101.  *    for the directive:
  102.  *
  103.  *        MetaDir .web
  104.  *
  105.  *  MetaSuffix <meta file suffix>
  106.  *
  107.  *    specifies the file name suffix for the file containing the
  108.  *    meta information.  eg:
  109.  *
  110.  *       # our meta files are suffixed with '.cern_meta'
  111.  *       MetaSuffix .cern_meta
  112.  *
  113.  *    the default is to look for files with the suffix '.meta'.  This
  114.  *    behaviour is the same as for the directive:
  115.  *
  116.  *       MetaSuffix .meta
  117.  *
  118.  * When accessing the file
  119.  *
  120.  *   DOCUMENT_ROOT/somedir/index.html
  121.  *
  122.  * this module will look for the file
  123.  *
  124.  *   DOCUMENT_ROOT/somedir/.web/index.html.meta
  125.  *
  126.  * and will use its contents to generate additional MIME header 
  127.  * information.
  128.  *
  129.  * For more information on the CERN Meta file semantics see:
  130.  *
  131.  *   http://www.w3.org/hypertext/WWW/Daemon/User/Config/General.html#MetaDir
  132.  *
  133.  * Change-log:
  134.  * 29.Jan.96 pfopen/pfclose instead of fopen/fclose
  135.  *           DECLINE when real file not found, we may be checking each
  136.  *           of the index.html/index.shtml/index.htm variants and don't
  137.  *           need to report missing ones as spurious errors. 
  138.  * 31.Jan.96 log_error reports about a malformed .meta file, rather
  139.  *           than a script error.
  140.  * 20.Jun.96 MetaFiles <on|off> default off, added, so that module
  141.  *           can be configured per-directory.  Prior to this the module
  142.  *           was running for each request anywhere on the server, naughty..
  143.  * 29.Jun.96 All directives made per-directory.
  144.  */
  145.  
  146. #include "httpd.h"
  147. #include "http_config.h"
  148. #include <sys/types.h>
  149. #include <sys/stat.h>
  150. #include "util_script.h"
  151. #include "http_log.h"
  152.  
  153. #define DIR_CMD_PERMS OR_INDEXES
  154.  
  155. #define DEFAULT_METADIR        ".web"
  156. #define DEFAULT_METASUFFIX    ".meta"
  157. #define DEFAULT_METAFILES    0
  158.  
  159. module cern_meta_module;
  160.  
  161. typedef struct {
  162.     char *metadir;
  163.     char *metasuffix;
  164.     char *metafiles;
  165. } cern_meta_dir_config;
  166.  
  167. void *create_cern_meta_dir_config (pool *p, char *dummy)
  168. {
  169.     cern_meta_dir_config *new =
  170.       (cern_meta_dir_config *) palloc (p, sizeof(cern_meta_dir_config));
  171.  
  172.     new->metadir = NULL;
  173.     new->metasuffix = NULL;
  174.     new->metafiles = DEFAULT_METAFILES;
  175.  
  176.     return new;
  177. }
  178.  
  179. void *merge_cern_meta_dir_configs (pool *p, void *basev, void *addv) 
  180. {
  181.     cern_meta_dir_config *base = (cern_meta_dir_config *)basev;
  182.     cern_meta_dir_config *add = (cern_meta_dir_config *)addv; 
  183.     cern_meta_dir_config *new =
  184.       (cern_meta_dir_config *)palloc (p, sizeof(cern_meta_dir_config));
  185.     
  186.     new->metadir = add->metadir ? add->metadir : base->metadir;
  187.     new->metasuffix = add->metasuffix ? add->metasuffix : base->metasuffix;
  188.     new->metafiles = add->metafiles;
  189.     
  190.     return new;
  191. }   
  192.  
  193.  
  194. char *set_metadir (cmd_parms *parms, cern_meta_dir_config *dconf, char *arg)
  195. {       
  196.     dconf->metadir = arg;
  197.     return NULL;
  198. }
  199.  
  200. char *set_metasuffix (cmd_parms *parms, cern_meta_dir_config *dconf, char *arg)
  201. {       
  202.     dconf->metasuffix = arg;
  203.     return NULL;
  204. }
  205.  
  206. char *set_metafiles (cmd_parms *parms, cern_meta_dir_config *dconf, char *arg) 
  207. {
  208.     dconf->metafiles = arg;
  209.     return NULL;
  210. }
  211.  
  212.  
  213. command_rec cern_meta_cmds[] = {
  214. { "MetaFiles", set_metafiles, NULL, DIR_CMD_PERMS, FLAG, NULL},
  215. { "MetaDir", set_metadir, NULL, DIR_CMD_PERMS, TAKE1,
  216.     "the name of the directory containing meta files"},
  217. { "MetaSuffix", set_metasuffix, NULL, DIR_CMD_PERMS, TAKE1,
  218.     "the filename suffix for meta files"},
  219. { NULL }
  220. };  
  221.  
  222. int scan_meta_file(request_rec *r, FILE *f)
  223. {
  224.     char w[MAX_STRING_LEN];
  225.     char *l;
  226.     int p;
  227.  
  228.     while( fgets(w, MAX_STRING_LEN-1, f) != NULL ) {
  229.  
  230.     /* Delete terminal (CR?)LF */
  231.     
  232.     p = strlen(w);
  233.     if (p > 0 && w[p-1] == '\n')
  234.     {
  235.         if (p > 1 && w[p-2] == '\015') w[p-2] = '\0';
  236.         else w[p-1] = '\0';
  237.     }
  238.  
  239.         if(w[0] == '\0') {
  240.         return OK;
  241.     }
  242.                                    
  243.     /* if we see a bogus header don't ignore it. Shout and scream */
  244.     
  245.         if(!(l = strchr(w,':'))) {
  246.         log_reason ("malformed header in meta file", r->filename, r);
  247.         return SERVER_ERROR;
  248.         }
  249.  
  250.         *l++ = '\0';
  251.     while (*l && isspace (*l)) ++l;
  252.     
  253.         if(!strcasecmp(w,"Content-type")) {
  254.  
  255.         /* Nuke trailing whitespace */
  256.         
  257.         char *endp = l + strlen(l) - 1;
  258.         while (endp > l && isspace(*endp)) *endp-- = '\0';
  259.         
  260.         r->content_type = pstrdup (r->pool, l);
  261.     }
  262.         else if(!strcasecmp(w,"Status")) {
  263.             sscanf(l, "%d", &r->status);
  264.             r->status_line = pstrdup(r->pool, l);
  265.         }
  266.         else {
  267.         table_set (r->headers_out, w, l);
  268.         }
  269.     }
  270.     return OK;
  271. }
  272.  
  273. int add_cern_meta_data(request_rec *r)
  274. {
  275.     char *metafilename;
  276.     char *last_slash;
  277.     char *real_file;
  278.     char *scrap_book;
  279.     struct stat meta_stat;
  280.     FILE *f;   
  281.     cern_meta_dir_config *dconf ;
  282.     int rv;
  283.  
  284.     dconf = get_module_config (r->per_dir_config, &cern_meta_module); 
  285.  
  286.     if (!dconf->metafiles) {
  287.         return DECLINED;
  288.     };
  289.  
  290.     /* if ./.web/$1.meta exists then output 'asis' */
  291.  
  292.     if (r->finfo.st_mode == 0) {
  293.     return DECLINED;
  294.     };
  295.  
  296.     /* does uri end in a trailing slash? */
  297.     if ( r->uri[strlen(r->uri) - 1] == '/' ) {
  298.     return DECLINED;
  299.     };
  300.  
  301.     /* what directory is this file in? */
  302.     scrap_book = pstrdup( r->pool, r->filename );
  303.     /* skip leading slash, recovered in later processing */
  304.     scrap_book++;
  305.     last_slash = strrchr( scrap_book, '/' );
  306.     if ( last_slash != NULL ) {
  307.     /* skip over last slash */
  308.     real_file = last_slash;
  309.     real_file++;
  310.     *last_slash = '\0';
  311.     } else {
  312.     /* no last slash, buh?! */
  313.         log_reason("internal error in mod_cern_meta", r->filename, r);
  314.     /* should really barf, but hey, let's be friends... */
  315.     return DECLINED;
  316.     };
  317.  
  318.     metafilename = pstrcat(r->pool, "/", scrap_book, "/", 
  319.         dconf->metadir ? dconf->metadir : DEFAULT_METADIR, 
  320.         "/", real_file, 
  321.         dconf->metasuffix ? dconf->metasuffix : DEFAULT_METASUFFIX, 
  322.         NULL);
  323.  
  324.     /*
  325.      * stat can legitimately fail for a bewildering number of reasons,
  326.      * only one of which implies the file isn't there.  A hardened
  327.      * version of this module should test for all conditions, but later...
  328.      */
  329.     if (stat(metafilename, &meta_stat) == -1) {
  330.     /* stat failed, possibly file missing */
  331.     return DECLINED;
  332.     };
  333.  
  334.     /*
  335.      * this check is to be found in other Jan/96 Apache code, I've
  336.      * not been able to find any corroboration in the man pages but
  337.      * I've been wrong before so I'll put it in anyway.  Never
  338.      * admit to being clueless...
  339.      */
  340.     if ( meta_stat.st_mode == 0 ) {
  341.     /* stat failed, definately file missing */
  342.     return DECLINED;
  343.     };
  344.  
  345.     f = pfopen (r->pool, metafilename, "r");
  346.     
  347.     if (f == NULL) {
  348.         log_reason("meta file permissions deny server access", metafilename, r);
  349.         return FORBIDDEN;
  350.     };
  351.  
  352.     /* read the headers in */
  353.     rv = scan_meta_file(r, f);
  354.     pfclose( r->pool, f );
  355.  
  356.     return rv;
  357. }
  358.  
  359. module cern_meta_module = {
  360.    STANDARD_MODULE_STUFF,
  361.    NULL,            /* initializer */
  362.    create_cern_meta_dir_config,    /* dir config creater */
  363.    merge_cern_meta_dir_configs,    /* dir merger --- default is to override */
  364.    NULL,            /* server config */
  365.    NULL,            /* merge server configs */
  366.    cern_meta_cmds,        /* command table */
  367.    NULL,            /* handlers */
  368.    NULL,            /* filename translation */
  369.    NULL,            /* check_user_id */
  370.    NULL,            /* check auth */
  371.    NULL,            /* check access */
  372.    NULL,            /* type_checker */
  373.    add_cern_meta_data,        /* fixups */
  374.    NULL,            /* logger */
  375. };
  376.