* add a leading '?'
[citadel.git] / webcit / paramhandling.c
1 /*
2  * $Id$
3  *
4  * parse urlparts and post data
5  */
6
7 #include "webcit.h"
8 #include "webserver.h"
9
10 void free_url(void *U)
11 {
12         urlcontent *u = (urlcontent*) U;
13         FreeStrBuf(&u->url_data);
14         free(u);
15 }
16
17 /*
18  * Extract variables from the URL.
19  */
20 void ParseURLParams(StrBuf *url)
21 {
22         const char *aptr, *bptr, *eptr, *up;
23         int len, keylen;
24         urlcontent *u;
25         wcsession *WCC = WC;
26
27         if (WCC->Hdr->urlstrings == NULL)
28                 WCC->Hdr->urlstrings = NewHash(1, NULL);
29         eptr = ChrPtr(url) + StrLength(url);
30         up = ChrPtr(url);
31         while ((up < eptr) && (!IsEmptyStr(up))) {
32                 aptr = up;
33                 while ((aptr < eptr) && (*aptr != '\0') && (*aptr != '='))
34                         aptr++;
35                 if (*aptr != '=') {
36                         return;
37                 }
38                 aptr++;
39                 bptr = aptr;
40                 while ((bptr < eptr) && (*bptr != '\0')
41                       && (*bptr != '&') && (*bptr != '?') && (*bptr != ' ')) {
42                         bptr++;
43                 }
44                 keylen = aptr - up - 1; /* -1 -> '=' */
45                 if(keylen > sizeof(u->url_key)) {
46                         lprintf(1, "URLkey to long! [%s]", up);
47                         continue;
48                 }
49
50                 u = (urlcontent *) malloc(sizeof(urlcontent));
51                 memcpy(u->url_key, up, keylen);
52                 u->url_key[keylen] = '\0';
53                 if (keylen < 0) {
54                         lprintf(1, "URLkey to long! [%s]", up);
55                         free(u);
56                         continue;
57                 }
58
59                 Put(WCC->Hdr->urlstrings, u->url_key, keylen, u, free_url);
60                 len = bptr - aptr;
61                 u->url_data = NewStrBufPlain(aptr, len);
62                 StrBufUnescape(u->url_data, 1);
63              
64                 up = bptr;
65                 ++up;
66 #ifdef DEBUG_URLSTRINGS
67                 lprintf(9, "%s = [%ld]  %s\n", 
68                         u->url_key, 
69                         StrLength(u->url_data), 
70                         ChrPtr(u->url_data)); 
71 #endif
72         }
73 }
74
75 /*
76  * free urlstring memory
77  */
78 void free_urls(void)
79 {
80         DeleteHash(&WC->Hdr->urlstrings);
81 }
82
83 /*
84  * Diagnostic function to display the contents of all variables
85  */
86
87 void dump_vars(void)
88 {
89         wcsession *WCC = WC;
90         urlcontent *u;
91         void *U;
92         long HKLen;
93         const char *HKey;
94         HashPos *Cursor;
95         
96         Cursor = GetNewHashPos (WCC->Hdr->urlstrings, 0);
97         while (GetNextHashPos(WCC->Hdr->urlstrings, Cursor, &HKLen, &HKey, &U)) {
98                 u = (urlcontent*) U;
99                 wc_printf("%38s = %s\n", u->url_key, ChrPtr(u->url_data));
100         }
101 }
102
103 /*
104  * Return the value of a variable supplied to the current web page (from the url or a form)
105  */
106
107 const char *XBstr(const char *key, size_t keylen, size_t *len)
108 {
109         void *U;
110
111         if ((WC->Hdr->urlstrings != NULL) && 
112             GetHash(WC->Hdr->urlstrings, key, keylen, &U)) {
113                 *len = StrLength(((urlcontent *)U)->url_data);
114                 return ChrPtr(((urlcontent *)U)->url_data);
115         }
116         else {
117                 *len = 0;
118                 return ("");
119         }
120 }
121
122 const char *XBSTR(const char *key, size_t *len)
123 {
124         void *U;
125
126         if ((WC->Hdr->urlstrings != NULL) &&
127             GetHash(WC->Hdr->urlstrings, key, strlen (key), &U)){
128                 *len = StrLength(((urlcontent *)U)->url_data);
129                 return ChrPtr(((urlcontent *)U)->url_data);
130         }
131         else {
132                 *len = 0;
133                 return ("");
134         }
135 }
136
137
138 const char *BSTR(const char *key)
139 {
140         void *U;
141
142         if ((WC->Hdr->urlstrings != NULL) &&
143             GetHash(WC->Hdr->urlstrings, key, strlen (key), &U))
144                 return ChrPtr(((urlcontent *)U)->url_data);
145         else    
146                 return ("");
147 }
148
149 const char *Bstr(const char *key, size_t keylen)
150 {
151         void *U;
152
153         if ((WC->Hdr->urlstrings != NULL) && 
154             GetHash(WC->Hdr->urlstrings, key, keylen, &U))
155                 return ChrPtr(((urlcontent *)U)->url_data);
156         else    
157                 return ("");
158 }
159
160 const StrBuf *SBSTR(const char *key)
161 {
162         void *U;
163
164         if ((WC->Hdr->urlstrings != NULL) &&
165             GetHash(WC->Hdr->urlstrings, key, strlen (key), &U))
166                 return ((urlcontent *)U)->url_data;
167         else    
168                 return NULL;
169 }
170
171 const StrBuf *SBstr(const char *key, size_t keylen)
172 {
173         void *U;
174
175         if ((WC->Hdr->urlstrings != NULL) && 
176             GetHash(WC->Hdr->urlstrings, key, keylen, &U))
177                 return ((urlcontent *)U)->url_data;
178         else    
179                 return NULL;
180 }
181
182 long LBstr(const char *key, size_t keylen)
183 {
184         void *U;
185
186         if ((WC->Hdr->urlstrings != NULL) && 
187             GetHash(WC->Hdr->urlstrings, key, keylen, &U))
188                 return StrTol(((urlcontent *)U)->url_data);
189         else    
190                 return (0);
191 }
192
193 long LBSTR(const char *key)
194 {
195         void *U;
196
197         if ((WC->Hdr->urlstrings != NULL) && 
198             GetHash(WC->Hdr->urlstrings, key, strlen(key), &U))
199                 return StrTol(((urlcontent *)U)->url_data);
200         else    
201                 return (0);
202 }
203
204 int IBstr(const char *key, size_t keylen)
205 {
206         void *U;
207
208         if ((WC->Hdr->urlstrings != NULL) && 
209             GetHash(WC->Hdr->urlstrings, key, keylen, &U))
210                 return StrTol(((urlcontent *)U)->url_data);
211         else    
212                 return (0);
213 }
214
215 int IBSTR(const char *key)
216 {
217         void *U;
218
219         if ((WC->Hdr->urlstrings != NULL) && 
220             GetHash(WC->Hdr->urlstrings, key, strlen(key), &U))
221                 return StrToi(((urlcontent *)U)->url_data);
222         else    
223                 return (0);
224 }
225
226 int HaveBstr(const char *key, size_t keylen)
227 {
228         void *U;
229
230         if ((WC->Hdr->urlstrings != NULL) && 
231             GetHash(WC->Hdr->urlstrings, key, keylen, &U))
232                 return (StrLength(((urlcontent *)U)->url_data) != 0);
233         else    
234                 return (0);
235 }
236
237 int HAVEBSTR(const char *key)
238 {
239         void *U;
240
241         if ((WC->Hdr->urlstrings != NULL) && 
242             GetHash(WC->Hdr->urlstrings, key, strlen(key), &U))
243                 return (StrLength(((urlcontent *)U)->url_data) != 0);
244         else    
245                 return (0);
246 }
247
248
249 int YesBstr(const char *key, size_t keylen)
250 {
251         void *U;
252
253         if ((WC->Hdr->urlstrings != NULL) && 
254             GetHash(WC->Hdr->urlstrings, key, keylen, &U))
255                 return strcmp( ChrPtr(((urlcontent *)U)->url_data), "yes") == 0;
256         else    
257                 return (0);
258 }
259
260 int YESBSTR(const char *key)
261 {
262         void *U;
263
264         if ((WC->Hdr->urlstrings != NULL) && 
265             GetHash(WC->Hdr->urlstrings, key, strlen(key), &U))
266                 return strcmp( ChrPtr(((urlcontent *)U)->url_data), "yes") == 0;
267         else    
268                 return (0);
269 }
270
271
272
273
274 /*
275  * This function is called by the MIME parser to handle data uploaded by
276  * the browser.  Form data, uploaded files, and the data from HTTP PUT
277  * operations (such as those found in GroupDAV) all arrive this way.
278  *
279  * name         Name of the item being uploaded
280  * filename     Filename of the item being uploaded
281  * partnum      MIME part identifier (not needed)
282  * disp         MIME content disposition (not needed)
283  * content      The actual data
284  * cbtype       MIME content-type
285  * cbcharset    Character set
286  * length       Content length
287  * encoding     MIME encoding type (not needed)
288  * cbid         Content ID (not needed)
289  * userdata     Not used here
290  */
291 void upload_handler(char *name, char *filename, char *partnum, char *disp,
292                         void *content, char *cbtype, char *cbcharset,
293                         size_t length, char *encoding, char *cbid, void *userdata)
294 {
295         wcsession *WCC = WC;
296         urlcontent *u;
297 #ifdef DEBUG_URLSTRINGS
298         lprintf(9, "upload_handler() name=%s, type=%s, len=%d\n", name, cbtype, length);
299 #endif
300         if (WCC->Hdr->urlstrings == NULL)
301                 WCC->Hdr->urlstrings = NewHash(1, NULL);
302
303         /* Form fields */
304         if ( (length > 0) && (IsEmptyStr(cbtype)) ) {
305                 u = (urlcontent *) malloc(sizeof(urlcontent));
306                 
307                 safestrncpy(u->url_key, name, sizeof(u->url_key));
308                 u->url_data = NewStrBufPlain(content, length);
309                 
310                 Put(WCC->Hdr->urlstrings, u->url_key, strlen(u->url_key), u, free_url);
311 #ifdef DEBUG_URLSTRINGS
312                 lprintf(9, "Key: <%s> len: [%ld] Data: <%s>\n", 
313                         u->url_key, 
314                         StrLength(u->url_data), 
315                         ChrPtr(u->url_data));
316 #endif
317         }
318
319         /** Uploaded files */
320         if ( (length > 0) && (!IsEmptyStr(cbtype)) ) {
321                 WCC->upload = NewStrBufPlain(content, length);
322                 WCC->upload_length = length;
323                 WCC->upload_filename = NewStrBufPlain(filename, -1);
324                 safestrncpy(WCC->upload_content_type, cbtype,
325                             sizeof(WC->upload_content_type));
326                 
327         }
328
329 }
330
331
332
333 void PutBstr(const char *key, long keylen, StrBuf *Value)
334 {
335         urlcontent *u;
336
337         if(keylen > sizeof(u->url_key)) {
338                 lprintf(1, "URLkey to long! [%s]", key);
339                 FreeStrBuf(&Value);
340                 return;
341         }
342         u = (urlcontent*)malloc(sizeof(urlcontent));
343         memcpy(u->url_key, key, keylen + 1);
344         u->url_data = Value;
345         Put(WC->Hdr->urlstrings, u->url_key, keylen, u, free_url);
346 }
347
348
349
350 int ConditionalBstr(StrBuf *Target, WCTemplputParams *TP)
351 {
352         if(TP->Tokens->nParameters == 3)
353                 return HaveBstr(TKEY(2));
354         else {
355                 if (IS_NUMBER(TP->Tokens->Params[3]->Type))
356                 {
357                         return LBstr(TKEY(2)) == 
358                                 GetTemplateTokenNumber(Target, 
359                                                        TP, 
360                                                        3, 
361                                                        0);
362                 }
363                 else {
364                         const char *pch;
365                         long len;
366
367                         GetTemplateTokenString (Target, TP, 3, &pch, &len);
368                         return strcmp(Bstr(TKEY(2)), pch) == 0;
369                 }
370         }
371 }
372
373 void tmplput_bstr(StrBuf *Target, WCTemplputParams *TP)
374 {
375         const StrBuf *Buf = SBstr(TKEY(0));
376         if (Buf != NULL)
377                 StrBufAppendTemplate(Target, TP, Buf, 1);
378 }
379
380
381 void tmplput_bstrforward(StrBuf *Target, WCTemplputParams *TP)
382 {
383         const StrBuf *Buf = SBstr(TKEY(0));
384         if (Buf != NULL) {
385                 StrBufAppendBufPlain(Target, HKEY("?"), 0);             
386                 StrBufAppendBufPlain(Target, TKEY(0), 0);
387                 StrBufAppendBufPlain(Target, HKEY("="), 0);             
388                 StrBufAppendTemplate(Target, TP, Buf, 1);
389         }
390 }
391
392 void diagnostics(void)
393 {
394         output_headers(1, 1, 1, 0, 0, 0);
395         wc_printf("Session: %d<hr />\n", WC->wc_session);
396         wc_printf("Command: <br /><PRE>\n");
397 /*      
398 StrEscPuts(WC->UrlFragment1);
399         wc_printf("<br />\n");
400         StrEscPuts(WC->UrlFragment2);
401         wc_printf("<br />\n");
402         StrEscPuts(WC->UrlFragment3);
403 */
404         wc_printf("</PRE><hr />\n");
405         wc_printf("Variables: <br /><PRE>\n");
406         dump_vars();
407         wc_printf("</PRE><hr />\n");
408         wDumpContent(1);
409 }
410
411
412 void tmplput_url_part(StrBuf *Target, WCTemplputParams *TP)
413 {
414         StrBuf *Name = NULL;
415         StrBuf *UrlBuf = NULL;
416         wcsession *WCC = WC;
417         
418         if (WCC != NULL) {
419                 long n;
420
421                 n = GetTemplateTokenNumber(Target, TP, 0, 0);
422                 if (n == 0) {
423                         if (WCC->Hdr->HR.Handler != NULL)
424                                 UrlBuf = Name = WCC->Hdr->HR.Handler->Name;
425                 }
426                 else if (n == 1) {
427                         UrlBuf = NewStrBuf();
428                         StrBufExtract_token(UrlBuf, WCC->Hdr->HR.ReqLine, 0, '/');
429                 }
430                 else {
431                         UrlBuf = NewStrBuf();
432                         StrBufExtract_token(UrlBuf, WCC->Hdr->HR.ReqLine, 1, '/');
433                 }
434
435                 if (UrlBuf == NULL)  {
436                         LogTemplateError(Target, "urlbuf", ERR_PARM1, TP, "not set.");
437                 }
438                 StrBufAppendTemplate(Target, TP, UrlBuf, 2);
439                 if (Name == NULL) FreeStrBuf(&UrlBuf);
440         }
441 }
442
443
444 void 
445 InitModule_PARAMHANDLING
446 (void)
447 {
448         WebcitAddUrlHandler(HKEY("diagnostics"), "", 0, diagnostics, NEED_URL);
449
450         RegisterConditional(HKEY("COND:BSTR"), 1, ConditionalBstr, CTX_NONE);
451         RegisterNamespace("BSTR", 1, 2, tmplput_bstr, NULL, CTX_NONE);
452         RegisterNamespace("BSTR:FORWARD", 1, 2, tmplput_bstrforward, NULL, CTX_NONE);
453         RegisterNamespace("URLPART", 1, 2, tmplput_url_part, NULL, CTX_NONE);
454 }
455
456
457 void
458 SessionAttachModule_PARAMHANDLING
459 (wcsession *sess)
460 {
461         sess->Hdr->urlstrings = NewHash(1,NULL);
462 }
463
464 void
465 SessionDetachModule_PARAMHANDLING
466 (wcsession *sess)
467 {
468         DeleteHash(&sess->Hdr->urlstrings);
469         FreeStrBuf(&sess->upload_filename);
470 }