cache control
This commit is contained in:
parent
d5e2f5e596
commit
31ebf3bd31
|
|
@ -17,12 +17,15 @@
|
|||
bioStreamPtr.I bioStreamPtr.h \
|
||||
bioStream.I bioStream.h bioStreamBuf.h \
|
||||
chunkedStream.I chunkedStream.h chunkedStreamBuf.h \
|
||||
documentSpec.I documentSpec.h \
|
||||
extractor.h \
|
||||
httpAuthorization.I httpAuthorization.h \
|
||||
httpBasicAuthorization.I httpBasicAuthorization.h \
|
||||
httpClient.I httpClient.h \
|
||||
httpChannel.I httpChannel.h \
|
||||
httpDate.I httpDate.h \
|
||||
httpDigestAuthorization.I httpDigestAuthorization.h \
|
||||
httpEntityTag.I httpEntityTag.h \
|
||||
httpEnum.h \
|
||||
identityStream.I identityStream.h identityStreamBuf.h \
|
||||
multiplexStream.I multiplexStream.h \
|
||||
|
|
@ -40,12 +43,15 @@
|
|||
bioStreamPtr.cxx \
|
||||
bioStream.cxx bioStreamBuf.cxx \
|
||||
chunkedStream.cxx chunkedStreamBuf.cxx \
|
||||
documentSpec.cxx \
|
||||
extractor.cxx \
|
||||
httpAuthorization.cxx \
|
||||
httpBasicAuthorization.cxx \
|
||||
httpClient.cxx \
|
||||
httpChannel.cxx \
|
||||
httpDate.cxx \
|
||||
httpDigestAuthorization.cxx \
|
||||
httpEntityTag.cxx \
|
||||
httpEnum.cxx \
|
||||
identityStream.cxx identityStreamBuf.cxx \
|
||||
multiplexStream.cxx multiplexStreamBuf.cxx \
|
||||
|
|
@ -62,13 +68,16 @@
|
|||
chunkedStream.I chunkedStream.h chunkedStreamBuf.h \
|
||||
config_downloader.h \
|
||||
decompressor.h \
|
||||
documentSpec.h documentSpec.I \
|
||||
download_utils.h downloadDb.h downloadDb.I \
|
||||
extractor.h \
|
||||
httpAuthorization.I httpAuthorization.h \
|
||||
httpBasicAuthorization.I httpBasicAuthorization.h \
|
||||
httpClient.I httpClient.h \
|
||||
httpChannel.I httpChannel.h \
|
||||
httpDate.I httpDate.h \
|
||||
httpDigestAuthorization.I httpDigestAuthorization.h \
|
||||
httpEntityTag.I httpEntityTag.h \
|
||||
httpEnum.h \
|
||||
identityStream.I identityStream.h identityStreamBuf.h \
|
||||
multiplexStream.I multiplexStream.h \
|
||||
|
|
|
|||
|
|
@ -0,0 +1,298 @@
|
|||
// Filename: documentSpec.I
|
||||
// Created by: drose (28Jan03)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DocumentSpec::Constructor
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE DocumentSpec::
|
||||
DocumentSpec() {
|
||||
_request_mode = RM_any;
|
||||
_flags = 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DocumentSpec::Constructor
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE DocumentSpec::
|
||||
DocumentSpec(const string &url) :
|
||||
_url(url)
|
||||
{
|
||||
_request_mode = RM_any;
|
||||
_flags = 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DocumentSpec::Constructor
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE DocumentSpec::
|
||||
DocumentSpec(const URLSpec &url) :
|
||||
_url(url)
|
||||
{
|
||||
_request_mode = RM_any;
|
||||
_flags = 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DocumentSpec::Copy Constructor
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE DocumentSpec::
|
||||
DocumentSpec(const DocumentSpec ©) :
|
||||
_url(copy._url),
|
||||
_tag(copy._tag),
|
||||
_date(copy._date),
|
||||
_request_mode(copy._request_mode),
|
||||
_flags(copy._flags)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DocumentSpec::Copy Assignment Operator
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void DocumentSpec::
|
||||
operator = (const DocumentSpec ©) {
|
||||
_url = copy._url;
|
||||
_tag = copy._tag;
|
||||
_date = copy._date;
|
||||
_request_mode = copy._request_mode;
|
||||
_flags = copy._flags;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DocumentSpec::operator ==
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool DocumentSpec::
|
||||
operator == (const DocumentSpec &other) const {
|
||||
return compare_to(other) == 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DocumentSpec::operator !=
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool DocumentSpec::
|
||||
operator != (const DocumentSpec &other) const {
|
||||
return compare_to(other) != 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DocumentSpec::operator <
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool DocumentSpec::
|
||||
operator < (const DocumentSpec &other) const {
|
||||
return compare_to(other) < 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DocumentSpec::set_url
|
||||
// Access: Published
|
||||
// Description: Changes the URL of the DocumentSpec without modifying
|
||||
// its other properties. Normally this would be a
|
||||
// strange thing to do, because the tag and date are
|
||||
// usually strongly associated with the URL. To get a
|
||||
// DocumentSpec pointing to a new URL, you would
|
||||
// normally create a new DocumentSpec object.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void DocumentSpec::
|
||||
set_url(const URLSpec &url) {
|
||||
_url = url;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DocumentSpec::get_url
|
||||
// Access: Published
|
||||
// Description: Retrieves the URL of the DocumentSpec.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const URLSpec &DocumentSpec::
|
||||
get_url() const {
|
||||
return _url;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DocumentSpec::set_tag
|
||||
// Access: Published
|
||||
// Description: Changes the identity tag associated with the
|
||||
// DocumentSpec.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void DocumentSpec::
|
||||
set_tag(const HTTPEntityTag &tag) {
|
||||
_tag = tag;
|
||||
_flags |= F_has_tag;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DocumentSpec::has_tag
|
||||
// Access: Published
|
||||
// Description: Returns true if an identity tag is associated with
|
||||
// the DocumentSpec.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool DocumentSpec::
|
||||
has_tag() const {
|
||||
return (_flags & F_has_tag) != 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DocumentSpec::get_tag
|
||||
// Access: Published
|
||||
// Description: Returns the identity tag associated with the
|
||||
// DocumentSpec, if there is one. It is an error to
|
||||
// call this if has_tag() returns false.
|
||||
//
|
||||
// The identity tag is set by the HTTP server to
|
||||
// uniquely refer to a particular version of a document.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const HTTPEntityTag &DocumentSpec::
|
||||
get_tag() const {
|
||||
nassertr(has_tag(), _tag);
|
||||
return _tag;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DocumentSpec::clear_tag
|
||||
// Access: Published
|
||||
// Description: Removes the identity tag associated with the
|
||||
// DocumentSpec, if there is one.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void DocumentSpec::
|
||||
clear_tag() {
|
||||
_flags &= ~F_has_tag;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DocumentSpec::set_date
|
||||
// Access: Published
|
||||
// Description: Changes the last-modified date associated with the
|
||||
// DocumentSpec.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void DocumentSpec::
|
||||
set_date(const HTTPDate &date) {
|
||||
_date = date;
|
||||
_flags |= F_has_date;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DocumentSpec::has_date
|
||||
// Access: Published
|
||||
// Description: Returns true if a last-modified date is associated
|
||||
// with the DocumentSpec.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool DocumentSpec::
|
||||
has_date() const {
|
||||
return (_flags & F_has_date) != 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DocumentSpec::get_date
|
||||
// Access: Published
|
||||
// Description: Returns the last-modified date associated with the
|
||||
// DocumentSpec, if there is one. It is an error to
|
||||
// call this if has_date() returns false.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const HTTPDate &DocumentSpec::
|
||||
get_date() const {
|
||||
nassertr(has_date(), _date);
|
||||
return _date;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DocumentSpec::clear_date
|
||||
// Access: Published
|
||||
// Description: Removes the last-modified date associated with the
|
||||
// DocumentSpec, if there is one.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void DocumentSpec::
|
||||
clear_date() {
|
||||
_flags &= ~F_has_date;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DocumentSpec::set_request_mode
|
||||
// Access: Published
|
||||
// Description: Sets the request mode of this DocumentSpec. This is
|
||||
// only relevant when using the DocumentSpec to generate
|
||||
// a request (for instance, in HTTPChannel). This
|
||||
// specifies whether the document request will ask the
|
||||
// server for a newer version than the indicated
|
||||
// version, or the exact version, neither, or either.
|
||||
//
|
||||
// The possible values are:
|
||||
//
|
||||
// RM_any: ignore date and tag (if specified), and
|
||||
// retrieve any document that matches the URL. For a
|
||||
// subrange request, if the document matches the
|
||||
// version indicated exactly, retrieve the subrange
|
||||
// only; otherwise, retrieve the entire document.
|
||||
//
|
||||
// RM_equal: request only the precise version of the
|
||||
// document that matches the particular date and/or
|
||||
// tag exactly, if specified; fail if this version is
|
||||
// not available.
|
||||
//
|
||||
// RM_newer: request any document that is newer than
|
||||
// the version indicated by the particular date and/or
|
||||
// tag; fail if only that version (or older versions)
|
||||
// are available.
|
||||
//
|
||||
// RM_newer_or_equal: request any document that
|
||||
// matches the version indicated by the particular
|
||||
// date and/or tag, or is a newer version; fail if
|
||||
// only older versions are available.
|
||||
//
|
||||
// In any of the above, you may specify either or both
|
||||
// of the last-modified date and the identity tag,
|
||||
// whichever is known to the client.
|
||||
//
|
||||
// The default mode is RM_any.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void DocumentSpec::
|
||||
set_request_mode(DocumentSpec::RequestMode request_mode) {
|
||||
_request_mode = request_mode;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DocumentSpec::get_request_mode
|
||||
// Access: Published
|
||||
// Description: Returns the request mode of this DocumentSpec. See
|
||||
// set_request_mode().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE DocumentSpec::RequestMode DocumentSpec::
|
||||
get_request_mode() const {
|
||||
return _request_mode;
|
||||
}
|
||||
|
||||
|
||||
INLINE ostream &
|
||||
operator << (ostream &out, const DocumentSpec &doc) {
|
||||
doc.output(out);
|
||||
return out;
|
||||
}
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
// Filename: documentSpec.cxx
|
||||
// Created by: drose (28Jan03)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "documentSpec.h"
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DocumentSpec::compare_to
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int DocumentSpec::
|
||||
compare_to(const DocumentSpec &other) const {
|
||||
if (_flags != other._flags) {
|
||||
return (_flags - other._flags);
|
||||
}
|
||||
if (_request_mode != other._request_mode) {
|
||||
return (int)_request_mode - (int)other._request_mode;
|
||||
}
|
||||
int c = _url.compare_to(other._url);
|
||||
if (c != 0) {
|
||||
return c;
|
||||
}
|
||||
c = _tag.compare_to(other._tag);
|
||||
if (c != 0) {
|
||||
return c;
|
||||
}
|
||||
return _date.compare_to(other._date);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DocumentSpec::output
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void DocumentSpec::
|
||||
output(ostream &out) const {
|
||||
out << get_url();
|
||||
if (has_tag()) {
|
||||
out << " (" << get_tag() << ")";
|
||||
}
|
||||
if (has_date()) {
|
||||
out << " " << get_date();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DocumentSpec::write
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void DocumentSpec::
|
||||
write(ostream &out) const {
|
||||
out << get_url() << "\n";
|
||||
if (has_tag()) {
|
||||
out << " " << get_tag() << "\n";
|
||||
}
|
||||
if (has_date()) {
|
||||
out << " " << get_date() << "\n";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
// Filename: documentSpec.h
|
||||
// Created by: drose (28Jan03)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef DOCUMENTSPEC_H
|
||||
#define DOCUMENTSPEC_H
|
||||
|
||||
#include "pandabase.h"
|
||||
#include "urlSpec.h"
|
||||
#include "httpEntityTag.h"
|
||||
#include "httpDate.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : DocumentSpec
|
||||
// Description : A descriptor that refers to a particular version of a
|
||||
// document. This includes the URL of the document and
|
||||
// its identity tag and last-modified dates.
|
||||
//
|
||||
// The DocumentSpec may also be used to request a newer
|
||||
// document than a particular one if available, for
|
||||
// instance to refresh a cached document.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDAEXPRESS DocumentSpec {
|
||||
PUBLISHED:
|
||||
INLINE DocumentSpec();
|
||||
INLINE DocumentSpec(const string &url);
|
||||
INLINE DocumentSpec(const URLSpec &url);
|
||||
INLINE DocumentSpec(const DocumentSpec ©);
|
||||
INLINE void operator = (const DocumentSpec ©);
|
||||
|
||||
INLINE bool operator == (const DocumentSpec &other) const;
|
||||
INLINE bool operator != (const DocumentSpec &other) const;
|
||||
INLINE bool operator < (const DocumentSpec &other) const;
|
||||
int compare_to(const DocumentSpec &other) const;
|
||||
|
||||
INLINE void set_url(const URLSpec &url);
|
||||
INLINE const URLSpec &get_url() const;
|
||||
|
||||
INLINE void set_tag(const HTTPEntityTag &tag);
|
||||
INLINE bool has_tag() const;
|
||||
INLINE const HTTPEntityTag &get_tag() const;
|
||||
INLINE void clear_tag();
|
||||
|
||||
INLINE void set_date(const HTTPDate &date);
|
||||
INLINE bool has_date() const;
|
||||
INLINE const HTTPDate &get_date() const;
|
||||
INLINE void clear_date();
|
||||
|
||||
enum RequestMode {
|
||||
RM_any,
|
||||
RM_equal,
|
||||
RM_newer,
|
||||
RM_equal_or_newer,
|
||||
};
|
||||
|
||||
INLINE void set_request_mode(RequestMode request_mode);
|
||||
INLINE RequestMode get_request_mode() const;
|
||||
|
||||
void output(ostream &out) const;
|
||||
void write(ostream &out) const;
|
||||
|
||||
private:
|
||||
URLSpec _url;
|
||||
HTTPEntityTag _tag;
|
||||
HTTPDate _date;
|
||||
RequestMode _request_mode;
|
||||
|
||||
enum Flags {
|
||||
F_has_tag = 0x0001,
|
||||
F_has_date = 0x0002,
|
||||
};
|
||||
int _flags;
|
||||
};
|
||||
|
||||
INLINE ostream &operator << (ostream &out, const DocumentSpec &doc);
|
||||
|
||||
#include "documentSpec.I"
|
||||
|
||||
#endif
|
||||
|
|
@ -7,3 +7,7 @@
|
|||
#include "chunkedStream.cxx"
|
||||
#include "chunkedStreamBuf.cxx"
|
||||
#include "extractor.cxx"
|
||||
#include "httpDate.cxx"
|
||||
#include "httpEntityTag.cxx"
|
||||
#include "documentSpec.cxx"
|
||||
|
||||
|
|
|
|||
|
|
@ -54,7 +54,25 @@ is_connection_ready() const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const URLSpec &HTTPChannel::
|
||||
get_url() const {
|
||||
return _url;
|
||||
return _document_spec.get_url();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: HTTPChannel::get_document_spec
|
||||
// Access: Published
|
||||
// Description: Returns the DocumentSpec associated with the most
|
||||
// recent document. This includes its actual URL
|
||||
// (following redirects) along with the identity tag and
|
||||
// last-modified date, if supplied by the server.
|
||||
//
|
||||
// This structure may be saved and used to retrieve the
|
||||
// same version of the document later, or to
|
||||
// conditionally retrieve a newer version if it is
|
||||
// available.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const DocumentSpec &HTTPChannel::
|
||||
get_document_spec() const {
|
||||
return _document_spec;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -462,7 +480,7 @@ send_extra_header(const string &key, const string &value) {
|
|||
// Returns true if successful, false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool HTTPChannel::
|
||||
get_document(const URLSpec &url) {
|
||||
get_document(const DocumentSpec &url) {
|
||||
begin_request(HTTPEnum::M_get, url, string(), false, 0, 0);
|
||||
run();
|
||||
return is_valid();
|
||||
|
|
@ -479,7 +497,7 @@ get_document(const URLSpec &url) {
|
|||
// not of the complete document.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool HTTPChannel::
|
||||
get_subdocument(const URLSpec &url, size_t first_byte, size_t last_byte) {
|
||||
get_subdocument(const DocumentSpec &url, size_t first_byte, size_t last_byte) {
|
||||
begin_request(HTTPEnum::M_get, url, string(), false, first_byte, last_byte);
|
||||
run();
|
||||
return is_valid();
|
||||
|
|
@ -495,7 +513,7 @@ get_subdocument(const URLSpec &url, size_t first_byte, size_t last_byte) {
|
|||
// server gives us this information).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool HTTPChannel::
|
||||
get_header(const URLSpec &url) {
|
||||
get_header(const DocumentSpec &url) {
|
||||
begin_request(HTTPEnum::M_head, url, string(), false, 0, 0);
|
||||
run();
|
||||
return is_valid();
|
||||
|
|
@ -508,7 +526,7 @@ get_header(const URLSpec &url) {
|
|||
// response.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool HTTPChannel::
|
||||
post_form(const URLSpec &url, const string &body) {
|
||||
post_form(const DocumentSpec &url, const string &body) {
|
||||
begin_request(HTTPEnum::M_post, url, body, false, 0, 0);
|
||||
run();
|
||||
return is_valid();
|
||||
|
|
@ -521,7 +539,7 @@ post_form(const URLSpec &url, const string &body) {
|
|||
// the indicated URL, if the server allows this.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool HTTPChannel::
|
||||
put_document(const URLSpec &url, const string &body) {
|
||||
put_document(const DocumentSpec &url, const string &body) {
|
||||
begin_request(HTTPEnum::M_put, url, body, false, 0, 0);
|
||||
run();
|
||||
return is_valid();
|
||||
|
|
@ -533,7 +551,7 @@ put_document(const URLSpec &url, const string &body) {
|
|||
// Description: Requests the server to remove the indicated URL.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool HTTPChannel::
|
||||
delete_document(const URLSpec &url) {
|
||||
delete_document(const DocumentSpec &url) {
|
||||
begin_request(HTTPEnum::M_delete, url, string(), false, 0, 0);
|
||||
run();
|
||||
return is_valid();
|
||||
|
|
@ -547,7 +565,7 @@ delete_document(const URLSpec &url) {
|
|||
// it, allowing inspection of proxy hops, etc.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool HTTPChannel::
|
||||
get_trace(const URLSpec &url) {
|
||||
get_trace(const DocumentSpec &url) {
|
||||
begin_request(HTTPEnum::M_trace, url, string(), false, 0, 0);
|
||||
run();
|
||||
return is_valid();
|
||||
|
|
@ -566,7 +584,7 @@ get_trace(const URLSpec &url) {
|
|||
// begin_connect_to().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool HTTPChannel::
|
||||
connect_to(const URLSpec &url) {
|
||||
connect_to(const DocumentSpec &url) {
|
||||
begin_request(HTTPEnum::M_connect, url, string(), false, 0, 0);
|
||||
run();
|
||||
return is_connection_ready();
|
||||
|
|
@ -587,7 +605,7 @@ connect_to(const URLSpec &url) {
|
|||
// is discarded.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void HTTPChannel::
|
||||
begin_get_document(const URLSpec &url) {
|
||||
begin_get_document(const DocumentSpec &url) {
|
||||
begin_request(HTTPEnum::M_get, url, string(), true, 0, 0);
|
||||
}
|
||||
|
||||
|
|
@ -603,7 +621,7 @@ begin_get_document(const URLSpec &url) {
|
|||
// the complete document.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void HTTPChannel::
|
||||
begin_get_subdocument(const URLSpec &url, size_t first_byte,
|
||||
begin_get_subdocument(const DocumentSpec &url, size_t first_byte,
|
||||
size_t last_byte) {
|
||||
begin_request(HTTPEnum::M_get, url, string(), true, first_byte, last_byte);
|
||||
}
|
||||
|
|
@ -615,7 +633,7 @@ begin_get_subdocument(const URLSpec &url, size_t first_byte,
|
|||
// header. See begin_get_document() and get_header().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void HTTPChannel::
|
||||
begin_get_header(const URLSpec &url) {
|
||||
begin_get_header(const DocumentSpec &url) {
|
||||
begin_request(HTTPEnum::M_head, url, string(), true, 0, 0);
|
||||
}
|
||||
|
||||
|
|
@ -634,7 +652,7 @@ begin_get_header(const URLSpec &url) {
|
|||
// may not get posted.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void HTTPChannel::
|
||||
begin_post_form(const URLSpec &url, const string &body) {
|
||||
begin_post_form(const DocumentSpec &url, const string &body) {
|
||||
begin_request(HTTPEnum::M_post, url, body, true, 0, 0);
|
||||
}
|
||||
|
||||
|
|
@ -657,7 +675,7 @@ begin_post_form(const URLSpec &url, const string &body) {
|
|||
// connect_to().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void HTTPChannel::
|
||||
begin_connect_to(const URLSpec &url) {
|
||||
begin_connect_to(const DocumentSpec &url) {
|
||||
begin_request(HTTPEnum::M_connect, url, string(), true, 0, 0);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -270,7 +270,7 @@ run() {
|
|||
_proxy = _client->get_proxy();
|
||||
|
||||
if (_proxy.empty()) {
|
||||
_bio = new BioPtr(_url);
|
||||
_bio = new BioPtr(_request.get_url());
|
||||
} else {
|
||||
_bio = new BioPtr(_proxy);
|
||||
}
|
||||
|
|
@ -686,7 +686,7 @@ run_connecting_wait() {
|
|||
|
||||
if (downloader_cat.is_debug()) {
|
||||
downloader_cat.debug()
|
||||
<< "waiting to connect to " << _url.get_server_and_port() << ".\n";
|
||||
<< "waiting to connect to " << _request.get_url().get_server_and_port() << ".\n";
|
||||
}
|
||||
fd_set wset;
|
||||
FD_ZERO(&wset);
|
||||
|
|
@ -717,7 +717,8 @@ run_connecting_wait() {
|
|||
_started_connecting_time > get_connect_timeout())) {
|
||||
// Time to give up.
|
||||
downloader_cat.info()
|
||||
<< "Timeout connecting to " << _url.get_server_and_port() << ".\n";
|
||||
<< "Timeout connecting to "
|
||||
<< _request.get_url().get_server_and_port() << ".\n";
|
||||
_state = S_failure;
|
||||
return false;
|
||||
}
|
||||
|
|
@ -894,7 +895,7 @@ run_ssl_handshake() {
|
|||
}
|
||||
downloader_cat.info()
|
||||
<< "Could not establish SSL handshake with "
|
||||
<< _url.get_server_and_port() << "\n";
|
||||
<< _request.get_url().get_server_and_port() << "\n";
|
||||
#ifdef REPORT_OPENSSL_ERRORS
|
||||
ERR_print_errors_fp(stderr);
|
||||
#endif
|
||||
|
|
@ -921,7 +922,7 @@ run_ssl_handshake() {
|
|||
long verify_result = SSL_get_verify_result(ssl);
|
||||
if (verify_result == X509_V_ERR_CERT_HAS_EXPIRED) {
|
||||
downloader_cat.info()
|
||||
<< "Expired certificate from " << _url.get_server_and_port() << "\n";
|
||||
<< "Expired certificate from " << _request.get_url().get_server_and_port() << "\n";
|
||||
if (_client->get_verify_ssl() == HTTPClient::VS_normal) {
|
||||
_state = S_failure;
|
||||
return false;
|
||||
|
|
@ -929,7 +930,7 @@ run_ssl_handshake() {
|
|||
|
||||
} else if (verify_result == X509_V_ERR_CERT_NOT_YET_VALID) {
|
||||
downloader_cat.info()
|
||||
<< "Premature certificate from " << _url.get_server_and_port() << "\n";
|
||||
<< "Premature certificate from " << _request.get_url().get_server_and_port() << "\n";
|
||||
if (_client->get_verify_ssl() == HTTPClient::VS_normal) {
|
||||
_state = S_failure;
|
||||
return false;
|
||||
|
|
@ -937,7 +938,7 @@ run_ssl_handshake() {
|
|||
|
||||
} else if (verify_result != X509_V_OK) {
|
||||
downloader_cat.info()
|
||||
<< "Unable to verify identity of " << _url.get_server_and_port()
|
||||
<< "Unable to verify identity of " << _request.get_url().get_server_and_port()
|
||||
<< ", verify error code " << verify_result << "\n";
|
||||
if (_client->get_verify_ssl() != HTTPClient::VS_no_verify) {
|
||||
_state = S_failure;
|
||||
|
|
@ -1046,7 +1047,7 @@ run_request_sent() {
|
|||
_sent_request_time > get_http_timeout()) {
|
||||
// Time to give up.
|
||||
downloader_cat.info()
|
||||
<< "Timeout waiting for " << _url.get_server_and_port() << ".\n";
|
||||
<< "Timeout waiting for " << _request.get_url().get_server_and_port() << ".\n";
|
||||
_state = S_failure;
|
||||
}
|
||||
|
||||
|
|
@ -1093,7 +1094,7 @@ run_reading_header() {
|
|||
_sent_request_time > get_http_timeout()) {
|
||||
// Time to give up.
|
||||
downloader_cat.info()
|
||||
<< "Timeout waiting for " << _url.get_server_and_port() << ".\n";
|
||||
<< "Timeout waiting for " << _request.get_url().get_server_and_port() << ".\n";
|
||||
_state = S_failure;
|
||||
}
|
||||
return true;
|
||||
|
|
@ -1133,6 +1134,17 @@ run_reading_header() {
|
|||
_last_byte = 0;
|
||||
}
|
||||
|
||||
// Set the _document_spec to reflect what we just retrieved.
|
||||
_document_spec = DocumentSpec(_request.get_url());
|
||||
string tag = get_header_value("ETag");
|
||||
if (!tag.empty()) {
|
||||
_document_spec.set_tag(HTTPEntityTag(tag));
|
||||
}
|
||||
string date = get_header_value("Last-Modified");
|
||||
if (!date.empty()) {
|
||||
_document_spec.set_date(HTTPDate(date));
|
||||
}
|
||||
|
||||
// In case we've got a download in effect, reset the download
|
||||
// position to match our starting byte.
|
||||
if (!reset_download_position()) {
|
||||
|
|
@ -1185,10 +1197,10 @@ run_reading_header() {
|
|||
if (get_status_code() == 401 && last_status != 401) {
|
||||
// 401: not authorized to remote server. Try to get the authorization.
|
||||
string authenticate_request = get_header_value("WWW-Authenticate");
|
||||
_www_auth = _client->generate_auth(_url, false, authenticate_request);
|
||||
_www_auth = _client->generate_auth(_request.get_url(), false, authenticate_request);
|
||||
if (_www_auth != (HTTPAuthorization *)NULL) {
|
||||
_www_realm = _www_auth->get_realm();
|
||||
_www_username = _client->select_username(_url, false, _www_realm);
|
||||
_www_username = _client->select_username(_request.get_url(), false, _www_realm);
|
||||
if (!_www_username.empty()) {
|
||||
make_request_text();
|
||||
|
||||
|
|
@ -1214,10 +1226,11 @@ run_reading_header() {
|
|||
downloader_cat.debug()
|
||||
<< "following redirect to " << new_url << "\n";
|
||||
}
|
||||
if (_url.has_username()) {
|
||||
new_url.set_username(_url.get_username());
|
||||
if (_request.get_url().has_username()) {
|
||||
new_url.set_username(_request.get_url().get_username());
|
||||
}
|
||||
set_url(new_url);
|
||||
reset_url(_request.get_url(), new_url);
|
||||
_document_spec.set_url(new_url);
|
||||
make_header();
|
||||
make_request_text();
|
||||
|
||||
|
|
@ -1507,7 +1520,7 @@ run_download_to_ram() {
|
|||
// necessary.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void HTTPChannel::
|
||||
begin_request(HTTPEnum::Method method, const URLSpec &url,
|
||||
begin_request(HTTPEnum::Method method, const DocumentSpec &url,
|
||||
const string &body, bool nonblocking,
|
||||
size_t first_byte, size_t last_byte) {
|
||||
reset_for_new_request();
|
||||
|
|
@ -1524,13 +1537,15 @@ begin_request(HTTPEnum::Method method, const URLSpec &url,
|
|||
reset_to_new();
|
||||
}
|
||||
|
||||
set_url(url);
|
||||
reset_url(_request.get_url(), url.get_url());
|
||||
_request = url;
|
||||
_document_spec = DocumentSpec();
|
||||
_method = method;
|
||||
_body = body;
|
||||
|
||||
// An https-style request means we'll need to establish an SSL
|
||||
// connection.
|
||||
_want_ssl = (_url.get_scheme() == "https");
|
||||
_want_ssl = (_request.get_url().get_scheme() == "https");
|
||||
|
||||
// If we have a proxy, we'll be asking the proxy to hand us the
|
||||
// document--except when we also have https, in which case we'll be
|
||||
|
|
@ -1550,11 +1565,11 @@ begin_request(HTTPEnum::Method method, const URLSpec &url,
|
|||
// requested a direct connection somewhere.
|
||||
ostringstream request;
|
||||
request
|
||||
<< "CONNECT " << _url.get_server_and_port()
|
||||
<< "CONNECT " << _request.get_url().get_server_and_port()
|
||||
<< " " << _client->get_http_version_string() << "\r\n";
|
||||
if (_client->get_http_version() >= HTTPEnum::HV_11) {
|
||||
request
|
||||
<< "Host: " << _url.get_server() << "\r\n";
|
||||
<< "Host: " << _request.get_url().get_server() << "\r\n";
|
||||
}
|
||||
_proxy_header = request.str();
|
||||
make_proxy_request_text();
|
||||
|
|
@ -2241,7 +2256,7 @@ x509_name_subset(X509_NAME *name_a, X509_NAME *name_b) {
|
|||
// Access: Private
|
||||
// Description: Formats the appropriate GET or POST (or whatever)
|
||||
// request to send to the server, based on the current
|
||||
// _method, _url, _body, and _proxy settings.
|
||||
// _method, _document_spec, _body, and _proxy settings.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void HTTPChannel::
|
||||
make_header() {
|
||||
|
|
@ -2261,25 +2276,25 @@ make_header() {
|
|||
return;
|
||||
}
|
||||
|
||||
_www_auth = _client->select_auth(_url, false, _www_realm);
|
||||
_www_auth = _client->select_auth(_request.get_url(), false, _www_realm);
|
||||
_www_username = string();
|
||||
if (_www_auth != (HTTPAuthorization *)NULL) {
|
||||
_www_realm = _www_auth->get_realm();
|
||||
_www_username = _client->select_username(_url, false, _www_realm);
|
||||
_www_username = _client->select_username(_request.get_url(), false, _www_realm);
|
||||
}
|
||||
|
||||
string request_path;
|
||||
if (_proxy_serves_document) {
|
||||
// If we'll be asking the proxy for the document, we need its full
|
||||
// URL--but we omit the username, which is information just for us.
|
||||
URLSpec url_no_username = _url;
|
||||
URLSpec url_no_username = _request.get_url();
|
||||
url_no_username.set_username(string());
|
||||
request_path = url_no_username.get_url();
|
||||
|
||||
} else {
|
||||
// If we'll be asking the server directly for the document, we
|
||||
// just want its path relative to the server.
|
||||
request_path = _url.get_path();
|
||||
request_path = _request.get_url().get_path();
|
||||
}
|
||||
|
||||
ostringstream stream;
|
||||
|
|
@ -2290,7 +2305,7 @@ make_header() {
|
|||
|
||||
if (_client->get_http_version() >= HTTPEnum::HV_11) {
|
||||
stream
|
||||
<< "Host: " << _url.get_server() << "\r\n";
|
||||
<< "Host: " << _request.get_url().get_server() << "\r\n";
|
||||
if (!get_persistent_connection()) {
|
||||
stream
|
||||
<< "Connection: close\r\n";
|
||||
|
|
@ -2306,6 +2321,64 @@ make_header() {
|
|||
<< "Range: bytes=" << _first_byte << "-\r\n";
|
||||
}
|
||||
|
||||
switch (_request.get_request_mode()) {
|
||||
case DocumentSpec::RM_any:
|
||||
// No particular request; give us any document that matches the
|
||||
// URL.
|
||||
if (_first_byte != 0) {
|
||||
// Unless we're requesting a subrange, in which case if the
|
||||
// exact document matches, retrieve the subrange indicated;
|
||||
// otherwise, retrieve the entire document.
|
||||
if (_request.has_tag()) {
|
||||
stream
|
||||
<< "If-Range: " << _request.get_tag().get_string() << "\r\n";
|
||||
} else if (_request.has_date()) {
|
||||
stream
|
||||
<< "If-Range: " << _request.get_date().get_string() << "\r\n";
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case DocumentSpec::RM_equal:
|
||||
// Give us only this particular version of the document, or
|
||||
// nothing.
|
||||
if (_request.has_tag()) {
|
||||
stream
|
||||
<< "If-Match: " << _request.get_tag().get_string() << "\r\n";
|
||||
}
|
||||
if (_request.has_date()) {
|
||||
stream
|
||||
<< "If-Unmodified-Since: " << _request.get_date().get_string()
|
||||
<< "\r\n";
|
||||
}
|
||||
break;
|
||||
|
||||
case DocumentSpec::RM_newer:
|
||||
// Give us anything newer than this document, or nothing.
|
||||
if (_request.has_tag()) {
|
||||
stream
|
||||
<< "If-None-Match: " << _request.get_tag().get_string() << "\r\n";
|
||||
}
|
||||
if (_request.has_date()) {
|
||||
stream
|
||||
<< "If-Modified-Since: " << _request.get_date().get_string()
|
||||
<< "\r\n";
|
||||
}
|
||||
break;
|
||||
|
||||
case DocumentSpec::RM_equal_or_newer:
|
||||
// Just don't give us anything older.
|
||||
if (_request.has_date()) {
|
||||
// This is a little unreliable: we ask for any document that's
|
||||
// been modified since one second before our last-modified-date.
|
||||
// Who knows whether the server will honor this properly.
|
||||
stream
|
||||
<< "If-Modified-Since: " << (_request.get_date() - 1).get_string()
|
||||
<< "\r\n";
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (!_body.empty()) {
|
||||
stream
|
||||
<< "Content-Type: application/x-www-form-urlencoded\r\n"
|
||||
|
|
@ -2331,7 +2404,7 @@ make_proxy_request_text() {
|
|||
if (_proxy_auth != (HTTPAuthorization *)NULL && !_proxy_username.empty()) {
|
||||
_proxy_request_text += "Proxy-Authorization: ";
|
||||
_proxy_request_text +=
|
||||
_proxy_auth->generate(HTTPEnum::M_connect, _url.get_server_and_port(),
|
||||
_proxy_auth->generate(HTTPEnum::M_connect, _request.get_url().get_server_and_port(),
|
||||
_proxy_username, _body);
|
||||
_proxy_request_text += "\r\n";
|
||||
}
|
||||
|
|
@ -2354,7 +2427,7 @@ make_request_text() {
|
|||
_proxy_auth != (HTTPAuthorization *)NULL && !_proxy_username.empty()) {
|
||||
_request_text += "Proxy-Authorization: ";
|
||||
_request_text +=
|
||||
_proxy_auth->generate(_method, _url.get_url(), _proxy_username, _body);
|
||||
_proxy_auth->generate(_method, _request.get_url().get_url(), _proxy_username, _body);
|
||||
_request_text += "\r\n";
|
||||
}
|
||||
|
||||
|
|
@ -2362,7 +2435,7 @@ make_request_text() {
|
|||
string authorization =
|
||||
_request_text += "Authorization: ";
|
||||
_request_text +=
|
||||
_www_auth->generate(_method, _url.get_path(), _www_username, _body);
|
||||
_www_auth->generate(_method, _request.get_url().get_path(), _www_username, _body);
|
||||
_request_text += "\r\n";
|
||||
}
|
||||
|
||||
|
|
@ -2372,25 +2445,24 @@ make_request_text() {
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: HTTPChannel::set_url
|
||||
// Function: HTTPChannel::reset_url
|
||||
// Access: Private
|
||||
// Description: Specifies the document's URL before attempting a
|
||||
// connection. This controls the name of the server to
|
||||
// be contacted, etc.
|
||||
// Description: Redirects the next connection to the indicated URL
|
||||
// (from the previous URL). This resets the socket if
|
||||
// necessary when we are about to switch servers.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void HTTPChannel::
|
||||
set_url(const URLSpec &url) {
|
||||
reset_url(const URLSpec &old_url, const URLSpec &new_url) {
|
||||
// If we change between http and https, we have to reset the
|
||||
// connection regardless of proxy. Otherwise, we have to drop the
|
||||
// connection if the server or port changes, unless we're
|
||||
// communicating through a proxy.
|
||||
|
||||
if (url.get_scheme() != _url.get_scheme() ||
|
||||
(_proxy.empty() && (url.get_server() != _url.get_server() ||
|
||||
url.get_port() != _url.get_port()))) {
|
||||
if (new_url.get_scheme() != old_url.get_scheme() ||
|
||||
(_proxy.empty() && (new_url.get_server() != old_url.get_server() ||
|
||||
new_url.get_port() != old_url.get_port()))) {
|
||||
reset_to_new();
|
||||
}
|
||||
_url = url;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
#include "httpClient.h"
|
||||
#include "httpEnum.h"
|
||||
#include "urlSpec.h"
|
||||
#include "documentSpec.h"
|
||||
#include "virtualFile.h"
|
||||
#include "bioPtr.h"
|
||||
#include "bioStreamPtr.h"
|
||||
|
|
@ -77,6 +78,7 @@ PUBLISHED:
|
|||
INLINE bool is_valid() const;
|
||||
INLINE bool is_connection_ready() const;
|
||||
INLINE const URLSpec &get_url() const;
|
||||
INLINE const DocumentSpec &get_document_spec() const;
|
||||
INLINE HTTPEnum::HTTPVersion get_http_version() const;
|
||||
INLINE const string &get_http_version_string() const;
|
||||
INLINE int get_status_code() const;
|
||||
|
|
@ -115,23 +117,23 @@ PUBLISHED:
|
|||
INLINE void clear_extra_headers();
|
||||
INLINE void send_extra_header(const string &key, const string &value);
|
||||
|
||||
INLINE bool get_document(const URLSpec &url);
|
||||
INLINE bool get_subdocument(const URLSpec &url,
|
||||
INLINE bool get_document(const DocumentSpec &url);
|
||||
INLINE bool get_subdocument(const DocumentSpec &url,
|
||||
size_t first_byte, size_t last_byte);
|
||||
INLINE bool get_header(const URLSpec &url);
|
||||
INLINE bool post_form(const URLSpec &url, const string &body);
|
||||
INLINE bool put_document(const URLSpec &url, const string &body);
|
||||
INLINE bool delete_document(const URLSpec &url);
|
||||
INLINE bool get_trace(const URLSpec &url);
|
||||
INLINE bool connect_to(const URLSpec &url);
|
||||
INLINE bool get_header(const DocumentSpec &url);
|
||||
INLINE bool post_form(const DocumentSpec &url, const string &body);
|
||||
INLINE bool put_document(const DocumentSpec &url, const string &body);
|
||||
INLINE bool delete_document(const DocumentSpec &url);
|
||||
INLINE bool get_trace(const DocumentSpec &url);
|
||||
INLINE bool connect_to(const DocumentSpec &url);
|
||||
|
||||
INLINE void begin_get_document(const URLSpec &url);
|
||||
INLINE void begin_get_subdocument(const URLSpec &url,
|
||||
INLINE void begin_get_document(const DocumentSpec &url);
|
||||
INLINE void begin_get_subdocument(const DocumentSpec &url,
|
||||
size_t first_byte, size_t last_byte);
|
||||
INLINE void begin_get_header(const URLSpec &url);
|
||||
INLINE void begin_post_form(const URLSpec &url, const string &body);
|
||||
INLINE void begin_get_header(const DocumentSpec &url);
|
||||
INLINE void begin_post_form(const DocumentSpec &url, const string &body);
|
||||
bool run();
|
||||
INLINE void begin_connect_to(const URLSpec &url);
|
||||
INLINE void begin_connect_to(const DocumentSpec &url);
|
||||
|
||||
ISocketStream *read_body();
|
||||
bool download_to_file(const Filename &filename, bool subdocument_resumes = true);
|
||||
|
|
@ -166,7 +168,7 @@ private:
|
|||
bool run_download_to_file();
|
||||
bool run_download_to_ram();
|
||||
|
||||
void begin_request(HTTPEnum::Method method, const URLSpec &url,
|
||||
void begin_request(HTTPEnum::Method method, const DocumentSpec &url,
|
||||
const string &body, bool nonblocking,
|
||||
size_t first_byte, size_t last_byte);
|
||||
void reset_for_new_request();
|
||||
|
|
@ -190,7 +192,7 @@ private:
|
|||
void make_proxy_request_text();
|
||||
void make_request_text();
|
||||
|
||||
void set_url(const URLSpec &url);
|
||||
void reset_url(const URLSpec &old_url, const URLSpec &new_url);
|
||||
void store_header_field(const string &field_name, const string &field_value);
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
|
@ -217,7 +219,8 @@ private:
|
|||
bool _nonblocking;
|
||||
string _send_extra_headers;
|
||||
|
||||
URLSpec _url;
|
||||
DocumentSpec _document_spec;
|
||||
DocumentSpec _request;
|
||||
HTTPEnum::Method _method;
|
||||
string request_path;
|
||||
string _header;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,199 @@
|
|||
// Filename: httpDate.I
|
||||
// Created by: drose (28Jan03)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: HTTPDate::Constructor
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE HTTPDate::
|
||||
HTTPDate() : _time(-1) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: HTTPDate::Constructor
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE HTTPDate::
|
||||
HTTPDate(time_t time) : _time(time) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: HTTPDate::Copy Constructor
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE HTTPDate::
|
||||
HTTPDate(const HTTPDate ©) : _time(copy._time) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: HTTPDate::Copy Assignment Operator
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void HTTPDate::
|
||||
operator = (const HTTPDate ©) {
|
||||
_time = copy._time;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: HTTPDate::now (named constructor)
|
||||
// Access: Published, Static
|
||||
// Description: Returns an HTTPDate that represents the current time
|
||||
// and date.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE HTTPDate HTTPDate::
|
||||
now() {
|
||||
return HTTPDate(time(NULL));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: HTTPDate::is_valid
|
||||
// Access: Published
|
||||
// Description: Returns true if the date is meaningful, or false if
|
||||
// it is -1 (which generally indicates the source string
|
||||
// could not be parsed.)
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool HTTPDate::
|
||||
is_valid() const {
|
||||
return (_time != (time_t)(-1));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: HTTPDate::get_time
|
||||
// Access: Published
|
||||
// Description: Returns the date as a C time_t value.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE time_t HTTPDate::
|
||||
get_time() const {
|
||||
return _time;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: HTTPDate::Operator ==
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool HTTPDate::
|
||||
operator == (const HTTPDate &other) const {
|
||||
return _time == other._time;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: HTTPDate::Operator !=
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool HTTPDate::
|
||||
operator != (const HTTPDate &other) const {
|
||||
return !operator == (other);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: HTTPDate::Operator <
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool HTTPDate::
|
||||
operator < (const HTTPDate &other) const {
|
||||
return _time < other._time;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: HTTPDate::compare_to
|
||||
// Access: Published
|
||||
// Description: Returns a number less than zero if this HTTPDate
|
||||
// sorts before the other one, greater than zero if it
|
||||
// sorts after, or zero if they are equivalent.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int HTTPDate::
|
||||
compare_to(const HTTPDate &other) const {
|
||||
return (int)(_time - other._time);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: HTTPDate::operator +=
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void HTTPDate::
|
||||
operator += (int seconds) {
|
||||
_time += seconds;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: HTTPDate::operator -=
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void HTTPDate::
|
||||
operator -= (int seconds) {
|
||||
_time -= seconds;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: HTTPDate::operator +
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE HTTPDate HTTPDate::
|
||||
operator + (int seconds) const {
|
||||
return HTTPDate(_time + seconds);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: HTTPDate::operator -
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE HTTPDate HTTPDate::
|
||||
operator - (int seconds) const {
|
||||
return HTTPDate(_time - seconds);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: HTTPDate::operator -
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int HTTPDate::
|
||||
operator - (const HTTPDate &other) const {
|
||||
return (int)(_time - other._time);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: HTTPDate::output
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void HTTPDate::
|
||||
output(ostream &out) const {
|
||||
out << get_string();
|
||||
}
|
||||
|
||||
|
||||
INLINE ostream &
|
||||
operator << (ostream &out, const HTTPDate &date) {
|
||||
date.output(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,313 @@
|
|||
// Filename: httpDate.cxx
|
||||
// Created by: drose (28Jan03)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "httpDate.h"
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
static const int num_weekdays = 7;
|
||||
static const char * const weekdays[num_weekdays] = {
|
||||
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
|
||||
};
|
||||
|
||||
static const int num_months = 12;
|
||||
static const char * const months[num_months] = {
|
||||
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: HTTPDate::Constructor
|
||||
// Access: Published
|
||||
// Description: Decodes the string into a sensible date. Returns 0
|
||||
// (!is_valid()) if the string cannot be correctly
|
||||
// decoded.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
HTTPDate::
|
||||
HTTPDate(const string &format) {
|
||||
_time = (time_t)(-1);
|
||||
|
||||
struct tm t;
|
||||
memset(&t, 0, sizeof(t));
|
||||
|
||||
bool got_weekday = false;
|
||||
bool got_month = false;
|
||||
bool got_day = false;
|
||||
bool got_year = false;
|
||||
bool got_hour = false;
|
||||
bool got_minute = false;
|
||||
bool got_second = false;
|
||||
bool got_timezone = false;
|
||||
|
||||
enum ExpectNext {
|
||||
EN_none,
|
||||
EN_second,
|
||||
EN_year
|
||||
};
|
||||
ExpectNext expect_next = EN_none;
|
||||
|
||||
size_t pos = 0;
|
||||
string token = get_token(format, pos);
|
||||
while (!token.empty()) {
|
||||
ExpectNext expected = expect_next;
|
||||
expect_next = EN_none;
|
||||
|
||||
if (isdigit(token[0])) {
|
||||
// Here's a number.
|
||||
int value = atoi(token.c_str());
|
||||
if (token[token.length() - 1] == ':') {
|
||||
// If it ends in a colon, it must be hh or mm.
|
||||
if (!got_hour) {
|
||||
t.tm_hour = value;
|
||||
got_hour = true;
|
||||
|
||||
} else if (!got_minute) {
|
||||
t.tm_min = value;
|
||||
got_minute = true;
|
||||
expect_next = EN_second;
|
||||
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
} else if (token[token.length() - 1] == '/') {
|
||||
// If it ends in a colon, it must be mm/dd/.
|
||||
if (!got_month) {
|
||||
t.tm_mon = value - 1;
|
||||
got_month = true;
|
||||
|
||||
} else if (!got_day) {
|
||||
t.tm_mday = value;
|
||||
got_day = true;
|
||||
expect_next = EN_year;
|
||||
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
} else {
|
||||
if (expected == EN_second) {
|
||||
// The first number following hh:mm: is always the seconds.
|
||||
t.tm_sec = value;
|
||||
got_second = true;
|
||||
|
||||
} else if (expected == EN_year) {
|
||||
// The first number following mm/dd/ is always the year.
|
||||
t.tm_year = value;
|
||||
got_year = true;
|
||||
|
||||
} else if (!got_day) {
|
||||
// Assume it's a day.
|
||||
t.tm_mday = value;
|
||||
got_day = true;
|
||||
|
||||
} else if (!got_year) {
|
||||
// It must be the year.
|
||||
t.tm_year = value;
|
||||
got_year = true;
|
||||
|
||||
} else if (!got_hour) {
|
||||
t.tm_hour = value;
|
||||
got_hour = true;
|
||||
|
||||
} else if (!got_minute) {
|
||||
t.tm_min = value;
|
||||
got_minute = true;
|
||||
|
||||
} else if (!got_second) {
|
||||
t.tm_sec = value;
|
||||
got_second = true;
|
||||
|
||||
} else {
|
||||
// Huh, an unexpected numeric value.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
// This is a string token. It should be either a month name or
|
||||
// a day name, or a timezone name--but the only timezone name we
|
||||
// expect to see is "GMT".
|
||||
bool matched = false;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_weekdays && !matched; i++) {
|
||||
if (token == weekdays[i]) {
|
||||
if (got_weekday) {
|
||||
return;
|
||||
}
|
||||
matched = true;
|
||||
got_weekday = true;
|
||||
t.tm_wday = i;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < num_months && !matched; i++) {
|
||||
if (token == months[i]) {
|
||||
if (got_month) {
|
||||
return;
|
||||
}
|
||||
matched = true;
|
||||
got_month = true;
|
||||
t.tm_mon = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (!matched && token == "Gmt") {
|
||||
matched = true;
|
||||
got_timezone = true;
|
||||
}
|
||||
|
||||
if (!matched) {
|
||||
// Couldn't figure this one out.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
token = get_token(format, pos);
|
||||
}
|
||||
|
||||
// Now check that we got the minimum expected tokens.
|
||||
if (!(got_month && got_day && got_year && got_hour && got_minute)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Also validate the tokens we did get.
|
||||
if (t.tm_year < 100) {
|
||||
// Two-digit year. Assume it's in the same century, unless
|
||||
// that assumption puts it more than 50 years in the future.
|
||||
time_t now = time(NULL);
|
||||
struct tm *tp = gmtime(&now);
|
||||
t.tm_year += 100 * (tp->tm_year / 100);
|
||||
if (t.tm_year - tp->tm_year > 50) {
|
||||
t.tm_year -= 100;
|
||||
}
|
||||
|
||||
} else if (t.tm_year < 1900) {
|
||||
// Invalid three- or four-digit year. Give up.
|
||||
return;
|
||||
|
||||
} else {
|
||||
t.tm_year -= 1900;
|
||||
}
|
||||
|
||||
if (!((t.tm_mon >= 0 && t.tm_mon < num_months) &&
|
||||
(t.tm_mday >= 1 && t.tm_mday <= 31) &&
|
||||
(t.tm_hour >= 0 && t.tm_hour < 60) &&
|
||||
(t.tm_min >= 0 && t.tm_min < 60) &&
|
||||
(t.tm_sec >= 0 && t.tm_sec < 62) /* maybe leap seconds */)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Everything checks out; convert the date.
|
||||
_time = mktime(&t);
|
||||
|
||||
if (_time != (time_t)-1) {
|
||||
// Unfortunately, mktime() assumes local time; convert this back
|
||||
// to GMT.
|
||||
extern long int timezone;
|
||||
_time -= timezone;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: HTTPDate::get_string
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
string HTTPDate::
|
||||
get_string() const {
|
||||
if (!is_valid()) {
|
||||
return "Invalid Date";
|
||||
}
|
||||
|
||||
struct tm *tp = gmtime(&_time);
|
||||
|
||||
ostringstream result;
|
||||
result
|
||||
<< weekdays[tp->tm_wday] << ", "
|
||||
<< setw(2) << setfill('0') << tp->tm_mday << " "
|
||||
<< months[tp->tm_mon] << " "
|
||||
<< setw(4) << setfill('0') << tp->tm_year + 1900 << " "
|
||||
<< setw(2) << setfill('0') << tp->tm_hour << ":"
|
||||
<< setw(2) << setfill('0') << tp->tm_min << ":"
|
||||
<< setw(2) << setfill('0') << tp->tm_sec << " GMT";
|
||||
|
||||
return result.str();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: HTTPDate::get_token
|
||||
// Access: Published
|
||||
// Description: Extracts the next token from the string starting at
|
||||
// the indicated position. Returns the token and
|
||||
// updates pos. When the last token has been extracted,
|
||||
// returns empty string.
|
||||
//
|
||||
// A token is defined as a contiguous sequence of digits
|
||||
// or letters. If it is a sequence of letters, the
|
||||
// function quietly truncates it to three letters before
|
||||
// returning, and forces the first letter to capital and
|
||||
// the second two to lowercase. If it is a sequence of
|
||||
// digits, the function also returns the next character
|
||||
// following the last digit (unless it is a letter).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
string HTTPDate::
|
||||
get_token(const string &str, size_t &pos) {
|
||||
// Start by scanning for the first alphanumeric character.
|
||||
size_t start = pos;
|
||||
while (start < str.length() && !isalnum(str[start])) {
|
||||
start++;
|
||||
}
|
||||
|
||||
if (start >= str.length()) {
|
||||
// End of the line.
|
||||
pos = string::npos;
|
||||
return string();
|
||||
}
|
||||
|
||||
string token;
|
||||
|
||||
if (isalpha(str[start])) {
|
||||
// A string of letters.
|
||||
token = toupper(str[start]);
|
||||
pos = start + 1;
|
||||
while (pos < str.length() && isalpha(str[pos])) {
|
||||
if (token.length() < 3) {
|
||||
token += tolower(str[pos]);
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
|
||||
} else {
|
||||
// A string of digits.
|
||||
pos = start + 1;
|
||||
while (pos < str.length() && isdigit(str[pos])) {
|
||||
pos++;
|
||||
}
|
||||
// Get one more character, so we can identify things like hh:
|
||||
if (pos < str.length() && !isalpha(str[pos])) {
|
||||
pos++;
|
||||
}
|
||||
token = str.substr(start, pos - start);
|
||||
}
|
||||
|
||||
return token;
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
// Filename: httpDate.h
|
||||
// Created by: drose (28Jan03)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef HTTPDATE_H
|
||||
#define HTTPDATE_H
|
||||
|
||||
#include "pandabase.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : HTTPDate
|
||||
// Description : A container for an HTTP-legal time/date indication.
|
||||
// This can accept a string from an HTTP header and will
|
||||
// decode it into a C time_t value; conversely, it can
|
||||
// accept a time_t value and encode it for output as a
|
||||
// string.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDAEXPRESS HTTPDate {
|
||||
PUBLISHED:
|
||||
INLINE HTTPDate();
|
||||
INLINE HTTPDate(time_t time);
|
||||
HTTPDate(const string &format);
|
||||
INLINE HTTPDate(const HTTPDate ©);
|
||||
INLINE void operator = (const HTTPDate ©);
|
||||
INLINE static HTTPDate now();
|
||||
|
||||
INLINE bool is_valid() const;
|
||||
|
||||
string get_string() const;
|
||||
INLINE time_t get_time() const;
|
||||
|
||||
INLINE bool operator == (const HTTPDate &other) const;
|
||||
INLINE bool operator != (const HTTPDate &other) const;
|
||||
INLINE bool operator < (const HTTPDate &other) const;
|
||||
INLINE int compare_to(const HTTPDate &other) const;
|
||||
|
||||
INLINE void operator += (int seconds);
|
||||
INLINE void operator -= (int seconds);
|
||||
|
||||
INLINE HTTPDate operator + (int seconds) const;
|
||||
INLINE HTTPDate operator - (int seconds) const;
|
||||
INLINE int operator - (const HTTPDate &other) const;
|
||||
|
||||
INLINE void output(ostream &out) const;
|
||||
|
||||
private:
|
||||
static string get_token(const string &str, size_t &pos);
|
||||
|
||||
time_t _time;
|
||||
};
|
||||
|
||||
INLINE ostream &operator << (ostream &out, const URLSpec &url);
|
||||
|
||||
#include "httpDate.I"
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,179 @@
|
|||
// Filename: httpEntityTag.I
|
||||
// Created by: drose (28Jan03)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: HTTPEntityTag::Constructor
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE HTTPEntityTag::
|
||||
HTTPEntityTag() {
|
||||
_weak = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: HTTPEntityTag::Constructor
|
||||
// Access: Published
|
||||
// Description: This constructor accepts an explicit weak flag and a
|
||||
// literal (not quoted) tag string.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE HTTPEntityTag::
|
||||
HTTPEntityTag(bool weak, const string &tag) :
|
||||
_weak(weak),
|
||||
_tag(tag)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: HTTPEntityTag::Copy Constructor
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE HTTPEntityTag::
|
||||
HTTPEntityTag(const HTTPEntityTag ©) :
|
||||
_weak(copy._weak),
|
||||
_tag(copy._tag)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: HTTPEntityTag::Copy Assignment Operator
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void HTTPEntityTag::
|
||||
operator = (const HTTPEntityTag ©) {
|
||||
_weak = copy._weak;
|
||||
_tag = copy._tag;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: HTTPEntityTag::is_weak
|
||||
// Access: Published
|
||||
// Description: Returns true if the entity tag is marked as "weak".
|
||||
// A consistent weak entity tag does not guarantee that
|
||||
// its resource has not changed in any way, but it does
|
||||
// promise that the resource has not changed in any
|
||||
// semantically meaningful way.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool HTTPEntityTag::
|
||||
is_weak() const {
|
||||
return _weak;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: HTTPEntityTag::get_tag
|
||||
// Access: Published
|
||||
// Description: Returns the tag as a literal string.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const string &HTTPEntityTag::
|
||||
get_tag() const {
|
||||
return _tag;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: HTTPEntityTag::strong_equiv
|
||||
// Access: Published
|
||||
// Description: Returns true if the two tags have "strong" equivalence:
|
||||
// they are the same tag, and both are "strong".
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool HTTPEntityTag::
|
||||
strong_equiv(const HTTPEntityTag &other) const {
|
||||
return _tag == other._tag && !_weak && !other._weak;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: HTTPEntityTag::weak_equiv
|
||||
// Access: Published
|
||||
// Description: Returns true if the two tags have "weak" equivalence:
|
||||
// they are the same tag, and one or both may be "weak".
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool HTTPEntityTag::
|
||||
weak_equiv(const HTTPEntityTag &other) const {
|
||||
return _tag == other._tag;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: HTTPEntityTag::Operator ==
|
||||
// Access: Published
|
||||
// Description: The == operator tests object equivalence; see also
|
||||
// strong_equiv() and weak_equiv() for the two kinds of
|
||||
// HTTP equivalence.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool HTTPEntityTag::
|
||||
operator == (const HTTPEntityTag &other) const {
|
||||
return _weak == other._weak && _tag == other._tag;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: HTTPEntityTag::Operator !=
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool HTTPEntityTag::
|
||||
operator != (const HTTPEntityTag &other) const {
|
||||
return !operator == (other);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: HTTPEntityTag::Operator <
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool HTTPEntityTag::
|
||||
operator < (const HTTPEntityTag &other) const {
|
||||
if (_weak != other._weak) {
|
||||
return (int)_weak < (int)other._weak;
|
||||
}
|
||||
return _tag < other._tag;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: HTTPEntityTag::compare_to
|
||||
// Access: Published
|
||||
// Description: Returns a number less than zero if this HTTPEntityTag
|
||||
// sorts before the other one, greater than zero if it
|
||||
// sorts after, or zero if they are equivalent.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int HTTPEntityTag::
|
||||
compare_to(const HTTPEntityTag &other) const {
|
||||
if (_weak != other._weak) {
|
||||
return (int)_weak - (int)other._weak;
|
||||
}
|
||||
return strcmp(_tag.c_str(), other._tag.c_str());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: HTTPEntityTag::output
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void HTTPEntityTag::
|
||||
output(ostream &out) const {
|
||||
out << get_string();
|
||||
}
|
||||
|
||||
|
||||
INLINE ostream &
|
||||
operator << (ostream &out, const HTTPEntityTag &entityTag) {
|
||||
entityTag.output(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
// Filename: httpEntityTag.cxx
|
||||
// Created by: drose (28Jan03)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "httpEntityTag.h"
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: HTTPEntityTag::Constructor
|
||||
// Access: Published
|
||||
// Description: This constructor accepts a string as formatted from
|
||||
// an HTTP server (e.g. the tag is quoted, with an
|
||||
// optional W/ prefix.)
|
||||
////////////////////////////////////////////////////////////////////
|
||||
HTTPEntityTag::
|
||||
HTTPEntityTag(const string &text) {
|
||||
_weak = false;
|
||||
|
||||
size_t p = 0;
|
||||
if (text.length() >= 2) {
|
||||
string sub = text.substr(0, 2);
|
||||
if (sub == "W/" || sub == "w/") {
|
||||
_weak = true;
|
||||
p = 2;
|
||||
}
|
||||
}
|
||||
|
||||
// Unquote the string.
|
||||
bool quoted = false;
|
||||
if (p < text.length() && text[p] == '"') {
|
||||
quoted = true;
|
||||
p++;
|
||||
}
|
||||
while (p < text.length() && !(quoted && text[p] == '"')) {
|
||||
if (text[p] == '\\') {
|
||||
p++;
|
||||
}
|
||||
_tag += text[p];
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: HTTPEntityTag::get_string
|
||||
// Access: Published
|
||||
// Description: Returns the entity tag formatted for sending to an
|
||||
// HTTP server (the tag is quoted, with a conditional W/
|
||||
// prefix).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
string HTTPEntityTag::
|
||||
get_string() const {
|
||||
ostringstream result;
|
||||
if (_weak) {
|
||||
result << "W/";
|
||||
}
|
||||
result << '"';
|
||||
|
||||
for (string::const_iterator ti = _tag.begin(); ti != _tag.end(); ++ti) {
|
||||
switch (*ti) {
|
||||
case '"':
|
||||
case '\\':
|
||||
result << '\\';
|
||||
// fall through
|
||||
|
||||
default:
|
||||
result << (*ti);
|
||||
}
|
||||
}
|
||||
|
||||
result << '"';
|
||||
|
||||
return result.str();
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
// Filename: httpEntityTag.h
|
||||
// Created by: drose (28Jan03)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef HTTPENTITYTAG_H
|
||||
#define HTTPENTITYTAG_H
|
||||
|
||||
#include "pandabase.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : HTTPEntityTag
|
||||
// Description : A container for an "entity tag" from an HTTP server.
|
||||
// This is used to identify a particular version of a
|
||||
// document or resource, particularly useful for
|
||||
// verifying caches.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDAEXPRESS HTTPEntityTag {
|
||||
PUBLISHED:
|
||||
INLINE HTTPEntityTag();
|
||||
HTTPEntityTag(const string &text);
|
||||
INLINE HTTPEntityTag(bool weak, const string &tag);
|
||||
INLINE HTTPEntityTag(const HTTPEntityTag ©);
|
||||
INLINE void operator = (const HTTPEntityTag ©);
|
||||
|
||||
INLINE bool is_weak() const;
|
||||
INLINE const string &get_tag() const;
|
||||
string get_string() const;
|
||||
|
||||
INLINE bool strong_equiv(const HTTPEntityTag &other) const;
|
||||
INLINE bool weak_equiv(const HTTPEntityTag &other) const;
|
||||
|
||||
INLINE bool operator == (const HTTPEntityTag &other) const;
|
||||
INLINE bool operator != (const HTTPEntityTag &other) const;
|
||||
INLINE bool operator < (const HTTPEntityTag &other) const;
|
||||
INLINE int compare_to(const HTTPEntityTag &other) const;
|
||||
|
||||
INLINE void output(ostream &out) const;
|
||||
|
||||
private:
|
||||
bool _weak;
|
||||
string _tag;
|
||||
};
|
||||
|
||||
INLINE ostream &operator << (ostream &out, const URLSpec &url);
|
||||
|
||||
#include "httpEntityTag.I"
|
||||
|
||||
#endif
|
||||
|
|
@ -77,6 +77,18 @@ operator < (const URLSpec &other) const {
|
|||
return _url < other._url;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: URLSpec::compare_to
|
||||
// Access: Published
|
||||
// Description: Returns a number less than zero if this URLSpec
|
||||
// sorts before the other one, greater than zero if it
|
||||
// sorts after, or zero if they are equivalent.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int URLSpec::
|
||||
compare_to(const URLSpec &other) const {
|
||||
return strcmp(_url.c_str(), other._url.c_str());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: URLSpec::has_scheme
|
||||
// Access: Published
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ PUBLISHED:
|
|||
INLINE bool operator == (const URLSpec &other) const;
|
||||
INLINE bool operator != (const URLSpec &other) const;
|
||||
INLINE bool operator < (const URLSpec &other) const;
|
||||
INLINE int compare_to(const URLSpec &other) const;
|
||||
|
||||
INLINE bool has_scheme() const;
|
||||
INLINE bool has_authority() const;
|
||||
|
|
|
|||
Loading…
Reference in New Issue