"Fossies" - the Fresh Open Source Software Archive

Member "mod_trigger-1.1/mod_trigger.c" (7 Jun 2002, 13415 Bytes) of package /linux/www/apache_httpd_modules/old/mod_trigger-1.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 /* 
    2 **  mod_trigger.c -- Fire off triggers for events
    3 **  -Brian (brian@tangent.org)
    4 */ 
    5 
    6 #include "httpd.h"
    7 #include "http_config.h"
    8 #include "http_protocol.h"
    9 #include "ap_config.h"
   10 #include "fnmatch.h"
   11 #include "http_log.h"
   12 
   13 /* Strings for help */
   14 #define TriggerEngine "On or Off (Off by default). This enables the trigger engine."
   15 #define TriggerLog "Triggers will send a log message to the error log when found."
   16 #define TriggerHandler "Supply a handler and then either a script or uri to call if the handler is found."
   17 #define TriggerURI "Supply a URI and then either a script or uri to call if the URI is found."
   18 #define TriggerAgent "Supply a browser agent and then either a script or uri to call if the agent is found."
   19 #define TriggerReferer "Supply a referer and then either a script or uri to call if the referer is found."
   20 #define TriggerMime "Supply a mime-type and then either a script or uri to call if the mime-type is found."
   21 #define TriggerAddress "Supply an IP address  and then either a script or uri to call if the address is found."
   22 #define TriggerUser "Supply a username (REMOTE_USER) and then either a script or uri to call if the user is found."
   23 #define TriggerIdent "Supply an ident and then either a script or uri to call if the ident is found."
   24 #define TriggerPathInfo "Supply a pthinfo and then either a script or uri to call if the pathinfo is found."
   25 #define TriggerAccept "Supply an accept header and then either a script or uri to call if the accept header is found."
   26 #define TriggerCookie "Supply a cookie name and then either a script or uri to call if the cookie is found."
   27 
   28 #define WATCHPOINT printf("WATCHPOINT %s %d\n", __FILE__, __LINE__);
   29 
   30 module MODULE_VAR_EXPORT trigger_module;
   31 
   32 typedef struct {
   33     int enabled;
   34     int log;
   35     table *handler;
   36     table *uri;
   37     table *agent;
   38     table *referer;
   39     table *mime;
   40     table *address;
   41     table *user;
   42     table *ident;
   43     table *pathinfo;
   44     table *accept;
   45     table *cookie;
   46     table *args;
   47 } trigger_conf;
   48 
   49 static void *create_dir_mconfig(pool *p, char *dir) {
   50     trigger_conf *cfg;
   51     cfg = ap_pcalloc(p, sizeof(trigger_conf));
   52 
   53     cfg->enabled=0;
   54     cfg->log=0;
   55     cfg->handler = NULL; 
   56     cfg->uri = NULL; 
   57     cfg->agent = NULL; 
   58     cfg->referer = NULL; 
   59     cfg->mime = NULL; 
   60     cfg->address = NULL; 
   61     cfg->user = NULL; 
   62     cfg->ident = NULL; 
   63     cfg->pathinfo = NULL; 
   64     cfg->accept = NULL; 
   65     cfg->cookie = NULL; 
   66     cfg->args = NULL; 
   67 
   68     return (void *) cfg;
   69 }
   70 
   71 int call_container(request_rec *r, char *uri) {
   72     int status = OK;
   73     request_rec *subr;
   74 
   75     subr = (request_rec *) ap_sub_req_lookup_uri(uri, r);
   76     ap_table_setn(subr->headers_in, "Content-Length", "0");
   77     subr->assbackwards = 1;
   78 
   79     ap_table_setn(subr->subprocess_env, "TRIGGER_SCRIPT_NAME", r->uri);
   80     ap_table_setn(subr->subprocess_env, "TRIGGER_PATH_INFO", r->path_info);
   81     ap_table_setn(subr->subprocess_env, "TRIGGER_QUERY_STRING", r->args);
   82     ap_table_setn(subr->subprocess_env, "TRIGGER_FILENAME", r->filename);
   83     subr->args = r->args;
   84 
   85     status = ap_run_sub_req(subr);
   86     ap_destroy_sub_req(subr);
   87 
   88     return status;
   89 }
   90 
   91 static int call_program(void *rp, child_info *pinfo) {
   92     char **env;
   93     request_rec *r = (request_rec *)rp;
   94 
   95     ap_add_cgi_vars(r);
   96     env = (char **)ap_create_environment(r->pool, r->subprocess_env);
   97     ap_error_log2stderr(r->server);
   98     ap_cleanup_for_exec();
   99     (void)ap_call_exec(r, pinfo, r->filename, env, 0);
  100     ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, "exec for %s failed", r->filename);
  101     exit(0);
  102     return 0;
  103 }
  104 
  105 static void execute(request_rec *r, char *string) {
  106     int status = OK;
  107     struct stat sbuf;
  108     char *temp = NULL;
  109     BUFF *pipe;
  110 
  111     /* Ok, reality? We should set this up to determine
  112          this ahead of time.
  113     */
  114     ap_table_setn(r->subprocess_env, "TRIGGER_SCRIPT_NAME", r->uri);
  115     ap_table_setn(r->subprocess_env, "TRIGGER_PATH_INFO", r->path_info);
  116     ap_table_setn(r->subprocess_env, "TRIGGER_QUERY_STRING", r->args);
  117     ap_table_setn(r->subprocess_env, "TRIGGER_FILENAME", r->filename);
  118     if(!stat(string, &sbuf)) {
  119         temp = r->filename;
  120         r->filename = string;
  121         if(!ap_bspawn_child(r->pool, call_program,
  122                     (void *) r, kill_after_timeout,
  123                     NULL, &pipe, NULL)) {
  124             ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
  125                     "could not spawn: %s", string);
  126         }
  127         r->filename = temp;
  128     } else {
  129         if ((status = call_container(r, string)) != OK) {
  130             ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, 
  131                     "The following error occured while processing the Triger : %s : %d", string, status);
  132         }
  133     }
  134 
  135 }
  136 
  137 void table_execute(request_rec *r, const table *t, const char *key, int log) {
  138     array_header *hdrs_arr;
  139     table_entry *elts;
  140     int x = 0;
  141 
  142     if (key == NULL)
  143         return;
  144     if (t == NULL)
  145         return;
  146 
  147     hdrs_arr = ap_table_elts(t);
  148     elts = (table_entry *) hdrs_arr->elts;
  149 
  150     for (x = 0; x < hdrs_arr->nelts; ++x) {
  151         if (!ap_fnmatch(elts[x].key, key, FNM_CASE_BLIND)) {
  152             execute(r, elts[x].val);
  153             if(log)
  154                 ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, r,
  155                     "mod_trigger:Firing off trigger %s, for %s", elts[x].val, elts[x].key);
  156         }
  157     }
  158 
  159     return;
  160 }
  161 
  162 /* Borrowed from mod_rewrite (and modified) */
  163 static char *lookup_header(request_rec *r, const char *name) {
  164     array_header *hdrs_arr;
  165     table_entry *hdrs;
  166     int i;
  167 
  168     hdrs_arr = ap_table_elts(r->headers_in);
  169     hdrs = (table_entry *)hdrs_arr->elts;
  170     for (i = 0; i < hdrs_arr->nelts; ++i) {
  171         if (hdrs[i].key == NULL) {
  172             continue;
  173         }
  174         if (!strcasecmp(hdrs[i].key, name)) {
  175             return hdrs[i].val;
  176         }
  177     }
  178     return NULL;
  179 }
  180 
  181 void table_print(request_rec *r, table *t, char *caption) {
  182     array_header *hdrs_arr;
  183     table_entry *elts;
  184     int x = 0;
  185 
  186     if (t == NULL)
  187         return;
  188 
  189     hdrs_arr = ap_table_elts(t);
  190     elts = (table_entry *) hdrs_arr->elts;
  191 
  192     ap_rprintf(r, "Caption: %s\n", caption);
  193     for (x = 0; x < hdrs_arr->nelts; ++x) {
  194         ap_rprintf(r, "%s:%s\n", elts[x].key, elts[x].val);
  195     }
  196 }
  197 
  198 static int trigger_handler(request_rec *r) {
  199     trigger_conf *cfg;
  200     cfg = ap_get_module_config(r->per_dir_config, &trigger_module);
  201     r->content_type = "text/html";      
  202     ap_rputs(DOCTYPE_HTML_3_2
  203          "<HTML><HEAD>\n<TITLE>Apache Status</TITLE>\n</HEAD><BODY>\n",
  204          r);
  205     ap_rputs("<H1>Apache Server Status for ", r);
  206     ap_rvputs(r, ap_get_server_name(r), "</H1>\n\n", NULL);
  207     ap_rvputs(r, "Server Version: ",
  208       ap_get_server_version(), "<br>\n", NULL);
  209     ap_rvputs(r, "Server Built: ",
  210       ap_get_server_built(), "<br>\n<hr>\n", NULL);
  211     /*
  212     ap_rvputs(r, "Current Time: ",
  213       ap_ht_time(r->pool, nowtime, DEFAULT_TIME_FORMAT, 0), "<br>\n", NULL);
  214     ap_rvputs(r, "Restart Time: ",
  215       ap_ht_time(r->pool, ap_restart_time, DEFAULT_TIME_FORMAT, 0), 
  216       "<br>\n", NULL);
  217     */
  218     ap_send_http_header(r);
  219     if (r->header_only)
  220         return OK;
  221     if(cfg->handler)
  222         table_print(r, cfg->handler, "This is the default caption" );
  223     if(cfg->uri)
  224         table_print(r, cfg->uri, "This is the default caption" );
  225     if(cfg->agent)
  226         table_print(r, cfg->agent, "This is the default caption" );
  227     if(cfg->referer)
  228         table_print(r, cfg->referer, "This is the default caption" );
  229     if(cfg->mime)
  230         table_print(r, cfg->mime, "This is the default caption" );
  231     if(cfg->address)
  232         table_print(r, cfg->address, "This is the default caption" );
  233     if(cfg->user)
  234         table_print(r, cfg->user, "This is the default caption" );
  235     if(cfg->ident)
  236         table_print(r, cfg->ident, "This is the default caption" );
  237     if(cfg->pathinfo)
  238         table_print(r, cfg->pathinfo,"This is the default caption" );
  239     if(cfg->accept)
  240         table_print(r, cfg->accept, "This is the default caption" );
  241     if(cfg->cookie)
  242         table_print(r, cfg->cookie, "This is the default caption" );
  243     if(cfg->args)
  244         table_print(r, cfg->args, "This is the default caption" );
  245     ap_rputs("</HTML>", r);
  246 
  247     return OK;
  248 }
  249 
  250 static int trigger_log (request_rec *r) {
  251     trigger_conf *cfg;
  252     cfg = ap_get_module_config(r->per_dir_config, &trigger_module);
  253 
  254     if(!cfg->enabled)
  255         return DECLINED;
  256 
  257     if(cfg->handler)
  258         table_execute(r, cfg->handler, r->handler, cfg->log);
  259     if(cfg->uri)
  260         table_execute(r, cfg->uri, r->uri, cfg->log);
  261     if(cfg->agent)
  262         table_execute(r, cfg->agent, lookup_header(r, "User-Agent"), cfg->log);
  263     if(cfg->referer)
  264         table_execute(r, cfg->referer, lookup_header(r, "Referer"), cfg->log);
  265     if(cfg->mime)
  266         table_execute(r, cfg->mime, r->content_type, cfg->log);
  267     if(cfg->address)
  268         table_execute(r, cfg->address, r->connection->remote_ip, cfg->log);
  269     if(cfg->user)
  270         table_execute(r, cfg->user, r->connection->user, cfg->log);
  271     if(cfg->ident)
  272         table_execute(r, cfg->ident, (char *)ap_get_remote_logname(r, r), cfg->log);
  273     if(cfg->pathinfo)
  274         table_execute(r, cfg->pathinfo, r->path_info, cfg->log);
  275     if(cfg->accept)
  276         table_execute(r, cfg->accept, lookup_header(r, "Accept"), cfg->log);
  277     if(cfg->cookie)
  278         table_execute(r, cfg->cookie, lookup_header(r, "Cookie"), cfg->log);
  279     if(cfg->args)
  280         table_execute(r, cfg->args, r->args, cfg->log);
  281 
  282     return DECLINED;
  283 }
  284 
  285 /* Dispatch list of content handlers */
  286 static const handler_rec trigger_handlers[] = { 
  287     { "trigger-status", trigger_handler }, 
  288     { NULL, NULL }
  289 };
  290 
  291 static const char * add_trigger (cmd_parms *cmd, void *mconfig,  char *key, char *value) {
  292     trigger_conf *cfg = (trigger_conf *) mconfig;
  293 
  294     if(!strcasecmp(cmd->cmd->name, "TriggerHandler")) {
  295         if(!cfg->handler)
  296             cfg->handler = ap_make_table(cmd->pool, 1);
  297         ap_table_set(cfg->handler, key, value);
  298     } else if(!strcasecmp(cmd->cmd->name, "TriggerURI")) {
  299         if(!cfg->uri)
  300             cfg->uri = ap_make_table(cmd->pool, 1);
  301         ap_table_set(cfg->uri, key, value);
  302     } else if(!strcasecmp(cmd->cmd->name, "TriggerAgent")) {
  303         if(!cfg->agent)
  304             cfg->agent = ap_make_table(cmd->pool, 1);
  305         ap_table_set(cfg->agent, key, value);
  306     } else if(!strcasecmp(cmd->cmd->name, "TriggerReferer")) {
  307         if(!cfg->referer)
  308             cfg->referer = ap_make_table(cmd->pool, 1);
  309         ap_table_set(cfg->referer, key, value);
  310     } else if(!strcasecmp(cmd->cmd->name, "TriggerMime")) {
  311         if(!cfg->mime)
  312             cfg->mime = ap_make_table(cmd->pool, 1);
  313         ap_table_set(cfg->mime, key, value);
  314     } else if(!strcasecmp(cmd->cmd->name, "TriggerAddress")) {
  315         if(!cfg->address)
  316             cfg->address = ap_make_table(cmd->pool, 1);
  317         ap_table_set(cfg->address, key, value);
  318     } else if(!strcasecmp(cmd->cmd->name, "TriggerUser")) {
  319         if(!cfg->user)
  320             cfg->user = ap_make_table(cmd->pool, 1);
  321         ap_table_set(cfg->user, key, value);
  322     } else if(!strcasecmp(cmd->cmd->name, "TriggerIdent")) {
  323         if(!cfg->ident)
  324             cfg->ident = ap_make_table(cmd->pool, 1);
  325         ap_table_set(cfg->ident, key, value);
  326     } else if(!strcasecmp(cmd->cmd->name, "TriggerPathInfo")) {
  327         if(!cfg->pathinfo)
  328             cfg->pathinfo = ap_make_table(cmd->pool, 1);
  329         ap_table_set(cfg->pathinfo, key, value);
  330     } else if(!strcasecmp(cmd->cmd->name, "TriggerAccept")) {
  331         if(!cfg->accept)
  332             cfg->accept = ap_make_table(cmd->pool, 1);
  333         ap_table_set(cfg->accept, key, value);
  334     } else if(!strcasecmp(cmd->cmd->name, "TriggerCookie")) {
  335         if(!cfg->cookie)
  336             cfg->cookie = ap_make_table(cmd->pool, 1);
  337         ap_table_set(cfg->cookie, key, value);
  338     } else if(!strcasecmp(cmd->cmd->name, "TriggerArgs")) {
  339         if(!cfg->args)
  340             cfg->args = ap_make_table(cmd->pool, 1);
  341         ap_table_set(cfg->args, key, value);
  342     }
  343 
  344     return NULL;
  345 }
  346 
  347 static const command_rec trigger_cmds[] = {
  348 
  349     {"TriggerEngine", ap_set_flag_slot, (void *) XtOffsetOf(trigger_conf, enabled), OR_ALL, TAKE1, TriggerHandler},
  350     {"TriggerLog", ap_set_flag_slot, (void *) XtOffsetOf(trigger_conf, log), OR_ALL, TAKE1, TriggerLog},
  351     {"TriggerHandler", add_trigger, NULL, OR_ALL, TAKE2, TriggerHandler},
  352     {"TriggerURI", add_trigger, NULL, OR_ALL, TAKE2, TriggerHandler},
  353     {"TriggerAgent", add_trigger, NULL, OR_ALL, TAKE2, TriggerHandler},
  354     {"TriggerReferer", add_trigger, NULL, OR_ALL, TAKE2, TriggerHandler},
  355     {"TriggerMime", add_trigger, NULL, OR_ALL, TAKE2, TriggerHandler},
  356     {"TriggerAddress", add_trigger, NULL, OR_ALL, TAKE2, TriggerHandler},
  357     {"TriggerUser", add_trigger, NULL, OR_ALL, TAKE2, TriggerHandler},
  358     {"TriggerIdent", add_trigger, NULL, OR_ALL, TAKE2, TriggerHandler},
  359     {"TriggerPathInfo", add_trigger, NULL, OR_ALL, TAKE2, TriggerHandler},
  360     {"TriggerAccept", add_trigger, NULL, OR_ALL, TAKE2, TriggerHandler},
  361     {"TriggerCookie", add_trigger, NULL, OR_ALL, TAKE2, TriggerHandler},
  362     {NULL},
  363 };
  364 
  365 /* Dispatch list for API hooks */
  366 module MODULE_VAR_EXPORT trigger_module = {
  367     STANDARD_MODULE_STUFF, 
  368     NULL,                  /* module initializer                  */
  369     create_dir_mconfig,                  /* create per-dir    config structures */
  370     NULL,                  /* merge  per-dir    config structures */
  371     NULL,                  /* create per-server config structures */
  372     NULL,                  /* merge  per-server config structures */
  373     trigger_cmds,          /* table of config file commands       */
  374     trigger_handlers,      /* [#8] MIME-typed-dispatched handlers */
  375     NULL,                  /* [#1] URI to filename translation    */
  376     NULL,                  /* [#4] validate user id from request  */
  377     NULL,                  /* [#5] check if the user is ok _here_ */
  378     NULL,                  /* [#3] check access by host address   */
  379     NULL,                  /* [#6] determine MIME type            */
  380     NULL,                  /* [#7] pre-run fixups                 */
  381     trigger_log,                  /* [#9] log a transaction              */
  382     NULL,                  /* [#2] header parser                  */
  383     NULL,                  /* child_init                          */
  384     NULL,                  /* child_exit                          */
  385     NULL                   /* [#0] post read-request              */
  386 };
  387