Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | 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
typedef struct Point	Point;
8
typedef struct OkPoint	OkPoint;
9
typedef struct Strings	Strings;
10
 
11
struct Point 
12
{
13
	int	x;
14
	int	y;
15
};
16
 
17
struct OkPoint 
18
{
19
	Point	p;
20
	int	ok;
21
};
22
 
23
struct Strings
24
{
25
	char	*s1;
26
	char	*s2;
27
};
28
 
29
static	char *me;
30
 
31
int		polytest(int, Point, Point, Point);
32
Strings		getfield(char*);
33
OkPoint		pt(char*);
34
char*		translate(HConnect*, char*, char*);
35
Point		sub(Point, Point);
36
float		dist(Point, Point);
37
 
38
void
39
main(int argc, char **argv)
40
{
41
	HConnect *c;
42
	Hio *hout;
43
	char *dest;
44
 
45
	me = "imagemap";
46
	c = init(argc, argv);
47
	hout = &c->hout;
48
	if(hparseheaders(c, HSTIMEOUT) < 0)
49
		exits("failed");
50
	anonymous(c);
51
 
52
	if(strcmp(c->req.meth, "GET") != 0 && strcmp(c->req.meth, "HEAD") != 0){
53
		hunallowed(c, "GET, HEAD");
54
		exits("unallowed");
55
	}
56
	if(c->head.expectother || c->head.expectcont){
57
		hfail(c, HExpectFail, nil);
58
		exits("failed");
59
	}
60
	dest = translate(c, c->req.uri, c->req.search);
61
 
62
	if(dest == nil){
63
		if(c->req.vermaj){
64
			hokheaders(c);
65
			hprint(hout, "Content-type: text/html\r\n");
66
			hprint(hout, "\r\n");
67
		}
68
		hprint(hout, "<head><title>Nothing Found</title></head><body>\n");
69
		hprint(hout, "Nothing satisfying your search request could be found.\n</body>\n");
70
		hflush(hout);
71
		writelog(c, "Reply: 200 imagemap %ld %ld\n", hout->seek, hout->seek);
72
		exits(nil);
73
	}
74
 
75
	if(http11(c) && strcmp(c->req.meth, "POST") == 0)
76
		hredirected(c, "303 See Other", dest);
77
	else
78
		hredirected(c, "302 Found", dest);
79
	exits(nil);
80
}
81
 
