// TJP COPYRIGHT HEADER // TJP 4/09/01 relative URLs have not been checked yet. don't expect them // to work the first time you use this class! // // TJP 4/11/01 getAsLocalPath needs to be modified to work with all sorts // of protocols and port numbers... right now, probably not #include "URL.h" #include "../file/Path.h" #include #include namespace tjp { namespace core { namespace internet { const URL Empty; const char FS = '/'; //const char BS = '\\'; const char *DD = ".."; bool URL::isAbsoluteURL (const std::string &url) { return url.find("://") != -1; } void URL::parseAbsoluteURL (const std::string &url) { auto protocolBegin = 0; auto protocolEnd = url.find("://"); if (protocolEnd==-1) { throw Exception ("Could not find protocol"); } auto serverBegin = protocolEnd + std::string("://").length(); auto serverEnd = url.find (FS, serverBegin); if (serverEnd==-1) { throw Exception ("Could not find server"); } auto directoryBegin = serverEnd + 1; auto directoryEnd = url.find_last_of (FS) + 1; auto fileBegin = directoryEnd; auto fileEnd = url.length(); protocol = url.substr (protocolBegin, protocolEnd-protocolBegin); server = url.substr (serverBegin, serverEnd-serverBegin); directory = url.substr (directoryBegin, directoryEnd-directoryBegin); file = url.substr (fileBegin, fileEnd-fileBegin); } void URL::parseRelativeURL (const std::string &url) { auto directoryBegin = 0; auto directoryEnd = url.find_last_of (FS) + 1; auto fileBegin = directoryEnd; auto fileEnd = url.length(); std::string relativeDirectory = url.substr (directoryBegin, directoryEnd-directoryBegin); if (relativeDirectory.substr (0,2) == "./") { relativeDirectory = relativeDirectory.substr(2); } std::string relativeFile = url.substr (fileBegin, fileEnd-fileBegin); if ( (relativeDirectory.length()>0 && directory.length()>0) && ((directory[directory.length()-1]==FS) && relativeDirectory[0]==FS) ) { directory += relativeDirectory.substr(1); } else { directory += relativeDirectory; } file = url.substr (fileBegin, fileEnd-fileBegin); } URL::URL () { } URL::URL (const std::string &url) { parseAbsoluteURL (url); } URL::URL (const URL &parent, const std::string &url) { if (isAbsoluteURL (url)) { parseAbsoluteURL (url); } else { protocol = parent.getProtocol(); server = parent.getServer(); directory = parent.getDirectory(); parseRelativeURL (url); } } URL::URL (const URL &url) { protocol = url.protocol; server = url.server; directory = url.directory; file = url.file; } URL::~URL () { } const std::string &URL::getProtocol () const { return protocol; } const std::string &URL::getServer() const { return server; } std::string URL::getPath () const { return directory + file; } const std::string &URL::getDirectory () const { return directory; } const std::string &URL::getFile () const { return file; } URL URL::join(const URL &url, const std::string &append) { if (append.empty()) return url; return URL((std::string)url + FS + append); } URL::operator std::string() const { return getProtocol() + "://" + getServer() + FS + getPath(); } bool URL::operator <(const URL &right) const { // this implementation should be redone probably auto p = cmp_case(protocol, right.protocol); if (p < 0) return true; if (p > 0) return false; auto s = cmp_case(server, right.server); if (s < 0) return true; if (s > 0) return false; auto d = cmp_case(directory, right.directory); if (d < 0) return true; if (d > 0) return false; return less_case(file, right.file); } bool URL::operator ==(const URL &right) const { return ( equal_case(protocol, right.protocol) && equal_case(server, right.server) && equal_case(directory, right.directory) && equal_case(file, right.file) ); } bool URL::operator !=(const URL &right) const { return (!(*this == right)); } std::ostream &operator <<(std::ostream &out, const URL &url) { return out << (std::string)url; } } // namespace } // namespace } // namespace