123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285 |
- #include <sstream>
- #include <algorithm>
- #include <map>
- #include <string.h>
- #include <ctype.h>
- #include "BBS2chProxyURL.h"
- #include "BBS2chProxyFormData.h"
- static std::string trim(const std::string& str, const char *trimCharacters = " \t\v\r\n")
- {
- std::string trimmed;
- size_t start = str.find_first_not_of(trimCharacters);
- if (start != std::string::npos) {
- size_t end = str.find_last_not_of(trimCharacters);
- trimmed = str.substr(start, end-start+1);
- }
- return trimmed;
- }
- static std::string trimEnd(const std::string& str, const char *trimCharacters = " \t\v\r\n")
- {
- std::string trimmed;
- size_t pos = str.find_last_not_of(trimCharacters);
- if (pos != std::string::npos) {
- trimmed = str.substr(0, pos+1);
- }
- return trimmed;
- }
- BBS2chProxyURL::BBS2chProxyURL(const char *url) : _port(0), _dirty(true)
- {
- const char *ptr = url;
- while (isspace(*ptr)) ptr++;
- const char *start = ptr;
- ptr = strstr(start, "://");
- if (ptr) {
- _scheme = std::string(start, ptr-start);
- ptr += 3;
- }
- if (!ptr) {
- ptr = start;
- }
- std::transform(_scheme.begin(), _scheme.end(), _scheme.begin(), tolower);
- start = ptr;
- const char *ptr2 = NULL;
- while (*ptr != '/' && *ptr) {
- if (*ptr == '@') {
- _auth = std::string(start, ptr-start);
- start = ptr+1;
- ptr2 = NULL;
- }
- else if (*ptr == ':') ptr2 = ptr;
- ptr++;
- }
- if (ptr2) {
- _port = atoi(ptr2+1);
- _host = std::string(start, ptr2-start);
- }
- else {
- _host = std::string(start, ptr-start);
- }
- std::transform(_host.begin(), _host.end(), _host.begin(), tolower);
- _pathAndOthers = trimEnd(std::string(ptr));
- if (_scheme.empty()) {
- if (_port == 443) _scheme = "https";
- else _scheme = "http";
- }
- if (_pathAndOthers.empty()) _pathAndOthers = "/";
- if (_port == 80 && _scheme == "http") _port = 0;
- else if (_port == 443 && _scheme == "https") _port = 0;
- }
- BBS2chProxyURL::BBS2chProxyURL(const char *scheme, const char *host) : _port(0), _dirty(true)
- {
- _scheme = trim(std::string(scheme));
- _host = trim(std::string(host));
- _pathAndOthers = "/";
- std::transform(_scheme.begin(), _scheme.end(), _scheme.begin(), tolower);
- std::transform(_host.begin(), _host.end(), _host.begin(), tolower);
- }
- BBS2chProxyURL::BBS2chProxyURL(const char *scheme, const char *host, int port, const char *path) : _dirty(true)
- {
- _scheme = trim(std::string(scheme));
- _host = trim(std::string(host));
- _port = port;
- if (*path == '/') _pathAndOthers = trim(std::string(path));
- else _pathAndOthers = "/" + trim(std::string(path));
- std::transform(_scheme.begin(), _scheme.end(), _scheme.begin(), tolower);
- std::transform(_host.begin(), _host.end(), _host.begin(), tolower);
- if (_port == 80 && _scheme == "http") _port = 0;
- else if (_port == 443 && _scheme == "https") _port = 0;
- }
- BBS2chProxyURL::BBS2chProxyURL(const BBS2chProxyURL &baseURL, const char *path) : _dirty(true)
- {
- _scheme = baseURL._scheme;
- _host = baseURL._host;
- _auth = baseURL._auth;
- _port = baseURL._port;
- if (*path == '/') _pathAndOthers = trim(std::string(path));
- else _pathAndOthers = "/" + trim(std::string(path));
- }
- const std::string& BBS2chProxyURL::absoluteString()
- {
- if (_dirty) {
- if (_port) {
- std::ostringstream url;
- url << _scheme << "://";
- if (!_auth.empty()) url << _auth << "@";
- url << _host;
- url << ":" << _port;
- url << _pathAndOthers;
- _absoluteURLString = url.str();
- }
- else {
- _absoluteURLString = _scheme;
- _absoluteURLString += "://";
- if (!_auth.empty()) {
- _absoluteURLString += _auth;
- _absoluteURLString += '@';
- }
- _absoluteURLString += _host;
- _absoluteURLString += _pathAndOthers;
- }
- _dirty = false;
- }
- return _absoluteURLString;
- }
- const std::string& BBS2chProxyURL::getScheme() const
- {
- return _scheme;
- }
- const std::string& BBS2chProxyURL::getHost() const
- {
- return _host;
- }
- const std::string& BBS2chProxyURL::getPathAndOthers() const
- {
- return _pathAndOthers;
- }
- std::string BBS2chProxyURL::getPath() const
- {
- size_t queryBegin = _pathAndOthers.find("?");
- size_t fragmentBegin = _pathAndOthers.find("#");
- return _pathAndOthers.substr(0, std::min(queryBegin, fragmentBegin));
- }
- int BBS2chProxyURL::getPort() const
- {
- return _port;
- }
- void BBS2chProxyURL::setScheme(const std::string &scheme)
- {
- _scheme = scheme;
- _port = 0;
- _dirty = true;
- }
- void BBS2chProxyURL::setPort(int port)
- {
- if (port == _port) return;
- _port = port;
- if (_port == 80 && _scheme == "http") _port = 0;
- else if (_port == 443 && _scheme == "https") _port = 0;
- _dirty = true;
- }
- bool BBS2chProxyURL::isHttp() const
- {
- return _scheme == "http" || _scheme == "https";
- }
- bool BBS2chProxyURL::isValid() const
- {
- return !_scheme.empty() && !_host.empty();
- }
- bool BBS2chProxyURL::equalsTo(const BBS2chProxyURL &url, bool ignoreHttpOrHttps) const
- {
- if (ignoreHttpOrHttps && isHttp() && url.isHttp()) {
- return _host == url._host && _pathAndOthers == url._pathAndOthers;
- }
- return _scheme == url._scheme && _host == url._host && _port == url._port && _pathAndOthers == url._pathAndOthers;
- }
- bool BBS2chProxyURL::isKindOfHost(const std::string &hostSuffix) const
- {
- size_t len1 = _host.length();
- size_t len2 = hostSuffix.length();
- if (len1 == len2) return (_host == hostSuffix);
- else if (len1 > len2) {
- return (_host.at(len1-len2-1) == '.') && (_host.compare(len1-len2, len2, hostSuffix) == 0);
- }
- return false;
- }
- bool BBS2chProxyURL::replaceHost(const std::string &fromHost, const std::string &toHost)
- {
- size_t len1 = _host.length();
- size_t len2 = fromHost.length();
- if (len1 == len2) {
- if (_host == fromHost) {
- _host = toHost;
- _dirty = true;
- return true;
- }
- }
- else if (len1 > len2) {
- if ((_host.at(len1-len2-1) == '.') && (_host.compare(len1-len2, len2, fromHost) == 0)) {
- _host.replace(len1-len2, len2, toHost);
- _dirty = true;
- return true;
- }
- }
- return false;
- }
- bool BBS2chProxyURL::isFamilyOf5chNet() const
- {
- return isKindOfHost("5ch.net") || isKindOfHost("2ch.net") || isKindOfHost("bbspink.com");
- }
- bool BBS2chProxyURL::pathStartsWith(const std::string &prefix) const
- {
- size_t len1 = _pathAndOthers.length();
- size_t len2 = prefix.length();
- if (len1 < len2) return false;
- return _pathAndOthers.compare(0, len2, prefix) == 0;
- }
- bool BBS2chProxyURL::pathEndsWith(const std::string &suffix) const
- {
- size_t len1 = _pathAndOthers.length();
- size_t len2 = suffix.length();
- if (len1 < len2) return false;
- return _pathAndOthers.compare(len1-len2, len2, suffix) == 0;
- }
- bool BBS2chProxyURL::hostStartsWith(const std::string &prefix) const
- {
- size_t len1 = _host.length();
- size_t len2 = prefix.length();
- if (len1 < len2) return false;
- return _host.compare(0, len2, prefix) == 0;
- }
- std::map<std::string, std::string> BBS2chProxyURL::getQuery() const
- {
- std::map<std::string, std::string> fields;
- size_t pos = _pathAndOthers.find("?");
- if (pos != std::string::npos) {
- const char *start = _pathAndOthers.c_str() + pos + 1;
- const char *ptr = start;
- while (*ptr != 0 && *ptr != '#') ptr++;
- BBS2chProxyFormData query(start, ptr-start);
- for (BBS2chProxyFormData::iterator it = query.begin(); it != query.end(); ++it) {
- fields.insert(std::make_pair(it->first, it->second.get()));
- }
- }
- return fields;
- }
- int BBS2chProxyURL::numberOfPathComponents() const
- {
- size_t idx = 0;
- int ret = 0;
- while (idx < _pathAndOthers.size()) {
- size_t pos = _pathAndOthers.find("/", idx);
- if (pos == std::string::npos) {
- ret++;
- break;
- }
- if (pos != idx) ret++;
- idx = pos + 1;
- }
- return ret;
- }
|