source: rtems/c/src/libnetworking/rtems_webserver/handler.c @ 19f4540e

Last change on this file since 19f4540e was fd16f5b5, checked in by Joel Sherrill <joel.sherrill@…>, on 06/01/00 at 21:50:37

Patch from Keith Outwater <vac4050@…> to rename
webserver trace() routine to goahead_trace() to avoid name conflicts
with ncurses.

  • Property mode set to 100644
File size: 7.3 KB
Line 
1/*
2 * handler.c -- URL handler support
3 *
4 * Copyright (c) Go Ahead Software Inc., 1995-1999. All Rights Reserved.
5 *
6 * See the file "license.txt" for usage and redistribution license requirements
7 */
8
9/******************************** Description *********************************/
10
11/*
12 *      This module implements a URL handler interface and API to permit
13 *      the addition of user definable URL processors.
14 */
15
16/********************************* Includes ***********************************/
17
18#include        "wsIntrn.h"
19
20/*********************************** Locals ***********************************/
21
22static websUrlHandlerType*      websUrlHandler;                         /* URL handler list */
23static int                                      websUrlHandlerMax;                      /* Number of entries */
24
25/**************************** Forward Declarations ****************************/
26
27static int      websUrlHandlerSort(const void* p1, const void* p2);
28static int      websPublishHandler(webs_t wp, char_t *urlPrefix, char_t *webDir,
29                                int sid, char_t *url, char_t *path, char_t *query);
30
31/*********************************** Code *************************************/
32/*
33 *      Initialize the URL handler module
34 */
35
36int websUrlHandlerOpen()
37{
38        websAspOpen();
39        return 0;
40}
41
42/******************************************************************************/
43/*
44 *      Close the URL handler module
45 */
46
47void websUrlHandlerClose()
48{
49        websUrlHandlerType*     sp;
50
51        websAspClose();
52        for (sp = websUrlHandler; sp < &websUrlHandler[websUrlHandlerMax]; sp++) {
53                bfree(B_L, sp->urlPrefix);
54                if (sp->webDir) {
55                        bfree(B_L, sp->webDir);
56                }
57        }
58        bfree(B_L, websUrlHandler);
59        websUrlHandlerMax = 0;
60}
61
62/******************************************************************************/
63/*
64 *      Define a new URL handler. urlPrefix is the URL prefix to match. webDir is
65 *      an optional root directory path for a web directory. arg is an optional
66 *      arg to pass to the URL handler. flags defines the matching order. Valid
67 *      flags include WEBS_HANDLER_LAST, WEBS_HANDLER_FIRST. If multiple users
68 *      specify last or first, their order is defined alphabetically by the
69 *      urlPrefix.
70 */
71
72int websUrlHandlerDefine(char_t *urlPrefix, char_t *webDir, int arg,
73                int (*handler)(webs_t wp, char_t *urlPrefix, char_t *webdir, int arg,
74                char_t *url, char_t *path, char_t *query), int flags)
75{
76        websUrlHandlerType      *sp;
77        int                                     len;
78
79        a_assert(urlPrefix);
80        a_assert(handler);
81
82/*
83 *      Grow the URL handler array to create a new slot
84 */
85        len = (websUrlHandlerMax + 1) * sizeof(websUrlHandlerType);
86        if ((websUrlHandler = brealloc(B_L, websUrlHandler, len)) == NULL) {
87                return -1;
88        }
89        sp = &websUrlHandler[websUrlHandlerMax++];
90        memset(sp, 0, sizeof(websUrlHandlerType));
91
92        sp->urlPrefix = bstrdup(B_L, urlPrefix);
93        sp->len = gstrlen(sp->urlPrefix);
94        if (webDir) {
95                sp->webDir = bstrdup(B_L, webDir);
96        } else {
97                sp->webDir = bstrdup(B_L, T(""));
98        }
99        sp->handler = handler;
100        sp->arg = arg;
101        sp->flags = flags;
102
103/*
104 *      Sort in decreasing URL length order observing the flags for first and last
105 */
106        qsort(websUrlHandler, websUrlHandlerMax, sizeof(websUrlHandlerType),
107                websUrlHandlerSort);
108        return 0;
109}
110
111/******************************************************************************/
112/*
113 *      Delete an existing URL handler. We don't reclaim the space of the old
114 *      handler, just NULL the entry. Return -1 if handler is not found.
115 */
116
117int websUrlHandlerDelete(int (*handler)(webs_t wp, char_t *urlPrefix,
118        char_t *webDir, int arg, char_t *url, char_t *path, char_t *query))
119{
120        websUrlHandlerType      *sp;
121        int                                     i;
122
123        for (i = 0; i < websUrlHandlerMax; i++) {
124                sp = &websUrlHandler[i];
125                if (sp->handler == handler) {
126                        sp->handler = NULL;
127                        return 0;
128                }
129        }
130        return -1;
131}
132
133/******************************************************************************/
134/*
135 *      Sort in decreasing URL length order observing the flags for first and last
136 */
137
138static int websUrlHandlerSort(const void* p1, const void* p2)
139{
140        websUrlHandlerType      *s1, *s2;
141        int                                     rc;
142
143        a_assert(p1);
144        a_assert(p2);
145
146        s1 = (websUrlHandlerType*) p1;
147        s2 = (websUrlHandlerType*) p2;
148
149        if ((s1->flags & WEBS_HANDLER_FIRST) || (s2->flags & WEBS_HANDLER_LAST)) {
150                return -1;
151        }
152
153        if ((s2->flags & WEBS_HANDLER_FIRST) || (s1->flags & WEBS_HANDLER_LAST)) {
154                return 1;
155        }
156
157        if ((rc = gstrcmp(s1->urlPrefix, s2->urlPrefix)) == 0) {
158                if (s1->len < s2->len) {
159                        return 1;
160                } else if (s1->len > s2->len) {
161                        return -1;
162                }
163        }
164        return -rc;
165}
166
167/******************************************************************************/
168/*
169 *      Publish a new web directory (Use the default URL handler)
170 */
171
172int websPublish(char_t *urlPrefix, char_t *path)
173{
174        return websUrlHandlerDefine(urlPrefix, path, 0, websPublishHandler, 0);
175}
176
177/******************************************************************************/
178/*
179 *      Return the directory for a given prefix. Ignore empty prefixes
180 */
181
182char_t *websGetPublishDir(char_t *path, char_t **urlPrefix)
183{
184        websUrlHandlerType      *sp;
185        int                                     i;
186
187        for (i = 0; i < websUrlHandlerMax; i++) {
188                sp = &websUrlHandler[i];
189                if (sp->urlPrefix[0] == '\0') {
190                        continue;
191                }
192                if (sp->handler && gstrncmp(sp->urlPrefix, path, sp->len) == 0) {
193                        if (urlPrefix) {
194                                *urlPrefix = sp->urlPrefix;
195                        }
196                        return sp->webDir;
197                }
198        }
199        return NULL;
200}
201
202/******************************************************************************/
203/*
204 *      Publish URL handler. We just patch the web page Directory and let the
205 *      default handler do the rest.
206 */
207
208static int websPublishHandler(webs_t wp, char_t *urlPrefix, char_t *webDir,
209        int sid, char_t *url, char_t *path, char_t *query)
210{
211        int             len;
212
213        a_assert(websValid(wp));
214        a_assert(path);
215
216/*
217 *      Trim the urlPrefix off the path and set the webdirectory. Add one to step
218 *      over the trailing '/'
219 */
220        len = gstrlen(urlPrefix) + 1;
221        websSetRequestPath(wp, webDir, &path[len]);
222        return 0;
223}
224
225/******************************************************************************/
226/*
227 *      See if any valid handlers are defined for this request. If so, call them
228 *      and continue calling valid handlers until one accepts the request.
229 *      Return true if a handler was invoked, else return FALSE.
230 */
231
232int websUrlHandlerRequest(webs_t wp)
233{
234        websUrlHandlerType      *sp;
235        int                                     i, first;
236
237        a_assert(websValid(wp));
238
239/*
240 *      Delete the socket handler as we don't want to start reading any
241 *      data on the connection as it may be for the next pipelined HTTP/1.1
242 *      request if using Keep Alive
243 */
244        socketDeleteHandler(wp->sid);
245        wp->state = WEBS_PROCESSING;
246        websStats.handlerHits++;
247       
248        websSetRequestPath(wp, websGetDefaultDir(), NULL);
249
250/*
251 *      We loop over each handler in order till one accepts the request.
252 *      The security handler will handle the request if access is NOT allowed.
253 */
254        first = 1;
255        for (i = 0; i < websUrlHandlerMax; i++) {
256                sp = &websUrlHandler[i];
257                if (sp->handler && gstrncmp(sp->urlPrefix, wp->path, sp->len) == 0) {
258                        if (first) {
259                                websSetEnv(wp);
260                                first = 0;
261                        }
262                        if ((*sp->handler)(wp, sp->urlPrefix, sp->webDir, sp->arg,
263                                        wp->url, wp->path, wp->query)) {
264                                return 1;
265                        }
266                        if (!websValid(wp)) {
267                                goahead_trace(0,
268                                T("webs: handler %s called websDone, but didn't return 1\n"),
269                                        sp->urlPrefix);
270                                return 1;
271                        }
272                }
273        }
274/*
275 *      If no handler processed the request, then return an error. Note: It was
276 *      the handlers responsibility to call websDone
277 */
278        if (i >= websUrlHandlerMax) {
279                websError(wp, 200, T("No handler for this URL %s"), wp->url);
280        }
281        return 0;
282}
283
284/******************************************************************************/
Note: See TracBrowser for help on using the repository browser.