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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [rtems/] [c/] [src/] [libnetworking/] [rtems_webserver/] [default.c] - Blame information for rev 373

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 30 unneback
/*
2
 * default.c -- Default URL handler. Includes support for ASP.
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 provides default URL handling and Active Server Page support.
13
 *
14
 *      In many cases we don't check the return code of calls to websWrite as
15
 *      it is easier, smaller and non-fatal to continue even when the requesting
16
 *      browser has gone away.
17
 */
18
 
19
/********************************* Includes ***********************************/
20
 
21
#include        "wsIntrn.h"
22
 
23
/*********************************** Locals ***********************************/
24
 
25
static char_t   *websDefaultPage;                       /* Default page name */
26
static char_t   *websDefaultDir;                        /* Default Web page directory */
27
 
28
/**************************** Forward Declarations ****************************/
29
 
30
static void websDefaultWriteEvent(webs_t wp);
31
 
32
/*********************************** Code *************************************/
33
/*
34
 *      Process a default URL request. This will validate the URL and handle "../"
35
 *      and will provide support for Active Server Pages. As the handler is the
36
 *      last handler to run, it always indicates that it has handled the URL
37
 *      by returning 1.
38
 */
39
 
40
int websDefaultHandler(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg,
41
                                                char_t *url, char_t *path, char_t* query)
42
{
43
        websStatType    sbuf;
44
        char_t                  *lpath, *tmp;
45
        char_t                  *date;
46
        int                             bytes, flags, nchars;
47
 
48
        a_assert(websValid(wp));
49
        a_assert(url && *url);
50
        a_assert(path && *path);
51
        a_assert(query);
52
 
53
/*
54
 *      Validate the URL and ensure that ".."s don't give access to unwanted files
55
 */
56
        flags = websGetRequestFlags(wp);
57
 
58
        if (websValidateUrl(wp, path) < 0) {
59
                websError(wp, 500, T("Invalid URL %s"), url);
60
                return 1;
61
        }
62
        lpath = websGetRequestLpath(wp);
63
        nchars = gstrlen(lpath) - 1;
64
        if (lpath[nchars] == '/' || lpath[nchars] == '\\') {
65
                lpath[nchars] = '\0';
66
        }
67
 
68
/*
69
 *      If the file is a directory, redirect using the nominated default page
70
 */
71
        if (websPageIsDirectory(lpath)) {
72
                nchars = gstrlen(path);
73
                if (path[nchars-1] == '/' || path[nchars-1] == '\\') {
74
                        path[--nchars] = '\0';
75
                }
76
                nchars += gstrlen(websDefaultPage) + 2;
77
                tmp = NULL;
78
                gsnprintf(&tmp, nchars, T("%s/%s"), path, websDefaultPage);
79
                websRedirect(wp, tmp);
80
                bfreeSafe(B_L, tmp);
81
                return 1;
82
        }
83
 
84
/*
85
 *      Open the document. Stat for later use.
86
 */
87
        if (websPageOpen(wp, lpath, path, SOCKET_RDONLY | SOCKET_BINARY,
88
                                0666) < 0) {
89
                        websError(wp, 400,
90
                                T("Can't open document <b>%s</b><br>for URL <b>%s</b>"),
91
                                        lpath, url);
92
                        return 1;
93
                }
94
                if (websPageStat(wp, lpath, path, &sbuf) < 0) {
95
                        websError(wp, 400, T("Can't stat page <b>%s</b><br>for URL <b>%s</b>"),
96
                                lpath, url);
97
                }
98
 
99
/*
100
 *      If the page has not been modified since the user last received it and it
101
 *      is not dynamically generated each time (ASP), then optimize request by
102
 *      sending a 304 Use local copy response
103
 */
104
        websStats.localHits++;
105
#if WEBS_IF_MODIFIED_SUPPORT
106
        if (flags & WEBS_IF_MODIFIED && !(flags & WEBS_ASP)) {
107
                if (sbuf.mtime <= wp->since) {
108
                        websWrite(wp, T("HTTP/1.0 304 Use local copy\r\n"));
109
 
110
                        /* by license terms the following line of code must
111
                         * not be modified.
112
                         */
113
                        websWrite(wp, T("Server: GoAhead-Webs\r\n"));
114
 
115
                        if (flags && WEBS_KEEP_ALIVE) {
116
                                websWrite(wp, T("Connection: keep-alive\r\n"));
117
                        }
118
                        websWrite(wp, T("\r\n"));
119
                        websSetRequestFlags(wp, flags |= WEBS_HEADER_DONE);
120
                        websDone(wp, 304);
121
                        return 1;
122
                }
123
        }
124
#endif
125
 
126
/*
127
 *      Output the normal HTTP response header
128
 */
129
        if ((date = websGetDateString(NULL)) != NULL) {
130
                websWrite(wp, T("HTTP/1.0 200 OK\r\nDate: %s\r\n"), date);
131
 
132
/*
133
 *              By license terms the following line of code must not be modified.
134
*/
135
                websWrite(wp, T("Server: GoAhead-Webs\r\n"));
136
                bfree(B_L, date);
137
        }
138
        flags |= WEBS_HEADER_DONE;
139
 
140
/*
141
 *      If this is an ASP request, ensure the remote browser doesn't cache it.
142
 *      Send back both HTTP/1.0 and HTTP/1.1 cache control directives
143
 */
144
        if (flags & WEBS_ASP) {
145
                bytes = 0;
146
                websWrite(wp, T("Pragma: no-cache\r\nCache-Control: no-cache\r\n"));
147
 
148
        } else {
149
                if ((date = websGetDateString(&sbuf)) != NULL) {
150
                        websWrite(wp, T("Last-modified: %s\r\n"), date);
151
                        bfree(B_L, date);
152
                }
153
                bytes = sbuf.size;
154
        }
155
 
156
        if (bytes) {
157
                websWrite(wp, T("Content-length: %d\r\n"), bytes);
158
                websSetRequestBytes(wp, bytes);
159
        }
160
        websWrite(wp, T("Content-type: %s\r\n"), websGetRequestType(wp));
161
 
162
        if ((flags & WEBS_KEEP_ALIVE) && !(flags & WEBS_ASP)) {
163
                websWrite(wp, T("Connection: keep-alive\r\n"));
164
        }
165
        websWrite(wp, T("\r\n"));
166
 
167
/*
168
 *      Evaluate ASP requests
169
 */
170
        if (flags & WEBS_ASP) {
171
                if (websAspRequest(wp, lpath) < 0) {
172
                        return 1;
173
                }
174
                websDone(wp, 200);
175
                return 1;
176
        }
177
 
178
/*
179
 *      All done if the browser did a HEAD request
180
 */
181
        if (flags & WEBS_HEAD_REQUEST) {
182
                websDone(wp, 200);
183
                return 1;
184
        }
185
/*
186
 *      For normal web documents, return the data via background write
187
 */
188
        websSetRequestSocketHandler(wp, SOCKET_WRITABLE, websDefaultWriteEvent);
189
        return 1;
190
}
191
 
