a1a80be227bd7d81445b8083b962b44018bad304
[citadel.git] / webcit / paramhandling.c
1 /*
2  * $Id: paramhandling.c 6808 2008-12-11 00:00:36Z dothebart $
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                 wprintf("%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         urlcontent *u;
296 #ifdef DEBUG_URLSTRINGS
297         lprintf(9, "upload_handler() name=%s, type=%s, len=%d\n", name, cbtype, length);
298 #endif
299         if (WC->Hdr->urlstrings == NULL)
300                 WC->Hdr->urlstrings = NewHash(1, NULL);
301
302         /* Form fields */
303         if ( (length > 0) && (IsEmptyStr(cbtype)) ) {
304                 u = (urlcontent *) malloc(sizeof(urlcontent));
305                 
306                 safestrncpy(u->url_key, name, sizeof(u->url_key));
307                 u->url_data = NewStrBufPlain(content, length);
308                 
309                 Put(WC->Hdr->urlstrings, u->url_key, strlen(u->url_key), u, free_url);
310 #ifdef DEBUG_URLSTRINGS
311                 lprintf(9, "Key: <%s> len: [%ld] Data: <%s>\n", 
312                         u->url_key, 
313                         StrLength(u->url_data), 
314                         ChrPtr(u->url_data));
315 #endif
316         }
317
318         /** Uploaded files */
319         if ( (length > 0) && (!IsEmptyStr(cbtype)) ) {
320                 WC->upload = malloc(length);
321                 if (WC->upload != NULL) {
322                         WC->upload_length = length;
323                         safestrncpy(WC->upload_filename, filename,
324                                         sizeof(WC->upload_filename));
325                         safestrncpy(WC->upload_content_type, cbtype,
326                                         sizeof(WC->upload_content_type));
327                         memcpy(WC->upload, content, length);
328                 }
329                 else {
330                         lprintf(3, "malloc() failed: %s\n", strerror(errno));
331                 }
332         }
333
334 }
335
336
337
338 void PutBstr(const char *key, long keylen, StrBuf *Value)
339 {
340         urlcontent *u;
341
342         if(keylen > sizeof(u->url_key)) {
343                 lprintf(1, "URLkey to long! [%s]", key);
344                 FreeStrBuf(&Value);
345                 return;
346         }
347         u = (urlcontent*)malloc(sizeof(urlcontent));
348         memcpy(u->url_key, key, keylen + 1);
349         u->url_data = Value;
350         Put(WC->Hdr->urlstrings, u->url_key, keylen, u, free_url);
351 }
352
353
354
355 int ConditionalBstr(StrBuf *Target, WCTemplputParams *TP)
356 {
357         if(TP->Tokens->nParameters == 3)
358                 return HaveBstr(TKEY(2));
359         else {
360                 if (TP->Tokens->Params[3]->Type == TYPE_LONG)
361                         return LBstr(TKEY(2)) == TP->Tokens->Params[3]->lvalue;
362                 else 
363                         return strcmp(Bstr(TKEY(2)),
364                                       TP->Tokens->Params[3]->Start) == 0;
365         }
366 }
367
368 void tmplput_bstr(StrBuf *Target, WCTemplputParams *TP)
369 {
370         const StrBuf *Buf = SBstr(TKEY(0));
371         if (Buf != NULL)
372                 StrBufAppendTemplate(Target, TP, Buf, 1);
373 }
374
375 void diagnostics(void)
376 {
377         output_headers(1, 1, 1, 0, 0, 0);
378         wprintf("Session: %d<hr />\n", WC->wc_session);
379         wprintf("Command: <br /><PRE>\n");
380 /*      
381 StrEscPuts(WC->UrlFragment1);
382         wprintf("<br />\n");
383         StrEscPuts(WC->UrlFragment2);
384         wprintf("<br />\n");
385         StrEscPuts(WC->UrlFragment3);
386 */
387         wprintf("</PRE><hr />\n");
388         wprintf("Variables: <br /><PRE>\n");
389         dump_vars();
390         wprintf("</PRE><hr />\n");
391         wDumpContent(1);
392 }
393
394
395 void tmplput_url_part(StrBuf *Target, WCTemplputParams *TP)
396 {
397         StrBuf *Name = NULL;
398         StrBuf *UrlBuf = NULL;
399         wcsession *WCC = WC;
400         
401         if (WCC != NULL) {
402                 if (TP->Tokens->Params[0]->lvalue == 0) {
403                         if (WCC->Hdr->Handler != NULL)
404                                 UrlBuf = Name = WCC->Hdr->Handler->Name;
405                 }
406                 else if (TP->Tokens->Params[0]->lvalue == 1) {
407                         UrlBuf = NewStrBuf();
408                         StrBufExtract_token(UrlBuf, WCC->Hdr->ReqLine, 0, '/');
409                 }
410                 else {
411                         UrlBuf = NewStrBuf();
412                         StrBufExtract_token(UrlBuf, WCC->Hdr->ReqLine, 1, '/');
413                 }
414
415                 if (UrlBuf == NULL)  {
416                         LogTemplateError(Target, "urlbuf", ERR_PARM1, TP, "not set.");
417                 }
418                 StrBufAppendTemplate(Target, TP, UrlBuf, 2);
419                 if (Name == NULL) FreeStrBuf(&UrlBuf);
420         }
421 }
422
423
424 void 
425 InitModule_PARAMHANDLING
426 (void)
427 {
428         WebcitAddUrlHandler(HKEY("diagnostics"), diagnostics, NEED_URL);
429
430         RegisterConditional(HKEY("COND:BSTR"), 1, ConditionalBstr, CTX_NONE);
431         RegisterNamespace("BSTR", 1, 2, tmplput_bstr, CTX_NONE);
432         RegisterNamespace("URLPART", 1, 2, tmplput_url_part, CTX_NONE);
433 }
434
435
436 void
437 SessionAttachModule_PARAMHANDLING
438 (wcsession *sess)
439 {
440         sess->Hdr->urlstrings = NewHash(1,NULL);
441 }
442
443 void
444 SessionDetachModule_PARAMHANDLING
445 (wcsession *sess)
446 {
447         DeleteHash(&sess->Hdr->urlstrings);
448 }