/* open a config file and separate it into lines for read_config_line() */ static void read_config_file(const fnchar *filename) { FILE *fp; int fsize; char *buf, *line; fp = fopen(filename, "rb"); if (!fp) return; /* obtain file size. */ fseek(fp , 0 , SEEK_END); fsize = ftell(fp); rewind(fp); if (!fsize) {/* truncated config file */ fclose(fp); return; } buf = malloc(fsize+1); if (!buf) { fclose(fp); return; } fread(buf, fsize, 1, fp); fclose(fp); buf[fsize] = '\0'; /* each option is expected to have the following format: * name=value\n */ line = strtok(buf, "\n"); do { read_config_line(line); line = strtok(NULL, "\n"); } while (line); free(buf); }
/* open a config file and separate it into lines for read_config_line() */ static void read_config_file(const fnchar * filename) { FILE *fp; int fsize; char *line; fp = fopen(filename, "rb"); if (!fp) return; /* obtain file size. */ fseek(fp, 0, SEEK_END); fsize = ftell(fp); rewind(fp); if (!fsize) { /* truncated config file */ fclose(fp); return; } char buf[fsize + 1]; if (fread(buf, 1, fsize, fp) < fsize) { /* This can only happen if the file shrinks while it's open; let's just not read the file at all, because it's probably corrupted */ curses_msgwin("warning: corrupted configuration file", krc_notification); fclose(fp); return; } fclose(fp); buf[fsize] = '\0'; /* each option is expected to have the following format: * name=value\n */ line = strtok(buf, "\n"); do { read_config_line(line); line = strtok(NULL, "\n"); } while (line); }
int parse_configfile(const char *filename, configfile_value_fn fn) { static int nesting; int len; char line[512]; const char *value; FILE *f; /* cancel deeply nested include-commands */ if (nesting > 8) return -1; if (!(f = fopen(filename, "r"))) return -1; nesting++; while((len = read_config_line(f, line, &value, sizeof(line))) > 0) fn(line, value); nesting--; fclose(f); return 0; }
/* * Returns -1 on (fatal) error, * 0 on success. */ static int read_config_file ( struct relabsd_config * const conf, char * const filename ) { FILE * f; char buffer[(RELABSD_CONF_AXIS_CODE_SIZE + 1)]; int continue_reading, prev_errno; buffer[RELABSD_CONF_AXIS_CODE_SIZE] = '\0'; f = fopen(filename, "r"); if (f == (FILE *) NULL) { RELABSD_FATAL ( "[CONFIG] Could not open file: %s.", strerror(errno) ); return -1; } prev_errno = errno; errno = 0; continue_reading = 1; while ( (continue_reading == 1) && ( fscanf ( f, "%" RELABSD_TO_STRING(RELABSD_CONF_AXIS_CODE_SIZE) "s", buffer ) != EOF ) ) { switch (read_config_line(conf, f, buffer)) { case 1: /* Everything is going well. */ break; case 0: /* EOF reached. */ continue_reading = 0; break; case -1: /* A fatal error occured. */ errno = prev_errno; fclose(f); return -1; } } if (errno != 0) { /* An error happened in the while loop condition. */ RELABSD_FATAL ( "[CONFIG] Error while reading file: %s, last read '%s'.", strerror(errno), buffer ); errno = prev_errno; fclose(f); return -1; } errno = prev_errno; fclose(f); 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; struct re_filterfile_spec *new_bl, *bl = NULL; struct file_list *fs; char buf[BUFFER_SIZE]; int error; unsigned long linenum = 0; pcrs_job *dummy, *lastjob = NULL; /* * No need to reload if unchanged */ if (!check_file_changed(current_re_filterfile[fileid], csp->config->re_filterfile[fileid], &fs)) { if (csp) { csp->rlist[fileid] = current_re_filterfile[fileid]; } return(0); } if (!fs) { goto load_re_filterfile_error; } /* * Open the file or fail */ if ((fp = fopen(csp->config->re_filterfile[fileid], "r")) == NULL) { goto load_re_filterfile_error; } /* * Read line by line */ while (read_config_line(buf, sizeof(buf), fp, &linenum) != NULL) { int new_filter = NO_NEW_FILTER; if (strncmp(buf, "FILTER:", 7) == 0) { new_filter = FT_CONTENT_FILTER; } else if (strncmp(buf, "SERVER-HEADER-FILTER:", 21) == 0) { new_filter = FT_SERVER_HEADER_FILTER; } else if (strncmp(buf, "CLIENT-HEADER-FILTER:", 21) == 0) { new_filter = FT_CLIENT_HEADER_FILTER; } else if (strncmp(buf, "CLIENT-HEADER-TAGGER:", 21) == 0) { new_filter = FT_CLIENT_HEADER_TAGGER; } else if (strncmp(buf, "SERVER-HEADER-TAGGER:", 21) == 0) { new_filter = FT_SERVER_HEADER_TAGGER; } /* * If this is the head of a new filter block, make it a * re_filterfile spec of its own and chain it to the list: */ if (new_filter != NO_NEW_FILTER) { new_bl = (struct re_filterfile_spec *)zalloc(sizeof(*bl)); if (new_bl == NULL) { goto load_re_filterfile_error; } if (new_filter == FT_CONTENT_FILTER) { new_bl->name = chomp(buf + 7); } else { new_bl->name = chomp(buf + 21); } new_bl->type = new_filter; /* * If a filter description is available, * encode it to HTML and save it. */ if (NULL != (new_bl->description = strpbrk(new_bl->name, " \t"))) { *new_bl->description++ = '\0'; new_bl->description = html_encode(chomp(new_bl->description)); if (NULL == new_bl->description) { new_bl->description = strdup("Out of memory while encoding this filter's description to HTML"); } } else { new_bl->description = strdup("No description available for this filter"); } new_bl->name = strdup(chomp(new_bl->name)); /* * If this is the first filter block, chain it * to the file_list rather than its (nonexistant) * predecessor */ if (fs->f == NULL) { fs->f = new_bl; } else { assert(NULL != bl); bl->next = new_bl; } bl = new_bl; log_error(LOG_LEVEL_RE_FILTER, "Reading in filter \"%s\" (\"%s\")", bl->name, bl->description); continue; } /* * Else, save the expression, make it a pcrs_job * and chain it into the current filter's joblist */ if (bl != NULL) { error = enlist(bl->patterns, buf); if (JB_ERR_MEMORY == error) { log_error(LOG_LEVEL_FATAL, "Out of memory while enlisting re_filter job \'%s\' for filter %s.", buf, bl->name); } assert(JB_ERR_OK == error); if (pcrs_job_is_dynamic(buf)) { /* * Dynamic pattern that might contain variables * and has to be recompiled for every request */ if (bl->joblist != NULL) { pcrs_free_joblist(bl->joblist); bl->joblist = NULL; } bl->dynamic = 1; log_error(LOG_LEVEL_RE_FILTER, "Adding dynamic re_filter job \'%s\' to filter %s succeeded.", buf, bl->name); continue; } else if (bl->dynamic) { /* * A previous job was dynamic and as we * recompile the whole filter anyway, it * makes no sense to compile this job now. */ log_error(LOG_LEVEL_RE_FILTER, "Adding static re_filter job \'%s\' to dynamic filter %s succeeded.", buf, bl->name); continue; } if ((dummy = pcrs_compile_command(buf, &error)) == NULL) { log_error(LOG_LEVEL_ERROR, "Adding re_filter job \'%s\' to filter %s failed with error %d.", buf, bl->name, error); continue; } else { if (bl->joblist == NULL) { bl->joblist = dummy; } else if (NULL != lastjob) { lastjob->next = dummy; } lastjob = dummy; log_error(LOG_LEVEL_RE_FILTER, "Adding re_filter job \'%s\' to filter %s succeeded.", buf, bl->name); } } else { log_error(LOG_LEVEL_ERROR, "Ignoring job %s outside filter block in %s, line %d", buf, csp->config->re_filterfile[fileid], linenum); } } fclose(fp); /* * Schedule the now-obsolete old data for unloading */ if ( NULL != current_re_filterfile[fileid] ) { current_re_filterfile[fileid]->unloader = unload_re_filterfile; } /* * Chain this file into the global list of loaded files */ fs->next = files->next; files->next = fs; current_re_filterfile[fileid] = fs; if (csp) { 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[fileid]); return(-1); }
/********************************************************************* * * Function : load_trustfile * * Description : Read and parse a trustfile and add to files list. * * Parameters : * 1 : csp = Current client state (buffers, headers, etc...) * * Returns : 0 => Ok, everything else is an error. * *********************************************************************/ int load_trustfile(struct client_state *csp) { FILE *fp; struct block_spec *b, *bl; struct url_spec **tl; char buf[BUFFER_SIZE], *p, *q; 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)) { /* No need to load */ if (csp) { csp->tlist = current_trustfile; } return(0); } if (!fs) { goto load_trustfile_error; } fs->f = bl = (struct block_spec *)zalloc(sizeof(*bl)); if (bl == NULL) { goto load_trustfile_error; } if ((fp = fopen(csp->config->trustfile, "r")) == NULL) { goto load_trustfile_error; } tl = csp->config->trust_list; while (read_config_line(buf, sizeof(buf), fp, &linenum) != NULL) { trusted = 0; reject = 1; if (*buf == '+') { trusted = 1; *buf = '~'; } if (*buf == '~') { reject = 0; p = buf; q = p+1; while ((*p++ = *q++) != '\0') { /* nop */ } } /* skip blank lines */ if (*buf == '\0') { continue; } /* allocate a new node */ if ((b = zalloc(sizeof(*b))) == NULL) { fclose(fp); goto load_trustfile_error; } /* add it to the list */ b->next = bl->next; bl->next = b; b->reject = reject; /* Save the URL pattern */ if (create_url_spec(b->url, buf)) { fclose(fp); goto load_trustfile_error; } /* * save a pointer to URL's spec in the list of trusted URL's, too */ if (trusted) { 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); /* the old one is now obsolete */ if (current_trustfile) { current_trustfile->unloader = unload_trustfile; } fs->next = files->next; files->next = fs; current_trustfile = fs; if (csp) { csp->tlist = fs; } return(0); load_trustfile_error: log_error(LOG_LEVEL_FATAL, "can't load trustfile '%s': %E", csp->config->trustfile); return(-1); }