home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 25 / CDROM25.iso / Share / linux / apache / contrib / modules / probably_obsolete / mod_trailer.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-06-11  |  7.5 KB  |  258 lines

  1. /*
  2.  * mod_trailer.c
  3.  *
  4.  *  An Apache module that adds document trailer functionality.
  5.  *
  6.  *  A document trailer is a text or HTML file that is appended to all
  7.  *  objects with a certain prefix in their URI.  This module allows
  8.  *  you to assign a trailer file to a URI with the config file directive
  9.  *
  10.  *  "Trailer <URI prefix> <trailer filename>"  
  11.  *
  12.  *  For example, to append a trailer with a filename of
  13.  *  "/usr/local/htdocs/trailer.html" to all objects with URIs beginning
  14.  *  with "/add/trailers/here/" you would place the following in your srm.conf:
  15.  *
  16.  *  Trailer /add/trailers/here/ /usr/local/htdocs/trailer.html
  17.  *
  18.  *
  19.  *  This is only my second Apache module, and is much more complex than the
  20.  *  first one I wrote (which was a simple authentication module to 
  21.  *  authenticate users from the unix password file).  If you have any 
  22.  *  comments or suggestions as to how this might be improved, please drop me
  23.  *  some email.
  24.  *
  25.  *  If someone wanted some fancy trailers, it would be pretty simple to
  26.  *  have this append server-parsed-html trailers instead of just plain
  27.  *  text or html.  Some other features that might be useful would be a
  28.  *  per directory default trailer (perhaps a .trailer file that gets appended
  29.  *  to all files in its directory) or a feature that appends a specified
  30.  *  trailer to all documents with a certain extension.
  31.  *
  32.  *  Feel free to use this module however you like, and distribute it freely.
  33.  *  I only ask that you do not remove my name from the credits.  If you
  34.  *  modify this code and distribute it, please include a list of revisions
  35.  *  in the history, along with your name.  And if you find this module
  36.  *  useful, send me some email and let me know!
  37.  *
  38.  *  Nathan W. Schrenk (nschrenk@neog.com) 11/10/95
  39.  *
  40.  *  HISTORY:
  41.  *
  42.  *  v 0.1 - 11/10/95 - mod_trailer.c created.  This is probably full of bugs,
  43.  *          and perhaps can be done in a much better way.  But hey, it
  44.  *          seems to work for me.
  45.  *
  46.  *  v 0.2 - 11/11/95 - A bug that popped up with the POST request method was
  47.  *          fixed and now only the most specific URI prefix is matched.
  48.  *          You can now specify overlapping trailers, and the trailer
  49.  *          associated with the longest prefix will be used).
  50.  */
  51.  
  52. #include "httpd.h"
  53. #include "http_config.h"
  54. #include "http_log.h"
  55. #include "http_main.h"
  56. #include "http_protocol.h"
  57. #include "http_request.h"
  58.  
  59. #define TRAILER_MAGIC_TYPE "text/x-trailer-appended-html"
  60. #define MAX_TRAILERS 20
  61.  
  62. /* trailer_entry = a struct to hold trailer alias info */
  63.  
  64. typedef struct {
  65.   char *prefix;   /* prefix in which to use trailer */
  66.   char *t_file;   /* filename of trailer to use */
  67. } trailer_entry;
  68.  
  69.  
  70. module trailer_module;
  71.  
  72. /*
  73.  * create_trailer_config() and merg_trailer_config() handle trailer
  74.  * configuration stuff.  Pretty self explanatory...
  75.  */
  76.  
  77. void *create_trailer_config(pool *p, server_rec *s)
  78. {
  79.   array_header *t_cf = (array_header *) pcalloc(p,sizeof(array_header));
  80.  
  81.   t_cf = make_array(p,MAX_TRAILERS,sizeof(trailer_entry));
  82.  
  83.   return t_cf;
  84. }
  85.  
  86. void *merge_trailer_config(pool *p, void *basev, void *overridesv)
  87. {
  88.   array_header *t_cf = (array_header *) pcalloc(p,sizeof(array_header));
  89.   array_header *base = (array_header *) basev,
  90.                *overrides = (array_header *) overridesv;
  91.  
  92.   t_cf = append_arrays(p,overrides,base);
  93.  
  94.   return t_cf;
  95. }
  96.  
  97.  
  98. /*
  99.  * add_trailer() adds trailer config file info into the server config
  100.  */
  101.  
  102. char *add_trailer(cmd_parms *cmd, void *dummy, char *p, char *f)
  103. {
  104.   server_rec *s = cmd->server;
  105.   array_header *trailer_conf = 
  106.     (array_header *) get_module_config(s->module_config,&trailer_module);
  107.   trailer_entry *new_trailer = push_array(trailer_conf);
  108.   
  109.   new_trailer->prefix = p;
  110.   new_trailer->t_file = f;
  111.  
  112.   return NULL;
  113. }
  114.   
  115. command_rec trailer_cmds[] = {
  116.   {"Trailer", add_trailer, NULL, RSRC_CONF, TAKE2,
  117.      "A URI prefix and a trailer filename"},
  118.   { NULL }
  119. };
  120.  
  121. /*
  122.  * find_trailer() returns the trailer filename for request r, or NULL
  123.  * if the trailer cannot be determined.  This has to give the trailer
  124.  * of the most specific prefix, so we can't stop when we find the first
  125.  * one that matches.
  126.  */
  127.  
  128. char *find_trailer(request_rec *r)
  129. {
  130.   void *sconf = r->server->module_config;
  131.   array_header *t_array = 
  132.     (array_header *) get_module_config(sconf,&trailer_module);
  133.   trailer_entry *entries = (trailer_entry *) t_array->elts, *t;
  134.   int i,l,longest = 0;
  135.   char *trailer = NULL;
  136.  
  137.   for (i = 0; i < t_array->nelts; i++) {
  138.     t = &entries[i];
  139.     l = strlen(t->prefix);
  140.     if (!strncmp(r->uri,t->prefix,l) && (l > longest)) {
  141.       longest = l;
  142.       trailer = t->t_file;
  143.     }
  144.   }
  145.   
  146.   return trailer;
  147. }
  148.  
  149. /*
  150.  * check_for_trailer() is run in the fixup stage to check
  151.  * and see if the requested object has a trailer.  If so, the request's
  152.  * real content type is noted in r->notes, then is set to
  153.  * TRAILER_MAGIC_TYPE.
  154.  */
  155.  
  156. int check_for_trailer(request_rec *r)
  157. {
  158.   if (r->method_number == M_GET)  
  159.     if (find_trailer(r)) {
  160.       
  161.       /* check to see if this is already typed as a trailer to
  162.      prevent recursively calling the trailer handler -- does this
  163.      ever do anything?  */
  164.       
  165.       if (!strcmp(r->content_type,TRAILER_MAGIC_TYPE))
  166.     return DECLINED;
  167.       
  168.       /* make a note of the real content type for the trailer handler */
  169.       
  170.       table_set(r->notes,"pre-trailer-type",r->content_type);
  171.       r->content_type = TRAILER_MAGIC_TYPE;
  172.       return OK;
  173.     }
  174.   
  175.   return DECLINED;
  176. }
  177.  
  178. /*
  179.  * trailer_handler() sends out the document requested and appends
  180.  * the trailer file to it if the requested document's content type begins
  181.  * with "text/"
  182.  */
  183.  
  184. int trailer_handler(request_rec *r)
  185. {
  186.   int subr_status;
  187.   char *t_file,*old_type,buf[MAX_STRING_LEN];
  188.   FILE *tf;
  189.   struct stat tf_stat;
  190.   request_rec *subr = sub_req_lookup_uri(r->uri,r);
  191.   
  192.   /* set subr's content_type to the old content type */
  193.   old_type = table_get(r->notes,"pre-trailer-type");
  194.   if (old_type)
  195.     subr->content_type = old_type;
  196.  
  197.   subr_status = run_sub_req(subr);  /* run subrequest */
  198.  
  199.   if ((subr_status == OK) && !strncmp(subr->content_type,"text/",5)) {
  200.     t_file = find_trailer(r);
  201.     if (t_file && (stat(t_file,&tf_stat) || (!tf_stat.st_mode))) {
  202.       sprintf(buf,"Trailer file %s does not exist",t_file);
  203.       log_reason(buf,r->uri,r);
  204.       
  205.       return subr_status;
  206.     }
  207.     
  208.     tf = pfopen(r->pool,t_file,"r");
  209.     if (tf == NULL) {
  210.       log_reason("file permissions deny server access to trailer file",
  211.          t_file, r);
  212.       return subr_status;
  213.     }
  214.     
  215.     soft_timeout ("send", r);
  216.     if (!r->header_only)
  217.       send_fd (tf, r);
  218.     pfclose (r->pool,tf);
  219.  
  220.     r->headers_out = subr->headers_out;
  221.     r->err_headers_out = subr->headers_out;
  222.  
  223.     return OK;
  224.   }
  225.  
  226.   /* copy headers out to handle redirect, etc */
  227.  
  228.   if (subr_status == REDIRECT) {
  229.     r->headers_out = subr->headers_out;
  230.     r->err_headers_out = subr->headers_out;
  231.   }
  232.  
  233.   return subr_status;
  234. }
  235.   
  236. handler_rec trailer_handlers[] = {
  237.   { TRAILER_MAGIC_TYPE, trailer_handler },
  238.   { NULL }
  239. };
  240.  
  241. module trailer_module = {
  242.    STANDARD_MODULE_STUFF,
  243.    NULL,            /* initializer */
  244.    NULL,            /* dir config creater */
  245.    NULL,            /* dir merger --- default is to override */
  246.    create_trailer_config,       /* server config */
  247.    merge_trailer_config,           /* merge server configs */
  248.    trailer_cmds,               /* command table */
  249.    trailer_handlers,               /* handlers */
  250.    NULL,                    /* filename translation */
  251.    NULL,            /* check_user_id */
  252.    NULL,            /* check auth */
  253.    NULL,            /* check access */
  254.    NULL,                        /* type_checker */
  255.    check_for_trailer,        /* fixups */
  256.    NULL                /* logger */
  257. };
  258.