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

📄 httpsrvr.cxx

📁 基于VXWORKS H323通信技术源代码
💻 CXX
📖 第 1 页 / 共 4 页
字号:
/*
 * httpsrvr.cxx
 *
 * HTTP server classes.
 *
 * Portable Windows Library
 *
 * Copyright (c) 1993-1998 Equivalence Pty. Ltd.
 *
 * The contents of this file are subject to the Mozilla Public License
 * Version 1.0 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
 * the License for the specific language governing rights and limitations
 * under the License.
 *
 * The Original Code is Portable Windows Library.
 *
 * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
 *
 * Portions are Copyright (C) 1993 Free Software Foundation, Inc.
 * All Rights Reserved.
 *
 * Contributor(s): ______________________________________.
 *
 * $Log: httpsrvr.cxx,v $
 * Revision 1.31  1999/05/13 04:04:04  robertj
 * Fixed problem of initialised commandName in ConnectionInfo.
 *
 * Revision 1.30  1999/05/12 01:40:47  robertj
 * Fixed "unknown" response codes being passed on when used with an "unknown" command.
 *
 * Revision 1.29  1999/05/11 12:23:22  robertj
 * Fixed search for persistent connection to accept kee-alive on multile MIME fields.
 *
 * Revision 1.28  1999/05/04 15:26:01  robertj
 * Improved HTTP/1.1 compatibility (pass through user commands).
 * Fixed problems with quicktime installer.
 *
 * Revision 1.27  1999/04/24 11:50:11  robertj
 * Changed HTTP command parser so will work if some idiot puts spaces in a URL.
 *
 * Revision 1.26  1999/04/21 01:58:08  robertj
 * Fixed problem with reading data for request using second form of PHTTPRequestInfo constructor.
 *
 * Revision 1.25  1998/11/30 04:51:59  robertj
 * New directory structure
 *
 * Revision 1.24  1998/11/14 01:11:38  robertj
 * PPC linux GNU compatibility.
 *
 * Revision 1.23  1998/10/31 12:49:23  robertj
 * Added read/write mutex to the HTTP space variable to avoid thread crashes.
 *
 * Revision 1.22  1998/10/25 01:02:41  craigs
 * Added ability to specify per-directory authorisation for PHTTPDirectory
 *
 * Revision 1.21  1998/10/13 14:06:23  robertj
 * Complete rewrite of memory leak detection code.
 *
 * Revision 1.20  1998/09/23 06:22:13  robertj
 * Added open source copyright license.
 *
 * Revision 1.19  1998/08/06 00:54:22  robertj
 * Fixed bug in sending empty files, caused endless wait in Netscape.
 *
 * Revision 1.18  1998/06/16 03:32:14  robertj
 * Propagated persistence and proxy flags in new connection info instances.
 *
 * Revision 1.17  1998/04/01 01:55:16  robertj
 * Fixed bug when serving HTTPFile that has zero bytes in it.
 *
 * Revision 1.16  1998/02/03 06:24:10  robertj
 * Added local address and port to PHTTPRequest.
 * Fixed bug in default entity length. should be read to EOF.
 * Fixed OnError() so can detec HTML bosy tag with parameters.
 *
 * Revision 1.14  1998/01/26 00:42:19  robertj
 * Added more information to PHTTPConnectionInfo.
 * Made SetDefaultMIMEFields in HTTP Server not set those fields if already set.
 *
 * Revision 1.13  1997/10/30 10:22:04  robertj
 * Added multiple user basic authorisation scheme.
 *
 * Revision 1.12  1997/10/03 13:39:25  robertj
 * Fixed race condition on socket close in Select() function.
 *
 * Revision 1.12  1997/10/03 13:31:12  craigs
 * Added ability to access client socket from within HTTP resources
 *
 * Revision 1.11  1997/08/04 10:44:36  robertj
 * Improved receiving of a POST on a non-persistant connection, do not wait for EOF if have CRLF.
 *
 * Revision 1.10  1997/07/14 11:47:13  robertj
 * Added "const" to numerous variables.
 *
 * Revision 1.9  1997/07/08 13:10:26  robertj
 * Fixed bug in HTTP server where standard error text is not sent to remote client.
 *
 * Revision 1.8  1997/04/15 14:32:19  robertj
 * Fixed case problem for HTTP version string.
 *
 * Revision 1.7  1997/03/20 13:01:32  robertj
 * Fixed bug in proxy POST having unexpexted reset of connection.
 *
 * Revision 1.6  1997/02/09 04:09:30  robertj
 * Fixed GCC warning
 *
 * Revision 1.5  1997/01/12 04:15:23  robertj
 * Globalised MIME tag strings.
 *
 * Revision 1.4  1996/12/12 09:24:16  robertj
 * Persistent proxy connection support (work in progress).
 *
 * Revision 1.3  1996/11/10 21:09:33  robertj
 * Removed redundent GetSocket() call.
 * Added flush of stream after processing request, important on persistent connections.
 *
 * Revision 1.2  1996/10/26 03:31:05  robertj
 * Changed OnError so can pass in full HTML page as parameter.
 *
 * Revision 1.1  1996/09/14 13:02:18  robertj
 * Initial revision
 *
 */

