X-Git-Url: http://www.privoxy.org/gitweb/?a=blobdiff_plain;f=filters.c;h=f29803bb38f2c84e39dc78925b9f6c8b72680e0d;hb=625fe85d139316efcc0cac532a8fd5208486dc88;hp=edead9da3c01c35d4d08cd22a65950dc16c12342;hpb=6214863ee264cc161a06bc58af5eec98714194c1;p=privoxy.git diff --git a/filters.c b/filters.c index edead9da..f29803bb 100644 --- a/filters.c +++ b/filters.c @@ -1,4 +1,4 @@ -const char filters_rcs[] = "$Id: filters.c,v 1.68 2006/12/05 14:45:48 fabiankeil Exp $"; +const char filters_rcs[] = "$Id: filters.c,v 1.73 2006/12/23 16:01:02 fabiankeil Exp $"; /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/filters.c,v $ @@ -40,6 +40,27 @@ const char filters_rcs[] = "$Id: filters.c,v 1.68 2006/12/05 14:45:48 fabiankeil * * Revisions : * $Log: filters.c,v $ + * Revision 1.73 2006/12/23 16:01:02 fabiankeil + * Don't crash if pcre returns an error code + * that pcrs didn't expect. Fixes BR 1621173. + * + * Revision 1.72 2006/12/22 18:52:53 fabiankeil + * Modified is_untrusted_url to complain in case of + * write errors and to give a reason when adding new + * entries to the trustfile. Closes FR 1097611. + * + * Revision 1.71 2006/12/22 14:24:52 fabiankeil + * Skip empty filter files in pcrs_filter_response, + * but don't ignore the ones that come afterwards. + * Fixes parts of BR 1619208. + * + * Revision 1.70 2006/12/09 13:33:15 fabiankeil + * Added some sanity checks for get_last_url(). + * Fixed possible segfault caused by my last commit. + * + * Revision 1.69 2006/12/08 12:39:13 fabiankeil + * Let get_last_url() catch https URLs as well. + * * Revision 1.68 2006/12/05 14:45:48 fabiankeil * Make sure get_last_url() behaves like advertised * and fast-redirects{} can be combined with redirect{}. @@ -1258,20 +1279,32 @@ char *rewrite_url(char *old_url, const char *pcrs_command) *********************************************************************/ char *get_last_url(char *subject, const char *redirect_mode) { - char *new_url; + char *new_url = NULL; char *tmp; assert(subject); assert(redirect_mode); subject = strdup(subject); + if (subject == NULL) + { + log_error(LOG_LEVEL_ERROR, "Out of memory while searching for redirects."); + return NULL; + } if (0 == strcmpic(redirect_mode, "check-decoded-url")) { log_error(LOG_LEVEL_REDIRECTS, "Decoding \"%s\" if necessary.", subject); new_url = url_decode(subject); - freez(subject); - subject = new_url; + if (new_url != NULL) + { + freez(subject); + subject = new_url; + } + else + { + log_error(LOG_LEVEL_ERROR, "Unable to decode \"%s\".", subject); + } } log_error(LOG_LEVEL_REDIRECTS, "Checking \"%s\" for redirects.", subject); @@ -1284,15 +1317,17 @@ char *get_last_url(char *subject, const char *redirect_mode) { new_url = tmp++; } - tmp = new_url; + tmp = (new_url != NULL) ? new_url : subject; while ((tmp = strstr(tmp, "https://")) != NULL) { new_url = tmp++; } - if ((new_url != subject) - || (0 == strncmpic(subject, "http://", 7)) - || (0 == strncmpic(subject, "https://", 8))) + if ((new_url != NULL) + && ( (new_url != subject) + || (0 == strncmpic(subject, "http://", 7)) + || (0 == strncmpic(subject, "https://", 8)) + )) { /* * Return new URL if we found a redirect @@ -1544,7 +1579,7 @@ int is_untrusted_url(struct client_state *csp) { /* if the URL's referrer is from a trusted referrer, then * add the target spec to the trustfile as an unblocked - * domain and return NULL (which means it's OK). + * domain and return 0 (which means it's OK). */ FILE *fp; @@ -1575,9 +1610,19 @@ int is_untrusted_url(struct client_state *csp) string_join(&new_entry, path); } + /* + * Give a reason for generating this entry. + */ + string_append(&new_entry, " # Trusted referrer was: "); + string_append(&new_entry, referer); + if (new_entry != NULL) { - fprintf(fp, "%s\n", new_entry); + if (-1 == fprintf(fp, "%s\n", new_entry)) + { + log_error(LOG_LEVEL_ERROR, "Failed to append \'%s\' to trustfile \'%s\': %E", + new_entry, csp->config->trustfile); + } free(new_entry); } else @@ -1588,6 +1633,11 @@ int is_untrusted_url(struct client_state *csp) fclose(fp); } + else + { + log_error(LOG_LEVEL_ERROR, "Failed to append new entry for \'%s\' to trustfile \'%s\': %E", + csp->http->hostport, csp->config->trustfile); + } return 0; } } @@ -1677,7 +1727,18 @@ char *pcrs_filter_response(struct client_state *csp) { fl = csp->rlist[i]; if ((NULL == fl) || (NULL == fl->f)) - break; + { + /* + * Either there are no filter files + * left, or this filter file just + * contains no valid filters. + * + * Continue to be sure we don't miss + * valid filter files that are chained + * after empty or invalid ones. + */ + continue; + } /* * For all applying +filter actions, look if a filter by that * name exists and if yes, execute it's pcrs_joblist on the @@ -1690,7 +1751,9 @@ char *pcrs_filter_response(struct client_state *csp) { if (strcmp(b->name, filtername->str) == 0) { - int current_hits = 0; + int current_hits = 0; /* Number of hits caused by this filter */ + int job_number = 0; /* Which job we're currently executing */ + int job_hits = 0; /* How many hits the current job caused */ if ( NULL == b->joblist ) { @@ -1702,13 +1765,50 @@ char *pcrs_filter_response(struct client_state *csp) /* Apply all jobs from the joblist */ for (job = b->joblist; NULL != job; job = job->next) { - current_hits += pcrs_execute(job, old, size, &new, &size); - if (old != csp->iob->cur) free(old); - old=new; + job_number++; + job_hits = pcrs_execute(job, old, size, &new, &size); + + if (job_hits >= 0) + { + /* + * That went well. Continue filtering + * and use the result of this job as + * input for the next one. + */ + current_hits += job_hits; + if (old != csp->iob->cur) + { + free(old); + } + old = new; + } + else + { + /* + * This job caused an unexpected error. Inform the user + * and skip the rest of the jobs in this filter. We could + * continue with the next job, but usually the jobs + * depend on each other or are similar enough to + * fail for the same reason. + * + * At the moment our pcrs expects the error codes of pcre 3.4, + * but newer pcre versions can return additional error codes. + * As a result pcrs_strerror()'s error message might be + * "Unknown error ...", therefore we print the numerical value + * as well. + * + * XXX: Is this important enough for LOG_LEVEL_ERROR or + * should we use LOG_LEVEL_RE_FILTER instead? + */ + log_error(LOG_LEVEL_ERROR, "Skipped filter \'%s\' after job number %u: %s (%d)", + b->name, job_number, pcrs_strerror(job_hits), job_hits); + break; + } } - log_error(LOG_LEVEL_RE_FILTER, "re_filtering %s%s (size %d) with filter %s produced %d hits (new size %d).", - csp->http->hostport, csp->http->path, prev_size, b->name, current_hits, size); + log_error(LOG_LEVEL_RE_FILTER, + "re_filtering %s%s (size %d) with filter %s produced %d hits (new size %d).", + csp->http->hostport, csp->http->path, prev_size, b->name, current_hits, size); hits += current_hits; }