source: rtems/cpukit/httpd/handler.c @ 19a0136

4.104.114.84.95
Last change on this file since 19a0136 was ee3afa2, checked in by Joel Sherrill <joel.sherrill@…>, on 04/11/03 at 14:46:55

2002-04-10 Mike Siers <mikes@…>

  • rtems_webserver/NOTES, rtems_webserver/asp.c, rtems_webserver/balloc.c, rtems_webserver/default.c, rtems_webserver/ej.h, rtems_webserver/ejIntrn.h, rtems_webserver/ejlex.c, rtems_webserver/ejparse.c, rtems_webserver/emfdb.c, rtems_webserver/emfdb.h, rtems_webserver/form.c, rtems_webserver/h.c, rtems_webserver/handler.c, rtems_webserver/license.txt, rtems_webserver/md5.h, rtems_webserver/md5c.c, rtems_webserver/mime.c, rtems_webserver/misc.c, rtems_webserver/ringq.c, rtems_webserver/rom.c, rtems_webserver/security.c, rtems_webserver/sock.c, rtems_webserver/sym.c, rtems_webserver/uemf.c, rtems_webserver/uemf.h, rtems_webserver/um.c, rtems_webserver/um.h, rtems_webserver/url.c, rtems_webserver/value.c, rtems_webserver/wbase64.c, rtems_webserver/webcomp.c, rtems_webserver/webpage.c, rtems_webserver/webrom.c, rtems_webserver/webs.c, rtems_webserver/webs.h, rtems_webserver/websuemf.c, rtems_webserver/wsIntrn.h: Update to GoAhead? Webserver 2.1.4. The following URL is the release notes from GoAhead?.

http://data.goahead.com/Software/Webserver/2.1.4/release.htm

I have only done a minimal amount of testing (i.e. the network
demo program works fine). Please try this out and let me know
if it works. The patch needs to be applied on the
c/src/libnetworking/rtems_webserver directory.

  • Property mode set to 100644
