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