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