192
/******************************************************************************/
193
/*
194
 *      Validate the URL path and process ".." path segments. Return -1 if the URL
195
 *      is bad.
196
 */
197
 
198
int websValidateUrl(webs_t wp, char_t *path)
199
{
200
        char_t  *parts[64];                                     /* Array of ptr's to URL parts */
201
        char_t  *token, *dir, *lpath;
202
        int             i, len, npart;
203
 
204
        a_assert(websValid(wp));
205
        a_assert(path);
206
 
207
        dir = websGetRequestDir(wp);
208
        if (dir == NULL || *dir == '\0') {
209
                return -1;
210
        }
211
 
212
/*
213
 *      Copy the string so we don't destroy the original
214
 */
215
        path = bstrdup(B_L, path);
216
        websDecodeUrl(path, path, gstrlen(path));
217
 
218
        len = npart = 0;
219
        parts[0] = NULL;
220
        token = gstrtok(path, T("/"));
221
 
222
/*
223
 *      Look at each directory segment and process "." and ".." segments
224
 *      Don't allow the browser to pop outside the root web.
225
 */
226
        while (token != NULL) {
227
                if (gstrcmp(token, T("..")) == 0) {
228
                        if (npart > 0) {
229
                                npart--;
230
                        }
231
 
232
                } else if (gstrcmp(token, T(".")) != 0) {
233
                        parts[npart] = token;
234
                        len += gstrlen(token) + 1;
235
                        npart++;
236
                }
237
                token = gstrtok(NULL, T("/"));
238
        }
239
 
240
/*
241
 *      Create local path for document. Need extra space all "/" and null.
242
 */
243
        if (npart) {
244
                lpath = balloc(B_L, (gstrlen(dir) + 1 + len + 1) * sizeof(char_t));
245
                gstrcpy(lpath, dir);
246
 
247
                for (i = 0; i < npart; i++) {
248
                        gstrcat(lpath, T("/"));
249
                        gstrcat(lpath, parts[i]);
250
                }
251
                websSetRequestLpath(wp, lpath);
252
                bfree(B_L, path);
253
                bfree(B_L, lpath);
254
 
255
        } else {
256
                bfree(B_L, path);
257
                return -1;
258
        }
259
        return 0;
260
}
261
 
