"Fossies" - the Fresh Open Source Software Archive

Member "mod_cgi_debug-0.7/mod_cgi_debug.c" (13 Apr 2000, 14268 Bytes) of package /linux/www/apache_httpd_modules/old/mod_cgi_debug-0.7.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_cgi_debug.c -- Apache cgi_debug module
    3 */ 
    4 
    5 #include "httpd.h"
    6 #include "http_config.h"
    7 #include "http_protocol.h"
    8 #include "ap_config.h"
    9 #include "http_log.h"
   10 #include <sys/stat.h>
   11 
   12 
   13 typedef struct {
   14   int headersin;
   15   int headersout;
   16   int getdata;
   17   int postdata;
   18   int pathinfo;
   19     int hangingindent;
   20   char *keycolor;
   21   char *valuecolor;
   22   char *handlerkey;
   23     table *types;
   24 } cgi_debug_conf;
   25 
   26 static void *create_dir_mconfig(pool *p, char *dir)
   27 {
   28     cgi_debug_conf *cfg;
   29     cfg = ap_pcalloc(p, sizeof(cgi_debug_conf));
   30     cfg->headersin=1;
   31     cfg->headersout=1;
   32     cfg->getdata=1;
   33     cfg->postdata=1;
   34     cfg->pathinfo=1;
   35     cfg->hangingindent=1;
   36     cfg->keycolor=ap_pstrdup(p,"#ccccee");
   37     cfg->valuecolor=ap_pstrdup(p,"#ffffff");
   38     cfg->handlerkey=ap_pstrdup(p,"_DEBUG");
   39     cfg->types = ap_make_table(p, 8);
   40 
   41     return (void *) cfg;
   42 }
   43 
   44 
   45 module MODULE_VAR_EXPORT cgi_debug_module;
   46 
   47 
   48 static int read_content(request_rec *r, char *data, long length) {
   49     int rc;
   50     char argsbuffer[HUGE_STRING_LEN];
   51     int rsize, rpos=0;
   52     long len_read = 0;
   53 
   54     if ((rc = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR)) != OK){
   55         return rc;
   56     }
   57 
   58     if (ap_should_client_block(r)) {
   59         ap_hard_timeout("client_read", r);
   60         while((len_read = ap_get_client_block(r, argsbuffer, HUGE_STRING_LEN)) > 0 ){
   61             ap_reset_timeout(r);
   62             if ((rpos + (int)len_read) > length) {
   63                 rsize = length -rpos;
   64             } else {
   65                 rsize = (int)len_read;
   66             }
   67             memcpy(data + rpos , argsbuffer, rsize);
   68             rpos += rsize;
   69         }
   70 
   71         ap_kill_timeout(r);
   72     }
   73 
   74     return rc;
   75 }
   76 
   77 static int print_elements(void *data, const char *key, const char *val){
   78     request_rec *r = (request_rec *)data;
   79     cgi_debug_conf *cfg = (cgi_debug_conf *)ap_get_module_config(r->per_dir_config, &cgi_debug_module); 
   80 
   81     ap_rprintf(r, "<TR bgcolor=\"%s\" VALIGN=\"TOP\">\n", cfg->valuecolor);
   82     if (cfg->hangingindent) {
   83         ap_rprintf(r, "\t<TD WIDTH=\"10%\"></TD>\n");
   84     }
   85     else {
   86         ap_rprintf(r, "\t<TD WIDTH=\"10%\">&nbsp;</TD>\n");
   87     }
   88     ap_rprintf(r, "\t<TD>%s</TD>\n", val);
   89     ap_rputs("</TR>\n",r);
   90 
   91     return 1;
   92 }
   93 
   94 int table_print(const table *t, request_rec *r, cgi_debug_conf *cfg)
   95 {
   96     array_header *hdrs_arr = ap_table_elts(t);
   97     table_entry *elts = (table_entry *) hdrs_arr->elts;
   98     int i;
   99 
  100     ap_rputs("<CENTER><TABLE BORDER=\"0\" WIDTH=\"90%\" CELLSPACING=\"0\" CELLPADDING=\"0\">\n",r);
  101     for (i = 0; i < hdrs_arr->nelts; ++i) {
  102         ap_rprintf(r,"<TR bgcolor=\"%s\" VALIGN=\"TOP\">\n", cfg->keycolor);
  103         ap_rprintf(r, "\t<TD COLSPAN=2><B>%s</B></TD>\n", elts[i].key);
  104         ap_rputs("</TR>\n",r);
  105         ap_table_do(print_elements, (void*)r, t, elts[i].key, NULL);
  106     }
  107     ap_rputs("</TABLE></CENTER>\n",r);
  108 
  109     return 0;
  110 }
  111 
  112 const char *args_rebuild (request_rec *r, table *values, const char *data, const char *handlerkey) {
  113     const char *key = NULL;
  114     const char *tempstring = NULL;
  115     const char *returntosender = NULL;
  116     int key_size = strlen(handlerkey);
  117 
  118     while(*data && (key = ap_getword(r->pool, &data, '&'))){
  119         if(!strncmp(key, handlerkey, key_size)) {
  120             (void)ap_getword(r->pool, &key, '=');
  121             tempstring = (char *)ap_pstrdup(r->pool, key);
  122             ap_table_add(values, tempstring, "enabled");
  123         } else {
  124             if (returntosender) {
  125                 returntosender = ap_pstrcat(r->pool, returntosender, "&", key, NULL);
  126             } else {
  127                 returntosender = ap_pstrdup(r->pool, key);
  128             }
  129         }
  130     }
  131 
  132     return ap_pstrdup(r->pool, returntosender);
  133 }
  134 
  135 static int include_virtual(request_rec * r, const char *uri, char *method) {
  136     int status = OK;
  137     request_rec *subr;
  138     subr = (request_rec *) ap_sub_req_method_uri(method, uri, r);
  139     ap_table_set(subr->headers_out, "Cache-Control", "no-cache");
  140     status = ap_run_sub_req(subr);
  141     ap_destroy_sub_req(subr);
  142 
  143     return status;
  144 }
  145 
  146 int args_parse (request_rec *r, table *values, const char *data) {
  147     const char *key;
  148     const char *val;
  149 
  150     while(*data && (val = ap_getword(r->pool, &data, '&'))){
  151         key = ap_getword(r->pool, &val, '=');
  152         ap_unescape_url((char *) key);
  153         ap_unescape_url((char *) val);
  154         ap_table_add(values, key, val);
  155     }
  156 
  157     return 0;
  158 }
  159 
  160 static int cgi_debug_handler(request_rec *r)
  161 {
  162     table *get_values = NULL;
  163     table *post_values = NULL;
  164     char *standard_input = NULL;
  165     char *content_length = NULL;
  166     long length = 0;
  167     cgi_debug_conf *cfg = (cgi_debug_conf *)ap_get_module_config(r->per_dir_config, &cgi_debug_module); 
  168     
  169 
  170     post_values = ap_make_table(r->pool, 10);
  171 
  172     r->content_type = "text/html";      
  173     ap_table_set(r->headers_out, "Cache-Control", "no-cache");
  174     ap_send_http_header(r);
  175     if (r->header_only)
  176         return OK;
  177 
  178     ap_rprintf(r, "<html> <title>mod_cgi_debug: %s</title><body text=\"#000000\" bgcolor=\"#000000\">\n", r->uri);
  179     ap_rputs("<CENTER><TABLE CELLPADDING=\"0\" bgcolor=\"#ffffff\" BORDER=\"0\" WIDTH=\"100\%\">\n",r);
  180     ap_rprintf(r, "<TD><H1> Debug output for: %s </H1></TD> \n", r->uri);
  181     ap_rputs("<TD><TABLE CELLPADDING=\"0\" CELLSPACING=\"0\">\n", r);
  182     ap_rprintf(r, "<TR ALIGN=\"LEFT\"><TH COLSPAN=\"2\" >Web Server Name:</TH></TR><TR ALIGN=\"LEFT\"><TD WIDTH=\"10\%\">&nbsp;</TD><TD><FONT SIZE=\"1\"> %s</FONT></TD>\n", ap_get_server_name(r) );
  183     ap_rprintf(r, "<TR ALIGN=\"LEFT\"><TH COLSPAN=\"2\">Web Server Version:</TH></TR><TR ALIGN=\"LEFT\"><TD WIDTH=\"10\%\">&nbsp;</TD><TD><FONT SIZE=\"1\"> %s</FONT></TD>\n", ap_get_server_version() );
  184     ap_rprintf(r, "<TR ALIGN=\"LEFT\"><TH COLSPAN=\"2\">Web Server Time:</TH></TR><TR ALIGN=\"LEFT\"><TD WIDTH=\"10\%\">&nbsp;</TD><TD><FONT SIZE=\"1\"> %s</FONT></TD>\n", ap_get_time() );
  185     ap_rprintf(r, "<TR ALIGN=\"LEFT\"><TH COLSPAN=\"2\">Web Server Built:</TH></TR><TR ALIGN=\"LEFT\"><TD WIDTH=\"10\%\">&nbsp;</TD><TD><FONT SIZE=\"1\"> %s</FONT></TD>\n", ap_get_server_built() );
  186     
  187   ap_rputs("</TABLE></TD></TR>\n", r);
  188     ap_rputs("</TABLE></CENTER>\n", r);
  189 
  190     ap_rputs("<TABLE CELLPADDING=15 bgcolor=\"#ffffff\" BORDER=\"0\" WIDTH=\"100%\">\n",r);
  191     ap_rputs("<TR>\n\t<TD>",r);
  192 /*  ap_rprintf(r, "<H1> Debug output for: %s </H1> \n", r->uri); */
  193     
  194     if(cfg->headersin) {
  195         ap_rprintf(r, "<H3>Inbound HTTP Headers</H3>\n");
  196         table_print(r->headers_in, r, cfg);
  197     }
  198     if(cfg->headersout) {
  199         ap_rprintf(r, "<H3>Outbound HTTP Headers</H3>\n");
  200         table_print(r->headers_out, r, cfg);
  201     }
  202 
  203     if(cfg->pathinfo) {
  204         if(strlen(r->path_info)) {
  205             ap_rprintf(r, "<H3>PATH Info</H3>\n");
  206             ap_rprintf(r, "%s", r->path_info);
  207         }
  208     }
  209 
  210     if(cfg->getdata) {
  211         if(r->args) {
  212             get_values = ap_make_table(r->pool, 10);
  213             ap_rprintf(r, "<H3>GET ARGS content</H3>\n");
  214             args_parse(r, get_values, r->args);
  215             table_print(get_values, r, cfg);
  216         }
  217     }
  218 
  219     if(cfg->postdata) {
  220         content_length = (char *)ap_table_get(r->headers_in, "Content-Length");
  221         if(length = (content_length ? atoi(content_length) : 0)) {
  222             ap_rprintf(r, "<H3>Post Contents:</H3>\n");
  223             standard_input = ap_palloc(r->pool, length);
  224             read_content(r, standard_input, length);
  225             args_parse(r, post_values, standard_input);
  226             table_print(post_values, r, cfg);
  227         }
  228     }
  229     ap_rputs("</TD></TR>\n",r);
  230     ap_rputs("</TABLE>\n",r);
  231 
  232     return OK;
  233 }
  234 
  235 static int cgi_environment(request_rec *r)
  236 {
  237     table *get_values;
  238     table *values;
  239     const char *new_location = NULL;
  240     const char *new_args = NULL;
  241     cgi_debug_conf *cfg; 
  242     int status;
  243     
  244 
  245     if (r->main) {
  246         return DECLINED;
  247     }
  248 
  249     if (r->header_only) {
  250         r->content_type = "text/html";      
  251         ap_send_http_header(r);
  252         return OK;
  253     }
  254 
  255     values = ap_make_table(r->pool, 8);
  256     cfg = (cgi_debug_conf *)ap_get_module_config(r->per_dir_config, &cgi_debug_module); 
  257 
  258     new_args = args_rebuild(r, values, r->args, cfg->handlerkey);
  259 
  260     /* Now lets put her back together */
  261     if(new_args) {
  262         new_location = ap_pstrcat(r->pool, r->uri, "?", new_args, r->path_info, NULL);
  263     }else {
  264         new_location = ap_pstrcat(r->pool, r->uri, "?", r->path_info, NULL);
  265     }
  266 
  267     if ( (status = include_virtual(r, new_location, (char *) r->method)) != OK) {
  268         ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, r,
  269         "The following error occured while processing the body : %d",
  270         status);
  271 
  272         return status;
  273     }
  274 
  275 
  276     if(ap_table_get(values, "banner")) {
  277         ap_rputs("<CENTER><TABLE CELLPADDING=15 bgcolor=\"#ffffff\" BORDER=\"0\" WIDTH=\"75%\">\n",r);
  278         ap_rprintf(r, "<TD><H1> Debug output for: %s </H1></TD> \n", r->uri);
  279         ap_rputs("<TD>\n", r);
  280         ap_rprintf(r, "Web Server Name: %s<BR>\n", ap_get_server_name(r) );
  281         ap_rprintf(r, "Web Server Version: %s<BR>\n", ap_get_server_version() );
  282         ap_rprintf(r, "Web Server Time: %s<BR>\n", ap_get_time() );
  283         ap_rprintf(r, "Web Server Built: %s<BR>\n", ap_get_server_built() );
  284         ap_rprintf(r, "Remote Username: %s<BR>\n", ap_get_remote_logname(r) );
  285         ap_rprintf(r, "Filename: %s<BR>\n", r->filename);
  286 
  287         if(r->finfo.st_mode) {
  288             ap_rprintf(r, "Last Modified: %s<BR>\n", 
  289                                 ap_ht_time(r->pool, r->finfo.st_mtime, "%a %d %b %Y %T %Z", 0));
  290             ap_rprintf(r, "File Created: %s<BR>\n",
  291                                 ap_ht_time(r->pool, r->finfo.st_ctime, "%a %d %b %Y %T %Z", 0));
  292             ap_rprintf(r, "File Last Accessed: %s<BR>\n",
  293                                 ap_ht_time(r->pool, r->finfo.st_atime, "%a %d %b %Y %T %Z", 0));
  294             ap_rprintf(r, "Owner UID %d\n<BR>", r->finfo.st_uid);
  295             ap_rprintf(r, "Owner GID %d\n<BR>", r->finfo.st_gid);
  296         }
  297         
  298         ap_rputs("</TD></TR>\n", r);
  299         ap_rputs("</TABLE></CENTER>\n", r);
  300     }
  301 
  302     ap_rputs("<TABLE CELLPADDING=15 bgcolor=\"#ffffff\" BORDER=\"0\" WIDTH=\"100%\">\n",r);
  303     ap_rputs("<TR>\n\t<TD>",r);
  304 /*  ap_rprintf(r, "<H1> Debug output for: %s </H1> \n", r->uri); */
  305     
  306     if(ap_table_get(values, "headersin")) {
  307         if(cfg->headersin) {
  308             ap_rprintf(r, "<H3>Inbound HTTP Headers</H3>\n");
  309             table_print(r->headers_in, r, cfg);
  310         }
  311     }
  312 
  313     if(ap_table_get(values, "headersout")) {
  314         if(cfg->headersout) {
  315             ap_rprintf(r, "<H3>Outbound HTTP Headers</H3>\n");
  316             table_print(r->headers_out, r, cfg);
  317         }
  318     }
  319 
  320     if(ap_table_get(values, "unparsed_uri")) {
  321         if(r->unparsed_uri) {
  322             if(strlen(r->unparsed_uri)) {
  323                 ap_rprintf(r, "<H3>Uri</H3>\n");
  324                 ap_rprintf(r, "%s", r->unparsed_uri);
  325             }
  326         }
  327     }
  328     
  329     if(ap_table_get(values, "path_info")) {
  330         if(cfg->pathinfo) {
  331             if(strlen(r->path_info)) {
  332                 ap_rprintf(r, "<H3>PATH Info</H3>\n");
  333                 ap_rprintf(r, "%s", r->path_info);
  334             }
  335         }
  336     }
  337 
  338     if(ap_table_get(values, "get_args")) {
  339         if(cfg->getdata) {
  340             if(r->args) {
  341                 get_values = ap_make_table(r->pool, 10);
  342                 ap_rprintf(r, "<H3>GET ARGS content</H3>\n");
  343                 args_parse(r, get_values, new_args);
  344                 table_print(get_values, r, cfg);
  345             }
  346         }
  347     }
  348 
  349     ap_rputs("</TD></TR>\n",r);
  350     ap_rputs("</TABLE>\n",r);
  351 
  352     return OK;
  353 }
  354 
  355 static int cgi_fixup(request_rec *r)
  356 {
  357     cgi_debug_conf *cfg = ap_get_module_config(r->per_dir_config, &cgi_debug_module);
  358     request_rec *subr;
  359     char *type = NULL;
  360 
  361     if (r->main) {
  362         return DECLINED;
  363     }
  364 
  365     /* So why switch to doing this? Somewhere since 1.3.6 something
  366          has changed about the way that CGI's are done. Not sure what
  367          it is, but this is now needed */
  368     /* First, we check to see if this is SSI, mod_perl or cgi */
  369     if(r->handler) {
  370         type = ap_pstrdup(r->pool, r->handler);
  371     } else {
  372         type = ap_pstrdup(r->pool, r->content_type);
  373     }
  374 
  375     if (!ap_table_get(cfg->types, type))
  376         return DECLINED;
  377 
  378     r->handler = "cgi_environment";
  379 
  380     return DECLINED;
  381 }
  382 
  383 static const char *add_type(cmd_parms * cmd, void *mconfig, char *type)
  384 {
  385   cgi_debug_conf *cfg = (cgi_debug_conf *) mconfig;
  386       ap_table_addn(cfg->types, type, "enabled");
  387 
  388     return NULL;
  389 }
  390 
  391 
  392 static const command_rec cgi_debug_cmds[] = {
  393     {"CGIDebugKeyColor", ap_set_string_slot, (void *) XtOffsetOf(cgi_debug_conf, keycolor), OR_ALL, TAKE1, "Background color for key values, in hex notation (#ffffff)."},
  394     {"CGIDebugValueColor", ap_set_string_slot, (void *) XtOffsetOf(cgi_debug_conf, valuecolor), OR_ALL, TAKE1, "Background color for key values, in hex notation (#ffffff)."},
  395     {"CGIDebugHeaderIn", ap_set_flag_slot, (void *) XtOffsetOf(cgi_debug_conf, headersin), OR_ALL, FLAG, "On or Off to print incomming headers."},
  396     {"CGIDebugHeaderOut", ap_set_flag_slot, (void *) XtOffsetOf(cgi_debug_conf, headersout), OR_ALL, FLAG, "On or Off to print incomming headers."},
  397     {"CGIDebugGetData", ap_set_flag_slot, (void *) XtOffsetOf(cgi_debug_conf, getdata), OR_ALL, FLAG, "On or Off to print the arguments on the URI."},
  398     {"CGIDebugPostData", ap_set_flag_slot, (void *) XtOffsetOf(cgi_debug_conf, postdata), OR_ALL, FLAG, "On or Off to print key pairs found in the POST data."},
  399     {"CGIDebugPathInfo", ap_set_flag_slot, (void *) XtOffsetOf(cgi_debug_conf, pathinfo), OR_ALL, FLAG, "On or Off to print the path_info."},
  400     {"CGIDebugHangingIndent", ap_set_flag_slot, (void *) XtOffsetOf(cgi_debug_conf, hangingindent), OR_ALL, FLAG, "On or Off. Changes coloration of value rows."},
  401     {"CGIDebugHandler", add_type, NULL, OR_ALL, TAKE1, "Enter either a mime type or a handler type."},
  402     {"CGIDebugHandlerKey", ap_set_string_slot, (void *) XtOffsetOf(cgi_debug_conf, handlerkey), OR_ALL, TAKE1, "Takes a single argument to override the default _DEBUG key."},
  403 
  404     {NULL},
  405 };
  406 
  407 
  408 /* Dispatch list of content handlers */
  409 static const handler_rec cgi_debug_handlers[] = { 
  410     { "cgi_debug", cgi_debug_handler }, 
  411     { "cgi_environment", cgi_environment }, 
  412     { NULL, NULL }
  413 };
  414 
  415 /* Dispatch list for API hooks */
  416 module MODULE_VAR_EXPORT cgi_debug_module = {
  417     STANDARD_MODULE_STUFF, 
  418     NULL,                  /* module initializer                  */
  419     create_dir_mconfig,    /* create per-dir    config structures */
  420     NULL,                  /* merge  per-dir    config structures */
  421     NULL,                  /* create per-server config structures */
  422     NULL,                  /* merge  per-server config structures */
  423     cgi_debug_cmds,        /* table of config file commands       */
  424     cgi_debug_handlers,    /* [#8] MIME-typed-dispatched handlers */
  425     NULL,                  /* [#1] URI to filename translation    */
  426     NULL,                  /* [#4] validate user id from request  */
  427     NULL,                  /* [#5] check if the user is ok _here_ */
  428     NULL,                  /* [#3] check access by host address   */
  429     NULL,                  /* [#6] determine MIME type            */
  430     cgi_fixup,             /* [#7] pre-run fixups                 */
  431     NULL,                  /* [#9] log a transaction              */
  432     NULL,                  /* [#2] header parser                  */
  433     NULL,                  /* child_init                          */
  434     NULL,                  /* child_exit                          */
  435     NULL                   /* [#0] post read-request              */
  436 };
  437