home *** CD-ROM | disk | FTP | other *** search
/ PC Online 1999 April / PCO0499.ISO / filesbbs / os2 / apach134.arj / APACH134.ZIP / src / modules / standard / mod_log_referer.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-01-01  |  8.0 KB  |  230 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. #include "httpd.h"
  60. #include "http_config.h"
  61. #include "http_log.h"
  62.  
  63. module referer_log_module;
  64.  
  65. static int xfer_flags = (O_WRONLY | O_APPEND | O_CREAT);
  66.  
  67. #ifdef OS2
  68. /* OS/2 lacks support for users and groups */
  69. static mode_t xfer_mode = (S_IREAD | S_IWRITE);
  70. #else
  71. static mode_t xfer_mode = (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
  72. #endif
  73.  
  74. typedef struct {
  75.     char *fname;
  76.     int referer_fd;
  77.     array_header *referer_ignore_list;
  78. } referer_log_state;
  79.  
  80. static void *make_referer_log_state(pool *p, server_rec *s)
  81. {
  82.     referer_log_state *cls =
  83.     (referer_log_state *) ap_palloc(p, sizeof(referer_log_state));
  84.  
  85.     cls->fname = "";
  86.     cls->referer_fd = -1;
  87.     cls->referer_ignore_list = ap_make_array(p, 1, sizeof(char *));
  88.     return (void *) cls;
  89. }
  90.  
  91. static const char *set_referer_log(cmd_parms *parms, void *dummy, char *arg)
  92. {
  93.     referer_log_state *cls = ap_get_module_config(parms->server->module_config,
  94.                                                &referer_log_module);
  95.  
  96.     cls->fname = arg;
  97.     return NULL;
  98. }
  99.  
  100. static const char *add_referer_ignore(cmd_parms *parms, void *dummy, char *arg)
  101. {
  102.     char **addme;
  103.     referer_log_state *cls = ap_get_module_config(parms->server->module_config,
  104.                                                &referer_log_module);
  105.  
  106.     addme = ap_push_array(cls->referer_ignore_list);
  107.     ap_str_tolower(arg);
  108.     *addme = arg;
  109.     return NULL;
  110. }
  111.  
  112. static const command_rec referer_log_cmds[] =
  113. {
  114.     {"RefererLog", set_referer_log, NULL, RSRC_CONF, TAKE1,
  115.      "the filename of the referer log"},
  116.     {"RefererIgnore", add_referer_ignore, NULL, RSRC_CONF, ITERATE,
  117.      "referer hostnames to ignore"},
  118.     {NULL}
  119. };
  120.  
  121. static void open_referer_log(server_rec *s, pool *p)
  122. {
  123.     referer_log_state *cls = ap_get_module_config(s->module_config,
  124.                                                &referer_log_module);
  125.  
  126.     char *fname = ap_server_root_relative(p, cls->fname);
  127.  
  128.     if (cls->referer_fd > 0)
  129.         return;                 /* virtual log shared w/main server */
  130.  
  131.     if (*cls->fname == '|') {
  132.         piped_log *pl;
  133.  
  134.     pl = ap_open_piped_log(p, cls->fname + 1);
  135.     if (pl == NULL) {
  136.         ap_log_error(APLOG_MARK, APLOG_ERR, s,
  137.              "couldn't spawn referer log pipe");
  138.             exit(1);
  139.         }
  140.  
  141.         cls->referer_fd = ap_piped_log_write_fd(pl);
  142.     }
  143.     else if (*cls->fname != '\0') {
  144.         if ((cls->referer_fd = ap_popenf(p, fname, xfer_flags, xfer_mode)) < 0) {
  145.         ap_log_error(APLOG_MARK, APLOG_ERR, s,
  146.              "could not open referer log file %s.", fname);        
  147.         exit(1);
  148.     }
  149.     }
  150. }
  151.  
  152. static void init_referer_log(server_rec *s, pool *p)
  153. {
  154.     for (; s; s = s->next)
  155.         open_referer_log(s, p);
  156. }
  157.  
  158. static int referer_log_transaction(request_rec *orig)
  159. {
  160.     char **ptrptr, **ptrptr2;
  161.     referer_log_state *cls = ap_get_module_config(orig->server->module_config,
  162.                                                &referer_log_module);
  163.  
  164.     char *str;
  165.     const char *referer;
  166.     char *referertest;
  167.     request_rec *r;
  168.  
  169.     if (cls->referer_fd < 0)
  170.         return OK;
  171.  
  172.     for (r = orig; r->next; r = r->next)
  173.         continue;
  174.     if (*cls->fname == '\0')    /* Don't log referer */
  175.         return DECLINED;
  176.  
  177.     referer = ap_table_get(orig->headers_in, "Referer");
  178.     if (referer != NULL) {
  179.  
  180.         referertest = ap_pstrdup(orig->pool, referer);
  181.         ap_str_tolower(referertest);
  182.         /* The following is an upsetting mess of pointers, I'm sorry
  183.            Anyone with the motiviation and/or the time should feel free
  184.            to make this cleaner... */
  185.  
  186.         ptrptr2 = (char **) (cls->referer_ignore_list->elts +
  187.                              (cls->referer_ignore_list->nelts *
  188.                               cls->referer_ignore_list->elt_size));
  189.  
  190.         /* Go through each element of the ignore list and compare it to the
  191.            referer_host.  If we get a match, return without logging */
  192.  
  193.         for (ptrptr = (char **) cls->referer_ignore_list->elts;
  194.              ptrptr < ptrptr2;
  195.              ptrptr = (char **) ((char *) ptrptr + cls->referer_ignore_list->elt_size)) {
  196.             if (strstr(referertest, *ptrptr))
  197.                 return OK;
  198.         }
  199.  
  200.  
  201.         str = ap_pstrcat(orig->pool, referer, " -> ", r->uri, "\n", NULL);
  202.         write(cls->referer_fd, str, strlen(str));
  203.     }
  204.  
  205.     return OK;
  206. }
  207.  
  208. module referer_log_module =
  209. {
  210.     STANDARD_MODULE_STUFF,
  211.     init_referer_log,           /* initializer */
  212.     NULL,                       /* create per-dir config */
  213.     NULL,                       /* merge per-dir config */
  214.     make_referer_log_state,     /* server config */
  215.     NULL,                       /* merge server config */
  216.     referer_log_cmds,           /* command table */
  217.     NULL,                       /* handlers */
  218.     NULL,                       /* filename translation */
  219.     NULL,                       /* check_user_id */
  220.     NULL,                       /* check auth */
  221.     NULL,                       /* check access */
  222.     NULL,                       /* type_checker */
  223.     NULL,                       /* fixups */
  224.     referer_log_transaction,    /* logger */
  225.     NULL,                       /* header parser */
  226.     NULL,                       /* child_init */
  227.     NULL,                       /* child_exit */
  228.     NULL                        /* post read-request */
  229. };
  230.