-const char loaders_rcs[] = "$Id: loaders.c,v 1.45 2002/03/16 23:54:06 jongfoster Exp $";
+const char loaders_rcs[] = "$Id: loaders.c,v 1.55 2006/09/07 10:25:39 fabiankeil Exp $";
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/loaders.c,v $
* unload files that are no longer in use.
*
* Copyright : Written by and Copyright (C) 2001 the SourceForge
- * Privoxy team. http://ijbswa.sourceforge.net
+ * Privoxy team. http://www.privoxy.org/
*
* Based on the Internet Junkbuster originally written
* by and Copyright (C) 1997 Anonymous Coders and
*
* Revisions :
* $Log: loaders.c,v $
+ * Revision 1.55 2006/09/07 10:25:39 fabiankeil
+ * Fix typo.
+ *
+ * Revision 1.54 2006/09/07 10:22:20 fabiankeil
+ * If too many trusted referrers are used,
+ * print only one error message instead of logging
+ * every single trusted referrer above the arbitrary
+ * limit.
+ *
+ * Revision 1.53 2006/08/31 16:25:06 fabiankeil
+ * Work around a buffer overflow that caused Privoxy to
+ * segfault if too many trusted referrers were used. Good
+ * enough for now, but should be replaced with a real
+ * solution after the next release.
+ *
+ * Revision 1.52 2006/07/18 14:48:46 david__schmidt
+ * Reorganizing the repository: swapping out what was HEAD (the old 3.1 branch)
+ * with what was really the latest development (the v_3_0_branch branch)
+ *
+ * Revision 1.50.2.8 2006/01/30 15:16:25 david__schmidt
+ * Remove a little residual debugging info
+ *
+ * Revision 1.50.2.7 2006/01/29 23:10:56 david__schmidt
+ * Multiple filter file support
+ *
+ * Revision 1.50.2.6 2003/10/24 10:17:54 oes
+ * Nit: Allowed tabs as separators in filter headings
+ *
+ * Revision 1.50.2.5 2003/05/08 15:19:15 oes
+ * sweep: Made loop structure of sweep step mirror that of mark step
+ *
+ * Revision 1.50.2.4 2003/05/06 15:57:12 oes
+ * Bugfix: Update last_active pointer in sweep() before
+ * leaving an active client. Closes bugs #724395, #727882
+ *
+ * Revision 1.50.2.3 2002/11/20 17:12:30 oes
+ * Ooops, forgot one change.
+ *
+ * Revision 1.50.2.2 2002/11/20 14:38:15 oes
+ * Fixed delayed/incomplete freeing of client resources and
+ * simplified loop structure in sweep.
+ * Thanks to Oliver Stoeneberg for the hint.
+ *
+ * Revision 1.50.2.1 2002/07/26 15:19:24 oes
+ * - PCRS jobs now chained in order of appearance. Previous
+ * reverse chaining was counter-intuitive.
+ * - Changed loglevel of PCRS job compile errors to
+ * LOG_LEVEL_ERROR
+ *
+ * Revision 1.50 2002/04/24 02:12:16 oes
+ * Jon's multiple AF patch: Sweep now takes care of all AFs
+ *
+ * Revision 1.49 2002/04/19 16:53:25 jongfoster
+ * Optimize away a function call by using an equivalent macro
+ *
+ * Revision 1.48 2002/04/05 00:56:09 gliptak
+ * Correcting typo to clean up on realloc failure
+ *
+ * Revision 1.47 2002/03/26 22:29:55 swa
+ * we have a new homepage!
+ *
+ * Revision 1.46 2002/03/24 13:25:43 swa
+ * name change related issues
+ *
* Revision 1.45 2002/03/16 23:54:06 jongfoster
* Adding graceful termination feature, to help look for memory leaks.
* If you enable this (which, by design, has to be done by hand
static struct file_list *current_trustfile = NULL;
#endif /* def FEATURE_TRUST */
-static struct file_list *current_re_filterfile = NULL;
+static int load_one_re_filterfile(struct client_state *csp, int fileid);
+
+static struct file_list *current_re_filterfile[MAX_AF_FILES] = {
+ NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL
+};
void sweep(void)
{
struct file_list *fl, *nfl;
- struct client_state *csp, *ncsp;
+ struct client_state *csp, *last_active;
+ int i;
/* clear all of the file's active flags */
for ( fl = files->next; NULL != fl; fl = fl->next )
fl->active = 0;
}
- for (csp = clients; csp && (NULL != (ncsp = csp->next)) ; csp = csp->next)
+ last_active = clients;
+ csp = clients->next;
+
+ while (NULL != csp)
{
- if (ncsp->flags & CSP_FLAG_ACTIVE)
+ if (csp->flags & CSP_FLAG_ACTIVE)
{
- /* mark this client's files as active */
+ /* Mark this client's files as active */
/*
* Always have a configuration file.
* (Also note the slightly non-standard extra
* indirection here.)
*/
- ncsp->config->config_file_list->active = 1;
+ csp->config->config_file_list->active = 1;
- if (ncsp->actions_list) /* actions files */
+ /*
+ * Actions files
+ */
+ for (i = 0; i < MAX_AF_FILES; i++)
{
- ncsp->actions_list->active = 1;
+ if (csp->actions_list[i])
+ {
+ csp->actions_list[i]->active = 1;
+ }
}
- if (ncsp->rlist) /* pcrsjob files */
+ /*
+ * Filter files
+ */
+ for (i = 0; i < MAX_AF_FILES; i++)
{
- ncsp->rlist->active = 1;
+ if (csp->rlist[i])
+ {
+ csp->rlist[i]->active = 1;
+ }
}
+ /*
+ * Trust file
+ */
#ifdef FEATURE_TRUST
- if (ncsp->tlist) /* trust files */
+ if (csp->tlist)
{
- ncsp->tlist->active = 1;
+ csp->tlist->active = 1;
}
#endif /* def FEATURE_TRUST */
+
+ last_active = csp;
+ csp = csp->next;
}
- else
+ else
/*
- * this client is not active, release its resources
- * and the ones of all inactive clients that might
- * follow it
+ * This client is not active. Free its resources.
*/
{
- while (!(ncsp->flags & CSP_FLAG_ACTIVE))
- {
- csp->next = ncsp->next;
+ last_active->next = csp->next;
- freez(ncsp->ip_addr_str);
- freez(ncsp->my_ip_addr_str);
- freez(ncsp->my_hostname);
- freez(ncsp->x_forwarded);
- freez(ncsp->iob->buf);
+ freez(csp->ip_addr_str);
+ freez(csp->my_ip_addr_str);
+ freez(csp->my_hostname);
+ freez(csp->x_forwarded);
+ freez(csp->iob->buf);
- free_http_request(ncsp->http);
+ free_http_request(csp->http);
- destroy_list(ncsp->headers);
- destroy_list(ncsp->cookie_list);
+ destroy_list(csp->headers);
+ destroy_list(csp->cookie_list);
- free_current_action(ncsp->action);
+ free_current_action(csp->action);
#ifdef FEATURE_STATISTICS
- urls_read++;
- if (ncsp->flags & CSP_FLAG_REJECTED)
- {
- urls_rejected++;
- }
+ urls_read++;
+ if (csp->flags & CSP_FLAG_REJECTED)
+ {
+ urls_rejected++;
+ }
#endif /* def FEATURE_STATISTICS */
- freez(ncsp);
-
- /* are there any more in sequence after it? */
- if( (ncsp = csp->next) == NULL)
- break;
- }
+ freez(csp);
+
+ csp = last_active->next;
}
}
- for (fl = files; fl && ((nfl = fl->next) != NULL) ; fl = fl->next)
+ nfl = files;
+ fl = files->next;
+
+ while (fl != NULL)
{
- if ( ( 0 == nfl->active ) && ( NULL != nfl->unloader ) )
+ if ( ( 0 == fl->active ) && ( NULL != fl->unloader ) )
{
- fl->next = nfl->next;
+ nfl->next = fl->next;
- (nfl->unloader)(nfl->f);
+ (fl->unloader)(fl->f);
- freez(nfl->filename);
+ freez(fl->filename);
+ freez(fl);
- freez(nfl);
+ fl = nfl->next;
+ }
+ else
+ {
+ nfl = fl;
+ fl = fl->next;
}
}
return 1;
}
+
fs->filename = strdup(filename);
fs->lastmodified = statbuf->st_mtime;
for (;;)
{
- ch = fgetc(fp);
+ ch = getc(fp);
if (ch == EOF)
{
if (len > 0)
if (++len >= buflen)
{
buflen += BUFFER_SIZE;
- if (NULL == (p = realloc(buf, buflen)));
+ if (NULL == (p = realloc(buf, buflen)))
{
free(buf);
return JB_ERR_MEMORY;
int reject, trusted;
struct file_list *fs;
unsigned long linenum = 0;
+ int trusted_referrers = 0;
if (!check_file_changed(current_trustfile, csp->config->trustfile, &fs))
{
*/
if (trusted)
{
- *tl++ = b->url;
- /* FIXME BUFFER OVERFLOW if >=64 entries */
+ if(++trusted_referrers < MAX_TRUSTED_REFERRERS)
+ {
+ *tl++ = b->url;
+ }
}
}
+ if(trusted_referrers >= MAX_TRUSTED_REFERRERS)
+ {
+ /*
+ * FIXME: ... after Privoxy 3.0.4 is out.
+ */
+ log_error(LOG_LEVEL_ERROR, "Too many trusted referrers. Current limit is %d, you are using %d.\n"
+ " Additional trusted referrers are treated like ordinary trusted URLs.\n"
+ " (You can increase this limit by changing MAX_TRUSTED_REFERRERS in project.h and recompiling).",
+ MAX_TRUSTED_REFERRERS, trusted_referrers);
+ }
+
*tl = NULL;
fclose(fp);
*********************************************************************/
void unload_current_re_filterfile(void)
{
- if (current_re_filterfile)
+ int i;
+
+ for (i = 0; i < MAX_AF_FILES; i++)
{
- current_re_filterfile->unloader = unload_re_filterfile;
- current_re_filterfile = NULL;
+ if (current_re_filterfile[i])
+ {
+ current_re_filterfile[i]->unloader = unload_re_filterfile;
+ current_re_filterfile[i] = NULL;
+ }
}
}
#endif
*
*********************************************************************/
int load_re_filterfile(struct client_state *csp)
+{
+ int i;
+ int result;
+
+ for (i = 0; i < MAX_AF_FILES; i++)
+ {
+ if (csp->config->re_filterfile[i])
+ {
+ result = load_one_re_filterfile(csp, i);
+ if (result)
+ {
+ return result;
+ }
+ }
+ else if (current_re_filterfile[i])
+ {
+ current_re_filterfile[i]->unloader = unload_re_filterfile;
+ current_re_filterfile[i] = NULL;
+ }
+ }
+
+ return 0;
+}
+
+/*********************************************************************
+ *
+ * Function : load_one_re_filterfile
+ *
+ * Description : Load a re_filterfile.
+ * Generate a chained list of re_filterfile_spec's from
+ * the "FILTER: " blocks, compiling all their substitutions
+ * into chained lists of pcrs_job structs.
+ *
+ * Parameters :
+ * 1 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : 0 => Ok, everything else is an error.
+ *
+ *********************************************************************/
+int load_one_re_filterfile(struct client_state *csp, int fileid)
{
FILE *fp;
char buf[BUFFER_SIZE];
int error;
unsigned long linenum = 0;
- pcrs_job *dummy;
+ pcrs_job *dummy, *lastjob = NULL;
/*
* No need to reload if unchanged
*/
- if (!check_file_changed(current_re_filterfile, csp->config->re_filterfile, &fs))
+ if (!check_file_changed(current_re_filterfile[fileid], csp->config->re_filterfile[fileid], &fs))
{
if (csp)
{
- csp->rlist = current_re_filterfile;
+ csp->rlist[fileid] = current_re_filterfile[fileid];
}
return(0);
}
/*
* Open the file or fail
*/
- if ((fp = fopen(csp->config->re_filterfile, "r")) == NULL)
+ if ((fp = fopen(csp->config->re_filterfile[fileid], "r")) == NULL)
{
goto load_re_filterfile_error;
}
new_bl->name = chomp(buf + 7);
- if (NULL != (new_bl->description = strchr(new_bl->name, ' ')))
+ if (NULL != (new_bl->description = strpbrk(new_bl->name, " \t")))
{
*new_bl->description++ = '\0';
new_bl->description = strdup(chomp(new_bl->description));
if ((dummy = pcrs_compile_command(buf, &error)) == NULL)
{
- log_error(LOG_LEVEL_RE_FILTER,
+ log_error(LOG_LEVEL_ERROR,
"Adding re_filter job %s to filter %s failed with error %d.", buf, bl->name, error);
continue;
}
else
{
- dummy->next = bl->joblist;
- bl->joblist = dummy;
+ if (bl->joblist == NULL)
+ {
+ bl->joblist = dummy;
+ }
+ else
+ {
+ lastjob->next = dummy;
+ }
+ lastjob = dummy;
log_error(LOG_LEVEL_RE_FILTER, "Adding re_filter job %s to filter %s succeeded.", buf, bl->name);
}
}
/*
* Schedule the now-obsolete old data for unloading
*/
- if ( NULL != current_re_filterfile )
+ if ( NULL != current_re_filterfile[fileid] )
{
- current_re_filterfile->unloader = unload_re_filterfile;
+ current_re_filterfile[fileid]->unloader = unload_re_filterfile;
}
/*
*/
fs->next = files->next;
files->next = fs;
- current_re_filterfile = fs;
+ current_re_filterfile[fileid] = fs;
if (csp)
{
- csp->rlist = fs;
+ csp->rlist[fileid] = fs;
}
return( 0 );
load_re_filterfile_error:
log_error(LOG_LEVEL_FATAL, "can't load re_filterfile '%s': %E",
- csp->config->re_filterfile);
+ csp->config->re_filterfile[fileid]);
return(-1);
}