summaryrefslogtreecommitdiffhomepage
path: root/src/filter.c
blob: a1f5ed86149cea32014b8764d7b149563f5c1bd9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
/* $Id: filter.c,v 1.7 2001-10-25 17:27:39 rjkaes Exp $
 *
 * Copyright (c) 1999  George Talusan (gstalusan@uwaterloo.ca)
 *
 * A substring of the domain to be filtered goes into the file
 * pointed at by DEFAULT_FILTER.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2, or (at your option) any
 * later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 */

#include "tinyproxy.h"

#include "filter.h"
#include "regexp.h"
#include "utils.h"

static int err;

struct filter_list {
	struct filter_list *next;
	char *pat;
	regex_t *cpat;
};


static struct filter_list *fl = NULL;
static int already_init = 0;

/* initializes a linked list of strings containing hosts to be filtered */
void filter_init(void)
{
	FILE *fd;
	struct filter_list *p;
	char buf[255];
	char *s;

	if (!fl && !already_init) {
		fd = fopen(config.filter, "r");
		if (fd) {
			p = NULL;

			while (fgets(buf, 255, fd)) {
				s = buf;
				if (!p)	/* head of list */
					fl = p = safecalloc(1, sizeof(struct filter_list));
				else {	/* next entry */
					p->next = safecalloc(1, sizeof(struct filter_list));
					p = p->next;
				}

				/* replace first whitespace with \0 */
				while (*s++)
					if (isspace((unsigned char)*s))
						*s = '\0';

				p->pat = strdup(buf);
				p->cpat = safemalloc(sizeof(regex_t));
				if ((err = regcomp(p->cpat, p->pat, REG_NEWLINE | REG_NOSUB)) != 0) {
					fprintf(stderr,
						"Bad regex in %s: %s\n",
						config.filter, p->pat);
					exit(EX_DATAERR);
				}
			}
			already_init = 1;
			fclose(fd);
		}
	}
}

/* unlink the list */
void filter_destroy(void)
{
	struct filter_list *p, *q;

	if (already_init) {
		for (p = q = fl; p; p = q) {
			regfree(p->cpat);
			safefree(p->cpat);
			safefree(p->pat);
			q = p->next;
			safefree(p);
		}
		fl = NULL;
		already_init = 0;
	}
}

/* returns 0 if host is not an element of filter list, non-zero otherwise */
int filter_url(char *host)
{
	struct filter_list *p;
	char *s, *port;
	int result;

	if (!fl || !already_init)
		return (0);

	/* strip off the port number */
	s = strdup(host);
	port = strchr(s, ':');
	if (port)
		*port = '\0';

	result = 0;

	for (p = fl; p; p = p->next) {
		result = !regexec(p->cpat, s, (size_t) 0, (regmatch_t *) 0, 0);

		if (result)
			break;
	}
	safefree(s);
	return (result);
}