OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rtems-20020807/] [c/] [src/] [libnetworking/] [rtems_webserver/] [handler.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.