add urlSpec
This commit is contained in:
parent
875e6a4f76
commit
ffc858f09e
|
|
@ -14,6 +14,7 @@
|
|||
config_downloader.h asyncUtility.I asyncUtility.h \
|
||||
extractor.h multiplexStream.I multiplexStream.h \
|
||||
multiplexStreamBuf.I multiplexStreamBuf.h \
|
||||
urlSpec.I urlSpec.h \
|
||||
$[if $[HAVE_NET], downloadDb.I downloadDb.h downloader.I downloader.h] \
|
||||
$[if $[HAVE_ZLIB], decompressor.h zcompressor.I zcompressor.h download_utils.h] \
|
||||
$[if $[HAVE_CRYPTO], patcher.cxx patcher.h patcher.I]
|
||||
|
|
@ -21,6 +22,7 @@
|
|||
#define INCLUDED_SOURCES \
|
||||
config_downloader.cxx asyncUtility.cxx \
|
||||
extractor.cxx multiplexStream.cxx multiplexStreamBuf.cxx \
|
||||
urlSpec.cxx \
|
||||
$[if $[HAVE_NET], downloadDb.cxx downloader.cxx] \
|
||||
$[if $[HAVE_ZLIB], decompressor.cxx zcompressor.cxx download_utils.cxx]
|
||||
|
||||
|
|
@ -34,8 +36,17 @@
|
|||
multiplexStream.I multiplexStream.h \
|
||||
multiplexStreamBuf.I multiplexStreamBuf.I \
|
||||
patcher.h patcher.I \
|
||||
urlSpec.h urlSpec.I \
|
||||
zcompressor.I zcompressor.h
|
||||
|
||||
#define IGATESCAN all
|
||||
|
||||
#end lib_target
|
||||
|
||||
#begin test_bin_target
|
||||
#define TARGET test_proxy
|
||||
|
||||
#define SOURCES test_proxy.cxx
|
||||
#define LOCAL_LIBS $[LOCAL_LIBS] putil net
|
||||
#define OTHER_LIBS $[OTHER_LIBS] pystub
|
||||
#end test_bin_target
|
||||
|
|
|
|||
|
|
@ -3,4 +3,5 @@
|
|||
#include "extractor.cxx"
|
||||
#include "multiplexStream.cxx"
|
||||
#include "multiplexStreamBuf.cxx"
|
||||
#include "urlSpec.cxx"
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,204 @@
|
|||
// Filename: urlSpec.I
|
||||
// Created by: drose (24Sep02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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: URLSpec::Constructor
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE URLSpec::
|
||||
URLSpec(const string &url) {
|
||||
(*this) = url;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: URLSpec::Copy Constructor
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE URLSpec::
|
||||
URLSpec(const URLSpec ©) {
|
||||
(*this) = copy;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: URLSpec::Assignment Operator
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void URLSpec::
|
||||
operator = (const string &url) {
|
||||
set_url(url);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: URLSpec::has_scheme
|
||||
// Access: Published
|
||||
// Description: Returns true if the URL specifies a scheme
|
||||
// (e.g. "http:"), false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool URLSpec::
|
||||
has_scheme() const {
|
||||
return (_flags & F_has_scheme) != 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: URLSpec::has_authority
|
||||
// Access: Published
|
||||
// Description: Returns true if the URL specifies an authority
|
||||
// (this includes username, server, and/or port), false
|
||||
// otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool URLSpec::
|
||||
has_authority() const {
|
||||
return (_flags & F_has_authority) != 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: URLSpec::has_username
|
||||
// Access: Published
|
||||
// Description: Returns true if the URL specifies a username
|
||||
// (and/or password), false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool URLSpec::
|
||||
has_username() const {
|
||||
return (_flags & F_has_username) != 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: URLSpec::has_server
|
||||
// Access: Published
|
||||
// Description: Returns true if the URL specifies a server name,
|
||||
// false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool URLSpec::
|
||||
has_server() const {
|
||||
return (_flags & F_has_server) != 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: URLSpec::has_port
|
||||
// Access: Published
|
||||
// Description: Returns true if the URL specifies a port number,
|
||||
// false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool URLSpec::
|
||||
has_port() const {
|
||||
return (_flags & F_has_port) != 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: URLSpec::has_path
|
||||
// Access: Published
|
||||
// Description: Returns true if the URL includes a path specification
|
||||
// (that is, the particular filename on the server to
|
||||
// retrieve), false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool URLSpec::
|
||||
has_path() const {
|
||||
return (_flags & F_has_path) != 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: URLSpec::has_query
|
||||
// Access: Published
|
||||
// Description: Returns true if the URL includes a query
|
||||
// specification, false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool URLSpec::
|
||||
has_query() const {
|
||||
return (_flags & F_has_query) != 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: URLSpec::get_authority
|
||||
// Access: Published
|
||||
// Description: Returns the authority specified by the URL (this
|
||||
// includes username, server, and/or port), or empty
|
||||
// string if no authority is specified.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE string URLSpec::
|
||||
get_authority() const {
|
||||
return _url.substr(_username_start, _port_end - _username_start);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: URLSpec::get_username
|
||||
// Access: Published
|
||||
// Description: Returns the username specified by the URL, if any.
|
||||
// This might also include a password,
|
||||
// e.g. "username:password", although putting a password
|
||||
// on the URL is probably a bad idea.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE string URLSpec::
|
||||
get_username() const {
|
||||
return _url.substr(_username_start, _username_end - _username_start);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: URLSpec::get_server
|
||||
// Access: Published
|
||||
// Description: Returns the server name specified by the URL, if any.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE string URLSpec::
|
||||
get_server() const {
|
||||
return _url.substr(_server_start, _server_end - _server_start);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: URLSpec::get_port_str
|
||||
// Access: Published
|
||||
// Description: Returns the port specified by the URL as a string, or
|
||||
// the empty string if no port is specified. Compare
|
||||
// this with get_port(), which returns a default port
|
||||
// number if no port is specified.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE string URLSpec::
|
||||
get_port_str() const {
|
||||
return _url.substr(_port_start, _port_end - _port_start);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: URLSpec::get_query
|
||||
// Access: Published
|
||||
// Description: Returns the query specified by the URL, or empty
|
||||
// string if no query is specified.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE string URLSpec::
|
||||
get_query() const {
|
||||
return _url.substr(_query_start);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: URLSpec::get_url
|
||||
// Access: Published
|
||||
// Description: Returns the complete URL specification.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const string &URLSpec::
|
||||
get_url() const {
|
||||
return _url;
|
||||
}
|
||||
|
||||
INLINE ostream &
|
||||
operator << (ostream &out, const URLSpec &url) {
|
||||
url.output(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,676 @@
|
|||
// Filename: urlSpec.cxx
|
||||
// Created by: drose (24Sep02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "urlSpec.h"
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: URLSpec::Constructor
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
URLSpec::
|
||||
URLSpec() {
|
||||
_port = 0;
|
||||
_flags = 0;
|
||||
_scheme_end = 0;
|
||||
_username_start = 0;
|
||||
_username_end = 0;
|
||||
_server_start = 0;
|
||||
_server_end = 0;
|
||||
_port_start = 0;
|
||||
_port_end = 0;
|
||||
_path_start = 0;
|
||||
_path_end = 0;
|
||||
_query_start = 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: URLSpec::Copy Assignment Operator
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void URLSpec::
|
||||
operator = (const URLSpec ©) {
|
||||
_url = copy._url;
|
||||
_port = copy._port;
|
||||
_flags = copy._flags;
|
||||
_scheme_end = copy._scheme_end;
|
||||
_username_start = copy._username_start;
|
||||
_username_end = copy._username_end;
|
||||
_server_start = copy._server_start;
|
||||
_server_end = copy._server_end;
|
||||
_port_start = copy._port_start;
|
||||
_port_end = copy._port_end;
|
||||
_path_start = copy._path_start;
|
||||
_path_end = copy._path_end;
|
||||
_query_start = copy._query_start;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: URLSpec::get_scheme
|
||||
// Access: Published
|
||||
// Description: Returns the scheme specified by the URL, or "http"
|
||||
// if no scheme is specified.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
string URLSpec::
|
||||
get_scheme() const {
|
||||
if (has_scheme()) {
|
||||
return _url.substr(0, _scheme_end);
|
||||
}
|
||||
return "http";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: URLSpec::get_port
|
||||
// Access: Published
|
||||
// Description: Returns the port number specified by the URL, or the
|
||||
// default port if not specified.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int URLSpec::
|
||||
get_port() const {
|
||||
if (has_port()) {
|
||||
return _port;
|
||||
}
|
||||
string scheme = get_scheme();
|
||||
if (scheme == "https") {
|
||||
return 443;
|
||||
|
||||
} else { // == "http"
|
||||
return 80;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: URLSpec::get_path
|
||||
// Access: Published
|
||||
// Description: Returns the path specified by the URL, or "/" if no
|
||||
// path is specified.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
string URLSpec::
|
||||
get_path() const {
|
||||
if (has_path()) {
|
||||
return _url.substr(_path_start, _path_end - _path_start);
|
||||
}
|
||||
return "/";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: URLSpec::set_scheme
|
||||
// Access: Published
|
||||
// Description: Replaces the scheme part of the URL specification.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void URLSpec::
|
||||
set_scheme(const string &scheme) {
|
||||
int length_adjust;
|
||||
|
||||
// The scheme is always converted to lowercase.
|
||||
string lc_scheme;
|
||||
lc_scheme.reserve(scheme.length());
|
||||
for (string::const_iterator si = scheme.begin(); si != scheme.end(); ++si) {
|
||||
lc_scheme += tolower(*si);
|
||||
}
|
||||
|
||||
if (lc_scheme.empty()) {
|
||||
// Remove the scheme specification.
|
||||
if (!has_scheme()) {
|
||||
return;
|
||||
}
|
||||
_scheme_end++;
|
||||
length_adjust = -(int)_scheme_end;
|
||||
_url = _url.substr(_scheme_end);
|
||||
_flags &= ~F_has_scheme;
|
||||
|
||||
} else if (!has_scheme()) {
|
||||
// Insert a new scheme specification.
|
||||
length_adjust = lc_scheme.length() + 1;
|
||||
|
||||
_url = lc_scheme + ":" + _url;
|
||||
_flags |= F_has_scheme;
|
||||
|
||||
} else {
|
||||
int old_length = (int)_scheme_end;
|
||||
length_adjust = scheme.length() - old_length;
|
||||
_url = lc_scheme + _url.substr(_scheme_end);
|
||||
}
|
||||
|
||||
_scheme_end += length_adjust;
|
||||
_username_start += length_adjust;
|
||||
_username_end += length_adjust;
|
||||
_server_start += length_adjust;
|
||||
_server_end += length_adjust;
|
||||
_port_start += length_adjust;
|
||||
_port_end += length_adjust;
|
||||
_path_start += length_adjust;
|
||||
_path_end += length_adjust;
|
||||
_query_start += length_adjust;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: URLSpec::set_authority
|
||||
// Access: Published
|
||||
// Description: Replaces the authority part of the URL specification.
|
||||
// This includes the username, server, and port.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void URLSpec::
|
||||
set_authority(const string &authority) {
|
||||
int length_adjust;
|
||||
|
||||
if (authority.empty()) {
|
||||
// Remove the authority specification.
|
||||
if (!has_authority()) {
|
||||
return;
|
||||
}
|
||||
_username_start -= 2;
|
||||
length_adjust = -((int)_port_end - (int)_username_start);
|
||||
_url = _url.substr(0, _username_start) + _url.substr(_port_end);
|
||||
_flags &= ~(F_has_authority | F_has_username | F_has_server | F_has_port);
|
||||
|
||||
_username_end = _username_start;
|
||||
_server_start = _username_start;
|
||||
_server_end = _username_start;
|
||||
_port_start = _username_start;
|
||||
|
||||
} else if (!has_authority()) {
|
||||
// Insert a new authority specification.
|
||||
length_adjust = authority.length() + 2;
|
||||
|
||||
_url = _url.substr(0, _username_start) + "//" + authority + _url.substr(_port_end);
|
||||
_flags |= F_has_authority;
|
||||
_username_start += 2;
|
||||
|
||||
} else {
|
||||
// Replace an existing authority specification.
|
||||
int old_length = (int)_port_end - (int)_username_start;
|
||||
length_adjust = authority.length() - old_length;
|
||||
_url = _url.substr(0, _username_start) + authority + _url.substr(_port_end);
|
||||
}
|
||||
|
||||
_port_end += length_adjust;
|
||||
_path_start += length_adjust;
|
||||
_path_end += length_adjust;
|
||||
_query_start += length_adjust;
|
||||
|
||||
parse_authority();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: URLSpec::set_username
|
||||
// Access: Published
|
||||
// Description: Replaces the username part of the URL specification.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void URLSpec::
|
||||
set_username(const string &username) {
|
||||
if (username.empty() && !has_authority()) {
|
||||
return;
|
||||
}
|
||||
string authority;
|
||||
|
||||
if (!username.empty()) {
|
||||
authority = username + "@";
|
||||
}
|
||||
authority += get_server();
|
||||
if (has_port()) {
|
||||
authority += ":";
|
||||
authority += get_port_str();
|
||||
}
|
||||
|
||||
set_authority(authority);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: URLSpec::set_server
|
||||
// Access: Published
|
||||
// Description: Replaces the server part of the URL specification.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void URLSpec::
|
||||
set_server(const string &server) {
|
||||
if (server.empty() && !has_authority()) {
|
||||
return;
|
||||
}
|
||||
string authority;
|
||||
|
||||
if (has_username()) {
|
||||
authority = get_username() + "@";
|
||||
}
|
||||
authority += server;
|
||||
if (has_port()) {
|
||||
authority += ":";
|
||||
authority += get_port_str();
|
||||
}
|
||||
|
||||
set_authority(authority);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: URLSpec::set_port
|
||||
// Access: Published
|
||||
// Description: Replaces the port part of the URL specification.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void URLSpec::
|
||||
set_port(const string &port) {
|
||||
if (port.empty() && !has_authority()) {
|
||||
return;
|
||||
}
|
||||
string authority;
|
||||
|
||||
if (has_username()) {
|
||||
authority = get_username() + "@";
|
||||
}
|
||||
authority += get_server();
|
||||
|
||||
if (!port.empty()) {
|
||||
authority += ":";
|
||||
authority += port;
|
||||
}
|
||||
|
||||
set_authority(authority);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: URLSpec::set_port
|
||||
// Access: Published
|
||||
// Description: Replaces the port part of the URL specification,
|
||||
// given a numeric port number.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void URLSpec::
|
||||
set_port(int port) {
|
||||
ostringstream str;
|
||||
str << port;
|
||||
set_port(str.str());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: URLSpec::set_path
|
||||
// Access: Published
|
||||
// Description: Replaces the path part of the URL specification.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void URLSpec::
|
||||
set_path(const string &path) {
|
||||
int length_adjust;
|
||||
|
||||
if (path.empty()) {
|
||||
// Remove the path specification.
|
||||
if (!has_path()) {
|
||||
return;
|
||||
}
|
||||
length_adjust = -((int)_path_end - (int)_path_start);
|
||||
_url = _url.substr(0, _path_start) + _url.substr(_path_end);
|
||||
_flags &= ~F_has_path;
|
||||
|
||||
} else if (!has_path()) {
|
||||
// Insert a new path specification.
|
||||
length_adjust = path.length();
|
||||
|
||||
_url = _url.substr(0, _path_start) + path + _url.substr(_path_end);
|
||||
_flags |= F_has_path;
|
||||
|
||||
} else {
|
||||
// Replace an existing path specification.
|
||||
int old_length = (int)_path_end - (int)_path_start;
|
||||
length_adjust = path.length() - old_length;
|
||||
_url = _url.substr(0, _path_start) + path + _url.substr(_path_end);
|
||||
}
|
||||
|
||||
_path_end += length_adjust;
|
||||
_query_start += length_adjust;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: URLSpec::set_query
|
||||
// Access: Published
|
||||
// Description: Replaces the query part of the URL specification.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void URLSpec::
|
||||
set_query(const string &query) {
|
||||
if (query.empty()) {
|
||||
// Remove the query specification.
|
||||
if (!has_query()) {
|
||||
return;
|
||||
}
|
||||
_query_start--;
|
||||
_url = _url.substr(0, _query_start);
|
||||
_flags &= ~F_has_query;
|
||||
|
||||
} else if (!has_query()) {
|
||||
// Insert a new query specification.
|
||||
_url = _url.substr(0, _query_start) + "?" + query;
|
||||
_flags |= F_has_query;
|
||||
_query_start++;
|
||||
|
||||
} else {
|
||||
// Replace an existing query specification.
|
||||
_url = _url.substr(0, _query_start) + query;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: URLSpec::set_url
|
||||
// Access: Published
|
||||
// Description: Completely replaces the URL with the indicated
|
||||
// string.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void URLSpec::
|
||||
set_url(const string &url) {
|
||||
_url = url;
|
||||
_flags = 0;
|
||||
|
||||
// First, replace backslashes with forward slashes, since this is a
|
||||
// common mistake among Windows users.
|
||||
size_t p;
|
||||
for (p = 0; p < _url.length(); p++) {
|
||||
if (_url[p] == '\\') {
|
||||
_url[p] = '/';
|
||||
}
|
||||
}
|
||||
|
||||
// What have we got?
|
||||
_flags = 0;
|
||||
_port = 0;
|
||||
|
||||
// Look for the scheme specification.
|
||||
size_t start = 0;
|
||||
|
||||
_scheme_end = start;
|
||||
size_t next = _url.find_first_of(":/", start);
|
||||
if (next != string::npos && _url[next] == ':') {
|
||||
// We have a scheme.
|
||||
_flags |= F_has_scheme;
|
||||
_scheme_end = next;
|
||||
|
||||
// Ensure the scheme is lowercase.
|
||||
for (size_t p = 0; p < _scheme_end; ++p) {
|
||||
_url[p] = tolower(_url[p]);
|
||||
}
|
||||
|
||||
start = next + 1;
|
||||
}
|
||||
|
||||
// Look for the authority specification, which may include any of
|
||||
// username, server, and/or port.
|
||||
_username_start = start;
|
||||
_username_end = start;
|
||||
_server_start = start;
|
||||
_server_end = start;
|
||||
_port_start = start;
|
||||
_port_end = start;
|
||||
if (start + 1 < _url.length() && _url.substr(start, 2) == "//") {
|
||||
// We have an authority specification.
|
||||
start += 2;
|
||||
_flags |= F_has_authority;
|
||||
_username_start = start;
|
||||
_port_end = _url.find_first_of("/?", start);
|
||||
if (_port_end == string::npos) {
|
||||
_port_end = _url.length();
|
||||
}
|
||||
parse_authority();
|
||||
start = _port_end;
|
||||
}
|
||||
|
||||
// Everything up to the ?, if any, is the path.
|
||||
_path_start = start;
|
||||
_path_end = start;
|
||||
if (start < _url.length() && url[start] != '?') {
|
||||
// We have a path.
|
||||
_flags |= F_has_path;
|
||||
_path_start = start;
|
||||
_path_end = _url.find("?", _path_start);
|
||||
if (_path_end == string::npos) {
|
||||
_path_end = _url.length();
|
||||
}
|
||||
start = _path_end;
|
||||
}
|
||||
|
||||
// Everything after the ? is the query.
|
||||
_query_start = start;
|
||||
if (start < _url.length()) {
|
||||
nassertv(_url[start] == '?');
|
||||
_flags |= F_has_query;
|
||||
_query_start++;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: URLSpec::output
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void URLSpec::
|
||||
output(ostream &out) const {
|
||||
out << get_url();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: URLSpec::quote
|
||||
// Access: Published, Static
|
||||
// Description: Returns the source string with all "unsafe"
|
||||
// characters quoted, making a string suitable for
|
||||
// placing in a URL. Letters, digits, and the
|
||||
// underscore, comma, period, and hyphen characters, as
|
||||
// well as any included in the safe string, are left
|
||||
// alone; all others are converted to hex
|
||||
// representation.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
string URLSpec::
|
||||
quote(const string &source, const string &safe) {
|
||||
ostringstream result;
|
||||
result << hex << setw(2) << setfill('0');
|
||||
|
||||
for (string::const_iterator si = source.begin(); si != source.end(); ++si) {
|
||||
char ch = (*si);
|
||||
switch (ch) {
|
||||
case '_':
|
||||
case ',':
|
||||
case '.':
|
||||
case '-':
|
||||
// Safe character.
|
||||
result << ch;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (isalnum(ch)) {
|
||||
// Letters and digits are safe.
|
||||
result << ch;
|
||||
|
||||
} else if (safe.find(ch) != string::npos) {
|
||||
// If it's listed in "safe", it's safe.
|
||||
result << ch;
|
||||
|
||||
} else {
|
||||
// Otherwise, escape it.
|
||||
result << "0x" << ch;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result.str();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: URLSpec::quote_plus
|
||||
// Access: Published, Static
|
||||
// Description: Behaves like quote() with the additional behavior of
|
||||
// replacing spaces with plus signs.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
string URLSpec::
|
||||
quote_plus(const string &source, const string &safe) {
|
||||
ostringstream result;
|
||||
result << hex << setw(2) << setfill('0');
|
||||
|
||||
for (string::const_iterator si = source.begin(); si != source.end(); ++si) {
|
||||
char ch = (*si);
|
||||
switch (ch) {
|
||||
case '_':
|
||||
case ',':
|
||||
case '.':
|
||||
case '-':
|
||||
// Safe character.
|
||||
result << ch;
|
||||
break;
|
||||
|
||||
case ' ':
|
||||
result << '+';
|
||||
break;
|
||||
|
||||
default:
|
||||
if (isalnum(ch)) {
|
||||
// Letters and digits are safe.
|
||||
result << ch;
|
||||
|
||||
} else if (safe.find(ch) != string::npos) {
|
||||
// If it's listed in "safe", it's safe.
|
||||
result << ch;
|
||||
|
||||
} else {
|
||||
// Otherwise, escape it.
|
||||
result << "0x" << ch;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result.str();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: URLSpec::unquote
|
||||
// Access: Published, Static
|
||||
// Description: Reverses the operation of quote(): converts escaped
|
||||
// characters of the form "%xx" to their ascii
|
||||
// equivalent.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
string URLSpec::
|
||||
unquote(const string &source) {
|
||||
string result;
|
||||
|
||||
string::const_iterator si = source.begin();
|
||||
while (si != source.end()) {
|
||||
if ((*si) == '%') {
|
||||
++si;
|
||||
int hex = 0;
|
||||
while (si != source.end() && isxdigit(*si)) {
|
||||
int value;
|
||||
char ch = *si;
|
||||
if (isdigit(ch)) {
|
||||
value = ch - '0';
|
||||
} else {
|
||||
value = tolower(ch) - 'a';
|
||||
}
|
||||
hex = (hex << 8) | value;
|
||||
++si;
|
||||
}
|
||||
result += (char)hex;
|
||||
|
||||
} else {
|
||||
result += (*si);
|
||||
++si;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: URLSpec::unquote_plus
|
||||
// Access: Published, Static
|
||||
// Description: Reverses the operation of quote_plus(): converts escaped
|
||||
// characters of the form "%xx" to their ascii
|
||||
// equivalent, and also converts plus signs to spaces.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
string URLSpec::
|
||||
unquote_plus(const string &source) {
|
||||
string result;
|
||||
|
||||
string::const_iterator si = source.begin();
|
||||
while (si != source.end()) {
|
||||
if ((*si) == '%') {
|
||||
++si;
|
||||
int hex = 0;
|
||||
while (si != source.end() && isxdigit(*si)) {
|
||||
int value;
|
||||
char ch = *si;
|
||||
if (isdigit(ch)) {
|
||||
value = ch - '0';
|
||||
} else {
|
||||
value = tolower(ch) - 'a';
|
||||
}
|
||||
hex = (hex << 8) | value;
|
||||
++si;
|
||||
}
|
||||
result += (char)hex;
|
||||
|
||||
} else if ((*si) == '+') {
|
||||
result += ' ';
|
||||
|
||||
} else {
|
||||
result += (*si);
|
||||
++si;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: URLSpec::parse_authority
|
||||
// Access: Private
|
||||
// Description: Assumes _url[_username_start .. _port_end - 1] is
|
||||
// the authority component if the URL, consisting of
|
||||
// [username@]server[:port]. Parses out the three
|
||||
// pieces and updates the various _start and _end
|
||||
// parameters accordingly.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void URLSpec::
|
||||
parse_authority() {
|
||||
if (!has_authority()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Assume we don't have a username or port unless we find them.
|
||||
_username_end = _username_start;
|
||||
_port_start = _port_end;
|
||||
|
||||
// We assume we have a server, even if it becomes the empty string.
|
||||
_flags |= F_has_server;
|
||||
_server_start = _username_start;
|
||||
_server_end = _port_end;
|
||||
|
||||
// Is there a username?
|
||||
size_t at_sign = _url.find('@', _username_start);
|
||||
if (at_sign < _port_end) {
|
||||
// We have a username.
|
||||
_flags |= F_has_username;
|
||||
_username_end = at_sign;
|
||||
_server_start = at_sign + 1;
|
||||
}
|
||||
|
||||
// Is there a port?
|
||||
size_t colon = _url.find(':', _server_start);
|
||||
if (colon < _port_end) {
|
||||
// Yep.
|
||||
_flags |= F_has_port;
|
||||
_server_end = colon;
|
||||
_port_start = colon + 1;
|
||||
|
||||
// Decode the port into an integer. Don't bother to error
|
||||
// check if it's not really an integer.
|
||||
string port_str = _url.substr(_port_start, _port_end - _port_start);
|
||||
_port = atoi(port_str.c_str());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
// Filename: urlSpec.h
|
||||
// Created by: drose (24Sep02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 URLSPEC_H
|
||||
#define URLSPEC_H
|
||||
|
||||
#include "pandabase.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : URLSpec
|
||||
// Description : A container for a URL, e.g. "http://server:port/path".
|
||||
//
|
||||
// The URLSpec object is similar to a Filename in that
|
||||
// it contains logic to identify the various parts of a
|
||||
// URL and return (or modify) them separately.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDAEXPRESS URLSpec {
|
||||
PUBLISHED:
|
||||
URLSpec();
|
||||
INLINE URLSpec(const string &url);
|
||||
INLINE URLSpec(const URLSpec ©);
|
||||
INLINE void operator = (const string &url);
|
||||
void operator = (const URLSpec ©);
|
||||
|
||||
INLINE bool has_scheme() const;
|
||||
INLINE bool has_authority() const;
|
||||
INLINE bool has_username() const;
|
||||
INLINE bool has_server() const;
|
||||
INLINE bool has_port() const;
|
||||
INLINE bool has_path() const;
|
||||
INLINE bool has_query() const;
|
||||
|
||||
string get_scheme() const;
|
||||
INLINE string get_authority() const;
|
||||
INLINE string get_username() const;
|
||||
INLINE string get_server() const;
|
||||
INLINE string get_port_str() const;
|
||||
int get_port() const;
|
||||
string get_path() const;
|
||||
INLINE string get_query() const;
|
||||
|
||||
INLINE const string &get_url() const;
|
||||
|
||||
void set_scheme(const string &scheme);
|
||||
void set_authority(const string &authority);
|
||||
void set_username(const string &username);
|
||||
void set_server(const string &server);
|
||||
void set_port(const string &port);
|
||||
void set_port(int port);
|
||||
void set_path(const string &path);
|
||||
void set_query(const string &query);
|
||||
|
||||
void set_url(const string &url);
|
||||
|
||||
void output(ostream &out) const;
|
||||
|
||||
static string quote(const string &source, const string &safe = "/");
|
||||
static string quote_plus(const string &source, const string &safe = "/");
|
||||
static string unquote(const string &source);
|
||||
static string unquote_plus(const string &source);
|
||||
|
||||
private:
|
||||
void parse_authority();
|
||||
|
||||
enum Flags {
|
||||
F_has_scheme = 0x0001,
|
||||
F_has_authority = 0x0002,
|
||||
F_has_username = 0x0004,
|
||||
F_has_server = 0x0008,
|
||||
F_has_port = 0x0010,
|
||||
F_has_path = 0x0020,
|
||||
F_has_query = 0x0040,
|
||||
};
|
||||
|
||||
string _url;
|
||||
int _port;
|
||||
int _flags;
|
||||
|
||||
size_t _scheme_end;
|
||||
size_t _username_start;
|
||||
size_t _username_end;
|
||||
size_t _server_start;
|
||||
size_t _server_end;
|
||||
size_t _port_start;
|
||||
size_t _port_end;
|
||||
size_t _path_start;
|
||||
size_t _path_end;
|
||||
size_t _query_start;
|
||||
};
|
||||
|
||||
INLINE ostream &operator << (ostream &out, const URLSpec &url);
|
||||
|
||||
#include "urlSpec.I"
|
||||
|
||||
#endif
|
||||
|
||||
Loading…
Reference in New Issue