X-Git-Url: http://www.privoxy.org/gitweb/?p=privoxy.git;a=blobdiff_plain;f=cgisimple.c;h=c3836db6a7e75cc9f17ef0389f0a13e623025aae;hp=005a83f1e012d0c826bd960b151fa4ff0e35ae27;hb=e37a59aca86ce1f33b5979f7456084b11919b3b7;hpb=3739843e889eb3d2cf3f52e61a5fa07db1b2b046 diff --git a/cgisimple.c b/cgisimple.c index 005a83f1..c3836db6 100644 --- a/cgisimple.c +++ b/cgisimple.c @@ -1,4 +1,4 @@ -const char cgisimple_rcs[] = "$Id: cgisimple.c,v 1.4 2001/10/02 15:31:12 oes Exp $"; +const char cgisimple_rcs[] = "$Id: cgisimple.c,v 1.14 2002/03/02 04:14:50 david__schmidt Exp $"; /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/cgisimple.c,v $ @@ -36,6 +36,51 @@ const char cgisimple_rcs[] = "$Id: cgisimple.c,v 1.4 2001/10/02 15:31:12 oes Exp * * Revisions : * $Log: cgisimple.c,v $ + * Revision 1.14 2002/03/02 04:14:50 david__schmidt + * Clean up a little CRLF unpleasantness that suddenly appeared + * + * Revision 1.13 2002/02/21 00:10:37 jongfoster + * Adding send-banner?type=auto option + * + * Revision 1.12 2002/01/23 01:03:32 jongfoster + * Fixing gcc [CygWin] compiler warnings + * + * Revision 1.11 2002/01/23 00:01:04 jongfoster + * Adding cgi_transparent_gif() for http://i.j.b/t + * Adding missing html_encode() to many CGI functions. + * Adding urlmatch.[ch] to http://i.j.b/show-version + * + * Revision 1.10 2002/01/17 21:10:37 jongfoster + * Changes to cgi_show_url_info to use new matching code from urlmatch.c. + * Also fixing a problem in the same function with improperly quoted URLs + * in output HTML, and adding code to handle https:// URLs correctly. + * + * Revision 1.9 2001/11/30 23:09:15 jongfoster + * Now reports on FEATURE_CGI_EDIT_ACTIONS + * Removing FEATURE_DENY_GZIP from template + * + * Revision 1.8 2001/11/13 00:14:07 jongfoster + * Fixing stupid bug now I've figured out what || means. + * (It always returns 0 or 1, not one of it's paramaters.) + * + * Revision 1.7 2001/10/23 21:48:19 jongfoster + * Cleaning up error handling in CGI functions - they now send back + * a HTML error page and should never cause a FATAL error. (Fixes one + * potential source of "denial of service" attacks). + * + * CGI actions file editor that works and is actually useful. + * + * Ability to toggle JunkBuster remotely using a CGI call. + * + * You can turn off both the above features in the main configuration + * file, e.g. if you are running a multi-user proxy. + * + * Revision 1.6 2001/10/14 22:00:32 jongfoster + * Adding support for a 404 error when an invalid CGI page is requested. + * + * Revision 1.5 2001/10/07 15:30:41 oes + * Removed FEATURE_DENY_GZIP + * * Revision 1.4 2001/10/02 15:31:12 oes * Introduced show-request cgi * @@ -76,12 +121,13 @@ const char cgisimple_rcs[] = "$Id: cgisimple.c,v 1.4 2001/10/02 15:31:12 oes Exp #include "miscutil.h" #include "loadcfg.h" #include "parsers.h" +#include "urlmatch.h" const char cgisimple_h_rcs[] = CGISIMPLE_H_VERSION; static char *show_rcs(void); -static void show_defines(struct map *exports); +static jb_err show_defines(struct map *exports); /********************************************************************* @@ -92,40 +138,106 @@ static void show_defines(struct map *exports); * Lists menu of available unhidden CGIs. * * Parameters : - * 1 : csp = Current client state (buffers, headers, etc...) - * 2 : rsp = http_response data structure for output - * 3 : parameters = map of cgi parameters + * 1 : csp = Current client state (buffers, headers, etc...) + * 2 : rsp = http_response data structure for output + * 3 : parameters = map of cgi parameters + * + * CGI Parameters : none * - * Returns : 0 + * Returns : JB_ERR_OK on success + * JB_ERR_MEMORY on out-of-memory + * (Problems other than out-of-memory should be + * handled by this routine - it should set the + * rsp appropriately and return "success") * *********************************************************************/ -int cgi_default(struct client_state *csp, struct http_response *rsp, - struct map *parameters) +jb_err cgi_default(struct client_state *csp, + struct http_response *rsp, + const struct map *parameters) { - char *p; - char *tmp = NULL; - struct map *exports = default_exports(csp, ""); + char *tmp; + struct map *exports; + + assert(csp); + assert(rsp); + assert(parameters); + + if (NULL == (exports = default_exports(csp, ""))) + { + return JB_ERR_MEMORY; + } /* If there were other parameters, export a dump as "cgi-parameters" */ - if(parameters) + if (parameters->first) { - p = dump_map(parameters); - tmp = strsav(tmp, "

What made you think this cgi takes parameters?\n" - "Anyway, here they are, in case you're interested:

