Fixing configure, to remove a command not found error.
[privoxy.git] / cgisimple.c
1 const char cgisimple_rcs[] = "$Id: cgisimple.c,v 1.15 2002/03/06 22:54:35 jongfoster Exp $";
2 /*********************************************************************
3  *
4  * File        :  $Source: /cvsroot/ijbswa/current/cgisimple.c,v $
5  *
6  * Purpose     :  Simple CGIs to get information about JunkBuster's
7  *                status.
8  *                
9  *                Functions declared include:
10  * 
11  *
12  * Copyright   :  Written by and Copyright (C) 2001 the SourceForge
13  *                IJBSWA team.  http://ijbswa.sourceforge.net
14  *
15  *                Based on the Internet Junkbuster originally written
16  *                by and Copyright (C) 1997 Anonymous Coders and 
17  *                Junkbusters Corporation.  http://www.junkbusters.com
18  *
19  *                This program is free software; you can redistribute it 
20  *                and/or modify it under the terms of the GNU General
21  *                Public License as published by the Free Software
22  *                Foundation; either version 2 of the License, or (at
23  *                your option) any later version.
24  *
25  *                This program is distributed in the hope that it will
26  *                be useful, but WITHOUT ANY WARRANTY; without even the
27  *                implied warranty of MERCHANTABILITY or FITNESS FOR A
28  *                PARTICULAR PURPOSE.  See the GNU General Public
29  *                License for more details.
30  *
31  *                The GNU General Public License should be included with
32  *                this file.  If not, you can view it at
33  *                http://www.gnu.org/copyleft/gpl.html
34  *                or write to the Free Software Foundation, Inc., 59
35  *                Temple Place - Suite 330, Boston, MA  02111-1307, USA.
36  *
37  * Revisions   :
38  *    $Log: cgisimple.c,v $
39  *    Revision 1.15  2002/03/06 22:54:35  jongfoster
40  *    Automated function-comment nitpicking.
41  *
42  *    Revision 1.14  2002/03/02 04:14:50  david__schmidt
43  *    Clean up a little CRLF unpleasantness that suddenly appeared
44  *
45  *    Revision 1.13  2002/02/21 00:10:37  jongfoster
46  *    Adding send-banner?type=auto option
47  *
48  *    Revision 1.12  2002/01/23 01:03:32  jongfoster
49  *    Fixing gcc [CygWin] compiler warnings
50  *
51  *    Revision 1.11  2002/01/23 00:01:04  jongfoster
52  *    Adding cgi_transparent_gif() for http://i.j.b/t
53  *    Adding missing html_encode() to many CGI functions.
54  *    Adding urlmatch.[ch] to http://i.j.b/show-version
55  *
56  *    Revision 1.10  2002/01/17 21:10:37  jongfoster
57  *    Changes to cgi_show_url_info to use new matching code from urlmatch.c.
58  *    Also fixing a problem in the same function with improperly quoted URLs
59  *    in output HTML, and adding code to handle https:// URLs correctly.
60  *
61  *    Revision 1.9  2001/11/30 23:09:15  jongfoster
62  *    Now reports on FEATURE_CGI_EDIT_ACTIONS
63  *    Removing FEATURE_DENY_GZIP from template
64  *
65  *    Revision 1.8  2001/11/13 00:14:07  jongfoster
66  *    Fixing stupid bug now I've figured out what || means.
67  *    (It always returns 0 or 1, not one of it's paramaters.)
68  *
69  *    Revision 1.7  2001/10/23 21:48:19  jongfoster
70  *    Cleaning up error handling in CGI functions - they now send back
71  *    a HTML error page and should never cause a FATAL error.  (Fixes one
72  *    potential source of "denial of service" attacks).
73  *
74  *    CGI actions file editor that works and is actually useful.
75  *
76  *    Ability to toggle JunkBuster remotely using a CGI call.
77  *
78  *    You can turn off both the above features in the main configuration
79  *    file, e.g. if you are running a multi-user proxy.
80  *
81  *    Revision 1.6  2001/10/14 22:00:32  jongfoster
82  *    Adding support for a 404 error when an invalid CGI page is requested.
83  *
84  *    Revision 1.5  2001/10/07 15:30:41  oes
85  *    Removed FEATURE_DENY_GZIP
86  *
87  *    Revision 1.4  2001/10/02 15:31:12  oes
88  *    Introduced show-request cgi
89  *
90  *    Revision 1.3  2001/09/22 16:34:44  jongfoster
91  *    Removing unneeded #includes
92  *
93  *    Revision 1.2  2001/09/19 18:01:11  oes
94  *    Fixed comments; cosmetics
95  *
96  *    Revision 1.1  2001/09/16 17:08:54  jongfoster
97  *    Moving simple CGI functions from cgi.c to new file cgisimple.c
98  *
99  *
100  **********************************************************************/
101 \f
102
103 #include "config.h"
104
105 #include <stdio.h>
106 #include <sys/types.h>
107 #include <stdlib.h>
108 #include <ctype.h>
109 #include <string.h>
110 #include <assert.h>
111
112 #ifdef _WIN32
113 #define snprintf _snprintf
114 #endif /* def _WIN32 */
115
116 #include "project.h"
117 #include "cgi.h"
118 #include "cgisimple.h"
119 #include "list.h"
120 #include "encode.h"
121 #include "jcc.h"
122 #include "filters.h"
123 #include "actions.h"
124 #include "miscutil.h"
125 #include "loadcfg.h"
126 #include "parsers.h"
127 #include "urlmatch.h"
128
129 const char cgisimple_h_rcs[] = CGISIMPLE_H_VERSION;
130
131
132 static char *show_rcs(void);
133 static jb_err show_defines(struct map *exports);
134
135
136 /*********************************************************************
137  *
138  * Function    :  cgi_default
139  *
140  * Description :  CGI function that is called if no action was given.
141  *                Lists menu of available unhidden CGIs.
142  *               
143  * Parameters  :
144  *          1  :  csp = Current client state (buffers, headers, etc...)
145  *          2  :  rsp = http_response data structure for output
146  *          3  :  parameters = map of cgi parameters
147  *
148  * CGI Parameters : none
149  *
150  * Returns     :  JB_ERR_OK on success
151  *                JB_ERR_MEMORY on out-of-memory
152  *                (Problems other than out-of-memory should be
153  *                handled by this routine - it should set the
154  *                rsp appropriately and return "success")
155  *
156  *********************************************************************/
157 jb_err cgi_default(struct client_state *csp,
158                    struct http_response *rsp,
159                    const struct map *parameters)
160 {
161    char *tmp;
162    struct map *exports;
163
164    assert(csp);
165    assert(rsp);
166    assert(parameters);
167
168    if (NULL == (exports = default_exports(csp, "")))
169    {
170       return JB_ERR_MEMORY;
171    }
172
173    /* If there were other parameters, export a dump as "cgi-parameters" */
174    if (parameters->first)
175    {
176       tmp = strdup("<p>What made you think this cgi takes parameters?\n"
177                    "Anyway, here they are, in case you're interested:</p>\n");
178       string_join(&tmp, dump_map(parameters));
179       if (tmp == NULL)
180       {
181          free_map(exports);
182          return JB_ERR_MEMORY;
183       }
184       if (map(exports, "cgi-parameters", 1, tmp, 0))
185       {
186          return JB_ERR_MEMORY;
187       }
188    }
189    else
190    {
191       if (map(exports, "cgi-parameters", 1, "", 1))
192       {
193          return JB_ERR_MEMORY;
194       }
195    }
196
197    return template_fill_for_cgi(csp, "default", exports, rsp);
198 }
199
200
201
202
203 /*********************************************************************
204  *
205  * Function    :  cgi_error_404
206  *
207  * Description :  CGI function that is called if an unknown action was
208  *                given.
209  *               
210  * Parameters  :
211  *          1  :  csp = Current client state (buffers, headers, etc...)
212  *          2  :  rsp = http_response data structure for output
213  *          3  :  parameters = map of cgi parameters
214  *
215  * CGI Parameters : none
216  *
217  * Returns     :  JB_ERR_OK on success
218  *                JB_ERR_MEMORY on out-of-memory error.  
219  *
220  *********************************************************************/
221 jb_err cgi_error_404(struct client_state *csp,
222                      struct http_response *rsp,
223                      const struct map *parameters)
224 {
225    struct map *exports;
226
227    assert(csp);
228    assert(rsp);
229    assert(parameters);
230
231    if (NULL == (exports = default_exports(csp, NULL)))
232    {
233       return JB_ERR_MEMORY;
234    }
235
236    rsp->status = strdup("404 JunkBuster configuration page not found");
237    if (rsp->status == NULL)
238    {
239       free_map(exports);
240       return JB_ERR_MEMORY;
241    }
242
243    return template_fill_for_cgi(csp, "cgi-error-404", exports, rsp);
244 }
245
246
247 /*********************************************************************
248  *
249  * Function    :  cgi_show_request
250  *
251  * Description :  Show the client's request and what sed() would have
252  *                made of it.
253  *               
254  * Parameters  :
255  *          1  :  csp = Current client state (buffers, headers, etc...)
256  *          2  :  rsp = http_response data structure for output
257  *          3  :  parameters = map of cgi parameters
258  *
259  * CGI Parameters : none
260  *
261  * Returns     :  JB_ERR_OK on success
262  *                JB_ERR_MEMORY on out-of-memory error.  
263  *
264  *********************************************************************/
265 jb_err cgi_show_request(struct client_state *csp,
266                         struct http_response *rsp,
267                         const struct map *parameters)
268 {
269    char *p;
270    struct map *exports;
271
272    assert(csp);
273    assert(rsp);
274    assert(parameters);
275
276    if (NULL == (exports = default_exports(csp, "show-request")))
277    {
278       return JB_ERR_MEMORY;
279    }
280    
281    /*
282     * Repair the damage done to the IOB by get_header()
283     */
284    for (p = csp->iob->buf; p < csp->iob->eod; p++)
285    {
286       if (*p == '\0') *p = '\n';
287    }
288
289    /*
290     * Export the original client's request and the one we would
291     * be sending to the server if this wasn't a CGI call
292     */
293
294    if (map(exports, "client-request", 1, html_encode(csp->iob->buf), 0))
295    {
296       free_map(exports);
297       return JB_ERR_MEMORY;
298    }
299
300    if (map(exports, "processed-request", 1, html_encode_and_free_original(
301       sed(client_patterns, add_client_headers, csp)), 0))
302    {
303       free_map(exports);
304       return JB_ERR_MEMORY;
305    }
306
307    return template_fill_for_cgi(csp, "show-request", exports, rsp);
308 }
309
310
311 /*********************************************************************
312  *
313  * Function    :  cgi_send_banner
314  *
315  * Description :  CGI function that returns a banner. 
316  *
317  * Parameters  :
318  *          1  :  csp = Current client state (buffers, headers, etc...)
319  *          2  :  rsp = http_response data structure for output
320  *          3  :  parameters = map of cgi parameters
321  *
322  * CGI Parameters :
323  *           type : Selects the type of banner between "trans", "logo",
324  *                  and "auto". Defaults to "logo" if absent or invalid.
325  *                  "auto" means to select as if we were image-blocking.
326  *                  (Only the first character really counts).
327  *
328  * Returns     :  JB_ERR_OK on success
329  *                JB_ERR_MEMORY on out-of-memory error.  
330  *
331  *********************************************************************/
332 jb_err cgi_send_banner(struct client_state *csp,
333                        struct http_response *rsp,
334                        const struct map *parameters)
335 {
336    char imagetype = lookup(parameters, "type")[0];
337
338    if (imagetype == 'a') /* auto */
339    {
340       /* Default to logo */
341       imagetype = 'l';
342 #ifdef FEATURE_IMAGE_BLOCKING
343       if ((csp->action->flags & ACTION_IMAGE_BLOCKER) != 0)
344       {
345          /* determine HOW images should be blocked */
346          const char * p = csp->action->string[ACTION_STRING_IMAGE_BLOCKER];
347
348          /* and handle accordingly: */
349          if ((p != NULL) && (0 == strcmpic(p, "blank")))
350          {
351             imagetype = 'b';
352          }
353          else if ((p != NULL) && (0 == strcmpic(p, "pattern")))
354          {
355             imagetype = 'p';
356          }
357       }
358 #endif /* def FEATURE_IMAGE_BLOCKING */
359    }
360       
361    if ((imagetype == 'b') || (imagetype == 't')) /* blank / transparent */
362    {
363       rsp->body = bindup(image_blank_data, image_blank_length);
364       rsp->content_length = image_blank_length;
365
366    }
367    else if (imagetype == 'p') /* pattern */
368    {
369       rsp->body = bindup(image_pattern_data, image_pattern_length);
370       rsp->content_length = image_pattern_length;
371    }   
372    else /* logo */
373    {
374       rsp->body = bindup(image_logo_data, image_logo_length);
375       rsp->content_length = image_logo_length;
376    }   
377
378    if (rsp->body == NULL)
379    {
380       return JB_ERR_MEMORY;
381    }
382
383    if (enlist(rsp->headers, "Content-Type: image/png"))
384    {
385       return JB_ERR_MEMORY;
386    }
387
388    rsp->is_static = 1;
389
390    return JB_ERR_OK;
391
392 }
393
394
395 /*********************************************************************
396  *
397  * Function    :  cgi_transparent_png
398  *
399  * Description :  CGI function that sends a 1x1 transparent PNG.
400  *
401  * Parameters  :
402  *          1  :  csp = Current client state (buffers, headers, etc...)
403  *          2  :  rsp = http_response data structure for output
404  *          3  :  parameters = map of cgi parameters
405  *
406  * CGI Parameters : None
407  *
408  * Returns     :  JB_ERR_OK on success
409  *                JB_ERR_MEMORY on out-of-memory error.  
410  *
411  *********************************************************************/
412 jb_err cgi_transparent_png(struct client_state *csp,
413                            struct http_response *rsp,
414                            const struct map *parameters)
415 {
416    rsp->body = bindup(image_blank_data, image_blank_length);
417    rsp->content_length = image_blank_length;
418
419    if (rsp->body == NULL)
420    {
421       return JB_ERR_MEMORY;
422    }
423
424    if (enlist(rsp->headers, "Content-Type: image/png"))
425    {
426       return JB_ERR_MEMORY;
427    }
428
429    rsp->is_static = 1;
430
431    return JB_ERR_OK;
432
433 }
434
435
436 /*********************************************************************
437  *
438  * Function    :  cgi_show_version
439  *
440  * Description :  CGI function that returns a a web page describing the
441  *                file versions of IJB.
442  *
443  * Parameters  :
444  *          1  :  csp = Current client state (buffers, headers, etc...)
445  *          2  :  rsp = http_response data structure for output
446  *          3  :  parameters = map of cgi parameters
447  *
448  * CGI Parameters : none
449  *
450  * Returns     :  JB_ERR_OK on success
451  *                JB_ERR_MEMORY on out-of-memory error.  
452  *
453  *********************************************************************/
454 jb_err cgi_show_version(struct client_state *csp,
455                         struct http_response *rsp,
456                         const struct map *parameters)
457 {
458    struct map *exports;
459
460    assert(csp);
461    assert(rsp);
462    assert(parameters);
463
464    if (NULL == (exports = default_exports(csp, "show-version")))
465    {
466       return JB_ERR_MEMORY;
467    }
468
469    if (map(exports, "sourceversions", 1, show_rcs(), 0))
470    {
471       free_map(exports);
472       return JB_ERR_MEMORY;
473    }
474
475    return template_fill_for_cgi(csp, "show-version", exports, rsp);
476 }
477
478  
479 /*********************************************************************
480  *
481  * Function    :  cgi_show_status
482  *
483  * Description :  CGI function that returns a a web page describing the
484  *                current status of IJB.
485  *
486  * Parameters  :
487  *          1  :  csp = Current client state (buffers, headers, etc...)
488  *          2  :  rsp = http_response data structure for output
489  *          3  :  parameters = map of cgi parameters
490  *
491  * CGI Parameters :
492  *        file :  Which file to show.  Only first letter is checked,
493  *                valid values are:
494  *                - "p"ermissions (actions) file
495  *                - "r"egex
496  *                - "t"rust
497  *                Default is to show menu and other information.
498  *
499  * Returns     :  JB_ERR_OK on success
500  *                JB_ERR_MEMORY on out-of-memory error.  
501  *
502  *********************************************************************/
503 jb_err cgi_show_status(struct client_state *csp,
504                        struct http_response *rsp,
505                        const struct map *parameters)
506 {
507    char *s = NULL;
508    int i;
509
510    FILE * fp;
511    char buf[BUFFER_SIZE];
512    const char * filename = NULL;
513    char * file_description = NULL;
514 #ifdef FEATURE_STATISTICS
515    float perc_rej;   /* Percentage of http requests rejected */
516    int local_urls_read;
517    int local_urls_rejected;
518 #endif /* ndef FEATURE_STATISTICS */
519    jb_err err;
520
521    struct map *exports;
522
523    assert(csp);
524    assert(rsp);
525    assert(parameters);
526
527    if (NULL == (exports = default_exports(csp, "show-status")))
528    {
529       return JB_ERR_MEMORY;
530    }
531
532    switch (*(lookup(parameters, "file")))
533    {
534    case 'p':
535       if (csp->actions_list)
536       {
537          filename = csp->actions_list->filename;
538          file_description = "Actions List";
539       }
540       break;
541
542    case 'r':
543       if (csp->rlist)
544       {
545          filename = csp->rlist->filename;
546          file_description = "Regex Filter List";
547       }
548       break;
549
550 #ifdef FEATURE_TRUST
551    case 't':
552       if (csp->tlist)
553       {
554          filename = csp->tlist->filename;
555          file_description = "Trust List";
556       }
557       break;
558 #endif /* def FEATURE_TRUST */
559    }
560
561    if (NULL != filename)
562    {
563       if ( map(exports, "file-description", 1, file_description, 1)
564         || map(exports, "filepath", 1, html_encode(filename), 0) )
565       {
566          free_map(exports);
567          return JB_ERR_MEMORY;
568       }
569
570       if ((fp = fopen(filename, "r")) == NULL)
571       {
572          if (map(exports, "content", 1, "<h1>ERROR OPENING FILE!</h1>", 1))
573          {
574             free_map(exports);
575             return JB_ERR_MEMORY;
576          }
577       }
578       else
579       {
580          s = strdup("");
581          while ((s != NULL) && fgets(buf, sizeof(buf), fp))
582          {
583             string_join  (&s, html_encode(buf));
584             string_append(&s, "<br>");
585          }
586          fclose(fp);
587
588          if (map(exports, "contents", 1, s, 0))
589          {
590             free_map(exports);
591             return JB_ERR_MEMORY;
592          }
593       }
594
595       return template_fill_for_cgi(csp, "show-status-file", exports, rsp);
596    }
597
598    if (map(exports, "redirect-url", 1, html_encode(REDIRECT_URL), 0))
599    {
600       free_map(exports);
601       return JB_ERR_MEMORY;
602    }
603    
604    s = strdup("");
605    for (i = 0; (s != NULL) && (i < Argc); i++)
606    {
607       string_join  (&s, html_encode(Argv[i]));
608       string_append(&s, " ");
609    }
610    if (map(exports, "invocation", 1, s, 0))
611    {
612       free_map(exports);
613       return JB_ERR_MEMORY;
614    }
615
616    err = map(exports, "options", 1, csp->config->proxy_args, 1);
617    if (!err) err = show_defines(exports);
618
619 #ifdef FEATURE_STATISTICS
620    local_urls_read     = urls_read;
621    local_urls_rejected = urls_rejected;
622
623    /*
624     * Need to alter the stats not to include the fetch of this
625     * page.
626     *
627     * Can't do following thread safely! doh!
628     *
629     * urls_read--;
630     * urls_rejected--; * This will be incremented subsequently *
631     */
632
633    if (local_urls_read == 0)
634    {
635       if (!err) err = map_block_killer(exports, "have-stats");
636    }
637    else
638    {
639       if (!err) err = map_block_killer(exports, "have-no-stats");
640
641       perc_rej = (float)local_urls_rejected * 100.0F /
642             (float)local_urls_read;
643
644       sprintf(buf, "%d", local_urls_read);
645       if (!err) err = map(exports, "requests-received", 1, buf, 1);
646
647       sprintf(buf, "%d", local_urls_rejected);
648       if (!err) err = map(exports, "requests-blocked", 1, buf, 1);
649
650       sprintf(buf, "%6.2f", perc_rej);
651       if (!err) err = map(exports, "percent-blocked", 1, buf, 1);
652    }
653
654 #else /* ndef FEATURE_STATISTICS */
655    err = err || map_block_killer(exports, "statistics");
656 #endif /* ndef FEATURE_STATISTICS */
657
658    if (csp->actions_list)
659    {
660       if (!err) err = map(exports, "actions-filename", 1, html_encode(csp->actions_list->filename), 0);
661    }
662    else
663    {
664       if (!err) err = map(exports, "actions-filename", 1, "None specified", 1);
665    }
666
667    if (csp->rlist)
668    {
669       if (!err) err = map(exports, "re-filter-filename", 1, html_encode(csp->rlist->filename), 0);
670    }
671    else
672    {
673       if (!err) err = map(exports, "re-filter-filename", 1, "None specified", 1);
674    }
675
676 #ifdef FEATURE_TRUST
677    if (csp->tlist)
678    {
679       if (!err) err = map(exports, "trust-filename", 1, html_encode(csp->tlist->filename), 0);
680    }
681    else
682    {
683       if (!err) err = map(exports, "trust-filename", 1, "None specified", 1);
684    }
685 #else
686    if (!err) err = map_block_killer(exports, "trust-support");
687 #endif /* ndef FEATURE_TRUST */
688
689    if (err)
690    {
691       free_map(exports);
692       return JB_ERR_MEMORY;
693    }
694
695    return template_fill_for_cgi(csp, "show-status", exports, rsp);
696 }
697
698  
699 /*********************************************************************
700  *
701  * Function    :  cgi_show_url_info
702  *
703  * Description :  CGI function that determines and shows which actions
704  *                junkbuster will perform for a given url, and which
705  *                matches starting from the defaults have lead to that.
706  *
707  * Parameters  :
708  *          1  :  csp = Current client state (buffers, headers, etc...)
709  *          2  :  rsp = http_response data structure for output
710  *          3  :  parameters = map of cgi parameters
711  *
712  * CGI Parameters :
713  *            url : The url whose actions are to be determined.
714  *                  If url is unset, the url-given conditional will be
715  *                  set, so that all but the form can be suppressed in
716  *                  the template.
717  *
718  * Returns     :  JB_ERR_OK on success
719  *                JB_ERR_MEMORY on out-of-memory error.  
720  *
721  *********************************************************************/
722 jb_err cgi_show_url_info(struct client_state *csp,
723                          struct http_response *rsp,
724                          const struct map *parameters)
725 {
726    char *url_param;
727    struct map *exports;
728
729    assert(csp);
730    assert(rsp);
731    assert(parameters);
732
733    if (NULL == (exports = default_exports(csp, "show-url-info")))
734    {
735       return JB_ERR_MEMORY;
736    }
737
738    /*
739     * Get the url= parameter (if present) and remove any leading/trailing spaces.
740     */
741    url_param = strdup(lookup(parameters, "url"));
742    if (url_param == NULL)
743    {
744       free_map(exports);
745       return JB_ERR_MEMORY;
746    }
747    chomp(url_param);
748
749    /*
750     * Handle prefixes.  4 possibilities:
751     * 1) "http://" or "https://" prefix present and followed by URL - OK
752     * 2) Only the "http://" or "https://" part is present, no URL - change
753     *    to empty string so it will be detected later as "no URL".
754     * 3) Parameter specified but doesn't contain "http(s?)://" - add a
755     *    "http://" prefix.
756     * 4) Parameter not specified or is empty string - let this fall through
757     *    for now, next block of code will handle it.
758     */
759    if (0 == strncmp(url_param, "http://", 7))
760    {
761       if (url_param[7] == '\0')
762       {
763          /*
764           * Empty URL (just prefix).
765           * Make it totally empty so it's caught by the next if()
766           */
767          url_param[0] = '\0';
768       }
769    }
770    else if (0 == strncmp(url_param, "https://", 8))
771    {
772       if (url_param[8] == '\0')
773       {
774          /*
775           * Empty URL (just prefix).
776           * Make it totally empty so it's caught by the next if()
777           */
778          url_param[0] = '\0';
779       }
780    }
781    else if (url_param[0] != '\0')
782    {
783       /*
784        * Unknown prefix - assume http://
785        */
786       char * url_param_prefixed = malloc(7 + 1 + strlen(url_param));
787       if (NULL == url_param_prefixed)
788       {
789          free(url_param);
790          free_map(exports);
791          return JB_ERR_MEMORY;
792       }
793       strcpy(url_param_prefixed, "http://");
794       strcpy(url_param_prefixed + 7, url_param);
795       free(url_param);
796       url_param = url_param_prefixed;
797    }
798
799
800    if (url_param[0] == '\0')
801    {
802       /* URL paramater not specified, display query form only. */
803       free(url_param);
804       if (map_block_killer(exports, "url-given")
805         || map(exports, "url", 1, "", 1))
806       {
807          free_map(exports);
808          return JB_ERR_MEMORY;
809       }
810    }
811    else
812    {
813       /* Given a URL, so query it. */
814       jb_err err;
815       char *matches;
816       char *s;
817       int hits = 0;
818       struct file_list *fl;
819       struct url_actions *b;
820       struct http_request url_to_query[1];
821       struct current_action_spec action[1];
822       
823       if (map(exports, "url", 1, html_encode(url_param), 0))
824       {
825          free(url_param);
826          free_map(exports);
827          return JB_ERR_MEMORY;
828       }
829
830       init_current_action(action);
831
832       if (map(exports, "default", 1, html_encode_and_free_original(
833          current_action_to_text(action)), 0))
834       {
835          free_current_action(action);
836          free(url_param);
837          free_map(exports);
838          return JB_ERR_MEMORY;
839       }
840
841       if (((fl = csp->actions_list) == NULL) || ((b = fl->f) == NULL))
842       {
843          err = map(exports, "matches", 1, "none" , 1);
844          if (!err) err = map(exports, "final", 1, lookup(exports, "default"), 1);
845
846          free_current_action(action);
847          free(url_param);
848
849          if (err)
850          {
851             free_map(exports);
852             return JB_ERR_MEMORY;
853          }
854
855          return template_fill_for_cgi(csp, "show-url-info", exports, rsp);
856       }
857
858       err = parse_http_url(url_param, url_to_query, csp);
859
860       free(url_param);
861
862       if (err == JB_ERR_MEMORY)
863       {
864          free_current_action(action);
865          free_map(exports);
866          return JB_ERR_MEMORY;
867       }
868       else if (err)
869       {
870          /* Invalid URL */
871
872          err = map(exports, "matches", 1, "<b>[Invalid URL specified!]</b>" , 1);
873          if (!err) err = map(exports, "final", 1, lookup(exports, "default"), 1);
874
875          free_current_action(action);
876
877          if (err)
878          {
879             free_map(exports);
880             return JB_ERR_MEMORY;
881          }
882
883          return template_fill_for_cgi(csp, "show-url-info", exports, rsp);
884       }
885
886       /*
887        * We have a warning about SSL paths.  Hide it for insecure sites.
888        */
889       if (!url_to_query->ssl)
890       {
891          if (map_block_killer(exports, "https"))
892          {
893             free_current_action(action);
894             free_map(exports);
895             return JB_ERR_MEMORY;
896          }
897       }
898
899       matches = strdup("");
900
901       for (b = b->next; (b != NULL) && (matches != NULL); b = b->next)
902       {
903          if (url_match(b->url, url_to_query))
904          {
905             string_append(&matches, "<b>{");
906             string_join  (&matches, html_encode_and_free_original(
907                                     actions_to_text(b->action)));
908             string_append(&matches, " }</b><br>\n<code>");
909             string_join  (&matches, html_encode(b->url->spec));
910             string_append(&matches, "</code><br>\n<br>\n");
911
912             if (merge_current_action(action, b->action))
913             {
914                freez(matches);
915                free_http_request(url_to_query);
916                free_current_action(action);
917                free_map(exports);
918                return JB_ERR_MEMORY;
919             }
920             hits++;
921          }
922       }
923
924       free_http_request(url_to_query);
925
926       if (matches == NULL)
927       {
928          free_current_action(action);
929          free_map(exports);
930          return JB_ERR_MEMORY;
931       }
932
933       if (!hits)
934       {
935          free(matches);
936          matches = strdup("none");
937       }
938       if (map(exports, "matches", 1, matches , 0))
939       {
940          free_current_action(action);
941          free_map(exports);
942          return JB_ERR_MEMORY;
943       }
944
945       s = html_encode_and_free_original(current_action_to_text(action));
946
947       free_current_action(action);
948
949       if (map(exports, "final", 1, s, 0))
950       {
951          free_map(exports);
952          return JB_ERR_MEMORY;
953       }
954    }
955
956    return template_fill_for_cgi(csp, "show-url-info", exports, rsp);
957 }
958
959
960 /*********************************************************************
961  *
962  * Function    :  cgi_robots_txt
963  *
964  * Description :  CGI function to return "/robots.txt".
965  *
966  * Parameters  :
967  *          1  :  csp = Current client state (buffers, headers, etc...)
968  *          2  :  rsp = http_response data structure for output
969  *          3  :  parameters = map of cgi parameters
970  *
971  * CGI Parameters : None
972  *
973  * Returns     :  JB_ERR_OK on success
974  *                JB_ERR_MEMORY on out-of-memory error.  
975  *
976  *********************************************************************/
977 jb_err cgi_robots_txt(struct client_state *csp,
978                       struct http_response *rsp,
979                       const struct map *parameters)
980 {
981    char buf[100];
982    jb_err err;
983
984    rsp->body = strdup(
985       "# This is the Internet Junkbuster control interface.\n"
986       "# It isn't very useful to index it, and you're likely to break stuff.\n"
987       "# So go away!\n"
988       "\n"
989       "User-agent: *\n"
990       "Disallow: /\n"
991       "\n");
992    if (rsp->body == NULL)
993    {
994       return JB_ERR_MEMORY;
995    }
996
997    err = enlist_unique(rsp->headers, "Content-Type: text/plain", 13);
998
999    rsp->is_static = 1;
1000
1001    get_http_time(7 * 24 * 60 * 60, buf); /* 7 days into future */
1002    if (!err) err = enlist_unique_header(rsp->headers, "Expires", buf);
1003
1004    return (err ? JB_ERR_MEMORY : JB_ERR_OK);
1005 }
1006
1007
1008 /*********************************************************************
1009  *
1010  * Function    :  show_defines
1011  *
1012  * Description :  Add to a map the state od all conditional #defines
1013  *                used when building
1014  *
1015  * Parameters  :
1016  *          1  :  exports = map to extend
1017  *
1018  * Returns     :  JB_ERR_OK on success
1019  *                JB_ERR_MEMORY on out-of-memory error.  
1020  *
1021  *********************************************************************/
1022 static jb_err show_defines(struct map *exports)
1023 {
1024    jb_err err = JB_ERR_OK;
1025
1026 #ifdef FEATURE_ACL
1027    if (!err) err = map_conditional(exports, "FEATURE_ACL", 1);
1028 #else /* ifndef FEATURE_ACL */
1029    if (!err) err = map_conditional(exports, "FEATURE_ACL", 0);
1030 #endif /* ndef FEATURE_ACL */
1031
1032 #ifdef FEATURE_CGI_EDIT_ACTIONS
1033    if (!err) err = map_conditional(exports, "FEATURE_CGI_EDIT_ACTIONS", 1);
1034 #else /* ifndef FEATURE_COOKIE_JAR */
1035    if (!err) err = map_conditional(exports, "FEATURE_CGI_EDIT_ACTIONS", 0);
1036 #endif /* ndef FEATURE_COOKIE_JAR */
1037
1038 #ifdef FEATURE_COOKIE_JAR
1039    if (!err) err = map_conditional(exports, "FEATURE_COOKIE_JAR", 1);
1040 #else /* ifndef FEATURE_COOKIE_JAR */
1041    if (!err) err = map_conditional(exports, "FEATURE_COOKIE_JAR", 0);
1042 #endif /* ndef FEATURE_COOKIE_JAR */
1043
1044 #ifdef FEATURE_FAST_REDIRECTS
1045    if (!err) err = map_conditional(exports, "FEATURE_FAST_REDIRECTS", 1);
1046 #else /* ifndef FEATURE_FAST_REDIRECTS */
1047    if (!err) err = map_conditional(exports, "FEATURE_FAST_REDIRECTS", 0);
1048 #endif /* ndef FEATURE_FAST_REDIRECTS */
1049
1050 #ifdef FEATURE_FORCE_LOAD
1051    if (!err) err = map_conditional(exports, "FEATURE_FORCE_LOAD", 1);
1052 #else /* ifndef FEATURE_FORCE_LOAD */
1053    if (!err) err = map_conditional(exports, "FEATURE_FORCE_LOAD", 0);
1054 #endif /* ndef FEATURE_FORCE_LOAD */
1055
1056 #ifdef FEATURE_IMAGE_BLOCKING
1057    if (!err) err = map_conditional(exports, "FEATURE_IMAGE_BLOCKING", 1);
1058 #else /* ifndef FEATURE_IMAGE_BLOCKING */
1059    if (!err) err = map_conditional(exports, "FEATURE_IMAGE_BLOCKING", 0);
1060 #endif /* ndef FEATURE_IMAGE_BLOCKING */
1061
1062 #ifdef FEATURE_IMAGE_DETECT_MSIE
1063    if (!err) err = map_conditional(exports, "FEATURE_IMAGE_DETECT_MSIE", 1);
1064 #else /* ifndef FEATURE_IMAGE_DETECT_MSIE */
1065    if (!err) err = map_conditional(exports, "FEATURE_IMAGE_DETECT_MSIE", 0);
1066 #endif /* ndef FEATURE_IMAGE_DETECT_MSIE */
1067
1068 #ifdef FEATURE_KILL_POPUPS
1069    if (!err) err = map_conditional(exports, "FEATURE_KILL_POPUPS", 1);
1070 #else /* ifndef FEATURE_KILL_POPUPS */
1071    if (!err) err = map_conditional(exports, "FEATURE_KILL_POPUPS", 0);
1072 #endif /* ndef FEATURE_KILL_POPUPS */
1073
1074 #ifdef FEATURE_PTHREAD
1075    if (!err) err = map_conditional(exports, "FEATURE_PTHREAD", 1);
1076 #else /* ifndef FEATURE_PTHREAD */
1077    if (!err) err = map_conditional(exports, "FEATURE_PTHREAD", 0);
1078 #endif /* ndef FEATURE_PTHREAD */
1079
1080 #ifdef FEATURE_STATISTICS
1081    if (!err) err = map_conditional(exports, "FEATURE_STATISTICS", 1);
1082 #else /* ifndef FEATURE_STATISTICS */
1083    if (!err) err = map_conditional(exports, "FEATURE_STATISTICS", 0);
1084 #endif /* ndef FEATURE_STATISTICS */
1085
1086 #ifdef FEATURE_TOGGLE
1087    if (!err) err = map_conditional(exports, "FEATURE_TOGGLE", 1);
1088 #else /* ifndef FEATURE_TOGGLE */
1089    if (!err) err = map_conditional(exports, "FEATURE_TOGGLE", 0);
1090 #endif /* ndef FEATURE_TOGGLE */
1091
1092 #ifdef FEATURE_TRUST
1093    if (!err) err = map_conditional(exports, "FEATURE_TRUST", 1);
1094 #else /* ifndef FEATURE_TRUST */
1095    if (!err) err = map_conditional(exports, "FEATURE_TRUST", 0);
1096 #endif /* ndef FEATURE_TRUST */
1097
1098 #ifdef REGEX_GNU
1099    if (!err) err = map_conditional(exports, "REGEX_GNU", 1);
1100 #else /* ifndef REGEX_GNU */
1101    if (!err) err = map_conditional(exports, "REGEX_GNU", 0);
1102 #endif /* def REGEX_GNU */
1103
1104 #ifdef REGEX_PCRE
1105    if (!err) err = map_conditional(exports, "REGEX_PCRE", 1);
1106 #else /* ifndef REGEX_PCRE */
1107    if (!err) err = map_conditional(exports, "REGEX_PCRE", 0);
1108 #endif /* def REGEX_PCRE */
1109
1110 #ifdef STATIC_PCRE
1111    if (!err) err = map_conditional(exports, "STATIC_PCRE", 1);
1112 #else /* ifndef STATIC_PCRE */
1113    if (!err) err = map_conditional(exports, "STATIC_PCRE", 0);
1114 #endif /* ndef STATIC_PCRE */
1115
1116 #ifdef STATIC_PCRS
1117    if (!err) err = map_conditional(exports, "STATIC_PCRS", 1);
1118 #else /* ifndef STATIC_PCRS */
1119    if (!err) err = map_conditional(exports, "STATIC_PCRS", 0);
1120 #endif /* ndef STATIC_PCRS */
1121
1122    if (!err) err = map(exports, "FORCE_PREFIX", 1, FORCE_PREFIX, 1);
1123
1124    return err;
1125 }
1126
1127
1128 /*********************************************************************
1129  *
1130  * Function    :  show_rcs
1131  *
1132  * Description :  Create a string with the rcs info for all sourcefiles
1133  *
1134  * Parameters  :  None
1135  *
1136  * Returns     :  A string, or NULL on out-of-memory.
1137  *
1138  *********************************************************************/
1139 static char *show_rcs(void)
1140 {
1141    char *result = strdup("");
1142    char buf[BUFFER_SIZE];
1143
1144    /* Instead of including *all* dot h's in the project (thus creating a
1145     * tremendous amount of dependencies), I will concede to declaring them
1146     * as extern's.  This forces the developer to add to this list, but oh well.
1147     */
1148
1149 #define SHOW_RCS(__x)              \
1150    {                               \
1151       extern const char __x[];     \
1152       sprintf(buf, "%s\n", __x);   \
1153       string_append(&result, buf); \
1154    }
1155
1156    /* In alphabetical order */
1157    SHOW_RCS(actions_h_rcs)
1158    SHOW_RCS(actions_rcs)
1159    SHOW_RCS(cgi_h_rcs)
1160    SHOW_RCS(cgi_rcs)
1161 #ifdef FEATURE_CGI_EDIT_ACTIONS
1162    SHOW_RCS(cgiedit_h_rcs)
1163    SHOW_RCS(cgiedit_rcs)
1164 #endif /* def FEATURE_CGI_EDIT_ACTIONS */
1165    SHOW_RCS(cgisimple_h_rcs)
1166    SHOW_RCS(cgisimple_rcs)
1167 #ifdef __MINGW32__
1168    SHOW_RCS(cygwin_h_rcs)
1169 #endif
1170    SHOW_RCS(deanimate_h_rcs)
1171    SHOW_RCS(deanimate_rcs)
1172    SHOW_RCS(encode_h_rcs)
1173    SHOW_RCS(encode_rcs)
1174    SHOW_RCS(errlog_h_rcs)
1175    SHOW_RCS(errlog_rcs)
1176    SHOW_RCS(filters_h_rcs)
1177    SHOW_RCS(filters_rcs)
1178    SHOW_RCS(gateway_h_rcs)
1179    SHOW_RCS(gateway_rcs)
1180 #ifdef GNU_REGEX
1181    SHOW_RCS(gnu_regex_h_rcs)
1182    SHOW_RCS(gnu_regex_rcs)
1183 #endif /* def GNU_REGEX */
1184    SHOW_RCS(jbsockets_h_rcs)
1185    SHOW_RCS(jbsockets_rcs)
1186    SHOW_RCS(jcc_h_rcs)
1187    SHOW_RCS(jcc_rcs)
1188 #ifdef FEATURE_KILL_POPUPS
1189    SHOW_RCS(killpopup_h_rcs)
1190    SHOW_RCS(killpopup_rcs)
1191 #endif /* def FEATURE_KILL_POPUPS */
1192    SHOW_RCS(list_h_rcs)
1193    SHOW_RCS(list_rcs)
1194    SHOW_RCS(loadcfg_h_rcs)
1195    SHOW_RCS(loadcfg_rcs)
1196    SHOW_RCS(loaders_h_rcs)
1197    SHOW_RCS(loaders_rcs)
1198    SHOW_RCS(miscutil_h_rcs)
1199    SHOW_RCS(miscutil_rcs)
1200    SHOW_RCS(parsers_h_rcs)
1201    SHOW_RCS(parsers_rcs)
1202    SHOW_RCS(pcrs_rcs)
1203    SHOW_RCS(pcrs_h_rcs)
1204    SHOW_RCS(project_h_rcs)
1205    SHOW_RCS(ssplit_h_rcs)
1206    SHOW_RCS(ssplit_rcs)
1207    SHOW_RCS(urlmatch_h_rcs)
1208    SHOW_RCS(urlmatch_rcs)
1209 #ifdef _WIN32
1210 #ifndef _WIN_CONSOLE
1211    SHOW_RCS(w32log_h_rcs)
1212    SHOW_RCS(w32log_rcs)
1213    SHOW_RCS(w32res_h_rcs)
1214    SHOW_RCS(w32taskbar_h_rcs)
1215    SHOW_RCS(w32taskbar_rcs)
1216 #endif /* ndef _WIN_CONSOLE */
1217    SHOW_RCS(win32_h_rcs)
1218    SHOW_RCS(win32_rcs)
1219 #endif /* def _WIN32 */
1220
1221 #undef SHOW_RCS
1222
1223    return result;
1224
1225 }
1226
1227
1228 /*
1229   Local Variables:
1230   tab-width: 3
1231   end:
1232 */