1 /* -----------------------------------------------------------------------------
2 * handlers.c
3 *
4 * Functions for registering SWIG handler functions. Also includes
5 * default handlers for various error conditions.
6 *
7 * Author(s) : David Beazley (beazley@cs.uchicago.edu)
8 * Mike Sliczniak (mzsliczn@midway.uchicago.edu)
9 *
10 * Copyright (C) 1999-2000. The University of Chicago
11 * See the file LICENSE for information on usage and redistribution.
12 * ----------------------------------------------------------------------------- */
13
14 static char cvsroot[] = "$Header: /dds/src/port/swill.RCS/Source/SWILL/handlers.c,v 1.2 2003/06/23 08:55:57 dds Exp $";
15
16 #include "swillint.h"
17 #include <stdarg.h>
18
19 static Hash *Handlers = 0;
20
21 /* -----------------------------------------------------------------------------
22 * int swill_handle()
23 *
24 * Register a handler function with the server
25 *
26 * servname = Document name used by the server (i.e., "foo.html")
27 * handler = Handler function
28 * clientdata = Data passed to the handler function
29 *
30 * Note: MIME type is guessed from the servname suffix.
31 *
32 * The servname may include options before the actual name. For example:
33 * "stdout:foo.html" indicates that output is going to use standard output
34 * ----------------------------------------------------------------------------- */
35
36 int
swill_handle(const char * servname,SwillHandler handler,void * clientdata)37 swill_handle(const char *servname, SwillHandler handler, void *clientdata) {
38 Hash *handobj;
39 const char *actname;
40 char opt[512] = { 0 };
41
42 if (!Handlers) {
43 Handlers = NewHash();
44 }
45 /* Check for options */
46 actname = strchr(servname,':');
47 if (actname) {
48 strncat(opt,servname,actname - servname);
49 actname++;
50 } else {
51 actname = servname;
52 }
53 handobj = NewHash();
54 if (*actname == '/') actname++;
55 Setattr(handobj,"servname",actname);
56 Setattr(handobj,"handler",NewVoid((void*)handler,0));
57 Setattr(handobj,"clientdata",NewVoid(clientdata,0));
58 Setattr(handobj,"mimetype", swill_guess_mimetype(servname));
59
60 if (strcmp(opt,"stdout") == 0) {
61 SetInt(handobj,"stdout",1);
62 }
63 Setattr(Handlers,actname,handobj);
64 return 0;
65 }
66
67 /* -----------------------------------------------------------------------------
68 * swill_file()
69 *
70 * Serve a registered filename
71 * ----------------------------------------------------------------------------- */
72
73 int
swill_file(const char * url,const char * path)74 swill_file(const char *url, const char *path)
75 {
76 Hash *handobj;
77 if (!Handlers) {
78 Handlers = NewHash();
79 }
80 handobj = NewHash();
81 Setattr(handobj,"servname",url);
82 if (path) {
83 Setattr(handobj,"filename",path);
84 } else {
85 Setattr(handobj,"filename",url);
86 }
87 Setattr(handobj,"mimetype",swill_guess_mimetype(url));
88 Setattr(Handlers,url,handobj);
89 return 0;
90 }
91
92 /* -----------------------------------------------------------------------------
93 * swill_remove()
94 *
95 * Remove a handler
96 * ----------------------------------------------------------------------------- */
97
98 void
swill_remove(const char * name)99 swill_remove(const char *name) {
100 if (!Handlers) return;
101 Delattr(Handlers,name);
102 }
103
104 /* -----------------------------------------------------------------------------
105 * swill_handler_reset()
106 *
107 * Reset all of the handlers
108 * ----------------------------------------------------------------------------- */
109
110 void
swill_handler_reset(void)111 swill_handler_reset(void) {
112 Delete(Handlers);
113 Handlers = 0;
114 }
115
116 /* -----------------------------------------------------------------------------
117 * swill_handler_lookup()
118 *
119 * Look up a handler given a URI
120 * ----------------------------------------------------------------------------- */
121
122 Hash *
swill_handler_lookup(const String * uri)123 swill_handler_lookup(const String *uri) {
124 if (!Handlers) return 0;
125 return Getattr(Handlers,uri);
126 }
127
128 /* -----------------------------------------------------------------------------
129 * SwillFileNotFound()
130 *
131 * Report a file not found error to the client.
132 * ----------------------------------------------------------------------------- */
133
134 static char *error404msg = "\n\
135 <html><head><title>File not found</title></head>\n\
136 <body bgcolor=\"#ffffff\">\n\
137 <h1>File not found</h1>\n\
138 Document '%s' not registered with the server.\n\
139 Click <a href=\"/info\">here</a> for a list of available documents.\n\n\
140 </body></html>\n";
141
142 int
SwillFileNotFound(DOH * out,void * clientdata)143 SwillFileNotFound(DOH *out, void *clientdata) {
144 swill_setresponse("404 File not found");
145 swill_setheader("Content-Type","text/html");
146 Printf(out,error404msg,swill_getvar("__uri__"));
147 return 0;
148 }
149
150 /* -----------------------------------------------------------------------------
151 * SwillAuthenticate()
152 *
153 * Ask the user to authenticate themselves with a username and password.
154 * ----------------------------------------------------------------------------- */
155
156 static char *error401msg = "\n\
157 <html><head><title>Unauthorized</title></head>\n\
158 <body bgcolor=\"#ffffff\">\n\
159 <h1>Unauthorized</h1>\n\
160 You don't have access to this document. Sorry.\n\
161 </body></html>\n";
162
163 int
SwillAuthenticate(DOH * out,void * clientdata)164 SwillAuthenticate(DOH *out, void *clientdata) {
165 swill_setresponse("401 Unauthorized");
166 swill_setheader("Content-Type","text/html");
167 Printf(out,error401msg);
168 return 0;
169 }
170
171 /* -----------------------------------------------------------------------------
172 * SwillUnsupported()
173 *
174 * Unsupported HTTP method
175 * ----------------------------------------------------------------------------- */
176
177 static char *error501msg = "\n\
178 <html><head><title>Not implemented</title></head>\n\
179 <body bgcolor=\"#ffffff\">\n\
180 <h1>Not implemented</h1>\n\
181 The server does not support '%s' requests.\n\
182 </body></html>\n";
183
184 int
SwillUnsupported(DOH * out,void * clientdata)185 SwillUnsupported(DOH *out, void *clientdata) {
186 swill_setresponse("501 Not Implemented");
187 swill_setheader("Content-Type","text/html");
188 Printf(out,error501msg,swill_getvar("__method__"));
189 return 0;
190 }
191
192 /* -----------------------------------------------------------------------------
193 * SwillInternalError()
194 *
195 * Internal server error.
196 * ----------------------------------------------------------------------------- */
197
198 static char *error500msg = "\n\
199 <html><head><title>Internal Error</title></head>\n\
200 <body bgcolor=\"#ffffff\">\n\
201 <h1>Internal Error</h1>\n\
202 </plaintext>\n";
203
204 int
SwillInternalError(DOH * out,void * clientdata)205 SwillInternalError(DOH *out, void *clientdata) {
206 swill_setresponse("500 Internal Error");
207 swill_setheader("Content-Type","text/html");
208 Printf(out,error500msg);
209 return 0;
210 }
211
212 /* -----------------------------------------------------------------------------
213 * SwillListHandlers()
214 *
215 * Print a list of all available handlers.
216 * ----------------------------------------------------------------------------- */
217
218 int
SwillListHandlers(DOH * out,void * clientdata)219 SwillListHandlers(DOH *out, void *clientdata) {
220 DOH *namelist, *key, *item;
221 int i;
222
223 swill_setheader("Content-Type","text/html");
224 Printf(out,"<html><head><title>%s</title></head>\n", swill_title(0));
225 Printf(out,"<body bgcolor=\"#ffffff\">\n");
226 Printf(out,"<h1>%s</h1>\n", swill_title(0));
227 Printf(out,"<b>Registered Handlers</b>\n");
228 Printf(out,"<ul>\n");
229 namelist = NewList();
230 for (key = Firstkey(Handlers); key; key = Nextkey(Handlers)) {
231 Append(namelist,key);
232 }
233 /* List_sort(namelist); */
234 for (i = 0; i < Len(namelist); i++ ) {
235 item = Getattr(Handlers,Getitem(namelist,i));
236 Printf(out,"<li> <a href=\"%s\">%s</a>\n", Getattr(item,"servname"),Getattr(item,"servname"));
237 }
238 if (Len(namelist) == 0) {
239 Printf(out,"<li> None\n");
240 }
241 Printf(out,"</ul>\n");
242
243 /*
244 if (swill_->docroot) {
245 Printf(out,"<p><b>Document Root</b>\n");
246 Printf(out,"<ul>\n");
247 Printf(out,"<li><a href=\"/\">%s</a>\n", swill_w->docroot);
248 Printf(out,"</ul>\n");
249 }
250 */
251
252 Printf(out,"<hr>\n");
253 Printf(out,"<em>SWILL %d.%d</em>\n", SWILL_MAJOR_VERSION, SWILL_MINOR_VERSION);
254 Delete(namelist);
255 return 0;
256 }
257
258 /* -----------------------------------------------------------------------------
259 * swill_getvars()
260 *
261 * A high level function for grabbing form variables. The user supplies a
262 * format string that specifies names and conversions. For example:
263 *
264 * swill_getvars("s(name)s(email)d(number)", &name, &email, &number)
265 *
266 * Returns 0 on failure. 1 on success.
267 * ----------------------------------------------------------------------------- */
268
isolate_name(const char * c,char * t)269 static const char *isolate_name(const char *c, char *t) {
270 int copy = 0;
271 while (*c) {
272 if (*c == '(') {
273 copy = 1;
274 c++;
275 continue;
276 }
277 if (*c == ')') {
278 *t = 0;
279 return c;
280 }
281 if (copy) {
282 *(t++) = *c;
283 }
284 c++;
285 }
286 *t = 0;
287 return c - 1;
288 }
289
290 int
swill_getargs(const char * fmt,...)291 swill_getargs(const char *fmt, ...) {
292 const char *c;
293 char name[256];
294 va_list ap;
295 int opt = 0;
296 int code = 0;
297 char *value = 0;
298 void *ptr = 0;
299
300 va_start(ap,fmt);
301 c = fmt;
302
303 /* Walk the fmt string and get arguments */
304 while (*c) {
305 if (*c == '|') {
306 opt = 1;
307 c++;
308 continue;
309 }
310 code = *c;
311 ptr = va_arg(ap, void *);
312 c = isolate_name(c,name);
313 value = swill_getvar(name);
314 if (!value) {
315 if (!opt) { /* Not optional. Error */
316 va_end(ap);
317 return 0;
318 }
319 c++;
320 continue;
321 }
322 switch(code) {
323 case 's': /* String */
324 *((char **) ptr) = value;
325 break;
326
327 case 'i': /* Integer */
328 *((int *) ptr) = (int) strtol(value,NULL,0);
329 break;
330
331 case 'l': /* Long */
332 *((long *) ptr) = atol(value);
333 break;
334
335 case 'h': /* Short */
336 *((short *) ptr) = (short) strtol(value,NULL,0);
337 break;
338
339 case 'b': /* Byte */
340 *((char *) ptr) = (char) strtol(value,NULL,0);
341 break;
342
343 case 'I': /* unsigned integer */
344 *((unsigned int *) ptr) = (unsigned int) strtoul(value, NULL, 0);
345 break;
346
347 case 'L': /* unsigned long */
348 *((unsigned long *) ptr) = (unsigned long) strtoul(value, NULL, 0);
349 break;
350
351 case 'H': /* unsigned short */
352 *((unsigned short *) ptr) = (unsigned short) strtoul(value,NULL,0);
353 break;
354
355 case 'B': /* unsigned byte */
356 *((unsigned char *) ptr) = (unsigned char) strtoul(value,NULL,0);
357 break;
358
359 case 'f': /* Float */
360 *((float *) ptr) = (float) atof(value);
361 break;
362
363 case 'd': /* Double */
364 *((double *) ptr) = atof(value);
365 break;
366
367 case 'p':
368 sscanf(value, "%p", (void **)ptr);
369 break;
370
371 default:
372 break;
373 }
374 c++;
375 }
376 va_end(ap);
377 return 1;
378 }
379
380 void
swill_printurl(FILE * f,const char * url,const char * fmt,...)381 swill_printurl(FILE *f, const char *url, const char *fmt, ...) {
382 const char *c;
383 char name[256];
384 va_list ap;
385 int code = 0;
386 char *svalue;
387 int ivalue;
388 unsigned int uivalue;
389 long lvalue;
390 unsigned long ulvalue;
391 double dvalue;
392 void *ptr = 0;
393 int first = 1;
394
395 va_start(ap,fmt);
396
397 fprintf(f,"%s",url);
398
399 c = fmt;
400 if (*c) {
401 fprintf(f,"?");
402 }
403 /* Walk the fmt string and get arguments */
404 while (*c) {
405 code = *c;
406 c = isolate_name(c,name);
407 if (!first) {
408 swill_fprintf(f,"&");
409 }
410 first = 0;
411 switch(code) {
412 case 's': /* String */
413 svalue = va_arg(ap, char *);
414 swill_fprintf(f,"%s=%(url)s", name, svalue);
415 break;
416
417 case 'i': /* Integer */
418 case 'h':
419 case 'b':
420 ivalue = va_arg(ap, int);
421 swill_fprintf(f,"%s=%(url)d", name, ivalue);
422 break;
423
424 case 'l': /* Long */
425 lvalue = va_arg(ap, long);
426 swill_fprintf(f,"%s=%(url)ld", name, lvalue);
427 break;
428
429 case 'I': /* unsigned integer */
430 case 'H':
431 case 'B':
432 uivalue = va_arg(ap, unsigned);
433 swill_fprintf(f,"%s=%(url)u", name, uivalue);
434 break;
435
436 case 'L': /* unsigned long */
437 ulvalue = va_arg(ap, unsigned long);
438 swill_fprintf(f,"%s=%(url)ul", name, ulvalue);
439 break;
440
441 case 'f': /* Float */
442 case 'd':
443 dvalue = va_arg(ap, double);
444 swill_fprintf(f,"%s=%(url)0.17f", name, dvalue);
445 break;
446
447 case 'p':
448 ptr = va_arg(ap, void *);
449 swill_fprintf(f,"%s=%(url)p", name, ptr);
450 break;
451
452 default:
453 break;
454 }
455 c++;
456 }
457 va_end(ap);
458 return;
459 }
460
461
462
463
464