BBS2chProxyURL.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. #include <sstream>
  2. #include <algorithm>
  3. #include <string.h>
  4. #include <ctype.h>
  5. #include "BBS2chProxyURL.h"
  6. static std::string trim(const std::string& str, const char *trimCharacters = " \t\v\r\n")
  7. {
  8. std::string trimmed;
  9. size_t start = str.find_first_not_of(trimCharacters);
  10. if (start != std::string::npos) {
  11. size_t end = str.find_last_not_of(trimCharacters);
  12. trimmed = str.substr(start, end-start+1);
  13. }
  14. return trimmed;
  15. }
  16. static std::string trimEnd(const std::string& str, const char *trimCharacters = " \t\v\r\n")
  17. {
  18. std::string trimmed;
  19. size_t pos = str.find_last_not_of(trimCharacters);
  20. if (pos != std::string::npos) {
  21. trimmed = str.substr(0, pos+1);
  22. }
  23. return trimmed;
  24. }
  25. BBS2chProxyURL::BBS2chProxyURL(const char *url) : _port(0), _dirty(true)
  26. {
  27. const char *ptr = url;
  28. while (isspace(*ptr)) ptr++;
  29. const char *start = ptr;
  30. ptr = strstr(start, "://");
  31. if (ptr) {
  32. _scheme = std::string(start, ptr-start);
  33. ptr += 3;
  34. }
  35. if (!ptr) {
  36. ptr = start;
  37. }
  38. std::transform(_scheme.begin(), _scheme.end(), _scheme.begin(), tolower);
  39. start = ptr;
  40. const char *ptr2 = NULL;
  41. while (*ptr != '/' && *ptr) {
  42. if (*ptr == '@') {
  43. _auth = std::string(start, ptr-start);
  44. start = ptr+1;
  45. ptr2 = NULL;
  46. }
  47. else if (*ptr == ':') ptr2 = ptr;
  48. ptr++;
  49. }
  50. if (ptr2) {
  51. _port = atoi(ptr2+1);
  52. _host = std::string(start, ptr2-start);
  53. }
  54. else {
  55. _host = std::string(start, ptr-start);
  56. }
  57. std::transform(_host.begin(), _host.end(), _host.begin(), tolower);
  58. _pathAndOthers = trimEnd(std::string(ptr));
  59. if (_scheme.empty()) {
  60. if (_port == 443) _scheme = "https";
  61. else _scheme = "http";
  62. }
  63. if (_pathAndOthers.empty()) _pathAndOthers = "/";
  64. if (_port == 80 && _scheme == "http") _port = 0;
  65. else if (_port == 443 && _scheme == "https") _port = 0;
  66. }
  67. BBS2chProxyURL::BBS2chProxyURL(const char *scheme, const char *host) : _port(0), _dirty(true)
  68. {
  69. _scheme = trim(std::string(scheme));
  70. _host = trim(std::string(host));
  71. _pathAndOthers = "/";
  72. std::transform(_scheme.begin(), _scheme.end(), _scheme.begin(), tolower);
  73. std::transform(_host.begin(), _host.end(), _host.begin(), tolower);
  74. }
  75. BBS2chProxyURL::BBS2chProxyURL(const char *scheme, const char *host, int port, const char *path) : _dirty(true)
  76. {
  77. _scheme = trim(std::string(scheme));
  78. _host = trim(std::string(host));
  79. _port = port;
  80. if (*path == '/') _pathAndOthers = trim(std::string(path));
  81. else _pathAndOthers = "/" + trim(std::string(path));
  82. std::transform(_scheme.begin(), _scheme.end(), _scheme.begin(), tolower);
  83. std::transform(_host.begin(), _host.end(), _host.begin(), tolower);
  84. if (_port == 80 && _scheme == "http") _port = 0;
  85. else if (_port == 443 && _scheme == "https") _port = 0;
  86. }
  87. BBS2chProxyURL::BBS2chProxyURL(const BBS2chProxyURL &baseURL, const char *path) : _dirty(true)
  88. {
  89. _scheme = baseURL._scheme;
  90. _host = baseURL._host;
  91. _auth = baseURL._auth;
  92. _port = baseURL._port;
  93. if (*path == '/') _pathAndOthers = trim(std::string(path));
  94. else _pathAndOthers = "/" + trim(std::string(path));
  95. }
  96. const std::string& BBS2chProxyURL::absoluteString()
  97. {
  98. if (_dirty) {
  99. if (_port) {
  100. std::ostringstream url;
  101. url << _scheme << "://";
  102. if (!_auth.empty()) url << _auth << "@";
  103. url << _host;
  104. url << ":" << _port;
  105. url << _pathAndOthers;
  106. _absoluteURLString = url.str();
  107. }
  108. else {
  109. _absoluteURLString = _scheme;
  110. _absoluteURLString += "://";
  111. if (!_auth.empty()) {
  112. _absoluteURLString += _auth;
  113. _absoluteURLString += '@';
  114. }
  115. _absoluteURLString += _host;
  116. _absoluteURLString += _pathAndOthers;
  117. }
  118. _dirty = false;
  119. }
  120. return _absoluteURLString;
  121. }
  122. const std::string& BBS2chProxyURL::getScheme() const
  123. {
  124. return _scheme;
  125. }
  126. const std::string& BBS2chProxyURL::getHost() const
  127. {
  128. return _host;
  129. }
  130. const std::string& BBS2chProxyURL::getPathAndOthers() const
  131. {
  132. return _pathAndOthers;
  133. }
  134. void BBS2chProxyURL::setScheme(const std::string &scheme)
  135. {
  136. _scheme = scheme;
  137. _port = 0;
  138. _dirty = true;
  139. }
  140. void BBS2chProxyURL::setPort(int port)
  141. {
  142. if (port == _port) return;
  143. _port = port;
  144. if (_port == 80 && _scheme == "http") _port = 0;
  145. else if (_port == 443 && _scheme == "https") _port = 0;
  146. _dirty = true;
  147. }
  148. bool BBS2chProxyURL::isHttp() const
  149. {
  150. return _scheme == "http" || _scheme == "https";
  151. }
  152. bool BBS2chProxyURL::isValid() const
  153. {
  154. return !_scheme.empty() && !_host.empty();
  155. }
  156. bool BBS2chProxyURL::equals(const BBS2chProxyURL &url, bool ignoreHttpOrHttps) const
  157. {
  158. if (ignoreHttpOrHttps && isHttp() && url.isHttp()) {
  159. return _host == url._host && _pathAndOthers == url._pathAndOthers;
  160. }
  161. return _scheme == url._scheme && _host == url._host && _port == url._port && _pathAndOthers == url._pathAndOthers;
  162. }
  163. bool BBS2chProxyURL::isKindOfHost(const std::string &hostSuffix) const
  164. {
  165. size_t len1 = _host.length();
  166. size_t len2 = hostSuffix.length();
  167. if (len1 == len2) return (_host == hostSuffix);
  168. else if (len1 > len2) {
  169. return (_host.at(len1-len2-1) == '.') && (_host.compare(len1-len2, len2, hostSuffix) == 0);
  170. }
  171. return false;
  172. }
  173. bool BBS2chProxyURL::replaceHost(const std::string &fromHost, const std::string &toHost)
  174. {
  175. size_t len1 = _host.length();
  176. size_t len2 = fromHost.length();
  177. if (len1 == len2) {
  178. if (_host == fromHost) {
  179. _host = toHost;
  180. _dirty = true;
  181. return true;
  182. }
  183. }
  184. else if (len1 > len2) {
  185. if ((_host.at(len1-len2-1) == '.') && (_host.compare(len1-len2, len2, fromHost) == 0)) {
  186. _host.replace(len1-len2, len2, toHost);
  187. _dirty = true;
  188. return true;
  189. }
  190. }
  191. return false;
  192. }
  193. bool BBS2chProxyURL::isFamilyOf5chNet() const
  194. {
  195. return isKindOfHost("5ch.net") || isKindOfHost("2ch.net") || isKindOfHost("bbspink.com");
  196. }
  197. bool BBS2chProxyURL::pathStartsWith(const std::string &prefix) const
  198. {
  199. size_t len1 = _pathAndOthers.length();
  200. size_t len2 = prefix.length();
  201. if (len1 < len2) return false;
  202. return _pathAndOthers.compare(0, len2, prefix) == 0;
  203. }
  204. bool BBS2chProxyURL::hostStartsWith(const std::string &prefix) const
  205. {
  206. size_t len1 = _host.length();
  207. size_t len2 = prefix.length();
  208. if (len1 < len2) return false;
  209. return _host.compare(0, len2, prefix) == 0;
  210. }