#include <ptlib.h>
#include <ptlib/sockets.h>
#include <ptclib/http.h>
#include <ctype.h>

#define new PNEW


// undefine to remove support for persistant connections
#define HAS_PERSISTANCE

// define to enable work-around for Netscape persistant connection bug
// set to lifetime of suspect sockets (in seconds)
#define STRANGE_NETSCAPE_BUG	3

// maximum lifetime (in seconds) of persistant connections
#define	MAX_LIFETIME		30

// maximum lifetime (in transactions) of persistant connections
#define MAX_TRANSACTIONS	10

// maximum delay between characters whilst reading a line of text
#define	READLINE_TIMEOUT	30

//  filename to use for directory access directives
static const PString accessFilename = "_access";


//////////////////////////////////////////////////////////////////////////////
// PHTTPSpace

PHTTPSpace::PHTTPSpace()
{
  mutex = new PReadWriteMutex;
  root = new Node(PString(), NULL);
}


void PHTTPSpace::DestroyContents()
{
  delete mutex;
  delete root;
}


void PHTTPSpace::CloneContents(const PHTTPSpace * c)
{
  mutex = new PReadWriteMutex;
  root = new Node(*c->root);
}


void PHTTPSpace::CopyContents(const PHTTPSpace & c)
{
  mutex = c.mutex;
  root = c.root;
}


PHTTPSpace::Node::Node(const PString & nam, Node * parentNode)
  : PString(nam)
{
  parent = parentNode;
  resource = NULL;
}


PHTTPSpace::Node::~Node()
{
  delete resource;
}


BOOL PHTTPSpace::AddResource(PHTTPResource * res, AddOptions overwrite)
{
  PAssert(res != NULL, PInvalidParameter);
  const PStringArray & path = res->GetURL().GetPath();
  Node * node = root;
  for (PINDEX i = 0; i < path.GetSize(); i++) {
    if (path[i].IsEmpty())
      break;

    if (node->resource != NULL)
      return FALSE;   // Already a resource in tree in partial path

    PINDEX pos = node->children.GetValuesIndex(path[i]);
    if (pos == P_MAX_INDEX)
      pos = node->children.Append(new Node(path[i], node));

    node = &node->children[pos];
  }

  if (!node->children.IsEmpty())
    return FALSE;   // Already a resource in tree further down path.

  if (overwrite == ErrorOnExist && node->resource != NULL)
    return FALSE;   // Already a resource in tree at leaf

  delete node->resource;
  node->resource = res;

  return TRUE;
}


BOOL PHTTPSpace::DelResource(const PURL & url)
{
  const PStringArray & path = url.GetPath();
  Node * node = root;
  for (PINDEX i = 0; i < path.GetSize(); i++) {
    if (path[i].IsEmpty())
      break;

    PINDEX pos = node->children.GetValuesIndex(path[i]);
    if (pos == P_MAX_INDEX)
      return FALSE;

    node = &node->children[pos];

    if (node->resource != NULL)
      return FALSE;
  }

  if (!node->children.IsEmpty())
    return FALSE;   // Still a resource in tree further down path.

  do {
    Node * par = node->parent;
    par->children.Remove(node);
    node = par;
  } while (node != NULL && node->children.IsEmpty());

  return TRUE;
}


