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