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

📄 httpsrvr.cxx

📁 sloedgy open sip stack source code
💻 CXX
📖 第 1 页 / 共 4 页
字号:
/*
 * httpsrvr.cxx
 *
 * HTTP server classes.
 *
 * Portable Windows Library
 *
 * Copyright (c) 1993-2002 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.
 *
 * Contributor(s): ______________________________________.
 *
 * $Log: httpsrvr.cxx,v $
 * Revision 1.1  2006/06/29 04:18:02  joegenbaclor
 * *** empty log message ***
 *
 * Revision 1.49  2005/11/30 12:47:41  csoutheren
 * Removed tabs, reformatted some code, and changed tags for Doxygen
 *
 * Revision 1.48  2005/01/15 07:53:55  csoutheren
 * Fixed problem when disabling http
 *
 * Revision 1.47  2004/02/03 09:37:20  rjongbloed
 * Added check to text files via the type extension, thanks David Parr
 *
 * Revision 1.46  2003/03/19 01:55:26  robertj
 * Fixed bugs in deleteing HTTP resources from server, thanks Diego T醨tara
 *
 * Revision 1.45  2002/11/06 22:47:25  robertj
 * Fixed header comment (copyright etc)
 *
 * Revision 1.44  2002/10/10 04:43:44  robertj
 * VxWorks port, thanks Martijn Roest
 *
 * Revision 1.43  2002/10/02 08:54:01  craigs
 * Added support for XMLRPC server
 *
 * Revision 1.42  2002/08/27 23:49:08  robertj
 * Fixed security hole where possible to get any file on disk when using
 *   PHTTPDirectory HTTP resource.
 *
 * Revision 1.41  2002/07/17 08:43:52  robertj
 * Fixed closing of html msg on generated post output.
 *
 * Revision 1.40  2002/05/08 05:38:54  robertj
 * Added PHTTPTailFile resource to do a unix 'tail -f' of a file.
 *
 * Revision 1.39  2002/04/12 08:15:23  robertj
 * Fixed warning on older GNU compilers, also guarantees numeric output.
 *
 * Revision 1.38  2001/10/31 01:37:13  robertj
 * Fixed deleting of object added to http name space if add fails.
 * Changes to support HTTP v1.1 chunked transfer encoding.
 *
 * Revision 1.37  2001/09/28 00:45:27  robertj
 * Removed HasKey() as is confusing due to ancestor Contains().
 *
 * Revision 1.36  2001/06/01 07:28:23  craigs
 * Added handling for binary data in multi-part MIME fields
 *
 * Revision 1.35  2001/03/14 01:49:54  craigs
 * Added ability to handle multi-part form POST commands
 *
 * Revision 1.34  2001/01/15 06:17:56  robertj
 * Set HTTP resource members to private to assure are not modified by
 *   dscendents in non-threadsafe manner.
 *
 * Revision 1.33  2000/09/04 03:57:58  robertj
 * Added ability to change the persistent connection parameters (timeout etc).
 *
 * Revision 1.32  2000/05/02 07:55:22  craigs
 * Changed static PString to static const char * to avoid "memory leak"
 *
 * 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>

#ifdef P_HTTP

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

#define new PNEW


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

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

#define DEFAULT_PERSIST_TIMEOUT 30
#define DEFAULT_PERSIST_TRANSATIONS 10

//  filename to use for directory access directives
static const char * 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) {
      delete res;
      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()) {
    delete res;
    return FALSE;   // Already a resource in tree further down path.
  }

  if (overwrite == ErrorOnExist && node->resource != NULL) {
    delete res;
    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 have resource and not last node, then trying to remove something
    // further down the tree than a leaf node.
    if (node->resource != NULL && i < (path.GetSize()-1))
      return FALSE;
  }

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

  if (node->parent != NULL) {
    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));
}

void PHTTPConnectionInfo::DecodeMultipartFormInfo(const PString & type, const PString & entityBody)
{
  // remove trailing ","
  PINDEX pos = type.Find(",");
  if (pos == P_MAX_INDEX) {
    pos = type.Find(";");
    if (pos == P_MAX_INDEX) 
      return;
  }
  PString seperator = type.Mid(pos+1).Trim();

  // remove "boundary"
  pos = seperator.Find("boundary");
  if (pos == P_MAX_INDEX)
    return;
  seperator = seperator.Mid(8).Trim();

  // remove "="
  pos = seperator.Find("=");
  if (pos == P_MAX_INDEX)
    return;
  seperator = seperator.Mid(1).Trim();

  // seperators have a "--" according to RFC 1521
  seperator = PString("--") + seperator;

  PINDEX sepLen = seperator.GetLength();
  const char * sep = (const char *)seperator;

  // split body into parts, assuming binary data
  const char * body = (const char *)entityBody;
  PINDEX entityOffs = 0;
  PINDEX entityLen = entityBody.GetSize()-1;

  BOOL ignore = TRUE;
  BOOL last = FALSE;

  PMultipartFormInfo * info = NULL;

  while (!last && (entityOffs < entityLen)) {

    // find end of part
    PINDEX partStart = entityOffs;
    PINDEX partLen;
    BOOL foundSep = FALSE;

    // collect length of part until seperator
    for (partLen = 0; (partStart + partLen) < entityLen; partLen++) {
      if ((partLen >= sepLen) && (memcmp(body + partStart + partLen - sepLen, sep, sepLen) == 0)) {
        foundSep = TRUE;
        break;
      }
    }

    // move entity ptr to the end of the part
    entityOffs = partStart + partLen;

    // if no seperator found, then this is the last part
    // otherwise, look for "--" trailer on seperator and remove CRLF
    if (!foundSep)
      last = TRUE;
    else {
      partLen -= sepLen;

      // determine if this is the last block
      if (((entityOffs + 2) <= entityLen) && (body[entityOffs] == '-') && (body[entityOffs+1] == '-')) {
        last = TRUE;
        entityOffs += 2;
      }

      // remove crlf
      if (((entityOffs + 2) <= entityLen) && (body[entityOffs] == '\r') && (body[entityOffs+1] == '\n')) 
        entityOffs += 2;
    }

    // ignore everything up to the first seperator, 
    // then adjust seperator to include leading CRLF
    if (ignore) {
      ignore = FALSE;
      seperator = PString("\r\n") + seperator;
      sepLen = seperator.GetLength();
      sep = (const char *)seperator;
      continue;
    }

    // extract the MIME header, by looking for a double CRLF
    PINDEX ptr;
    PINDEX nlCount = 0;
    for (ptr = partStart;(ptr < (partStart + partLen)) && (nlCount < 2); ptr++) {
      if (body[ptr] == '\r') {
        nlCount++;
        if ((ptr < entityLen-1) && (body[ptr+1] == '\n'))
          ptr++;
      } else
        nlCount = 0;
    }

    // create the new part info
    info = new PMultipartFormInfo;

    // read MIME information
    PStringStream strm(PString(body + partStart, ptr - partStart));
    info->mime.ReadFrom(strm);

    // save the entity body, being careful of binary files
    int savedLen = partStart + partLen - ptr;
    char * saved = info->body.GetPointer(savedLen + 1);
    memcpy(saved, body + ptr, savedLen);
    saved[savedLen] = '\0';

    // add the data to the array
    multipartFormInfoArray.Append(info);
    info = NULL;
  }
  
#if 0
  // ignore until first separator
  do {
    data >> line;
    if (line.IsEmpty())
      return;
  } while (line.Find(sep) != 0);

⌨️ 快捷键说明

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