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