\n"); - tmp = strsav(tmp, p); - map(exports, "cgi-parameters", 1, tmp, 0); - free(p); + tmp = strdup("

What made you think this cgi takes parameters?\n" + "Anyway, here they are, in case you're interested:

\n"); + string_join(&tmp, dump_map(parameters)); + if (tmp == NULL) + { + free_map(exports); + return JB_ERR_MEMORY; + } + if (map(exports, "cgi-parameters", 1, tmp, 0)) + { + return JB_ERR_MEMORY; + } } else { - map(exports, "cgi-parameters", 1, "", 1); + if (map(exports, "cgi-parameters", 1, "", 1)) + { + return JB_ERR_MEMORY; + } } - rsp->body = template_load(csp, "default"); - template_fill(&rsp->body, exports); - free_map(exports); - return(0); + return template_fill_for_cgi(csp, "default", exports, rsp); +} + + + +/********************************************************************* + * + * Function : cgi_error_404 + * + * Description : CGI function that is called if an unknown action was + * given. + * + * Parameters : + * 1 : csp = Current client state (buffers, headers, etc...) + * 2 : rsp = http_response data structure for output + * 3 : parameters = map of cgi parameters + * + * CGI Parameters : none + * + * Returns : JB_ERR_OK on success + * JB_ERR_MEMORY on out-of-memory error. + * + *********************************************************************/ +jb_err cgi_error_404(struct client_state *csp, + struct http_response *rsp, + const struct map *parameters) +{ + struct map *exports; + + assert(csp); + assert(rsp); + assert(parameters); + + if (NULL == (exports = default_exports(csp, NULL))) + { + return JB_ERR_MEMORY; + } + + rsp->status = strdup("404 JunkBuster configuration page not found"); + if (rsp->status == NULL) + { + free_map(exports); + return JB_ERR_MEMORY; + } + + return template_fill_for_cgi(csp, "cgi-error-404", exports, rsp); } @@ -137,18 +249,31 @@ int cgi_default(struct client_state *csp, struct http_response *rsp, * made of it. * * Parameters : - * 1 : csp = Current client state (buffers, headers, etc...) - * 2 : rsp = http_response data structure for output - * 3 : parameters = map of cgi parameters + * 1 : csp = Current client state (buffers, headers, etc...) + * 2 : rsp = http_response data structure for output + * 3 : parameters = map of cgi parameters + * + * CGI Parameters : none * - * Returns : 0 + * Returns : JB_ERR_OK on success + * JB_ERR_MEMORY on out-of-memory error. * *********************************************************************/ -int cgi_show_request(struct client_state *csp, struct http_response *rsp, - struct map *parameters) +jb_err cgi_show_request(struct client_state *csp, + struct http_response *rsp, + const struct map *parameters) { char *p; - struct map *exports = default_exports(csp, "show-request"); + struct map *exports; + + assert(csp); + assert(rsp); + assert(parameters); + + if (NULL == (exports = default_exports(csp, "show-request"))) + { + return JB_ERR_MEMORY; + } /* * Repair the damage done to the IOB by get_header() @@ -162,14 +287,21 @@ int cgi_show_request(struct client_state *csp, struct http_response *rsp, * Export the original client's request and the one we would * be sending to the server if this wasn't a CGI call */ - map(exports, "client-request", 1, csp->iob->buf, 1); - map(exports, "processed-request", 1, sed(client_patterns, add_client_headers, csp), 0); - - rsp->body = template_load(csp, "show-request"); - template_fill(&rsp->body, exports); - free_map(exports); - return(0); - + + if (map(exports, "client-request", 1, html_encode(csp->iob->buf), 0)) + { + free_map(exports); + return JB_ERR_MEMORY; + } + + if (map(exports, "processed-request", 1, html_encode_and_free_original( + sed(client_patterns, add_client_headers, csp)), 0)) + { + free_map(exports); + return JB_ERR_MEMORY; + } + + return template_fill_for_cgi(csp, "show-request", exports, rsp); } @@ -180,21 +312,46 @@ int cgi_show_request(struct client_state *csp, struct http_response *rsp, * Description : CGI function that returns a banner. * * Parameters : - * 1 : csp = Current client state (buffers, headers, etc...) - * 2 : rsp = http_response data structure for output - * 3 : parameters = map of cgi parameters + * 1 : csp = Current client state (buffers, headers, etc...) + * 2 : rsp = http_response data structure for output + * 3 : parameters = map of cgi parameters * * CGI Parameters : - * type : Selects the type of banner between "trans" and "jb". - * Defaults to "jb" if absent or != "trans". + * type : Selects the type of banner between "trans", "logo", + * and "auto". Defaults to "logo" if absent or invalid. + * "auto" means to select as if we were image-blocking. + * (Only the first character really counts). * - * Returns : 0 + * Returns : JB_ERR_OK on success + * JB_ERR_MEMORY on out-of-memory error. * *********************************************************************/ -int cgi_send_banner(struct client_state *csp, struct http_response *rsp, - struct map *parameters) +jb_err cgi_send_banner(struct client_state *csp, + struct http_response *rsp, + const struct map *parameters) { - if(strcmp(lookup(parameters, "type"), "trans")) + char imagetype = lookup(parameters, "type")[0]; + + if (imagetype == 'a') /* auto */ + { + /* Default to logo */ + imagetype = 'l'; +#ifdef FEATURE_IMAGE_BLOCKING + if ((csp->action->flags & ACTION_IMAGE_BLOCKER) != 0) + { + /* determine HOW images should be blocked */ + const char * p = csp->action->string[ACTION_STRING_IMAGE_BLOCKER]; + + /* and handle accordingly: */ + if ((p != NULL) && (0 == strcmpic(p, "blank"))) + { + imagetype = 't'; + } + } +#endif /* def FEATURE_IMAGE_BLOCKING */ + } + + if ((imagetype != 't') && (imagetype != 'b')) /* transparant/blank */ { rsp->body = bindup(image_junkbuster_gif_data, image_junkbuster_gif_length); rsp->content_length = image_junkbuster_gif_length; @@ -205,10 +362,60 @@ int cgi_send_banner(struct client_state *csp, struct http_response *rsp, rsp->content_length = image_blank_gif_length; } - enlist(rsp->headers, "Content-Type: image/gif"); + if (rsp->body == NULL) + { + return JB_ERR_MEMORY; + } + + if (enlist(rsp->headers, "Content-Type: image/gif")) + { + return JB_ERR_MEMORY; + } + + rsp->is_static = 1; + + return JB_ERR_OK; + +} + + +/********************************************************************* + * + * Function : cgi_transparent_gif + * + * Description : CGI function that sends a 1x1 transparent GIF. + * + * Parameters : + * 1 : csp = Current client state (buffers, headers, etc...) + * 2 : rsp = http_response data structure for output + * 3 : parameters = map of cgi parameters + * + * CGI Parameters : None + * + * Returns : JB_ERR_OK on success + * JB_ERR_MEMORY on out-of-memory error. + * + *********************************************************************/ +jb_err cgi_transparent_gif(struct client_state *csp, + struct http_response *rsp, + const struct map *parameters) +{ + rsp->body = bindup(image_blank_gif_data, image_blank_gif_length); + rsp->content_length = image_blank_gif_length; + + if (rsp->body == NULL) + { + return JB_ERR_MEMORY; + } + + if (enlist(rsp->headers, "Content-Type: image/gif")) + { + return JB_ERR_MEMORY; + } + rsp->is_static = 1; - return(0); + return JB_ERR_OK; } @@ -221,28 +428,38 @@ int cgi_send_banner(struct client_state *csp, struct http_response *rsp, * file versions of IJB. * * Parameters : - * 1 : csp = Current client state (buffers, headers, etc...) - * 2 : rsp = http_response data structure for output - * 3 : parameters = map of cgi parameters + * 1 : csp = Current client state (buffers, headers, etc...) + * 2 : rsp = http_response data structure for output + * 3 : parameters = map of cgi parameters * * CGI Parameters : none * - * Returns : 0 + * Returns : JB_ERR_OK on success + * JB_ERR_MEMORY on out-of-memory error. * *********************************************************************/ -int cgi_show_version(struct client_state *csp, struct http_response *rsp, - struct map *parameters) +jb_err cgi_show_version(struct client_state *csp, + struct http_response *rsp, + const struct map *parameters) { - struct map * exports = default_exports(csp, "show-version"); + struct map *exports; - map(exports, "sourceversions", 1, show_rcs(), 0); + assert(csp); + assert(rsp); + assert(parameters); - rsp->body = template_load(csp, "show-version"); - template_fill(&rsp->body, exports); - free_map(exports); + if (NULL == (exports = default_exports(csp, "show-version"))) + { + return JB_ERR_MEMORY; + } - return(0); + if (map(exports, "sourceversions", 1, show_rcs(), 0)) + { + free_map(exports); + return JB_ERR_MEMORY; + } + return template_fill_for_cgi(csp, "show-version", exports, rsp); } @@ -254,24 +471,31 @@ int cgi_show_version(struct client_state *csp, struct http_response *rsp, * current status of IJB. * * Parameters : - * 1 : csp = Current client state (buffers, headers, etc...) - * 2 : rsp = http_response data structure for output - * 3 : parameters = map of cgi parameters + * 1 : csp = Current client state (buffers, headers, etc...) + * 2 : rsp = http_response data structure for output + * 3 : parameters = map of cgi parameters * - * CGI Parameters : none + * CGI Parameters : + * file : Which file to show. Only first letter is checked, + * valid values are: + * - "p"ermissions (actions) file + * - "r"egex + * - "t"rust + * Default is to show menu and other information. * - * Returns : 0 + * Returns : JB_ERR_OK on success + * JB_ERR_MEMORY on out-of-memory error. * *********************************************************************/ -int cgi_show_status(struct client_state *csp, struct http_response *rsp, - struct map *parameters) +jb_err cgi_show_status(struct client_state *csp, + struct http_response *rsp, + const struct map *parameters) { char *s = NULL; int i; FILE * fp; char buf[BUFFER_SIZE]; - char * p; const char * filename = NULL; char * file_description = NULL; #ifdef FEATURE_STATISTICS @@ -279,8 +503,18 @@ int cgi_show_status(struct client_state *csp, struct http_response *rsp, int local_urls_read; int local_urls_rejected; #endif /* ndef FEATURE_STATISTICS */ + jb_err err; + + struct map *exports; + + assert(csp); + assert(rsp); + assert(parameters); - struct map * exports = default_exports(csp, "show-status"); + if (NULL == (exports = default_exports(csp, "show-status"))) + { + return JB_ERR_MEMORY; + } switch (*(lookup(parameters, "file"))) { @@ -313,47 +547,61 @@ int cgi_show_status(struct client_state *csp, struct http_response *rsp, if (NULL != filename) { - map(exports, "file-description", 1, file_description, 1); - map(exports, "filepath", 1, html_encode(filename), 0); + if ( map(exports, "file-description", 1, file_description, 1) + || map(exports, "filepath", 1, html_encode(filename), 0) ) + { + free_map(exports); + return JB_ERR_MEMORY; + } if ((fp = fopen(filename, "r")) == NULL) { - map(exports, "content", 1, "

