add get_file_size()

This commit is contained in:
David Rose 2002-10-03 03:02:52 +00:00
parent 66f53d3764
commit 26961c650f
13 changed files with 254 additions and 98 deletions

View File

@ -32,8 +32,9 @@ IChunkedStream() : istream(&_buf) {
// Description: // Description:
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE IChunkedStream:: INLINE IChunkedStream::
IChunkedStream(istream *source, bool owns_source) : istream(&_buf) { IChunkedStream(istream *source, bool owns_source,
open(source, owns_source); HTTPDocument *doc) : istream(&_buf) {
open(source, owns_source, doc);
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -42,9 +43,9 @@ IChunkedStream(istream *source, bool owns_source) : istream(&_buf) {
// Description: // Description:
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE IChunkedStream &IChunkedStream:: INLINE IChunkedStream &IChunkedStream::
open(istream *source, bool owns_source) { open(istream *source, bool owns_source, HTTPDocument *doc) {
clear(0); clear(0);
_buf.open_read(source, owns_source); _buf.open_read(source, owns_source, doc);
return *this; return *this;
} }

View File

@ -23,6 +23,8 @@
#include "chunkedStreamBuf.h" #include "chunkedStreamBuf.h"
class HTTPDocument;
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Class : IChunkedStream // Class : IChunkedStream
// Description : An input stream object that reads data from a source // Description : An input stream object that reads data from a source
@ -34,9 +36,11 @@
class EXPCL_PANDAEXPRESS IChunkedStream : public istream { class EXPCL_PANDAEXPRESS IChunkedStream : public istream {
public: public:
INLINE IChunkedStream(); INLINE IChunkedStream();
INLINE IChunkedStream(istream *source, bool owns_source); INLINE IChunkedStream(istream *source, bool owns_source,
HTTPDocument *doc = NULL);
INLINE IChunkedStream &open(istream *source, bool owns_source); INLINE IChunkedStream &open(istream *source, bool owns_source,
HTTPDocument *doc = NULL);
INLINE IChunkedStream &close(); INLINE IChunkedStream &close();
private: private:

View File

@ -64,14 +64,26 @@ ChunkedStreamBuf::
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: ChunkedStreamBuf::open_read // Function: ChunkedStreamBuf::open_read
// Access: Public // Access: Public
// Description: // Description: If the document pointer is non-NULL, it will be
// updated with the length of the file as it is derived
// from the chunked encoding.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
void ChunkedStreamBuf:: void ChunkedStreamBuf::
open_read(istream *source, bool owns_source) { open_read(istream *source, bool owns_source, HTTPDocument *doc) {
_source = source; _source = source;
_owns_source = owns_source; _owns_source = owns_source;
_chunk_remaining = 0; _chunk_remaining = 0;
_done = false; _done = false;
_doc = doc;
if (_doc != (HTTPDocument *)NULL) {
_doc->_file_size = 0;
// Read a little bit from the file to get the first chunk (and
// therefore the file size, or at least the size of the first
// chunk).
underflow();
}
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -157,6 +169,10 @@ read_chars(char *start, size_t length) {
return 0; return 0;
} }
if (_doc != (HTTPDocument *)NULL) {
_doc->_file_size += (size_t)chunk_size;
}
_chunk_remaining = (size_t)chunk_size; _chunk_remaining = (size_t)chunk_size;
return read_chars(start, length); return read_chars(start, length);
} }

View File

@ -20,6 +20,8 @@
#define CHUNKEDSTREAMBUF_H #define CHUNKEDSTREAMBUF_H
#include "pandabase.h" #include "pandabase.h"
#include "httpDocument.h"
#include "pointerTo.h"
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Class : ChunkedStreamBuf // Class : ChunkedStreamBuf
@ -31,7 +33,7 @@ public:
ChunkedStreamBuf(); ChunkedStreamBuf();
virtual ~ChunkedStreamBuf(); virtual ~ChunkedStreamBuf();
void open_read(istream *source, bool owns_source); void open_read(istream *source, bool owns_source, HTTPDocument *doc);
void close_read(); void close_read();
protected: protected:
@ -44,6 +46,8 @@ private:
bool _owns_source; bool _owns_source;
size_t _chunk_remaining; size_t _chunk_remaining;
bool _done; bool _done;
PT(HTTPDocument) _doc;
}; };
#endif #endif

View File

@ -803,7 +803,7 @@ read(istream &read_stream, bool want_server_info) {
uchar *header_buf = new uchar[_header_length]; uchar *header_buf = new uchar[_header_length];
// Read the header // Read the header
read_stream.read((char *)header_buf, _header_length); read_stream.read((char *)header_buf, _header_length);
if (read_stream.gcount() != _header_length) { if (read_stream.gcount() != (size_t)_header_length) {
downloader_cat.error() << "DownloadDb::read() - Empty file" << endl; downloader_cat.error() << "DownloadDb::read() - Empty file" << endl;
return false; return false;
} }

View File

@ -16,16 +16,16 @@
// //
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
#include "config_downloader.h"
#include <error_utils.h> #include "downloader.h"
#include <filename.h> #include "config_downloader.h"
#include "urlSpec.h"
#include "error_utils.h"
#include "filename.h"
#include <errno.h> #include <errno.h>
#include <math.h> #include <math.h>
#include "downloader.h"
#if !defined(WIN32_VC) #if !defined(WIN32_VC)
#include <sys/time.h> #include <sys/time.h>
#include <netinet/in.h> #include <netinet/in.h>
@ -92,12 +92,11 @@ Downloader::
// Description: // Description:
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
int Downloader:: int Downloader::
connect_to_server_by_proxy(const string &proxy_name, uint proxy_port, connect_to_server_by_proxy(const URLSpec &proxy, const string &server_name) {
const string &server_name) { if (connect_to_server(proxy.get_server(), proxy.get_port()) != EU_success) {
if (connect_to_server(proxy_name, proxy_port) != EU_success) {
downloader_cat.error() downloader_cat.error()
<< "Downloader::connect_to_server_by_proxy() - could not connect to: " << "Downloader::connect_to_server_by_proxy() - could not connect to: "
<< proxy_name << endl; << proxy << endl;
return EU_error_abort; return EU_error_abort;
} }
@ -544,7 +543,7 @@ run(void) {
} }
// Attempt to receive the bytes from the socket // Attempt to receive the bytes from the socket
int fret; int fret = 0;
// Handle the case of a fast connection // Handle the case of a fast connection
if (_receive_size > (ulong)MAX_RECEIVE_BYTES) { if (_receive_size > (ulong)MAX_RECEIVE_BYTES) {
int repeat = (int)(_receive_size / MAX_RECEIVE_BYTES); int repeat = (int)(_receive_size / MAX_RECEIVE_BYTES);
@ -667,7 +666,7 @@ run_to_ram(void) {
} }
// Attempt to receive the bytes from the socket // Attempt to receive the bytes from the socket
int fret; int fret = 0;
// Handle the case of a fast connection // Handle the case of a fast connection
if (_receive_size > (ulong)MAX_RECEIVE_BYTES) { if (_receive_size > (ulong)MAX_RECEIVE_BYTES) {
int repeat = (int)(_receive_size / MAX_RECEIVE_BYTES); int repeat = (int)(_receive_size / MAX_RECEIVE_BYTES);

View File

@ -37,6 +37,8 @@
#include <resolv.h> #include <resolv.h>
#endif #endif
class URLSpec;
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Class : Downloader // Class : Downloader
// Description : // Description :
@ -46,8 +48,7 @@ PUBLISHED:
Downloader(void); Downloader(void);
virtual ~Downloader(void); virtual ~Downloader(void);
int connect_to_server_by_proxy(const string &proxy_name, uint proxy_port, int connect_to_server_by_proxy(const URLSpec &proxy, const string &server_name);
const string &server_name);
int connect_to_server(const string &name, uint port=80); int connect_to_server(const string &name, uint port=80);
void disconnect_from_server(void); void disconnect_from_server(void);

View File

@ -39,6 +39,30 @@ get_proxy() const {
return _proxy; return _proxy;
} }
////////////////////////////////////////////////////////////////////
// Function: HTTPClient::set_http_version
// Access: Published
// Description: Specifies the version of HTTP that the client uses to
// identify itself to the server. The default is HV_11,
// or HTTP 1.0; you can set this to HV_10 (HTTP 1.0) to
// request the server use the older interface.
////////////////////////////////////////////////////////////////////
INLINE void HTTPClient::
set_http_version(HTTPClient::HTTPVersion version) {
_http_version = version;
}
////////////////////////////////////////////////////////////////////
// Function: HTTPClient::get_http_version
// Access: Published
// Description: Returns the client's current setting for HTTP
// version. See set_http_version().
////////////////////////////////////////////////////////////////////
INLINE HTTPClient::HTTPVersion HTTPClient::
get_http_version() const {
return _http_version;
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: HTTPClient::set_verify_ssl // Function: HTTPClient::set_verify_ssl
// Access: Published // Access: Published
@ -68,3 +92,37 @@ INLINE bool HTTPClient::
get_verify_ssl() const { get_verify_ssl() const {
return _verify_ssl; return _verify_ssl;
} }
////////////////////////////////////////////////////////////////////
// Function: HTTPClient::get_document
// Access: Published
// Description: Opens the named document for reading, or if body is
// nonempty, posts data for a particular URL and
// retrieves the response. Returns a new HTTPDocument
// object whether the document is successfully read or
// not; you can test is_valid() and get_return_code() to
// determine whether the document was retrieved.
////////////////////////////////////////////////////////////////////
INLINE PT(HTTPDocument) HTTPClient::
get_document(const URLSpec &url, const string &body) {
const char *method = "GET";
if (!body.empty()) {
method = "POST";
}
return make_request(method, url, body);
}
////////////////////////////////////////////////////////////////////
// Function: HTTPClient::get_header
// Access: Published
// Description: Like get_document(), except only the header
// associated with the file is retrieved. This may be
// used to test for existence of the file; it might also
// return the size of the file (if the server gives us
// this information).
////////////////////////////////////////////////////////////////////
INLINE PT(HTTPDocument) HTTPClient::
get_header(const URLSpec &url) {
return make_request("HEAD", url, string());
}

View File

@ -43,6 +43,7 @@ X509_STORE *HTTPClient::_x509_store = NULL;
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
HTTPClient:: HTTPClient::
HTTPClient() { HTTPClient() {
_http_version = HV_11;
_verify_ssl = verify_ssl; _verify_ssl = verify_ssl;
make_ctx(); make_ctx();
} }
@ -54,6 +55,9 @@ HTTPClient() {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
HTTPClient:: HTTPClient::
HTTPClient(const HTTPClient &copy) { HTTPClient(const HTTPClient &copy) {
// We can initialize these to default values because the operator =
// function will copy them in a second.
_http_version = HV_11;
_verify_ssl = verify_ssl; _verify_ssl = verify_ssl;
make_ctx(); make_ctx();
@ -68,6 +72,7 @@ HTTPClient(const HTTPClient &copy) {
void HTTPClient:: void HTTPClient::
operator = (const HTTPClient &copy) { operator = (const HTTPClient &copy) {
_proxy = copy._proxy; _proxy = copy._proxy;
_http_version = copy._http_version;
set_verify_ssl(copy._verify_ssl); set_verify_ssl(copy._verify_ssl);
clear_expected_servers(); clear_expected_servers();
@ -99,6 +104,25 @@ HTTPClient::
clear_expected_servers(); clear_expected_servers();
} }
////////////////////////////////////////////////////////////////////
// Function: HTTPClient::get_http_version_string
// Access: Published
// Description: Returns the current HTTP version setting as a string,
// e.g. "HTTP/1.0" or "HTTP/1.1".
////////////////////////////////////////////////////////////////////
string HTTPClient::
get_http_version_string() const {
switch (_http_version) {
case HV_10:
return "HTTP/1.0";
case HV_11:
return "HTTP/1.1";
}
return "unknown";
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: HTTPClient::load_certificates // Function: HTTPClient::load_certificates
// Access: Published // Access: Published
@ -183,36 +207,6 @@ clear_expected_servers() {
_expected_servers.clear(); _expected_servers.clear();
} }
////////////////////////////////////////////////////////////////////
// Function: HTTPClient::get_document
// Access: Published
// Description: Opens the named document for reading, or if body is
// nonempty, posts data for a particular URL and
// retrieves the response. Returns a new HTTPDocument
// object whether the document is successfully read or
// not; you can test is_valid() and get_return_code() to
// determine whether the document was retrieved.
////////////////////////////////////////////////////////////////////
PT(HTTPDocument) HTTPClient::
get_document(const URLSpec &url, const string &body) {
BIO *bio;
if (_proxy.empty()) {
if (url.get_scheme() == "https") {
bio = get_https(url, body);
} else {
bio = get_http(url, body);
}
} else {
if (url.get_scheme() == "https") {
bio = get_https_proxy(url, body);
} else {
bio = get_http_proxy(url, body);
}
}
return new HTTPDocument(bio, true);
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: HTTPClient::make_ctx // Function: HTTPClient::make_ctx
@ -379,6 +373,36 @@ load_verify_locations(SSL_CTX *ctx, const Filename &ca_file) {
return count; return count;
} }
////////////////////////////////////////////////////////////////////
// Function: HTTPClient::make_request
// Access: Private
// Description: Chooses a suitable mechanism to handle this request,
// based on whether it is an http or https request, and
// according to whether we have a proxy in place.
// Issues the request and returns an HTTPDocument that
// represents the results.
////////////////////////////////////////////////////////////////////
PT(HTTPDocument) HTTPClient::
make_request(const string &method, const URLSpec &url, const string &body) {
BIO *bio;
if (_proxy.empty()) {
if (url.get_scheme() == "https") {
bio = get_https(method, url, body);
} else {
bio = get_http(method, url, body);
}
} else {
if (url.get_scheme() == "https") {
bio = get_https_proxy(method, url, body);
} else {
bio = get_http_proxy(method, url, body);
}
}
return new HTTPDocument(bio, true);
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: HTTPClient::get_https // Function: HTTPClient::get_https
// Access: Private // Access: Private
@ -386,7 +410,7 @@ load_verify_locations(SSL_CTX *ctx, const Filename &ca_file) {
// document. // document.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
BIO *HTTPClient:: BIO *HTTPClient::
get_http(const URLSpec &url, const string &body) { get_http(const string &method, const URLSpec &url, const string &body) {
ostringstream server; ostringstream server;
server << url.get_server() << ":" << url.get_port(); server << url.get_server() << ":" << url.get_port();
string server_str = server.str(); string server_str = server.str();
@ -405,7 +429,7 @@ get_http(const URLSpec &url, const string &body) {
return NULL; return NULL;
} }
send_get_request(bio, url.get_path(), url.get_server(), body); send_request(bio, method, url.get_path(), url.get_server(), body);
return bio; return bio;
} }
@ -416,7 +440,7 @@ get_http(const URLSpec &url, const string &body) {
// document. // document.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
BIO *HTTPClient:: BIO *HTTPClient::
get_https(const URLSpec &url, const string &body) { get_https(const string &method, const URLSpec &url, const string &body) {
ostringstream server; ostringstream server;
server << url.get_server() << ":" << url.get_port(); server << url.get_server() << ":" << url.get_port();
string server_str = server.str(); string server_str = server.str();
@ -438,7 +462,7 @@ get_https(const URLSpec &url, const string &body) {
BIO *sbio = make_https_connection(bio, url); BIO *sbio = make_https_connection(bio, url);
if (sbio != (BIO *)NULL) { if (sbio != (BIO *)NULL) {
send_get_request(sbio, url.get_path(), url.get_server(), body); send_request(sbio, method, url.get_path(), url.get_server(), body);
} }
return sbio; return sbio;
} }
@ -450,7 +474,7 @@ get_https(const URLSpec &url, const string &body) {
// http document. // http document.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
BIO *HTTPClient:: BIO *HTTPClient::
get_http_proxy(const URLSpec &url, const string &body) { get_http_proxy(const string &method, const URLSpec &url, const string &body) {
ostringstream proxy_server; ostringstream proxy_server;
proxy_server << _proxy.get_server() << ":" << _proxy.get_port(); proxy_server << _proxy.get_server() << ":" << _proxy.get_port();
string proxy_server_str = proxy_server.str(); string proxy_server_str = proxy_server.str();
@ -470,7 +494,7 @@ get_http_proxy(const URLSpec &url, const string &body) {
return NULL; return NULL;
} }
send_get_request(bio, url, url.get_server(), body); send_request(bio, method, url, url.get_server(), body);
return bio; return bio;
} }
@ -481,7 +505,7 @@ get_http_proxy(const URLSpec &url, const string &body) {
// document. // document.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
BIO *HTTPClient:: BIO *HTTPClient::
get_https_proxy(const URLSpec &url, const string &body) { get_https_proxy(const string &method, const URLSpec &url, const string &body) {
// First, ask the proxy to open a connection for us. // First, ask the proxy to open a connection for us.
ostringstream proxy_server; ostringstream proxy_server;
proxy_server << _proxy.get_server() << ":" << _proxy.get_port(); proxy_server << _proxy.get_server() << ":" << _proxy.get_port();
@ -505,7 +529,7 @@ get_https_proxy(const URLSpec &url, const string &body) {
{ {
ostringstream request; ostringstream request;
request request
<< "CONNECT " << url.get_authority() << " HTTP/1.1\r\n" << "CONNECT " << url.get_authority() << " " << get_http_version_string()
<< "\r\n"; << "\r\n";
string request_str = request.str(); string request_str = request.str();
@ -540,7 +564,7 @@ get_https_proxy(const URLSpec &url, const string &body) {
// us.) // us.)
if ((doc->get_status_code() / 100) == 4) { if ((doc->get_status_code() / 100) == 4) {
BIO_free_all(bio); BIO_free_all(bio);
return get_http_proxy(url, body); return get_http_proxy(method, url, body);
} }
} }
return NULL; return NULL;
@ -557,7 +581,7 @@ get_https_proxy(const URLSpec &url, const string &body) {
BIO *sbio = make_https_connection(bio, url); BIO *sbio = make_https_connection(bio, url);
if (sbio != (BIO *)NULL) { if (sbio != (BIO *)NULL) {
send_get_request(sbio, url.get_path(), url.get_server(), body); send_request(sbio, method, url.get_path(), url.get_server(), body);
} }
return sbio; return sbio;
} }
@ -630,7 +654,7 @@ make_https_connection(BIO *bio, const URLSpec &url) const {
downloader_cat.info() downloader_cat.info()
<< "Server is " << common_name << " from " << org_unit_name << "Server is " << common_name << " from " << org_unit_name
<< " of " << org_name << "\n"; << " / " << org_name << "\n";
if (!verify_server(subject)) { if (!verify_server(subject)) {
downloader_cat.info() downloader_cat.info()
@ -824,34 +848,30 @@ certificate signing
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: HTTPClient::send_get_request // Function: HTTPClient::send_request
// Access: Private // Access: Private
// Description: Sends the appropriate GET or POST request to the // Description: Sends the appropriate GET or POST (or whatever)
// server on the indicated connection. // request to the server on the indicated connection.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
void HTTPClient:: void HTTPClient::
send_get_request(BIO *bio, send_request(BIO *bio, const string &method,
const string &path, const string &server, const string &path, const string &server,
const string &body) const { const string &body) const {
ostringstream request; ostringstream request;
if (body.empty()) { request
<< method << " " << path << " " << get_http_version_string() << "\r\n";
if (_http_version > HV_10) {
request request
<< "GET " << path << " HTTP/1.1\r\n"
<< "Host: " << server << "\r\n" << "Host: " << server << "\r\n"
<< "Connection: close\r\n" << "Connection: close\r\n";
<< "\r\n";
} else {
request
<< "POST " << path << " HTTP/1.1\r\n"
<< "Host: " << server << "\r\n"
<< "Connection: close\r\n"
<< "Content-type: application/x-www-form-urlencoded\r\n"
<< "Content-Length: " << body.length() << "\r\n"
<< "\r\n"
<< body;
} }
request
<< "\r\n"
<< body;
string request_str = request.str(); string request_str = request.str();
#ifndef NDEBUG #ifndef NDEBUG
if (downloader_cat.is_debug()) { if (downloader_cat.is_debug()) {

View File

@ -60,6 +60,15 @@ PUBLISHED:
INLINE void set_proxy(const URLSpec &proxy); INLINE void set_proxy(const URLSpec &proxy);
INLINE const URLSpec &get_proxy() const; INLINE const URLSpec &get_proxy() const;
enum HTTPVersion {
HV_10, // HTTP 1.0
HV_11, // HTTP 1.1
};
INLINE void set_http_version(HTTPVersion version);
INLINE HTTPVersion get_http_version() const;
string get_http_version_string() const;
bool load_certificates(const Filename &filename); bool load_certificates(const Filename &filename);
INLINE void set_verify_ssl(bool verify_ssl); INLINE void set_verify_ssl(bool verify_ssl);
@ -68,22 +77,27 @@ PUBLISHED:
bool add_expected_server(const string &server_attributes); bool add_expected_server(const string &server_attributes);
void clear_expected_servers(); void clear_expected_servers();
PT(HTTPDocument) get_document(const URLSpec &url, const string &body = string()); INLINE PT(HTTPDocument) get_document(const URLSpec &url,
const string &body = string());
INLINE PT(HTTPDocument) get_header(const URLSpec &url);
private: private:
void make_ctx(); void make_ctx();
static void initialize_ssl(); static void initialize_ssl();
static int load_verify_locations(SSL_CTX *ctx, const Filename &ca_file); static int load_verify_locations(SSL_CTX *ctx, const Filename &ca_file);
BIO *get_http(const URLSpec &url, const string &body); PT(HTTPDocument) make_request(const string &method, const URLSpec &url,
BIO *get_https(const URLSpec &url, const string &body); const string &body);
BIO *get_http_proxy(const URLSpec &url, const string &body);
BIO *get_https_proxy(const URLSpec &url, const string &body); BIO *get_http(const string &method, const URLSpec &url, const string &body);
BIO *get_https(const string &method, const URLSpec &url, const string &body);
BIO *get_http_proxy(const string &method, const URLSpec &url, const string &body);
BIO *get_https_proxy(const string &method, const URLSpec &url, const string &body);
BIO *make_https_connection(BIO *bio, const URLSpec &url) const; BIO *make_https_connection(BIO *bio, const URLSpec &url) const;
void send_get_request(BIO *bio, void send_request(BIO *bio, const string &method,
const string &path, const string &server, const string &path, const string &server,
const string &body) const; const string &body) const;
bool verify_server(X509_NAME *subject) const; bool verify_server(X509_NAME *subject) const;
static X509_NAME *parse_x509_name(const string &source); static X509_NAME *parse_x509_name(const string &source);
@ -101,6 +115,7 @@ private:
#endif #endif
URLSpec _proxy; URLSpec _proxy;
HTTPVersion _http_version;
bool _verify_ssl; bool _verify_ssl;
// List of allowable SSL servers to connect to. If the list is // List of allowable SSL servers to connect to. If the list is

View File

@ -64,3 +64,17 @@ INLINE const string &HTTPDocument::
get_status_string() const { get_status_string() const {
return _status_string; return _status_string;
} }
////////////////////////////////////////////////////////////////////
// Function: HTTPDocument::get_file_size
// Access: Published
// Description: Returns the size of the file, if it is known.
// Returns 0 if the file size is not known. This may
// increase as the file is read due to the nature of
// HTTP/1.1 requests which can change their minds
// midstream about how much data they're sending you.
////////////////////////////////////////////////////////////////////
INLINE size_t HTTPDocument::
get_file_size() const {
return _file_size;
}

View File

@ -31,9 +31,12 @@ TypeHandle HTTPDocument::_type_handle;
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
HTTPDocument:: HTTPDocument::
HTTPDocument(BIO *bio, bool owns_bio) { HTTPDocument(BIO *bio, bool owns_bio) {
_file_size = 0;
if (bio != (BIO *)NULL) { if (bio != (BIO *)NULL) {
_source = new IBioStream(bio, owns_bio); _source = new IBioStream(bio, owns_bio);
read_headers(); read_headers();
determine_content_length();
} else { } else {
_source = (IBioStream *)NULL; _source = (IBioStream *)NULL;
@ -94,7 +97,8 @@ is_regular_file() const {
// Description: Opens the document for reading. Returns a newly // Description: Opens the document for reading. Returns a newly
// allocated istream on success (which you should // allocated istream on success (which you should
// eventually delete when you are done reading). // eventually delete when you are done reading).
// Returns NULL on failure. // Returns NULL on failure. This may only be called
// once for a particular HTTPDocument.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
istream *HTTPDocument:: istream *HTTPDocument::
open_read_file() const { open_read_file() const {
@ -109,14 +113,13 @@ open_read_file() const {
(*si) = tolower(*si); (*si) = tolower(*si);
} }
istream *result = _source;
if (transfer_coding == "chunked") { if (transfer_coding == "chunked") {
return new IChunkedStream(_source, false); result = new IChunkedStream(_source, true, (HTTPDocument *)this);
} else {
istream *result = _source;
((HTTPDocument *)this)->_source = (IBioStream *)NULL;
return result;
} }
((HTTPDocument *)this)->_source = (IBioStream *)NULL;
return result;
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -256,4 +259,19 @@ read_headers() {
// A blank line terminates the headers. // A blank line terminates the headers.
} }
////////////////////////////////////////////////////////////////////
// Function: HTTPDocument::determine_content_length
// Access: Private
// Description: Determines the file size based on the Content-Length
// field if it has been supplied.
////////////////////////////////////////////////////////////////////
void HTTPDocument::
determine_content_length() {
string content_length = get_header_value("Content-Length");
if (!content_length.empty()) {
_file_size = atoi(content_length.c_str());
}
}
#endif // HAVE_SSL #endif // HAVE_SSL

View File

@ -57,10 +57,13 @@ PUBLISHED:
INLINE const string &get_status_string() const; INLINE const string &get_status_string() const;
string get_header_value(const string &key) const; string get_header_value(const string &key) const;
INLINE size_t get_file_size() const;
void write_headers(ostream &out) const; void write_headers(ostream &out) const;
private: private:
void read_headers(); void read_headers();
void determine_content_length();
IBioStream *_source; IBioStream *_source;
@ -71,6 +74,8 @@ private:
typedef pmap<string, string> Headers; typedef pmap<string, string> Headers;
Headers _headers; Headers _headers;
size_t _file_size;
public: public:
virtual TypeHandle get_type() const { virtual TypeHandle get_type() const {
@ -88,6 +93,7 @@ public:
private: private:
static TypeHandle _type_handle; static TypeHandle _type_handle;
friend class ChunkedStreamBuf;
}; };
#include "httpDocument.I" #include "httpDocument.I"