Removed logging subsystem from webcit. It's all syslog now.
[citadel.git] / webcit / paramhandling.c
1 /*
2  * parse urlparts and post data
3  */
4
5 #include "webcit.h"
6 #include "webserver.h"
7
8 void free_url(void *U)
9 {
10         urlcontent *u = (urlcontent*) U;
11         FreeStrBuf(&u->url_data);
12         free(u);
13 }
14
15 /*
16  * Extract variables from the URL.
17  */
18 void ParseURLParams(StrBuf *url)
19 {
20         const char *aptr, *bptr, *eptr, *up;
21         int len, keylen;
22         urlcontent *u;
23         wcsession *WCC = WC;
24
25         if (WCC->Hdr->urlstrings == NULL)
26                 WCC->Hdr->urlstrings = NewHash(1, NULL);
27         eptr = ChrPtr(url) + StrLength(url);
28         up = ChrPtr(url);
29         while ((up < eptr) && (!IsEmptyStr(up))) {
30                 aptr = up;
31                 while ((aptr < eptr) && (*aptr != '\0') && (*aptr != '='))
32                         aptr++;
33                 if (*aptr != '=') {
34                         return;
35                 }
36                 aptr++;
37                 bptr = aptr;
38                 while ((bptr < eptr) && (*bptr != '\0')
39                       && (*bptr != '&') && (*bptr != '?') && (*bptr != ' ')) {
40                         bptr++;
41                 }
42                 keylen = aptr - up - 1; /* -1 -> '=' */
43                 if(keylen > sizeof(u->url_key)) {
44                         syslog(1, "URLkey to long! [%s]", up);
45                         continue;
46                 }
47
48                 u = (urlcontent *) malloc(sizeof(urlcontent));
49                 memcpy(u->url_key, up, keylen);
50                 u->url_key[keylen] = '\0';
51                 if (keylen < 0) {
52                         syslog(1, "URLkey to long! [%s]", up);
53                         free(u);
54                         continue;
55                 }
56                 
57                 if (strncmp(u->url_key, "__", 2) != 0)
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 #ifdef DEBUG_URLSTRINGS
64                         syslog(9, "%s = [%ld]  %s\n", 
65                                 u->url_key, 
66                                 StrLength(u->url_data), 
67                                 ChrPtr(u->url_data)); 
68 #endif
69                 }
70                 else {
71                         len = bptr - aptr;
72                         u->url_data = NewStrBufPlain(aptr, len);
73                         StrBufUnescape(u->url_data, 1);
74                         syslog(1, "REJECTED because of __ is internal only: %s = [%ld]  %s\n", 
75                                 u->url_key, 
76                                 StrLength(u->url_data), 
77                                 ChrPtr(u->url_data)); 
78                         
79                         free_url(u);
80                 }
81                 up = bptr;
82                 ++up;
83         }
84 }
85
86 /*
87  * free urlstring memory
88  */
89 void free_urls(void)
90 {
91         DeleteHash(&WC->Hdr->urlstrings);
92 }
93
94 /*
95  * Diagnostic function to display the contents of all variables
96  */
97
98 void dump_vars(void)
99 {
100         wcsession *WCC = WC;
101         urlcontent *u;
102         void *U;
103         long HKLen;
104         const char *HKey;
105         HashPos *Cursor;
106         
107         Cursor = GetNewHashPos (WCC->Hdr->urlstrings, 0);
108         while (GetNextHashPos(WCC->Hdr->urlstrings, Cursor, &HKLen, &HKey, &U)) {
109                 u = (urlcontent*) U;
110                 wc_printf("%38s = %s\n", u->url_key, ChrPtr(u->url_data));
111         }
112 }
113
114 /*
115  * Return the value of a variable supplied to the current web page (from the url or a form)
116  */
117
118 const char *XBstr(const char *key, size_t keylen, size_t *len)
119 {
120         void *U;
121
122         if ((WC->Hdr->urlstrings != NULL) && 
123             GetHash(WC->Hdr->urlstrings, key, keylen, &U)) {
124                 *len = StrLength(((urlcontent *)U)->url_data);
125                 return ChrPtr(((urlcontent *)U)->url_data);
126         }
127         else {
128                 *len = 0;
129                 return ("");
130         }
131 }
132
133 const char *XBSTR(const char *key, size_t *len)
134 {
135         void *U;
136
137         if ((WC->Hdr->urlstrings != NULL) &&
138             GetHash(WC->Hdr->urlstrings, key, strlen (key), &U)){
139                 *len = StrLength(((urlcontent *)U)->url_data);
140                 return ChrPtr(((urlcontent *)U)->url_data);
141         }
142         else {
143                 *len = 0;
144                 return ("");
145         }
146 }
147
148
149 const char *BSTR(const char *key)
150 {
151         void *U;
152
153         if ((WC->Hdr->urlstrings != NULL) &&
154             GetHash(WC->Hdr->urlstrings, key, strlen (key), &U))
155                 return ChrPtr(((urlcontent *)U)->url_data);
156         else    
157                 return ("");
158 }
159
160 const char *Bstr(const char *key, size_t keylen)
161 {
162         void *U;
163
164         if ((WC->Hdr->urlstrings != NULL) && 
165             GetHash(WC->Hdr->urlstrings, key, keylen, &U))
166                 return ChrPtr(((urlcontent *)U)->url_data);
167         else    
168                 return ("");
169 }
170
171 const StrBuf *SBSTR(const char *key)
172 {
173         void *U;
174
175         if ((WC->Hdr->urlstrings != NULL) &&
176             GetHash(WC->Hdr->urlstrings, key, strlen (key), &U))
177                 return ((urlcontent *)U)->url_data;
178         else    
179                 return NULL;
180 }
181
182 const StrBuf *SBstr(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 ((urlcontent *)U)->url_data;
189         else    
190                 return NULL;
191 }
192
193 long LBstr(const char *key, size_t keylen)
194 {
195         void *U;
196
197         if ((WC->Hdr->urlstrings != NULL) && 
198             GetHash(WC->Hdr->urlstrings, key, keylen, &U))
199                 return StrTol(((urlcontent *)U)->url_data);
200         else    
201                 return (0);
202 }
203
204 long LBSTR(const char *key)
205 {
206         void *U;
207
208         if ((WC->Hdr->urlstrings != NULL) && 
209             GetHash(WC->Hdr->urlstrings, key, strlen(key), &U))
210                 return StrTol(((urlcontent *)U)->url_data);
211         else    
212                 return (0);
213 }
214
215 int IBstr(const char *key, size_t keylen)
216 {
217         void *U;
218
219         if ((WC->Hdr->urlstrings != NULL) && 
220             GetHash(WC->Hdr->urlstrings, key, keylen, &U))
221                 return StrTol(((urlcontent *)U)->url_data);
222         else    
223                 return (0);
224 }
225
226 int IBSTR(const char *key)
227 {
228         void *U;
229
230         if ((WC->Hdr->urlstrings != NULL) && 
231             GetHash(WC->Hdr->urlstrings, key, strlen(key), &U))
232                 return StrToi(((urlcontent *)U)->url_data);
233         else    
234                 return (0);
235 }
236
237 int HaveBstr(const char *key, size_t keylen)
238 {
239         void *U;
240
241         if ((WC->Hdr->urlstrings != NULL) && 
242             GetHash(WC->Hdr->urlstrings, key, keylen, &U))
243                 return (StrLength(((urlcontent *)U)->url_data) != 0);
244         else    
245                 return (0);
246 }
247
248 int HAVEBSTR(const char *key)
249 {
250         void *U;
251
252         if ((WC->Hdr->urlstrings != NULL) && 
253             GetHash(WC->Hdr->urlstrings, key, strlen(key), &U))
254                 return (StrLength(((urlcontent *)U)->url_data) != 0);
255         else    
256                 return (0);
257 }
258
259
260 int YesBstr(const char *key, size_t keylen)
261 {
262         void *U;
263
264         if ((WC->Hdr->urlstrings != NULL) && 
265             GetHash(WC->Hdr->urlstrings, key, keylen, &U))
266                 return strcmp( ChrPtr(((urlcontent *)U)->url_data), "yes") == 0;
267         else    
268                 return (0);
269 }
270
271 int YESBSTR(const char *key)
272 {
273         void *U;
274
275         if ((WC->Hdr->urlstrings != NULL) && 
276             GetHash(WC->Hdr->urlstrings, key, strlen(key), &U))
277                 return strcmp( ChrPtr(((urlcontent *)U)->url_data), "yes") == 0;
278         else    
279                 return (0);
280 }
281
282
283
284
285 /*
286  * This function is called by the MIME parser to handle data uploaded by
287  * the browser.  Form data, uploaded files, and the data from HTTP PUT
288  * operations (such as those found in GroupDAV) all arrive this way.
289  *
290  * name         Name of the item being uploaded
291  * filename     Filename of the item being uploaded
292  * partnum      MIME part identifier (not needed)
293  * disp         MIME content disposition (not needed)
294  * content      The actual data
295  * cbtype       MIME content-type
296  * cbcharset    Character set
297  * length       Content length
298  * encoding     MIME encoding type (not needed)
299  * cbid         Content ID (not needed)
300  * userdata     Not used here
301  */
302 void upload_handler(char *name, char *filename, char *partnum, char *disp,
303                         void *content, char *cbtype, char *cbcharset,
304                         size_t length, char *encoding, char *cbid, void *userdata)
305 {
306         wcsession *WCC = WC;
307         urlcontent *u;
308         long keylen;
309
310 #ifdef DEBUG_URLSTRINGS
311         syslog(9, "\033[31mupload_handler() name=%s, type=%s, len=%d\033[0m\n", name, cbtype, length);
312 #endif
313         if (WCC->Hdr->urlstrings == NULL)
314                 WCC->Hdr->urlstrings = NewHash(1, NULL);
315
316         /* Form fields */
317         if ( (length > 0) && (IsEmptyStr(cbtype)) ) {
318                 u = (urlcontent *) malloc(sizeof(urlcontent));
319                 
320                 keylen = safestrncpy(u->url_key, name, sizeof(u->url_key));
321                 u->url_data = NewStrBufPlain(content, length);
322                 
323                 if (strncmp(u->url_key, "__", 2) != 0)
324                 {
325                         Put(WCC->Hdr->urlstrings, u->url_key, keylen, u, free_url);
326                 }
327                 else {
328                         syslog(1, "REJECTED because of __ is internal only: %s = [%ld]  %s\n", 
329                                 u->url_key, 
330                                 StrLength(u->url_data), 
331                                 ChrPtr(u->url_data)); 
332                         
333                         free_url(u);
334                 }
335 #ifdef DEBUG_URLSTRINGS
336                 syslog(9, "Key: <%s> len: [%ld] Data: <%s>\n", 
337                         u->url_key, 
338                         StrLength(u->url_data), 
339                         ChrPtr(u->url_data));
340 #endif
341         }
342
343         /* Uploaded files */
344         if ( (length > 0) && (!IsEmptyStr(cbtype)) ) {
345                 WCC->upload = NewStrBufPlain(content, length);
346                 WCC->upload_length = length;
347                 WCC->upload_filename = NewStrBufPlain(filename, -1);
348                 safestrncpy(WCC->upload_content_type, cbtype, sizeof(WC->upload_content_type));
349 #ifdef DEBUG_URLSTRINGS
350                 syslog(9, "File: <%s> len: [%ld]\n", filename, length);
351 #endif
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                 syslog(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 }