static const char * const HTMLIndexFiles[] = {
  "Welcome.html", "welcome.html", "index.html",
  "Welcome.htm",  "welcome.htm",  "index.htm"
};

PHTTPResource * PHTTPSpace::FindResource(const PURL & url)
{
  const PStringArray & path = url.GetPath();

  Node * node = root;
  PINDEX i;
  for (i = 0; i < path.GetSize(); i++) {
    if (path[i].IsEmpty())
      break;

    PINDEX pos = node->children.GetValuesIndex(path[i]);
    if (pos == P_MAX_INDEX)
      return NULL;

    node = &node->children[pos];

    if (node->resource != NULL)
      return node->resource;
  }

  for (i = 0; i < PARRAYSIZE(HTMLIndexFiles); i++) {
    PINDEX pos = node->children.GetValuesIndex(PString(HTMLIndexFiles[i]));
    if (pos != P_MAX_INDEX)
      return node->children[pos].resource;
  }

  return NULL;
}


//////////////////////////////////////////////////////////////////////////////
// PHTTPServer

PHTTPServer::PHTTPServer()
{
  Construct();
}


PHTTPServer::PHTTPServer(const PHTTPSpace & space)
  : urlSpace(space)
{
  Construct();
}


void PHTTPServer::Construct()
{
  transactionCount = 0;
  SetReadLineTimeout(PTimeInterval(0, READLINE_TIMEOUT));
}


BOOL PHTTPServer::ProcessCommand()
{
  PString args;
  PINDEX cmd;

  // if this is not the first command received by this socket, then set
  // the read timeout appropriately.
  if (transactionCount > 0) 
    SetReadTimeout(nextTimeout);

  // this will only return false upon timeout or completely invalid command
  if (!ReadCommand(cmd, args))
    return FALSE;

  connectInfo.commandCode = (Commands)cmd;
  if (cmd < NumCommands)
    connectInfo.commandName = commandNames[cmd];
  else {
    PINDEX spacePos = args.Find(' ');
    connectInfo.commandName = args.Left(spacePos);
    args = args.Mid(spacePos);
  }

  // if no tokens, error
  if (args.IsEmpty()) {
    OnError(BadRequest, args, connectInfo);
    return FALSE;
  }

  if (!connectInfo.Initialise(*this, args))
      return FALSE;

  // now that we've decided we did receive a HTTP request, increment the
  // count of transactions
  transactionCount++;
  nextTimeout.SetInterval(MAX_LIFETIME*1000);

  PIPSocket * socket = GetSocket();
  WORD myPort = (WORD)(socket != NULL ? socket->GetPort() : 80);

  // the URL that comes with Connect requests is not quite kosher, so 
  // mangle it into a proper URL and do NOT close the connection.
  // for all other commands, close the read connection if not persistant
  if (cmd == CONNECT) 
    connectInfo.url = "https://" + args;
  else {
    connectInfo.url = args;
    if (connectInfo.url.GetPort() == 0)
      connectInfo.url.SetPort(myPort);
  }

  BOOL persist;

  // If the incoming URL is of a proxy type then call OnProxy() which will
  // probably just go OnError(). Even if a full URL is provided in the
  // command we should check to see if it is a local server request and process
  // it anyway even though we are not a proxy. The usage of GetHostName()
  // below are to catch every way of specifying the host (name, alias, any of
  // several IP numbers etc).
  const PURL & url = connectInfo.GetURL();
  if (url.GetScheme() != "http" ||
      (url.GetPort() != 0 && url.GetPort() != myPort) ||
      (!url.GetHostName() && !PIPSocket::IsLocalHost(url.GetHostName())))
    persist = OnProxy(connectInfo);
  else {
    PString entityBody = ReadEntityBody();

    // Handle the local request
    PStringToString postData;
    switch (cmd) {
      case GET :
        persist = OnGET(url, connectInfo.GetMIME(), connectInfo);
        break;

      case HEAD :
        persist = OnHEAD(url, connectInfo.GetMIME(), connectInfo);
        break;

      case POST :
        PURL::SplitQueryVars(entityBody, postData);
        persist = OnPOST(url, connectInfo.GetMIME(), postData, connectInfo);
        break;

⌨️ 快捷键说明

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