ERROR OPENING FILE!

", 1); + if (map(exports, "content", 1, "

ERROR OPENING FILE!

", 1)) + { + free_map(exports); + return JB_ERR_MEMORY; + } } else { - while (fgets(buf, sizeof(buf), fp)) + s = strdup(""); + while ((s != NULL) && fgets(buf, sizeof(buf), fp)) { - p = html_encode(buf); - if (p) - { - s = strsav(s, p); - freez(p); - s = strsav(s, "
"); - } + string_join (&s, html_encode(buf)); + string_append(&s, "
"); } fclose(fp); - map(exports, "contents", 1, s, 0); + + if (map(exports, "contents", 1, s, 0)) + { + free_map(exports); + return JB_ERR_MEMORY; + } } - rsp->body = template_load(csp, "show-status-file"); - template_fill(&rsp->body, exports); - free_map(exports); - return(0); + return template_fill_for_cgi(csp, "show-status-file", exports, rsp); } - map(exports, "redirect-url", 1, REDIRECT_URL, 1); + if (map(exports, "redirect-url", 1, html_encode(REDIRECT_URL), 0)) + { + free_map(exports); + return JB_ERR_MEMORY; + } - s = NULL; - for (i=0; i < Argc; i++) + s = strdup(""); + for (i = 0; (s != NULL) && (i < Argc); i++) + { + string_join (&s, html_encode(Argv[i])); + string_append(&s, " "); + } + if (map(exports, "invocation", 1, s, 0)) { - s = strsav(s, Argv[i]); - s = strsav(s, " "); + free_map(exports); + return JB_ERR_MEMORY; } - map(exports, "invocation", 1, s, 0); - map(exports, "options", 1, csp->config->proxy_args, 1); - show_defines(exports); + err = map(exports, "options", 1, csp->config->proxy_args, 1); + if (!err) err = show_defines(exports); #ifdef FEATURE_STATISTICS local_urls_read = urls_read; @@ -371,65 +619,67 @@ int cgi_show_status(struct client_state *csp, struct http_response *rsp, if (local_urls_read == 0) { - map_block_killer(exports, "have-stats"); + if (!err) err = map_block_killer(exports, "have-stats"); } else { - map_block_killer(exports, "have-no-stats"); + if (!err) err = map_block_killer(exports, "have-no-stats"); perc_rej = (float)local_urls_rejected * 100.0F / (float)local_urls_read; sprintf(buf, "%d", local_urls_read); - map(exports, "requests-received", 1, buf, 1); + if (!err) err = map(exports, "requests-received", 1, buf, 1); sprintf(buf, "%d", local_urls_rejected); - map(exports, "requests-blocked", 1, buf, 1); + if (!err) err = map(exports, "requests-blocked", 1, buf, 1); sprintf(buf, "%6.2f", perc_rej); - map(exports, "percent-blocked", 1, buf, 1); + if (!err) err = map(exports, "percent-blocked", 1, buf, 1); } #else /* ndef FEATURE_STATISTICS */ - map_block_killer(exports, "statistics"); + err = err || map_block_killer(exports, "statistics"); #endif /* ndef FEATURE_STATISTICS */ if (csp->actions_list) { - map(exports, "actions-filename", 1, csp->actions_list->filename, 1); + if (!err) err = map(exports, "actions-filename", 1, html_encode(csp->actions_list->filename), 0); } else { - map(exports, "actions-filename", 1, "None specified", 1); + if (!err) err = map(exports, "actions-filename", 1, "None specified", 1); } if (csp->rlist) { - map(exports, "re-filter-filename", 1, csp->rlist->filename, 1); + if (!err) err = map(exports, "re-filter-filename", 1, html_encode(csp->rlist->filename), 0); } else { - map(exports, "re-filter-filename", 1, "None specified", 1); + if (!err) err = map(exports, "re-filter-filename", 1, "None specified", 1); } #ifdef FEATURE_TRUST if (csp->tlist) { - map(exports, "trust-filename", 1, csp->tlist->filename, 1); + if (!err) err = map(exports, "trust-filename", 1, html_encode(csp->tlist->filename), 0); } else { - map(exports, "trust-filename", 1, "None specified", 1); + if (!err) err = map(exports, "trust-filename", 1, "None specified", 1); } #else - map_block_killer(exports, "trust-support"); + if (!err) err = map_block_killer(exports, "trust-support"); #endif /* ndef FEATURE_TRUST */ - rsp->body = template_load(csp, "show-status"); - template_fill(&rsp->body, exports); - free_map(exports); - return(0); + if (err) + { + free_map(exports); + return JB_ERR_MEMORY; + } + return template_fill_for_cgi(csp, "show-status", exports, rsp); } @@ -442,9 +692,9 @@ int cgi_show_status(struct client_state *csp, struct http_response *rsp, * matches starting from the defaults have lead to that. * * Parameters : - * 1 : csp = Current client state (buffers, headers, etc...) - * 2 : rsp = http_response data structure for output - * 3 : parameters = map of cgi parameters + * 1 : csp = Current client state (buffers, headers, etc...) + * 2 : rsp = http_response data structure for output + * 3 : parameters = map of cgi parameters * * CGI Parameters : * url : The url whose actions are to be determined. @@ -452,153 +702,245 @@ int cgi_show_status(struct client_state *csp, struct http_response *rsp, * set, so that all but the form can be suppressed in * the template. * - * Returns : 0 + * Returns : JB_ERR_OK on success + * JB_ERR_MEMORY on out-of-memory error. * *********************************************************************/ -int cgi_show_url_info(struct client_state *csp, struct http_response *rsp, - struct map *parameters) +jb_err cgi_show_url_info(struct client_state *csp, + struct http_response *rsp, + const struct map *parameters) { char *url_param; - char *host = NULL; - struct map * exports = default_exports(csp, "show-url-info"); + struct map *exports; - if (NULL == (url_param = strdup(lookup(parameters, "url"))) || *url_param == '\0') + assert(csp); + assert(rsp); + assert(parameters); + + if (NULL == (exports = default_exports(csp, "show-url-info"))) { - map_block_killer(exports, "url-given"); - map(exports, "url", 1, "", 1); + return JB_ERR_MEMORY; + } + + /* + * Get the url= parameter (if present) and remove any leading/trailing spaces. + */ + url_param = strdup(lookup(parameters, "url")); + if (url_param == NULL) + { + free_map(exports); + return JB_ERR_MEMORY; + } + chomp(url_param); + + /* + * Handle prefixes. 4 possibilities: + * 1) "http://" or "https://" prefix present and followed by URL - OK + * 2) Only the "http://" or "https://" part is present, no URL - change + * to empty string so it will be detected later as "no URL". + * 3) Parameter specified but doesn't contain "http(s?)://" - add a + * "http://" prefix. + * 4) Parameter not specified or is empty string - let this fall through + * for now, next block of code will handle it. + */ + if (0 == strncmp(url_param, "http://", 7)) + { + if (url_param[7] == '\0') + { + /* + * Empty URL (just prefix). + * Make it totally empty so it's caught by the next if() + */ + url_param[0] = '\0'; + } + } + else if (0 == strncmp(url_param, "https://", 8)) + { + if (url_param[8] == '\0') + { + /* + * Empty URL (just prefix). + * Make it totally empty so it's caught by the next if() + */ + url_param[0] = '\0'; + } + } + else if (url_param[0] != '\0') + { + /* + * Unknown prefix - assume http:// + */ + char * url_param_prefixed = malloc(7 + 1 + strlen(url_param)); + if (NULL == url_param_prefixed) + { + free(url_param); + free_map(exports); + return JB_ERR_MEMORY; + } + strcpy(url_param_prefixed, "http://"); + strcpy(url_param_prefixed + 7, url_param); + free(url_param); + url_param = url_param_prefixed; + } + + + if (url_param[0] == '\0') + { + /* URL paramater not specified, display query form only. */ + free(url_param); + if (map_block_killer(exports, "url-given") + || map(exports, "url", 1, "", 1)) + { + free_map(exports); + return JB_ERR_MEMORY; + } } else { - char *matches = NULL; - char *path; + /* Given a URL, so query it. */ + jb_err err; + char *matches; char *s; - int port = 80; int hits = 0; struct file_list *fl; struct url_actions *b; - struct url_spec url[1]; + struct http_request url_to_query[1]; struct current_action_spec action[1]; - host = url_param; - host += (strncmp(url_param, "http://", 7)) ? 0 : 7; - - map(exports, "url", 1, host, 1); - map(exports, "url-html", 1, html_encode(host), 0); + if (map(exports, "url", 1, html_encode(url_param), 0)) + { + free(url_param); + free_map(exports); + return JB_ERR_MEMORY; + } init_current_action(action); - s = current_action_to_text(action); - map(exports, "default", 1, s , 0); + if (map(exports, "default", 1, html_encode_and_free_original( + current_action_to_text(action)), 0)) + { + free_current_action(action); + free(url_param); + free_map(exports); + return JB_ERR_MEMORY; + } if (((fl = csp->actions_list) == NULL) || ((b = fl->f) == NULL)) { - map(exports, "matches", 1, "none" , 1); - map(exports, "final", 1, lookup(exports, "default"), 1); + err = map(exports, "matches", 1, "none" , 1); + if (!err) err = map(exports, "final", 1, lookup(exports, "default"), 1); - freez(url_param); free_current_action(action); + free(url_param); - rsp->body = template_load(csp, "show-url-info"); - template_fill(&rsp->body, exports); - free_map(exports); + if (err) + { + free_map(exports); + return JB_ERR_MEMORY; + } - return 0; + return template_fill_for_cgi(csp, "show-url-info", exports, rsp); } - s = strchr(host, '/'); - if (s != NULL) - { - path = strdup(s); - *s = '\0'; - } - else + err = parse_http_url(url_param, url_to_query, csp); + + free(url_param); + + if (err == JB_ERR_MEMORY) { - path = strdup(""); + free_current_action(action); + free_map(exports); + return JB_ERR_MEMORY; } - s = strchr(host, ':'); - if (s != NULL) + else if (err) { - *s++ = '\0'; - port = atoi(s); - s = NULL; - } + /* Invalid URL */ - *url = dsplit(host); + err = map(exports, "matches", 1, "[Invalid URL specified!]" , 1); + if (!err) err = map(exports, "final", 1, lookup(exports, "default"), 1); - /* if splitting the domain fails, punt */ - if (url->dbuf == NULL) - { - map(exports, "matches", 1, "none" , 1); - map(exports, "final", 1, lookup(exports, "default"), 1); - - freez(url_param); - freez(path); free_current_action(action); - rsp->body = template_load(csp, "show-url-info"); - template_fill(&rsp->body, exports); - free_map(exports); + if (err) + { + free_map(exports); + return JB_ERR_MEMORY; + } + + return template_fill_for_cgi(csp, "show-url-info", exports, rsp); + } - return 0; + /* + * We have a warning about SSL paths. Hide it for insecure sites. + */ + if (!url_to_query->ssl) + { + if (map_block_killer(exports, "https")) + { + free_current_action(action); + free_map(exports); + return JB_ERR_MEMORY; + } } - for (b = b->next; NULL != b; b = b->next) + matches = strdup(""); + + for (b = b->next; (b != NULL) && (matches != NULL); b = b->next) { - if ((b->url->port == 0) || (b->url->port == port)) + if (url_match(b->url, url_to_query)) { - if ((b->url->domain[0] == '\0') || (domaincmp(b->url, url) == 0)) + string_append(&matches, "{"); + string_join (&matches, html_encode_and_free_original( + actions_to_text(b->action))); + string_append(&matches, " }
\n"); + string_join (&matches, html_encode(b->url->spec)); + string_append(&matches, "
\n
\n"); + + if (merge_current_action(action, b->action)) { - if ((b->url->path == NULL) || -#ifdef REGEX - (regexec(b->url->preg, path, 0, NULL, 0) == 0) -#else - (strncmp(b->url->path, path, b->url->pathlen) == 0) -#endif - ) - { - s = actions_to_text(b->action); - matches = strsav(matches, "{"); - matches = strsav(matches, s); - matches = strsav(matches, " }
\n"); - matches = strsav(matches, b->url->spec); - matches = strsav(matches, "
\n
\n"); - freez(s); - - merge_current_action(action, b->action); - hits++; - } + freez(matches); + free_http_request(url_to_query); + free_current_action(action); + free_map(exports); + return JB_ERR_MEMORY; } + hits++; } } - if (hits) + free_http_request(url_to_query); + + if (matches == NULL) { - map(exports, "matches", 1, matches , 0); + free_current_action(action); + free_map(exports); + return JB_ERR_MEMORY; } - else + + if (!hits) { - map(exports, "matches", 1, "none", 1); + free(matches); + matches = strdup("none"); + } + if (map(exports, "matches", 1, matches , 0)) + { + free_current_action(action); + free_map(exports); + return JB_ERR_MEMORY; } - matches = NULL; - - freez(url->dbuf); - freez(url->dvec); - - freez(url_param); - freez(path); - s = current_action_to_text(action); - map(exports, "final", 1, s, 0); - s = NULL; + s = html_encode_and_free_original(current_action_to_text(action)); free_current_action(action); - } - rsp->body = template_load(csp, "show-url-info"); - template_fill(&rsp->body, exports); - free_map(exports); - return 0; + if (map(exports, "final", 1, s, 0)) + { + free_map(exports); + return JB_ERR_MEMORY; + } + } + return template_fill_for_cgi(csp, "show-url-info", exports, rsp); } @@ -609,19 +951,22 @@ int cgi_show_url_info(struct client_state *csp, struct http_response *rsp, * Description : CGI function to return "/robots.txt". * * Parameters : - * 1 : csp = Current client state (buffers, headers, etc...) - * 2 : rsp = http_response data structure for output - * 3 : parameters = map of cgi parameters + * 1 : csp = Current client state (buffers, headers, etc...) + * 2 : rsp = http_response data structure for output + * 3 : parameters = map of cgi parameters * * CGI Parameters : None * - * Returns : 0 + * Returns : JB_ERR_OK on success + * JB_ERR_MEMORY on out-of-memory error. * *********************************************************************/ -int cgi_robots_txt(struct client_state *csp, struct http_response *rsp, - struct map *parameters) +jb_err cgi_robots_txt(struct client_state *csp, + struct http_response *rsp, + const struct map *parameters) { char buf[100]; + jb_err err; rsp->body = strdup( "# This is the Internet Junkbuster control interface.\n" @@ -631,16 +976,19 @@ int cgi_robots_txt(struct client_state *csp, struct http_response *rsp, "User-agent: *\n" "Disallow: /\n" "\n"); + if (rsp->body == NULL) + { + return JB_ERR_MEMORY; + } - enlist_unique(rsp->headers, "Content-Type: text/plain", 13); + err = enlist_unique(rsp->headers, "Content-Type: text/plain", 13); rsp->is_static = 1; get_http_time(7 * 24 * 60 * 60, buf); /* 7 days into future */ - enlist_unique_header(rsp->headers, "Expires", buf); - - return 0; + if (!err) err = enlist_unique_header(rsp->headers, "Expires", buf); + return (err ? JB_ERR_MEMORY : JB_ERR_OK); } @@ -648,109 +996,119 @@ int cgi_robots_txt(struct client_state *csp, struct http_response *rsp, * * Function : show_defines * - * Description : Create a string with all conditional #defines used - * when building + * Description : Add to a map the state od all conditional #defines + * used when building * - * Parameters : None + * Parameters : + * 1 : exports = map to extend * - * Returns : string + * Returns : JB_ERR_OK on success + * JB_ERR_MEMORY on out-of-memory error. * *********************************************************************/ -static void show_defines(struct map *exports) +static jb_err show_defines(struct map *exports) { + jb_err err = JB_ERR_OK; #ifdef FEATURE_ACL - map_conditional(exports, "FEATURE_ACL", 1); + if (!err) err = map_conditional(exports, "FEATURE_ACL", 1); #else /* ifndef FEATURE_ACL */ - map_conditional(exports, "FEATURE_ACL", 0); + if (!err) err = map_conditional(exports, "FEATURE_ACL", 0); #endif /* ndef FEATURE_ACL */ +#ifdef FEATURE_CGI_EDIT_ACTIONS + if (!err) err = map_conditional(exports, "FEATURE_CGI_EDIT_ACTIONS", 1); +#else /* ifndef FEATURE_COOKIE_JAR */ + if (!err) err = map_conditional(exports, "FEATURE_CGI_EDIT_ACTIONS", 0); +#endif /* ndef FEATURE_COOKIE_JAR */ + #ifdef FEATURE_COOKIE_JAR - map_conditional(exports, "FEATURE_COOKIE_JAR", 1); + if (!err) err = map_conditional(exports, "FEATURE_COOKIE_JAR", 1); #else /* ifndef FEATURE_COOKIE_JAR */ - map_conditional(exports, "FEATURE_COOKIE_JAR", 0); + if (!err) err = map_conditional(exports, "FEATURE_COOKIE_JAR", 0); #endif /* ndef FEATURE_COOKIE_JAR */ #ifdef FEATURE_FAST_REDIRECTS - map_conditional(exports, "FEATURE_FAST_REDIRECTS", 1); + if (!err) err = map_conditional(exports, "FEATURE_FAST_REDIRECTS", 1); #else /* ifndef FEATURE_FAST_REDIRECTS */ - map_conditional(exports, "FEATURE_FAST_REDIRECTS", 0); + if (!err) err = map_conditional(exports, "FEATURE_FAST_REDIRECTS", 0); #endif /* ndef FEATURE_FAST_REDIRECTS */ #ifdef FEATURE_FORCE_LOAD - map_conditional(exports, "FEATURE_FORCE_LOAD", 1); + if (!err) err = map_conditional(exports, "FEATURE_FORCE_LOAD", 1); #else /* ifndef FEATURE_FORCE_LOAD */ - map_conditional(exports, "FEATURE_FORCE_LOAD", 0); + if (!err) err = map_conditional(exports, "FEATURE_FORCE_LOAD", 0); #endif /* ndef FEATURE_FORCE_LOAD */ #ifdef FEATURE_IMAGE_BLOCKING - map_conditional(exports, "FEATURE_IMAGE_BLOCKING", 1); + if (!err) err = map_conditional(exports, "FEATURE_IMAGE_BLOCKING", 1); #else /* ifndef FEATURE_IMAGE_BLOCKING */ - map_conditional(exports, "FEATURE_IMAGE_BLOCKING", 0); + if (!err) err = map_conditional(exports, "FEATURE_IMAGE_BLOCKING", 0); #endif /* ndef FEATURE_IMAGE_BLOCKING */ #ifdef FEATURE_IMAGE_DETECT_MSIE - map_conditional(exports, "FEATURE_IMAGE_DETECT_MSIE", 1); + if (!err) err = map_conditional(exports, "FEATURE_IMAGE_DETECT_MSIE", 1); #else /* ifndef FEATURE_IMAGE_DETECT_MSIE */ - map_conditional(exports, "FEATURE_IMAGE_DETECT_MSIE", 0); + if (!err) err = map_conditional(exports, "FEATURE_IMAGE_DETECT_MSIE", 0); #endif /* ndef FEATURE_IMAGE_DETECT_MSIE */ #ifdef FEATURE_KILL_POPUPS - map_conditional(exports, "FEATURE_KILL_POPUPS", 1); + if (!err) err = map_conditional(exports, "FEATURE_KILL_POPUPS", 1); #else /* ifndef FEATURE_KILL_POPUPS */ - map_conditional(exports, "FEATURE_KILL_POPUPS", 0); + if (!err) err = map_conditional(exports, "FEATURE_KILL_POPUPS", 0); #endif /* ndef FEATURE_KILL_POPUPS */ #ifdef FEATURE_PTHREAD - map_conditional(exports, "FEATURE_PTHREAD", 1); + if (!err) err = map_conditional(exports, "FEATURE_PTHREAD", 1); #else /* ifndef FEATURE_PTHREAD */ - map_conditional(exports, "FEATURE_PTHREAD", 0); + if (!err) err = map_conditional(exports, "FEATURE_PTHREAD", 0); #endif /* ndef FEATURE_PTHREAD */ #ifdef FEATURE_STATISTICS - map_conditional(exports, "FEATURE_STATISTICS", 1); + if (!err) err = map_conditional(exports, "FEATURE_STATISTICS", 1); #else /* ifndef FEATURE_STATISTICS */ - map_conditional(exports, "FEATURE_STATISTICS", 0); + if (!err) err = map_conditional(exports, "FEATURE_STATISTICS", 0); #endif /* ndef FEATURE_STATISTICS */ #ifdef FEATURE_TOGGLE - map_conditional(exports, "FEATURE_TOGGLE", 1); + if (!err) err = map_conditional(exports, "FEATURE_TOGGLE", 1); #else /* ifndef FEATURE_TOGGLE */ - map_conditional(exports, "FEATURE_TOGGLE", 0); + if (!err) err = map_conditional(exports, "FEATURE_TOGGLE", 0); #endif /* ndef FEATURE_TOGGLE */ #ifdef FEATURE_TRUST - map_conditional(exports, "FEATURE_TRUST", 1); + if (!err) err = map_conditional(exports, "FEATURE_TRUST", 1); #else /* ifndef FEATURE_TRUST */ - map_conditional(exports, "FEATURE_TRUST", 0); + if (!err) err = map_conditional(exports, "FEATURE_TRUST", 0); #endif /* ndef FEATURE_TRUST */ #ifdef REGEX_GNU - map_conditional(exports, "REGEX_GNU", 1); + if (!err) err = map_conditional(exports, "REGEX_GNU", 1); #else /* ifndef REGEX_GNU */ - map_conditional(exports, "REGEX_GNU", 0); + if (!err) err = map_conditional(exports, "REGEX_GNU", 0); #endif /* def REGEX_GNU */ #ifdef REGEX_PCRE - map_conditional(exports, "REGEX_PCRE", 1); + if (!err) err = map_conditional(exports, "REGEX_PCRE", 1); #else /* ifndef REGEX_PCRE */ - map_conditional(exports, "REGEX_PCRE", 0); + if (!err) err = map_conditional(exports, "REGEX_PCRE", 0); #endif /* def REGEX_PCRE */ #ifdef STATIC_PCRE - map_conditional(exports, "STATIC_PCRE", 1); + if (!err) err = map_conditional(exports, "STATIC_PCRE", 1); #else /* ifndef STATIC_PCRE */ - map_conditional(exports, "STATIC_PCRE", 0); + if (!err) err = map_conditional(exports, "STATIC_PCRE", 0); #endif /* ndef STATIC_PCRE */ #ifdef STATIC_PCRS - map_conditional(exports, "STATIC_PCRS", 1); + if (!err) err = map_conditional(exports, "STATIC_PCRS", 1); #else /* ifndef STATIC_PCRS */ - map_conditional(exports, "STATIC_PCRS", 0); + if (!err) err = map_conditional(exports, "STATIC_PCRS", 0); #endif /* ndef STATIC_PCRS */ - map(exports, "FORCE_PREFIX", 1, FORCE_PREFIX, 1); + if (!err) err = map(exports, "FORCE_PREFIX", 1, FORCE_PREFIX, 1); + return err; } @@ -762,12 +1120,12 @@ static void show_defines(struct map *exports) * * Parameters : None * - * Returns : string + * Returns : A string, or NULL on out-of-memory. * *********************************************************************/ static char *show_rcs(void) { - char *b = NULL; + char *result = strdup(""); char buf[BUFFER_SIZE]; /* Instead of including *all* dot h's in the project (thus creating a @@ -775,11 +1133,11 @@ static char *show_rcs(void) * as extern's. This forces the developer to add to this list, but oh well. */ -#define SHOW_RCS(__x) \ - { \ - extern const char __x[]; \ - sprintf(buf, "%s\n", __x); \ - b = strsav(b, buf); \ +#define SHOW_RCS(__x) \ + { \ + extern const char __x[]; \ + sprintf(buf, "%s\n", __x); \ + string_append(&result, buf); \ } /* In alphabetical order */ @@ -833,6 +1191,8 @@ static char *show_rcs(void) SHOW_RCS(project_h_rcs) SHOW_RCS(ssplit_h_rcs) SHOW_RCS(ssplit_rcs) + SHOW_RCS(urlmatch_h_rcs) + SHOW_RCS(urlmatch_rcs) #ifdef _WIN32 #ifndef _WIN_CONSOLE SHOW_RCS(w32log_h_rcs) @@ -847,7 +1207,7 @@ static char *show_rcs(void) #undef SHOW_RCS - return(b); + return result; }