262
/******************************************************************************/
263
/*
264
 *      Do output back to the browser in the background. This is a socket
265
 *      write handler.
266
 */
267
 
268
static void websDefaultWriteEvent(webs_t wp)
269
{
270
        int                     len, wrote, flags, bytes, written;
271
        char *          buf;
272
 
273
        a_assert(websValid(wp));
274
 
275
        flags = websGetRequestFlags(wp);
276
 
277
        wrote = 0;
278
        bytes = 0;
279
        written = websGetRequestWritten(wp);
280
 
281
/*
282
 *      We only do this for non-ASP documents
283
 */
284
        if ( !(flags & WEBS_ASP)) {
285
                bytes = websGetRequestBytes(wp);
286
/*
287
 *              Note: websWriteBlock may return less than we wanted. It will return
288
 *              -1 on a socket error
289
 */
290
                if ((buf = balloc(B_L, PAGE_READ_BUFSIZE)) == NULL) {
291
                        websError(wp, 200, T("Can't get memory"));
292
                }
293
                else {
294
                        while ((len = websPageReadData(wp, buf, PAGE_READ_BUFSIZE)) > 0) {
295
                                if ((wrote = websWriteBlockData(wp, buf, len)) < 0) {
296
                                        break;
297
                                }
298
                                written += wrote;
299
                                if (wrote != len) {
300
                                        websPageSeek(wp, - (wrote - len));
301
                                        break;
302
                                }
303
                        }
304
/*
305
 *                      Safety. If we are at EOF, we must be done
306
 */
307
                        if (len == 0) {
308
                                a_assert(written >= bytes);
309
                                written = bytes;
310
                        }
311
                        bfree(B_L, buf);
312
                }
313
        }
314
 
315
/*
316
 *      We're done if an error, or all bytes output
317
 */
318
        websSetRequestWritten(wp, written);
319
        if (wrote < 0 || written >= bytes) {
320
                websDone(wp, 200);
321
        }
322
}
323
 
324
/******************************************************************************/
325
/*
326
 *      Closing down. Free resources.
327
 */
328
 
329
void websDefaultClose()
330
{
331
        if (websDefaultPage) {
332
                bfree(B_L, websDefaultPage);
333
        }
334
        if (websDefaultDir) {
335
                bfree(B_L, websDefaultDir);
336
        }
337
}
338
 
339
/******************************************************************************/
340
/*
341
 *      Get the default page for URL requests ending in "/"
342
 */
343
 
344
char_t *websGetDefaultPage()
345
{
346
        return websDefaultPage;
347
}
348
 
349
/******************************************************************************/
350
/*
351
 *      Get the default web directory
352
 */
353
 
354
char_t *websGetDefaultDir()
355
{
356
        return websDefaultDir;
357
}
358
 
359
/******************************************************************************/
360
/*
361
 *      Set the default page for URL requests ending in "/"
362
 */
363
 
364
void websSetDefaultPage(char_t *page)
365
{
366
        a_assert(page && *page);
367
 
368
        if (websDefaultPage) {
369
                bfree(B_L, websDefaultPage);
370
        }
371
        websDefaultPage = bstrdup(B_L, page);
372
}
373
 
374
/******************************************************************************/
375
/*
376
 *      Set the default web directory
377
 */
378
 
379
void websSetDefaultDir(char_t *dir)
380
{
381
        a_assert(dir && *dir);
382
        if (websDefaultDir) {
383
                bfree(B_L, websDefaultDir);
384
        }
385
        websDefaultDir = bstrdup(B_L, dir);
386
}
387
 
388
/******************************************************************************/
389
 

powered by: WebSVN 2.1.0

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