82
char*
83
translate(HConnect *c, char *uri, char *search)
84
{
85
	Biobuf *b;
86
	Strings ss;
87
	OkPoint okp;
88
	Point p, cen, q, start;
89
	float close, d;
90
	char *line, *to, *def, *s, *dst;
91
	int n, inside, r, ncsa;
92
 
93
	if(search == nil){
94
		hfail(c, HNoData, me);
95
		exits("failed");
96
	}
97
	okp = pt(search);
98
	if(!okp.ok){
99
		hfail(c, HBadSearch, me);
100
		exits("failed");
101
	}
102
	p = okp.p;
103
 
104
	b = Bopen(uri, OREAD);
105
	if(b == nil){
106
		hfail(c, HNotFound, uri);
107
		exits("failed");
108
	}
109
 
110
	to = nil;
111
	def = nil;
112
	dst = nil;
113
	close = 0.;
114
	ncsa = 1;
115
	while(line = Brdline(b, '\n')){
116
		line[Blinelen(b)-1] = 0;
117
 
118
		ss = getfield(line);
119
		s = ss.s1;
120
		line = ss.s2;
121
		if(ncsa){
122
			ss = getfield(line);
123
			dst = ss.s1;
124
			line = ss.s2;
125
		}
126
		if(strcmp(s, "#cern") == 0){
127
			ncsa = 0;
128
			continue;
129
		}
130
		if(strcmp(s, "rect") == 0){
131
			ss = getfield(line);
132
			s = ss.s1;
133
			line = ss.s2;
134
			okp = pt(s);
135
			q = okp.p;
136
			if(!okp.ok || q.x > p.x || q.y > p.y)
137
				continue;
138
			ss = getfield(line);
139
			s = ss.s1;
140
			line = ss.s2;
141
			okp = pt(s);
142
			q = okp.p;
143
			if(!okp.ok || q.x < p.x || q.y < p.y)
144
				continue;
145
			if(!ncsa){
146
				ss = getfield(line);
147
				dst = ss.s1;
148
			}
149
			return dst;
150
		}else if(strcmp(s, "circle") == 0){
151
			ss = getfield(line);
152
			s = ss.s1;
153
			line = ss.s2;
154
			okp = pt(s);
155
			cen = okp.p;
156
			if(!okp.ok)
157
				continue;
158
			ss = getfield(line);
159
			s = ss.s1;
160
			line = ss.s2;
161
			if(ncsa){
162
				okp = pt(s);
163
				if(!okp.ok)
164
					continue;
165
				if(dist(okp.p, cen) >= dist(p, cen))
166
					return dst;
167
			}else{
168
				r = strtol(s, nil, 10);
169
				ss = getfield(line);
170
				dst = ss.s1;
171
				d = (float)r * r;
172
				if(d >= dist(p, cen))
173
					return dst;
174
			}
175
		}else if(strcmp(s, "poly") == 0){
176
			ss = getfield(line);
177
			s = ss.s1;
178
			line = ss.s2;
179
			okp = pt(s);
180
			start = okp.p;
181
			if(!okp.ok)
182
				continue;
183
			inside = 0;
184
			cen = start;
185
			for(n = 1; ; n++){
186
				ss = getfield(line);
187
				s = ss.s1;
188
				line = ss.s2;
189
				okp = pt(s);
190
				q = okp.p;
191
				if(!okp.ok)
192
					break;
193
				inside = polytest(inside, p, cen, q);
194
				cen = q;
195
			}
196
			inside = polytest(inside, p, cen, start);
197
			if(!ncsa)
198
				dst = s;
199
			if(n >= 3 && inside)
200
				return dst;
201
		}else if(strcmp(s, "point") == 0){
202
			ss = getfield(line);
203
			s = ss.s1;
204
			line = ss.s2;
205
			okp = pt(s);
206
			q = okp.p;
207
			if(!okp.ok)
208
				continue;
209
			d = dist(p, q);
210
			if(!ncsa){
211
				ss = getfield(line);
212
				dst = ss.s1;
213
			}
214
			if(d == 0.)
215
				return dst;
216
			if(close == 0. || d < close){
217
				close = d;
218
				to = dst;
219
			}
220
		}else if(strcmp(s, "default") == 0){
221
			if(!ncsa){
222
				ss = getfield(line);
223
				dst = ss.s1;
224
			}
225
			def = dst;
226
		}
227
	}
228
	if(to == nil)
229
		to = def;
230
	return to;
231
}
232
 
233
int
234
polytest(int inside, Point p, Point b, Point a)
235
{
236
	Point pa, ba;
237
 
238
	if(b.y>a.y){
239
		pa=sub(p, a);
240
		ba=sub(b, a);
241
	}else{
242
		pa=sub(p, b);
243
		ba=sub(a, b);
244
	}
245
	if(0<=pa.y && pa.y<ba.y && pa.y*ba.x<=pa.x*ba.y)
246
		inside = !inside;
247
	return inside;
248
}
249
 
250
Point
251
sub(Point p, Point q)
252
{
253
	p.x -= q.x;
254
	p.y -= q.y;
255
	return p;
256
}
257
 
258
float
259
dist(Point p, Point q)
260
{
261
	p.x -= q.x;
262
	p.y -= q.y;
263
	return (float)p.x * p.x + (float)p.y * p.y;
264
}
265
 
266
OkPoint
267
pt(char *s)
268
{
269
	OkPoint okp;
270
	Point p;
271
	char *t, *e;
272
 
273
	if(*s == '(')
274
		s++;
275
	t = strchr(s, ')');
276
	if(t != nil)
277
		*t = 0;
278
	p.x = 0;
279
	p.y = 0;
280
	t = strchr(s, ',');
281
	if(t == nil){
282
		okp.p = p;
283
		okp.ok = 0;
284
		return okp;
285
	}
286
	e = nil;
287
	p.x = strtol(s, &e, 10);
288
	if(e != t){
289
		okp.p = p;
290
		okp.ok = 0;
291
		return okp;
292
	}
293
	p.y = strtol(t+1, &e, 10);
294
	if(e == nil || *e != 0){
295
		okp.p = p;
296
		okp.ok = 0;
297
		return okp;
298
	}
299
	okp.p = p;
300
	okp.ok = 1;
301
	return okp;
302
}
303
 
304
Strings
305
getfield(char *s)
306
{
307
	Strings ss;
308
	char *f;
309
 
310
	while(*s == '\t' || *s == ' ')
311
		s++;
312
	f = s;
313
	while(*s && *s != '\t' && *s != ' ')
314
		s++;
315
	if(*s)
316
		*s++ = 0;
317
	ss.s1 = f;
318
	ss.s2 = s;
319
	return ss;
320
}