⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 default.c

📁 GOAHEAD WEBSERVER嵌入式的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * 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.9 2003/04/11 18:10:28 bporter 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) 
   {
      /* 
       * preventing a cross-site scripting exploit -- you may restore the
       * following line of code to revert to the original behavior...
       */
		/*websError(wp, 500, T("Invalid URL %s"), url);*/
      websError(wp, 500, T("Invalid 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) 
   {
      /* 10 Dec 02 BgP -- according to 
       * <http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html>, 
       * the proper code to return here is NOT 400 (old code), which is used
       * to indicate a malformed request. Here, the request is good, but the
       * error we need to tell the client about is 404 (Not Found).
       */
      /* 
       * 17 Mar 03 BgP -- prevent a cross-site scripting exploit
		websError(wp, 404, T("Cannot open URL %s"), url);
       */
      
		websError(wp, 404, T("Cannot open URL"));
		return 1;
	} 

	if (websPageStat(wp, lpath, path, &sbuf) < 0) {
      /*
       * 17 Mar 03 BgP
       * prevent a cross-site scripting exploit
		websError(wp, 400, T("Cannot stat page for URL %s"), url);
       */
		websError(wp, 400, T("Cannot stat page for 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++;
#ifdef 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;
}


#ifdef WIN32

static int badPath(char_t* path, char_t* badPath, int badLen)
{
   int retval = 0;
   int len = gstrlen(path);
   int i = 0;

   if (len <= badLen +1)
   {
      for (i = 0; i < badLen; ++i)
      {
         if (badPath[i] != gtolower(path[i]))
         {
            return 0;
         }
      }
      /* if we get here, the first 'badLen' characters match.
       * If 'path' is 1 character larger than 'badPath' and that extra 
       * character is NOT a letter or a number, we have a bad path.
       */
      retval = 1;
      if (badLen + 1 == len)
      {
         /* e.g. path == "aux:" */
         if (gisalnum(path[len-1]))
         {
            /* the last character is alphanumeric, so we let this path go 
             * through. 
             */
            retval = 0;
         }
      }
   }

   return retval;
}


static int isBadWindowsPath(char_t** parts, int partCount)
{
   /*
    * If we're running on Windows 95/98/ME, malicious users can crash the 
    * OS by requesting an URL with any of several reserved DOS device names 
    * in them (AUX, NUL, etc.).
    * If we're running on any of those OS versions, we scan the URL 
    * for paths with any of these elements before 
    * trying to access them. If any of the subdirectory names match one
    * of our prohibited links, we declare this to be a 'bad' path, and return 
    * 1 to indicate this. This may be an overly heavy-handed approach, but should 
    * prevent the DOS attack.
    * NOTE that this function is only compiled in when we are running on Win32, 
    * and only has an effect when we are running on Win95/98, or ME. On all other 
    * versions of Windows, we check the version info, and return 0 immediately.
    *
    * According to http://packetstormsecurity.nl/0003-exploits/SCX-SA-01.txt:

    *  II.  Problem Description
    *   When the Microsoft Windows operating system is parsing a path that 
    *   is being crafted like "c:\[device]\[device]" it will halt, and crash 
    *   the entire operating system.  
    *   Four device drivers have been found to crash the system.  The CON,
    *   NUL, AUX, CLOCK$ and CONFIG$ are the two device drivers which are 
    *   known to crash.  Other devices as LPT[x]:, COM[x]: and PRN have not 
    *   been found to crash the system.  
    *   Making combinations as CON\NUL, NUL\CON, AUX\NUL, ... seems to 
    *   crash Ms Windows as well.
    *   Calling a path such as "C:\CON\[filename]" won't result in a crash
    *   but in an error-message.  Creating the map "CON", "CLOCK$", "AUX"
    *   "NUL" or "CONFIG$" will also result in a simple error-message 
    *   saying: ''creating that map isn't allowed''.
    *
    * returns 1 if it finds a bad path element.
    */
   OSVERSIONINFO version;
   int i;
   version.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
   if (GetVersionEx(&version))

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -