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