Files
core_misc/tjp/core/internet/URL.cpp
Timothy Prepscius fa54be052a flatten 20260225
2026-02-25 12:39:24 -05:00

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