httpclnt.cxx
上传用户:hzhsqp
上传日期:2007-01-06
资源大小:1600k
文件大小:13k
源码类别:

IP电话/视频会议

开发平台:

Visual C++

  1. /*
  2.  * httpclnt.cxx
  3.  *
  4.  * HTTP Client class.
  5.  *
  6.  * Portable Windows Library
  7.  *
  8.  * Copyright (c) 1993-1998 Equivalence Pty. Ltd.
  9.  *
  10.  * The contents of this file are subject to the Mozilla Public License
  11.  * Version 1.0 (the "License"); you may not use this file except in
  12.  * compliance with the License. You may obtain a copy of the License at
  13.  * http://www.mozilla.org/MPL/
  14.  *
  15.  * Software distributed under the License is distributed on an "AS IS"
  16.  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
  17.  * the License for the specific language governing rights and limitations
  18.  * under the License.
  19.  *
  20.  * The Original Code is Portable Windows Library.
  21.  *
  22.  * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
  23.  *
  24.  * Portions are Copyright (C) 1993 Free Software Foundation, Inc.
  25.  * All Rights Reserved.
  26.  *
  27.  * Contributor(s): ______________________________________.
  28.  *
  29.  * $Log: httpclnt.cxx,v $
  30.  * Revision 1.20  1999/05/13 04:59:24  robertj
  31.  * Increased amount of buffering on output request write.
  32.  *
  33.  * Revision 1.19  1999/05/11 12:23:52  robertj
  34.  * Fixed bug introduced in last revision to have arbitrary HTTP commands, missing CRLF.
  35.  *
  36.  * Revision 1.18  1999/05/04 15:26:01  robertj
  37.  * Improved HTTP/1.1 compatibility (pass through user commands).
  38.  * Fixed problems with quicktime installer.
  39.  *
  40.  * Revision 1.17  1998/11/30 04:51:55  robertj
  41.  * New directory structure
  42.  *
  43.  * Revision 1.16  1998/09/23 06:22:09  robertj
  44.  * Added open source copyright license.
  45.  *
  46.  * Revision 1.15  1998/07/24 06:57:21  robertj
  47.  * Fixed error returned on illegal URL passed to unopened socket.
  48.  * Changed PostData function so just has string for data instead of dictionary.
  49.  *
  50.  * Revision 1.14  1998/06/16 03:32:56  robertj
  51.  * Changed TCP connection shutdown to be parameterised.
  52.  *
  53.  * Revision 1.13  1998/06/13 15:03:58  robertj
  54.  * More conditions for NOT shutting down write.
  55.  *
  56.  * Revision 1.12  1998/06/13 12:28:04  robertj
  57.  * Added shutdown to client command if no content length specified.
  58.  *
  59.  * Revision 1.11  1998/04/14 03:42:41  robertj
  60.  * Fixed error code propagation in HTTP client.
  61.  *
  62.  * Revision 1.10  1998/02/03 06:27:10  robertj
  63.  * Fixed propagation of error codes, especially EOF.
  64.  * Fixed writing to some CGI scripts that require CRLF outside of byte count.
  65.  *
  66.  * Revision 1.9  1998/01/26 00:39:00  robertj
  67.  * Added function to allow HTTPClient to automatically connect if URL has hostname.
  68.  * Fixed incorrect return values on HTTPClient GetDocument(), Post etc functions.
  69.  *
  70.  * Revision 1.8  1997/06/12 12:33:35  robertj
  71.  * Fixed bug where mising MIME fields is regarded as an eror.
  72.  *
  73.  * Revision 1.7  1997/03/31 08:26:58  robertj
  74.  * GNU compiler compatibilty.
  75.  *
  76.  * Revision 1.6  1997/03/28 04:40:46  robertj
  77.  * Fixed bug in Post function doing wrong command.
  78.  *
  79.  * Revision 1.5  1997/03/18 22:04:03  robertj
  80.  * Fix bug for binary POST commands.
  81.  *
  82.  * Revision 1.4  1996/12/21 01:26:21  robertj
  83.  * Fixed bug in persistent connections when server closes socket during command.
  84.  *
  85.  * Revision 1.3  1996/12/12 09:24:44  robertj
  86.  * Persistent connection support.
  87.  *
  88.  * Revision 1.2  1996/10/08 13:12:03  robertj
  89.  * Fixed bug in HTTP/0.9 response, first 5 character not put back properly.
  90.  *
  91.  * Revision 1.1  1996/09/14 13:02:18  robertj
  92.  * Initial revision
  93.  *
  94.  * Revision 1.37  1996/08/25 09:37:41  robertj
  95.  * Added function to detect "local" host name.
  96.  * Fixed printing of trailing '/' in empty URL, is distinction between with and without.
  97.  *
  98.  * Revision 1.36  1996/08/22 13:22:26  robertj
  99.  * Fixed bug in print of URLs, extra @ signs.
  100.  *
  101.  * Revision 1.35  1996/08/19 13:42:40  robertj
  102.  * Fixed errors in URL parsing and display.
  103.  * Fixed "Forbidden" problem out of HTTP authorisation system.
  104.  * Fixed authorisation so if have no user/password on basic authentication, does not require it.
  105.  *
  106.  * Revision 1.34  1996/07/27 04:13:47  robertj
  107.  * Fixed use of HTTP proxy on non-persistent connections.
  108.  *
  109.  * Revision 1.33  1996/07/15 10:37:20  robertj
  110.  * Improved proxy "self" detection (especially localhost).
  111.  *
  112.  * Revision 1.32  1996/06/28 13:20:24  robertj
  113.  * Modified HTTPAuthority so gets PHTTPReqest (mainly for URL) passed in.
  114.  * Moved HTTP form resource to another compilation module.
  115.  * Fixed memory leak in POST command.
  116.  *
  117.  * Revision 1.31  1996/06/10 10:00:00  robertj
  118.  * Added global function for query parameters parsing.
  119.  *
  120.  * Revision 1.30  1996/06/07 13:52:23  robertj
  121.  * Added PUT to HTTP proxy FTP. Necessitating redisign of entity body processing.
  122.  *
  123.  * Revision 1.29  1996/06/05 12:33:04  robertj
  124.  * Fixed bug in parsing URL with no path, is NOT absolute!
  125.  *
  126.  * Revision 1.28  1996/05/30 10:07:26  robertj
  127.  * Fixed bug in version number checking of return code compatibility.
  128.  *
  129.  * Revision 1.27  1996/05/26 03:46:42  robertj
  130.  * Compatibility to GNU 2.7.x
  131.  *
  132.  * Revision 1.26  1996/05/23 10:02:13  robertj
  133.  * Added common function for GET and HEAD commands.
  134.  * Fixed status codes to be the actual status code instead of sequential enum.
  135.  * This fixed some problems with proxy pass through of status codes.
  136.  * Fixed bug in URL parsing of username and passwords.
  137.  *
  138.  * Revision 1.19.1.1  1996/04/17 11:08:22  craigs
  139.  * New version by craig pending confirmation by robert
  140.  *
  141.  * Revision 1.19  1996/04/05 01:46:30  robertj
  142.  * Assured PSocket::Write always writes the number of bytes specified, no longer need write loops.
  143.  * Added workaraound for NT Netscape Navigator bug with persistent connections.
  144.  *
  145.  * Revision 1.18  1996/03/31 09:05:07  robertj
  146.  * HTTP 1.1 upgrade.
  147.  *
  148.  * Revision 1.17  1996/03/17 05:48:07  robertj
  149.  * Fixed host name print out of URLs.
  150.  * Added hit count to PHTTPResource.
  151.  *
  152.  * Revision 1.16  1996/03/16 05:00:26  robertj
  153.  * Added ParseReponse() for splitting reponse line into code and info.
  154.  * Added client side support for HTTP socket.
  155.  * Added hooks for proxy support in HTTP socket.
  156.  * Added translation type to TranslateString() to accommodate query variables.
  157.  * Defaulted scheme field in URL to "http".
  158.  * Inhibited output of port field on string conversion of URL according to scheme.
  159.  *
  160.  * Revision 1.15  1996/03/11 10:29:50  robertj
  161.  * Fixed bug in help image HTML.
  162.  *
  163.  * Revision 1.14  1996/03/10 13:15:24  robertj
  164.  * Redesign to make resources thread safe.
  165.  *
  166.  * Revision 1.13  1996/03/02 03:27:37  robertj
  167.  * Added function to translate a string to a form suitable for inclusion in a URL.
  168.  * Added radio button and selection boxes to HTTP form resource.
  169.  * Fixed bug in URL parsing, losing first / if hostname specified.
  170.  *
  171.  * Revision 1.12  1996/02/25 11:14:24  robertj
  172.  * Radio button support for forms.
  173.  *
  174.  * Revision 1.11  1996/02/25 03:10:34  robertj
  175.  * Removed pass through HTTP resource.
  176.  * Fixed PHTTPConfig resource to use correct name for config key.
  177.  *
  178.  * Revision 1.10  1996/02/19 13:48:28  robertj
  179.  * Put multiple uses of literal strings into const variables.
  180.  * Fixed URL parsing so that the unmangling of strings occurs correctly.
  181.  * Moved nested classes from PHTTPForm.
  182.  * Added overwrite option to AddResource().
  183.  * Added get/set string to PHTTPString resource.
  184.  *
  185.  * Revision 1.9  1996/02/13 13:09:17  robertj
  186.  * Added extra parameters to callback function in PHTTPResources, required
  187.  *   by descendants to make informed decisions on data being loaded.
  188.  *
  189.  * Revision 1.8  1996/02/08 12:26:29  robertj
  190.  * Redesign of resource callback mechanism.
  191.  * Added new resource types for HTML data entry forms.
  192.  *
  193.  * Revision 1.7  1996/02/03 11:33:19  robertj
  194.  * Changed RadCmd() so can distinguish between I/O error and unknown command.
  195.  *
  196.  * Revision 1.6  1996/02/03 11:11:49  robertj
  197.  * Numerous bug fixes.
  198.  * Added expiry date and ismodifiedsince support.
  199.  *
  200.  * Revision 1.5  1996/01/30 23:32:40  robertj
  201.  * Added single .
  202.  *
  203.  * Revision 1.4  1996/01/28 14:19:09  robertj
  204.  * Split HTML into separate source file.
  205.  * Beginning of pass through resource type.
  206.  * Changed PCharArray in OnLoadData to PString for convenience in mangling data.
  207.  * Made PHTTPSpace return standard page on selection of partial path.
  208.  *
  209.  * Revision 1.3  1996/01/28 02:49:16  robertj
  210.  * Further implementation.
  211.  *
  212.  * Revision 1.2  1996/01/26 02:24:30  robertj
  213.  * Further implemetation.
  214.  *
  215.  * Revision 1.1  1996/01/23 13:04:32  robertj
  216.  * Initial revision
  217.  *
  218.  */
  219. #include <ptlib.h>
  220. #include <ptlib/sockets.h>
  221. #include <ptclib/http.h>
  222. #include <ctype.h>
  223. //////////////////////////////////////////////////////////////////////////////
  224. // PHTTPClient
  225. PHTTPClient::PHTTPClient()
  226. {
  227. }
  228. int PHTTPClient::ExecuteCommand(Commands cmd,
  229.                                 const PString & url,
  230.                                 const PMIMEInfo & outMIME,
  231.                                 const PString & dataBody,
  232.                                 PMIMEInfo & replyMime,
  233.                                 BOOL persist)
  234. {
  235.   return ExecuteCommand(commandNames[cmd], url, outMIME, dataBody, replyMime, persist);
  236. }
  237. int PHTTPClient::ExecuteCommand(const PString & cmdName,
  238.                                 const PString & url,
  239.                                 const PMIMEInfo & outMIME,
  240.                                 const PString & dataBody,
  241.                                 PMIMEInfo & replyMime,
  242.                                 BOOL persist)
  243. {
  244.   if (WriteCommand(cmdName, url, outMIME, dataBody)) {
  245.     if (!persist)
  246.       Shutdown(ShutdownWrite);
  247.     ReadResponse(replyMime);
  248.   }
  249.   else {
  250.     lastResponseCode = -1;
  251.     lastResponseInfo = GetErrorText();
  252.   }
  253.   return lastResponseCode;
  254. }
  255. BOOL PHTTPClient::WriteCommand(Commands cmd,
  256.                                const PString & url,
  257.                                const PMIMEInfo & outMIME,
  258.                                const PString & dataBody)
  259. {
  260.   return WriteCommand(commandNames[cmd], url, outMIME, dataBody);
  261. }
  262. BOOL PHTTPClient::WriteCommand(const PString & cmdName,
  263.                                const PString & url,
  264.                                const PMIMEInfo & outMIME,
  265.                                const PString & dataBody)
  266. {
  267.   if (cmdName.IsEmpty())
  268.     *this << "GET";
  269.   else
  270.     *this << cmdName;
  271.   *this << ' ' << url << " HTTP/1.0rn"
  272.         << setfill('r') << outMIME;
  273.   PINDEX len = dataBody.GetSize()-1;
  274.   if (!Write((const char *)dataBody, len))
  275.     return FALSE;
  276.   if (len < 2 || (dataBody[len-2] == 'r' && dataBody[len-1] == 'n'))
  277.     return TRUE;
  278.   return Write("rn", 2);
  279. }
  280. BOOL PHTTPClient::ReadResponse(PMIMEInfo & replyMIME)
  281. {
  282.   BOOL bad = TRUE;
  283.   PString http = ReadString(7);
  284.   if (!http) {
  285.     UnRead(http);
  286.     if (http.Find("HTTP/") == P_MAX_INDEX) {
  287.       lastResponseCode = PHTTP::OK;
  288.       lastResponseInfo = "HTTP/0.9";
  289.       return TRUE;
  290.     }
  291.     if (http[0] == 'n')
  292.       ReadString(1);
  293.     else if (http[0] == 'r' &&  http[1] == 'n')
  294.       ReadString(2);
  295.     if (PHTTP::ReadResponse())
  296.       bad = FALSE;
  297.   }
  298.   if (bad) {
  299.     lastResponseCode = -1;
  300.     lastResponseInfo = GetErrorText();
  301.     if (lastResponseInfo.IsEmpty())
  302.       lastResponseInfo = "Remote shutdown";
  303.     return FALSE;
  304.   }
  305.   if (replyMIME.Read(*this))
  306.     return TRUE;
  307.   return lastError == NoError;
  308. }
  309. BOOL PHTTPClient::GetDocument(const PURL & url,
  310.                               PMIMEInfo & outMIME,
  311.                               PMIMEInfo & replyMIME,
  312.                               BOOL persist)
  313. {
  314.   if (!AssureConnect(url, outMIME))
  315.     return FALSE;
  316.   return ExecuteCommand(GET, url.AsString(PURL::URIOnly), outMIME, PString(), replyMIME, persist) == OK;
  317. }
  318. BOOL PHTTPClient::GetHeader(const PURL & url,
  319.                             PMIMEInfo & outMIME,
  320.                             PMIMEInfo & replyMIME,
  321.                             BOOL persist)
  322. {
  323.   if (!AssureConnect(url, outMIME))
  324.     return FALSE;
  325.   return ExecuteCommand(HEAD, url.AsString(PURL::URIOnly), outMIME, PString(), replyMIME, persist) == OK;
  326. }
  327. BOOL PHTTPClient::PostData(const PURL & url,
  328.                            PMIMEInfo & outMIME,
  329.                            const PString & data,
  330.                            PMIMEInfo & replyMIME,
  331.                            BOOL persist)
  332. {
  333.   if (!AssureConnect(url, outMIME))
  334.     return FALSE;
  335.   return ExecuteCommand(POST, url.AsString(PURL::URIOnly), outMIME, data, replyMIME, persist) == OK;
  336. }
  337. BOOL PHTTPClient::AssureConnect(const PURL & url, PMIMEInfo & outMIME)
  338. {
  339.   PString host = url.GetHostName();
  340.   if (!IsOpen()) {
  341.     if (host.IsEmpty()) {
  342.       lastResponseCode = BadRequest;
  343.       lastResponseInfo = "No host specified";
  344.       return FALSE;
  345.     }
  346.     if (!Connect(host, url.GetPort())) {
  347.       lastResponseCode = -2;
  348.       lastResponseInfo = GetErrorText();
  349.       return FALSE;
  350.     }
  351.   }
  352.   static char HostTag[] = "Host";
  353.   if (!outMIME.Contains(HostTag)) {
  354.     if (!host)
  355.       outMIME.SetAt(HostTag, host);
  356.     else {
  357.       PIPSocket * sock = GetSocket();
  358.       if (sock != NULL)
  359.         outMIME.SetAt(HostTag, sock->GetHostName());
  360.     }
  361.   }
  362.   return TRUE;
  363. }
  364. // End Of File ///////////////////////////////////////////////////////////////