Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/feature-vt/sys/src/cmd/ip/httpd/redirect.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
#include <bio.h>
4
#include "httpd.h"
5
#include "httpsrv.h"
6
 
7
enum
8
{
9
	HASHSIZE = 1019,
10
};
11
 
12
typedef struct Redir	Redir;
13
struct Redir
14
{
15
	Redir	*next;
16
	char	*pat;
17
	char	*repl;
18
	uint	flags;		/* generated from repl's decorations */
19
};
20
 
21
static Redir *redirtab[HASHSIZE];
22
static Redir *vhosttab[HASHSIZE];
23
static char emptystring[1];
24
/* these two arrays must be kept in sync */
25
static char decorations[] = { Modsilent, Modperm, Modsubord, Modonly, '\0' };
26
static uint redirflags[] = { Redirsilent, Redirperm, Redirsubord, Redironly, };
27
 
28
/* replacement field decorated with redirection modifiers? */
29
static int
30
isdecorated(char *repl)
31
{
32
	return strchr(decorations, repl[0]) != nil;
33
}
34
 
35
static uint
36
decor2flags(char *repl)
37
{
38
	uint flags;
39
	char *p;
40
 
41
	flags = 0;
42
	while ((p = strchr(decorations, *repl++)) != nil)
43
		flags |= redirflags[p - decorations];
44
	return flags;
45
}
46
 
47
/* return replacement without redirection modifiers */
48
char *
49
undecorated(char *repl)
50
{
51
	while (isdecorated(repl))
52
		repl++;
53
	return repl;
54
}
55
 
56
static int
57
hashasu(char *key, int n)
58
{
59
        ulong h;
60
 
61
	h = 0;
62
        while(*key != 0)
63
                h = 65599*h + *(uchar*)key++;
64
        return h % n;
65
}
66
 
67
static void
68
insert(Redir **tab, char *pat, char *repl)
69
{
70
	Redir **l;
71
	Redir *srch;
72
	ulong hash;
73
 
74
	hash = hashasu(pat, HASHSIZE);
75
	for(l = &tab[hash]; *l; l = &(*l)->next)
76
		;
77
	*l = srch = ezalloc(sizeof(Redir));
78
	srch->pat = pat;
79
	srch->flags = decor2flags(repl);
80
	srch->repl = undecorated(repl);
81
	srch->next = 0;
82
}
83
 
84
static void
85
cleartab(Redir **tab)
86
{
87
	Redir *t;
88
	int i;
89
 
90
	for(i = 0; i < HASHSIZE; i++){
91
		while((t = tab[i]) != nil){
92
			tab[i] = t->next;
93
			free(t->pat);
94
			free(t->repl);
95
			free(t);
96
		}
97
	}
98
}
99
 
100
void
101
redirectinit(void)
102
{
103
	static Biobuf *b = nil;
104
	static Qid qid;
105
	char *file, *line, *s, *host, *field[3];
106
	static char pfx[] = "http://";
107
 
108
	file = "/sys/lib/httpd.rewrite";
109
	if(b != nil){
110
		if(updateQid(Bfildes(b), &qid) == 0)
111
			return;
112
		Bterm(b);
113
	}
114
	b = Bopen(file, OREAD);
115
	if(b == nil)
116
		sysfatal("can't read from %s", file);
117
	updateQid(Bfildes(b), &qid);
118
 
119
	cleartab(redirtab);
120
	cleartab(vhosttab);
121
 
122
	while((line = Brdline(b, '\n')) != nil){
123
		line[Blinelen(b)-1] = 0;
124
		s = strchr(line, '#');
125
		if(s != nil && (s == line || s[-1] == ' ' || s[-1] == '\t'))
126
			*s = '\0'; 	/* chop comment iff after whitespace */
127
		if(tokenize(line, field, nelem(field)) == 2){
128
			if(strncmp(field[0], pfx, STRLEN(pfx)) == 0 &&
129
			   strncmp(undecorated(field[1]), pfx, STRLEN(pfx)) != 0){
130
				/* url -> filename */
131
				host = field[0] + STRLEN(pfx);
132
				s = strrchr(host, '/');
133
				if(s)
134
					*s = 0;  /* chop trailing slash */
135
 
136
				insert(vhosttab, estrdup(host), estrdup(field[1]));
137
			}else{
138
				insert(redirtab, estrdup(field[0]), estrdup(field[1]));
139
			}
140
		}
141
	}
142
	syslog(0, HTTPLOG, "redirectinit pid=%d", getpid());
143
}
144
 
145
static Redir*
146
lookup(Redir **tab, char *pat, int count)
147
{
148
	Redir *srch;
149
	ulong hash;
150
 
151
	hash = hashasu(pat,HASHSIZE);
152
	for(srch = tab[hash]; srch != nil; srch = srch->next)
153
		if(strcmp(pat, srch->pat) == 0) {
154
			/* only exact match wanted? */
155
			if (!(srch->flags & Redironly) || count == 0)
156
				return srch;
157
		}
158
	return nil;
159
}
160
 
161
static char*
162
prevslash(char *p, char *s)
163
{
164
	while(--s > p)
165
		if(*s == '/')
166
			break;
167
	return s;
168
}
169
 
170
/*
171
 * find the longest match of path against the redirection table,
172
 * chopping off the rightmost path component until success or
173
 * there's nothing left.  return a copy of the replacement string
174
 * concatenated with a slash and the portion of the path *not* matched.
175
 * So a match of /who/gre/some/stuff.html matched against
176
 *	/who/gre	http://gremlinsrus.org
177
 * returns
178
 *	http://gremlinsrus.org/some/stuff.html
179
 *
180
 * further flags: if Redironly, match only the named page and no
181
 * subordinate ones.  if Redirsubord, map the named patch and any
182
 * subordinate ones to the same replacement URL.
183
 */
184
char*
185
redirect(HConnect *hc, char *path, uint *flagp)
186
{
187
	Redir *redir;
188
	char *s, *newpath, *repl;
189
	int c, n, count;
190
 
191
	count = 0;
192
	for(s = strchr(path, '\0'); s > path; s = prevslash(path, s)){
193
		c = *s;
194
		*s = '\0';
195
		redir = lookup(redirtab, path, count++);
196
		*s = c;
197
		if(redir != nil){
198
			if (flagp)
199
				*flagp = redir->flags;
200
			repl = redir->repl;
201
			if(redir->flags & Redirsubord)
202
				/* don't append s, all matches map to repl */
203
				s = "";
204
			n = strlen(repl) + strlen(s) + 2 + UTFmax;
205
			newpath = halloc(hc, n);
206
			snprint(newpath, n, "%s%s", repl, s);
207
			return newpath;
208
		}
209
	}
210
	return nil;
211
}
212
 
213
/*
214
 * if host is virtual, return implicit prefix for URI within webroot.
215
 * if not, return empty string.
216
 * return value should not be freed by caller.
217
 */
218
char*
219
masquerade(char *host)
220
{
221
	Redir *redir;
222
 
223
	redir = lookup(vhosttab, host, 0);
224
	if(redir == nil)
225
		return emptystring;
226
	return redir->repl;
227
}