File size: 9.9 KB
Line 
1/*
2 * handler.c -- URL handler support
3 *
4 * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
5 *
6 * See the file "license.txt" for usage and redistribution license requirements
7 *
8 * $Id$
9 */
10
11/******************************** Description *********************************/
12
13/*
14 *      This module implements a URL handler interface and API to permit
15 *      the addition of user definable URL processors.
16 */
17
18/********************************* Includes ***********************************/
19
20#include        "wsIntrn.h"
21
22/*********************************** Locals ***********************************/
23
24static websUrlHandlerType       *websUrlHandler;                        /* URL handler list */
25static int                                      websUrlHandlerMax;                      /* Number of entries */
26static int                                      urlHandlerOpenCount = 0;        /* count of apps */
27
28/**************************** Forward Declarations ****************************/
29
30static int              websUrlHandlerSort(const void *p1, const void *p2);
31static int              websPublishHandler(webs_t wp, char_t *urlPrefix, char_t *webDir,
32                                int sid, char_t *url, char_t *path, char_t *query);
33static char_t   *websCondenseMultipleChars(char_t *strToCondense, char_t cCondense);
34
35/*********************************** Code *************************************/
36/*
37 *      Initialize the URL handler module
38 */
39
40int websUrlHandlerOpen()
41{
42        if (++urlHandlerOpenCount == 1) {
43                websAspOpen();
44                websUrlHandler = NULL;
45                websUrlHandlerMax = 0;
46        }
47        return 0;
48}
49
50/******************************************************************************/
51/*
52 *      Close the URL handler module
53 */
54
55void websUrlHandlerClose()
56{
57        websUrlHandlerType *sp;
58
59        if (--urlHandlerOpenCount <= 0) {
60                websAspClose();
61                for (sp = websUrlHandler; sp < &websUrlHandler[websUrlHandlerMax];
62                        sp++) {
63                        bfree(B_L, sp->urlPrefix);
64                        if (sp->webDir) {
65                                bfree(B_L, sp->webDir);
66                        }
67                }
68                bfree(B_L, websUrlHandler);
69                websUrlHandlerMax = 0;
70        }
71}
72
73/******************************************************************************/
74/*
75 *      Define a new URL handler. urlPrefix is the URL prefix to match. webDir is
76 *      an optional root directory path for a web directory. arg is an optional
77 *      arg to pass to the URL handler. flags defines the matching order. Valid
78 *      flags include WEBS_HANDLER_LAST, WEBS_HANDLER_FIRST. If multiple users
79 *      specify last or first, their order is defined alphabetically by the
80 *      urlPrefix.
81 */
82
83int websUrlHandlerDefine(char_t *urlPrefix, char_t *webDir, int arg,
84                int (*handler)(webs_t wp, char_t *urlPrefix, char_t *webdir, int arg,
85                char_t *url, char_t *path, char_t *query), int flags)
86{
87        websUrlHandlerType      *sp;
88        int                                     len;
89
90        a_assert(urlPrefix);
91        a_assert(handler);
92
93/*
94 *      Grow the URL handler array to create a new slot
95 */
96        len = (websUrlHandlerMax + 1) * sizeof(websUrlHandlerType);
97        if ((websUrlHandler = brealloc(B_L, websUrlHandler, len)) == NULL) {
98                return -1;
99        }
100        sp = &websUrlHandler[websUrlHandlerMax++];
101        memset(sp, 0, sizeof(websUrlHandlerType));
102
103        sp->urlPrefix = bstrdup(B_L, urlPrefix);
104        sp->len = gstrlen(sp->urlPrefix);
105        if (webDir) {
106                sp->webDir = bstrdup(B_L, webDir);
107        } else {
108                sp->webDir = bstrdup(B_L, T(""));
109        }
110        sp->handler = handler;
111        sp->arg = arg;
112        sp->flags = flags;
113
114/*
115 *      Sort in decreasing URL length order observing the flags for first and last
116 */
117        qsort(websUrlHandler, websUrlHandlerMax, sizeof(websUrlHandlerType),
118                websUrlHandlerSort);
119        return 0;
120}
121
122/******************************************************************************/
123/*
124 *      Delete an existing URL handler. We don't reclaim the space of the old
125 *      handler, just NULL the entry. Return -1 if handler is not found.
126 */
127
128int websUrlHandlerDelete(int (*handler)(webs_t wp, char_t *urlPrefix,
129        char_t *webDir, int arg, char_t *url, char_t *path, char_t *query))
130{
131        websUrlHandlerType      *sp;
132        int                                     i;
133
134        for (i = 0; i < websUrlHandlerMax; i++) {
135                sp = &websUrlHandler[i];
136                if (sp->handler == handler) {
137                        sp->handler = NULL;
138                        return 0;
139                }
140        }
141        return -1;
142}
143
144/******************************************************************************/
145/*
146 *      Sort in decreasing URL length order observing the flags for first and last
147 */
148
149static int websUrlHandlerSort(const void *p1, const void *p2)
150{
151        websUrlHandlerType      *s1, *s2;
152        int                                     rc;
153
154        a_assert(p1);
155        a_assert(p2);
156
157        s1 = (websUrlHandlerType*) p1;
158        s2 = (websUrlHandlerType*) p2;
159
160        if ((s1->flags & WEBS_HANDLER_FIRST) || (s2->flags & WEBS_HANDLER_LAST)) {
161                return -1;
162        }
163
164        if ((s2->flags & WEBS_HANDLER_FIRST) || (s1->flags & WEBS_HANDLER_LAST)) {
165                return 1;
166        }
167
168        if ((rc = gstrcmp(s1->urlPrefix, s2->urlPrefix)) == 0) {
169                if (s1->len < s2->len) {
170                        return 1;
171                } else if (s1->len > s2->len) {
172                        return -1;
173                }
174        }
175        return -rc;
176}
177
178/******************************************************************************/
179/*
180 *      Publish a new web directory (Use the default URL handler)
181 */
182
183int websPublish(char_t *urlPrefix, char_t *path)
184{
185        return websUrlHandlerDefine(urlPrefix, path, 0, websPublishHandler, 0);
186}
187
188/******************************************************************************/
189/*
190 *      Return the directory for a given prefix. Ignore empty prefixes
191 */
192
193char_t *websGetPublishDir(char_t *path, char_t **urlPrefix)
194{
195        websUrlHandlerType      *sp;
196        int                                     i;
197
198        for (i = 0; i < websUrlHandlerMax; i++) {
199                sp = &websUrlHandler[i];
200                if (sp->urlPrefix[0] == '\0') {
201                        continue;
202                }
203                if (sp->handler && gstrncmp(sp->urlPrefix, path, sp->len) == 0) {
204                        if (urlPrefix) {
205                                *urlPrefix = sp->urlPrefix;
206                        }
207                        return sp->webDir;
208                }
209        }
210        return NULL;
211}
212
213/******************************************************************************/
214/*
215 *      Publish URL handler. We just patch the web page Directory and let the
216 *      default handler do the rest.
217 */
218
219static int websPublishHandler(webs_t wp, char_t *urlPrefix, char_t *webDir,
220        int sid, char_t *url, char_t *path, char_t *query)
221{
222        int             len;
223
224        a_assert(websValid(wp));
225        a_assert(path);
226
227/*
228 *      Trim the urlPrefix off the path and set the webdirectory. Add one to step
229 *      over the trailing '/'
230 */
231        len = gstrlen(urlPrefix) + 1;
232        websSetRequestPath(wp, webDir, &path[len]);
233        return 0;
234}
235
236/******************************************************************************/
237/*
238 *      See if any valid handlers are defined for this request. If so, call them
239 *      and continue calling valid handlers until one accepts the request.
240 *      Return true if a handler was invoked, else return FALSE.
241 */
242
243int websUrlHandlerRequest(webs_t wp)
244{
245        websUrlHandlerType      *sp;
246        int                                     i, first;
247
248        a_assert(websValid(wp));
249
250/*
251 *      Delete the socket handler as we don't want to start reading any
252 *      data on the connection as it may be for the next pipelined HTTP/1.1
253 *      request if using Keep Alive
254 */
255        socketDeleteHandler(wp->sid);
256        wp->state = WEBS_PROCESSING;
257        websStats.handlerHits++;
258       
259        websSetRequestPath(wp, websGetDefaultDir(), NULL);
260
261/*
262 *      Eliminate security hole
263 */
264        websCondenseMultipleChars(wp->path, '/');
265        websCondenseMultipleChars(wp->url, '/');
266
267/*
268 *      We loop over each handler in order till one accepts the request.
269 *      The security handler will handle the request if access is NOT allowed.
270 */
271        first = 1;
272        for (i = 0; i < websUrlHandlerMax; i++) {
273                sp = &websUrlHandler[i];
274                if (sp->handler && gstrncmp(sp->urlPrefix, wp->path, sp->len) == 0) {
275                        if (first) {
276                                websSetEnv(wp);
277                                first = 0;
278                        }
279                        if ((*sp->handler)(wp, sp->urlPrefix, sp->webDir, sp->arg,
280                                        wp->url, wp->path, wp->query)) {
281                                return 1;
282                        }
283                        if (!websValid(wp)) {
284                                trace(0,
285                                T("webs: handler %s called websDone, but didn't return 1\n"),
286                                        sp->urlPrefix);
287                                return 1;
288                        }
289                }
290        }
291/*
292 *      If no handler processed the request, then return an error. Note: It is
293 *      the handlers responsibility to call websDone
294 */
295        if (i >= websUrlHandlerMax) {
296                websError(wp, 200, T("No handler for this URL %s"), wp->url);
297        }
298        return 0;
299}
300
301#ifdef OBSOLETE_CODE
302
303/******************************************************************************/
304/*
305 *      Tidy up the URL path. Return -1 if the URL is bad.
306 *  Used to eliminate repeated directory delimiters ('/').
307 */
308
309static int websTidyUrl(webs_t wp)
310{
311        char_t  *parts[64];                                     /* Array of ptr's to URL parts */
312        char_t  *token, *url, *tidyurl;
313        int             i, len, npart;
314
315        a_assert(websValid(wp));
316
317/*
318 *      Copy the string so we don't destroy the original (yet)
319 */
320        url = bstrdup(B_L, wp->url);
321        websDecodeUrl(url, url, gstrlen(url));
322
323        len = npart = 0;
324        parts[0] = NULL;
325        token = gstrtok(url, T("/"));
326
327/*
328 *      Look at each directory segment and process "." and ".." segments
329 *      Don't allow the browser to pop outside the root web.
330 */
331        while (token != NULL) {
332                if (gstrcmp(token, T("..")) == 0) {
333                        if (npart > 0) {
334                                npart--;
335                        }
336
337                } else if (gstrcmp(token, T(".")) != 0) {
338                        parts[npart] = token;
339                        len += gstrlen(token) + 1;
340                        npart++;
341                }
342                token = gstrtok(NULL, T("/"));
343        }
344
345/*
346 *      Re-construct URL. Need extra space all "/" and null.
347 */
348        if (npart || (gstrcmp(url, T("/")) == 0) || (url[0] == '\0')) {
349                tidyurl = balloc(B_L, (len + 2) * sizeof(char_t));
350                *tidyurl = '\0';
351
352                for (i = 0; i < npart; i++) {
353                        gstrcat(tidyurl, T("/"));
354                        gstrcat(tidyurl, parts[i]);
355                }
356
357                bfree(B_L, url);
358
359                bfree(B_L, wp->url);
360                wp->url = tidyurl;
361                return 0;
362        } else {
363                bfree(B_L, url);
364                return -1;
365        }
366}
367
368#endif
369
370/******************************************************************************/
371/*
372 *      Convert multiple adjacent occurrences of a given character to a single
373 *      instance.
374 */
375
376static char_t *websCondenseMultipleChars(char_t *strToCondense, char_t cCondense)
377{
378        if (strToCondense != NULL) {
379                char_t *pStr, *pScan;
380
381                pStr = pScan = strToCondense;
382
383                while (*pScan && *pStr) {
384/*
385 *                      Advance scan pointer over multiple occurences of condense character
386 */
387                        while ((*pScan == cCondense) && (*(pScan + 1) == cCondense)) {
388                                pScan++;
389                        }
390/*
391 *                      Copy character if an advance of the scan pointer has occurred
392 */
393                        if (pStr != pScan) {
394                                *pStr = *pScan;
395                        }
396                       
397                        pScan++;
398                        pStr++;
399                }
400/*
401 *              Zero terminate string if multiple adjacent characters were found and condensed
402 */
403                if (pStr != pScan) {
404                        *pStr = 0;
405                }
406        }
407
408        return strToCondense;
409}
410
411/******************************************************************************/
Note: See TracBrowser for help on using the repository browser.