default.c
来自「RTEMS (Real-Time Executive for Multiproc」· C语言 代码 · 共 403 行
C
403 行
/* * default.c -- Default URL handler. Includes support for ASP. * * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved. * * See the file "license.txt" for usage and redistribution license requirements * * $Id: default.c,v 1.2 2000/09/01 10:57:21 joel Exp $ *//******************************** Description *********************************//* * This module provides default URL handling and Active Server Page support. * * In many cases we don't check the return code of calls to websWrite as * it is easier, smaller and non-fatal to continue even when the requesting * browser has gone away. *//********************************* Includes ***********************************/#include "wsIntrn.h"/*********************************** Locals ***********************************/static char_t *websDefaultPage; /* Default page name */static char_t *websDefaultDir; /* Default Web page directory *//**************************** Forward Declarations ****************************/static void websDefaultWriteEvent(webs_t wp);/*********************************** Code *************************************//* * Process a default URL request. This will validate the URL and handle "../" * and will provide support for Active Server Pages. As the handler is the * last handler to run, it always indicates that it has handled the URL * by returning 1. */int websDefaultHandler(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg, char_t *url, char_t *path, char_t *query){ websStatType sbuf; char_t *lpath, *tmp, *date; int bytes, flags, nchars; a_assert(websValid(wp)); a_assert(url && *url); a_assert(path); a_assert(query);/* * Validate the URL and ensure that ".."s don't give access to unwanted files */ flags = websGetRequestFlags(wp); if (websValidateUrl(wp, path) < 0) { websError(wp, 500, T("Invalid URL %s"), url); return 1; } lpath = websGetRequestLpath(wp); nchars = gstrlen(lpath) - 1; if (lpath[nchars] == '/' || lpath[nchars] == '\\') { lpath[nchars] = '\0'; }/* * If the file is a directory, redirect using the nominated default page */ if (websPageIsDirectory(lpath)) { nchars = gstrlen(path); if (path[nchars-1] == '/' || path[nchars-1] == '\\') { path[--nchars] = '\0'; } nchars += gstrlen(websDefaultPage) + 2; fmtAlloc(&tmp, nchars, T("%s/%s"), path, websDefaultPage); websRedirect(wp, tmp); bfreeSafe(B_L, tmp); return 1; }/* * Open the document. Stat for later use. */ if (websPageOpen(wp, lpath, path, SOCKET_RDONLY | SOCKET_BINARY, 0666) < 0) { websError(wp, 400, T("Cannot open URL <b>%s</b>"), url); return 1; } if (websPageStat(wp, lpath, path, &sbuf) < 0) { websError(wp, 400, T("Cannot stat page for URL <b>%s</b>"), url); return 1; }/* * If the page has not been modified since the user last received it and it * is not dynamically generated each time (ASP), then optimize request by * sending a 304 Use local copy response */ websStats.localHits++;#if WEBS_IF_MODIFIED_SUPPORT if (flags & WEBS_IF_MODIFIED && !(flags & WEBS_ASP)) { if (sbuf.mtime <= wp->since) { websWrite(wp, T("HTTP/1.0 304 Use local copy\r\n"));/* * by license terms the following line of code must * not be modified. */ websWrite(wp, T("Server: %s\r\n"), WEBS_NAME); if (flags & WEBS_KEEP_ALIVE) { websWrite(wp, T("Connection: keep-alive\r\n")); } websWrite(wp, T("\r\n")); websSetRequestFlags(wp, flags |= WEBS_HEADER_DONE); websDone(wp, 304); return 1; } }#endif/* * Output the normal HTTP response header */ if ((date = websGetDateString(NULL)) != NULL) { websWrite(wp, T("HTTP/1.0 200 OK\r\nDate: %s\r\n"), date);/* * By license terms the following line of code must not be modified. */ websWrite(wp, T("Server: %s\r\n"), WEBS_NAME); bfree(B_L, date); } flags |= WEBS_HEADER_DONE;/* * If this is an ASP request, ensure the remote browser doesn't cache it. * Send back both HTTP/1.0 and HTTP/1.1 cache control directives */ if (flags & WEBS_ASP) { bytes = 0; websWrite(wp, T("Pragma: no-cache\r\nCache-Control: no-cache\r\n")); } else { if ((date = websGetDateString(&sbuf)) != NULL) { websWrite(wp, T("Last-modified: %s\r\n"), date); bfree(B_L, date); } bytes = sbuf.size; } if (bytes) { websWrite(wp, T("Content-length: %d\r\n"), bytes); websSetRequestBytes(wp, bytes); } websWrite(wp, T("Content-type: %s\r\n"), websGetRequestType(wp)); if ((flags & WEBS_KEEP_ALIVE) && !(flags & WEBS_ASP)) { websWrite(wp, T("Connection: keep-alive\r\n")); } websWrite(wp, T("\r\n"));/* * All done if the browser did a HEAD request */ if (flags & WEBS_HEAD_REQUEST) { websDone(wp, 200); return 1; }/* * Evaluate ASP requests */ if (flags & WEBS_ASP) { if (websAspRequest(wp, lpath) < 0) { return 1; } websDone(wp, 200); return 1; }#ifdef WEBS_SSL_SUPPORT if (wp->flags & WEBS_SECURE) { websDefaultWriteEvent(wp); } else { websSetRequestSocketHandler(wp, SOCKET_WRITABLE, websDefaultWriteEvent); }#else/* * For normal web documents, return the data via background write */ websSetRequestSocketHandler(wp, SOCKET_WRITABLE, websDefaultWriteEvent);#endif return 1;}/******************************************************************************//* * Validate the URL path and process ".." path segments. Return -1 if the URL * is bad. */int websValidateUrl(webs_t wp, char_t *path){ char_t *parts[64]; /* Array of ptr's to URL parts */ char_t *token, *dir, *lpath; int i, len, npart; a_assert(websValid(wp)); a_assert(path); dir = websGetRequestDir(wp); if (dir == NULL || *dir == '\0') { return -1; }/* * Copy the string so we don't destroy the original */ path = bstrdup(B_L, path); websDecodeUrl(path, path, gstrlen(path)); len = npart = 0; parts[0] = NULL; token = gstrtok(path, T("/"));/* * Look at each directory segment and process "." and ".." segments * Don't allow the browser to pop outside the root web. */ while (token != NULL) { if (gstrcmp(token, T("..")) == 0) { if (npart > 0) { npart--; } } else if (gstrcmp(token, T(".")) != 0) { parts[npart] = token; len += gstrlen(token) + 1; npart++; } token = gstrtok(NULL, T("/")); }/* * Create local path for document. Need extra space all "/" and null. */ if (npart || (gstrcmp(path, T("/")) == 0) || (path[0] == '\0')) { lpath = balloc(B_L, (gstrlen(dir) + 1 + len + 1) * sizeof(char_t)); gstrcpy(lpath, dir); for (i = 0; i < npart; i++) { gstrcat(lpath, T("/")); gstrcat(lpath, parts[i]); } websSetRequestLpath(wp, lpath); bfree(B_L, path); bfree(B_L, lpath); } else { bfree(B_L, path); return -1; } return 0;}/******************************************************************************//* * Do output back to the browser in the background. This is a socket * write handler. */static void websDefaultWriteEvent(webs_t wp){ int len, wrote, flags, bytes, written; char *buf; a_assert(websValid(wp)); flags = websGetRequestFlags(wp); websMarkTime(wp); wrote = bytes = 0; written = websGetRequestWritten(wp);/* * We only do this for non-ASP documents */ if ( !(flags & WEBS_ASP)) { bytes = websGetRequestBytes(wp);/* * Note: websWriteDataNonBlock may return less than we wanted. It will * return -1 on a socket error */ if ((buf = balloc(B_L, PAGE_READ_BUFSIZE)) == NULL) { websError(wp, 200, T("Can't get memory")); } else { while ((len = websPageReadData(wp, buf, PAGE_READ_BUFSIZE)) > 0) { if ((wrote = websWriteDataNonBlock(wp, buf, len)) < 0) { break; } written += wrote; if (wrote != len) { websPageSeek(wp, - (len - wrote)); break; } }/* * Safety. If we are at EOF, we must be done */ if (len == 0) { a_assert(written >= bytes); written = bytes; } bfree(B_L, buf); } }/* * We're done if an error, or all bytes output */ websSetRequestWritten(wp, written); if (wrote < 0 || written >= bytes) { websDone(wp, 200); }}/******************************************************************************//* * Closing down. Free resources. */void websDefaultClose(){ if (websDefaultPage) { bfree(B_L, websDefaultPage); websDefaultPage = NULL; } if (websDefaultDir) { bfree(B_L, websDefaultDir); websDefaultDir = NULL; }}/******************************************************************************//* * Get the default page for URL requests ending in "/" */char_t *websGetDefaultPage(){ return websDefaultPage;}/******************************************************************************//* * Get the default web directory */char_t *websGetDefaultDir(){ return websDefaultDir;}/******************************************************************************//* * Set the default page for URL requests ending in "/" */void websSetDefaultPage(char_t *page){ a_assert(page && *page); if (websDefaultPage) { bfree(B_L, websDefaultPage); } websDefaultPage = bstrdup(B_L, page);}/******************************************************************************//* * Set the default web directory */void websSetDefaultDir(char_t *dir){ a_assert(dir && *dir); if (websDefaultDir) { bfree(B_L, websDefaultDir); } websDefaultDir = bstrdup(B_L, dir);}/******************************************************************************/
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?