208 lines
4.0 KiB
C++
Executable File
208 lines
4.0 KiB
C++
Executable File
// 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 <tjp/core/string/cmp_case.hpp>
|
|
#include <iostream>
|
|
|
|
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
|