* BSTR:FORWARD : just append a query param if it was already in our URL line
[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, TKEY(0), 0);
386                 StrBufAppendBufPlain(Target, HKEY("="), 0);             
387                 StrBufAppendTemplate(Target, TP, Buf, 1);
388         }
389 }
390
391 void diagnostics(void)
392 {
393         output_headers(1, 1, 1, 0, 0, 0);
394         wc_printf("Session: %d<hr />\n", WC->wc_session);
395         wc_printf("Command: <br /><PRE>\n");
396 /*      
397 StrEscPuts(WC->UrlFragment1);
398         wc_printf("<br />\n");
399         StrEscPuts(WC->UrlFragment2);
400         wc_printf("<br />\n");
401         StrEscPuts(WC->UrlFragment3);
402 */
403         wc_printf("</PRE><hr />\n");
404         wc_printf("Variables: <br /><PRE>\n");
405         dump_vars();
406         wc_printf("</PRE><hr />\n");
407         wDumpContent(1);
408 }
409
410
411 void tmplput_url_part(StrBuf *Target, WCTemplputParams *TP)
412 {
413         StrBuf *Name = NULL;
414         StrBuf *UrlBuf = NULL;
415         wcsession *WCC = WC;
416         
417         if (WCC != NULL) {
418                 long n;
419
420                 n = GetTemplateTokenNumber(Target, TP, 0, 0);
421                 if (n == 0) {
422                         if (WCC->Hdr->HR.Handler != NULL)
423                                 UrlBuf = Name = WCC->Hdr->HR.Handler->Name;
424                 }
425                 else if (n == 1) {
426                         UrlBuf = NewStrBuf();
427                         StrBufExtract_token(UrlBuf, WCC->Hdr->HR.ReqLine, 0, '/');
428                 }
429                 else {
430                         UrlBuf = NewStrBuf();
431                         StrBufExtract_token(UrlBuf, WCC->Hdr->HR.ReqLine, 1, '/');
432                 }
433
434                 if (UrlBuf == NULL)  {
435                         LogTemplateError(Target, "urlbuf", ERR_PARM1, TP, "not set.");
436                 }
437                 StrBufAppendTemplate(Target, TP, UrlBuf, 2);
438                 if (Name == NULL) FreeStrBuf(&UrlBuf);
439         }
440 }
441
442
443 void 
444 InitModule_PARAMHANDLING
445 (void)
446 {
447         WebcitAddUrlHandler(HKEY("diagnostics"), "", 0, diagnostics, NEED_URL);
448
449         RegisterConditional(HKEY("COND:BSTR"), 1, ConditionalBstr, CTX_NONE);
450         RegisterNamespace("BSTR", 1, 2, tmplput_bstr, NULL, CTX_NONE);
451         RegisterNamespace("BSTR:FORWARD", 1, 2, tmplput_bstrforward, NULL, CTX_NONE);
452         RegisterNamespace("URLPART", 1, 2, tmplput_url_part, NULL, CTX_NONE);
453 }
454
455
456 void
457 SessionAttachModule_PARAMHANDLING
458 (wcsession *sess)
459 {
460         sess->Hdr->urlstrings = NewHash(1,NULL);
461 }
462
463 void
464 SessionDetachModule_PARAMHANDLING
465 (wcsession *sess)
466 {
467         DeleteHash(&sess->Hdr->urlstrings);
468         FreeStrBuf(&sess->upload_filename);
469 }