#pragma once #include #include #include "utility.hpp" #ifndef YAHTTP_MAX_URL_LENGTH #define YAHTTP_MAX_URL_LENGTH 2048 #endif namespace YaHTTP { /*! URL parser and container */ class URL { private: bool parseSchema(const std::string& url, size_t &pos) { size_t pos1; if (pos >= url.size()) return false; // no data if ( (pos1 = url.find_first_of(":",pos)) == std::string::npos ) return false; // schema is mandatory protocol = url.substr(pos, pos1-pos); if (protocol == "http") port = 80; if (protocol == "https") port = 443; pos = pos1+1; // after : if (url.compare(pos, 2, "//") == 0) { pathless = false; // if this is true we put rest into parameters pos += 2; } return true; }; //= url.size()) return true; // no data if ( (pos1 = url.find_first_of("/", pos)) == std::string::npos ) { host = url.substr(pos); path = "/"; pos = url.size(); } else { host = url.substr(pos, pos1-pos); pos = pos1; } if (host.at(0) == '[') { // IPv6 if ((pos1 = host.find_first_of("]")) == std::string::npos) { // incomplete address return false; } size_t pos2; if ((pos2 = host.find_first_of(":", pos1)) != std::string::npos) { std::istringstream tmp(host.substr(pos2 + 1)); tmp >> port; } host = host.substr(1, pos1 - 1); } else if ( (pos1 = host.find_first_of(":")) != std::string::npos ) { std::istringstream tmp(host.substr(pos1+1)); tmp >> port; host = host.substr(0, pos1); } return true; }; //= url.size()) return true; // no data if ( (pos1 = url.find_first_of("@",pos)) == std::string::npos ) return true; // no userinfo pos2 = url.find_first_of(":",pos); if (pos2 != std::string::npos) { // comes with password username = url.substr(pos, pos2 - pos); password = url.substr(pos2+1, pos1 - pos2 - 1); password = Utility::decodeURL(password); } else { username = url.substr(pos, pos1 - pos); } pos = pos1+1; username = Utility::decodeURL(username); return true; }; //= url.size()) return true; // no data if (url[pos] != '/') return false; // not an url if ( (pos1 = url.find_first_of("?", pos)) == std::string::npos ) { path = url.substr(pos); pos = url.size(); } else { path = url.substr(pos, pos1-pos); pos = pos1; } return true; }; //= url.size()) return true; // no data if (url[pos] == '#') return true; // anchor starts here if (url[pos] != '?') return false; // not a parameter if ( (pos1 = url.find_first_of("#", pos)) == std::string::npos ) { parameters = url.substr(pos+1);; pos = url.size(); } else { parameters = url.substr(pos+1, pos1-pos-1); pos = pos1; } if (parameters.size()>0 && *(parameters.end()-1) == '&') parameters.resize(parameters.size()-1); return true; }; //= url.size()) return true; // no data if (url[pos] != '#') return false; // not anchor anchor = url.substr(pos+1); return true; }; // 0) oss << ":" << port; oss << path; if (parameters.empty() == false) { if (!pathless) oss << "?"; oss << parameters; } if (anchor.empty() == false) oss << "#" << anchor; return oss.str(); }; // YAHTTP_MAX_URL_LENGTH) return false; size_t pos = 0; if (*(url.begin()) != '/') { // full url? if (parseSchema(url, pos) == false) return false; if (pathless) { parameters = url.substr(pos); return true; } if (parseUserPass(url, pos) == false) return false; if (parseHost(url, pos) == false) return false; } if (parsePath(url, pos) == false) return false; if (parseParameters(url, pos) == false) return false; return parseAnchor(url, pos); }; //