diff options
| author | Vincent Richard <[email protected]> | 2005-04-14 13:27:49 +0200 |
|---|---|---|
| committer | Vincent Richard <[email protected]> | 2005-04-14 13:27:49 +0200 |
| commit | 34595491817bd3d062b05fe0d2bfd4289410ab51 (patch) | |
| tree | de05c249d6e43a1b89c36ef95bd6f62743b9ea79 /src/utility | |
| parent | Implemented comparison operators. (diff) | |
| download | vmime-34595491817bd3d062b05fe0d2bfd4289410ab51.tar.gz vmime-34595491817bd3d062b05fe0d2bfd4289410ab51.zip | |
Moved 'url' and 'urlUtils' classes to 'utility' namespace.
Diffstat (limited to 'src/utility')
| -rw-r--r-- | src/utility/url.cpp | 306 | ||||
| -rw-r--r-- | src/utility/urlUtils.cpp | 94 |
2 files changed, 400 insertions, 0 deletions
diff --git a/src/utility/url.cpp b/src/utility/url.cpp new file mode 100644 index 00000000..0c0a5799 --- /dev/null +++ b/src/utility/url.cpp @@ -0,0 +1,306 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2005 Vincent Richard <[email protected]> +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#include "vmime/utility/url.hpp" + +#include "vmime/parserHelpers.hpp" +#include "vmime/utility/urlUtils.hpp" +#include "vmime/exception.hpp" + +#include <sstream> + + +namespace vmime { +namespace utility { + + +// Known protocols +const string url::PROTOCOL_FILE = "file"; +const string url::PROTOCOL_HTTP = "http"; +const string url::PROTOCOL_FTP = "ftp"; + + + +url::url(const string& s) +{ + parse(s); +} + + +url::url(const url& u) +{ + operator=(u); +} + + +url::url(const string& protocol, const string& host, const port_t port, + const string& path, const string& username, const string& password) + : m_protocol(protocol), m_username(username), m_password(password), + m_host(host), m_port(port), m_path(path) +{ +} + + +url& url::operator=(const url& u) +{ + m_protocol = u.m_protocol; + + m_username = u.m_username; + m_password = u.m_password; + + m_host = u.m_host; + m_port = u.m_port; + + m_path = u.m_path; + + return (*this); +} + + +url& url::operator=(const string& s) +{ + parse(s); + + return (*this); +} + + +url::operator string() const +{ + return build(); +} + + +const string url::build() const +{ + std::ostringstream oss; + + oss << m_protocol << "://"; + + if (!m_username.empty()) + { + oss << urlUtils::encode(m_username); + + if (!m_password.empty()) + { + oss << ":"; + oss << urlUtils::encode(m_password); + } + + oss << "@"; + } + + oss << urlUtils::encode(m_host); + + if (m_port != UNSPECIFIED_PORT) + { + oss << ":"; + oss << m_port; + } + + if (!m_path.empty()) + { + oss << "/"; + oss << urlUtils::encode(m_path); + } + + return (oss.str()); +} + + +void url::parse(const string& str) +{ + // Protocol + const string::size_type protoEnd = str.find("://"); + if (protoEnd == string::npos) throw exceptions::malformed_url("No protocol separator"); + + const string proto = + utility::stringUtils::toLower(string(str.begin(), str.begin() + protoEnd)); + + // Username/password + string::size_type slashPos = str.find('/', protoEnd + 3); + if (slashPos == string::npos) slashPos = str.length(); + + string::size_type atPos = str.find('@', protoEnd + 3); + string hostPart; + + string username; + string password; + + if (proto == PROTOCOL_FILE) + { + // No user name, password and host part. + slashPos = protoEnd + 3; + } + else + { + if (atPos != string::npos && atPos < slashPos) + { + const string userPart(str.begin() + protoEnd + 3, str.begin() + atPos); + const string::size_type colonPos = userPart.find(':'); + + if (colonPos == string::npos) + { + username = userPart; + } + else + { + username = string(userPart.begin(), userPart.begin() + colonPos); + password = string(userPart.begin() + colonPos + 1, userPart.end()); + } + + hostPart = string(str.begin() + atPos + 1, str.begin() + slashPos); + } + else + { + hostPart = string(str.begin() + protoEnd + 3, str.begin() + slashPos); + } + } + + // Host/port + const string::size_type colonPos = hostPart.find(':'); + + string host; + string port; + + if (colonPos == string::npos) + { + host = hostPart; + } + else + { + host = string(hostPart.begin(), hostPart.begin() + colonPos); + port = string(hostPart.begin() + colonPos + 1, hostPart.end()); + } + + // Path + string path = utility::stringUtils::trim(string(str.begin() + slashPos, str.end())); + + if (path == "/") + path.clear(); + + // Some sanity check + if (proto.empty()) + throw exceptions::malformed_url("No protocol specified"); + else if (host.empty() && path.empty()) // Accept empty host (eg. "file:///home/vincent/mydoc") + throw exceptions::malformed_url("No host specified"); + + bool onlyDigit = true; + + for (string::const_iterator it = port.begin() ; + onlyDigit && it != port.end() ; ++it) + { + onlyDigit = parserHelpers::isDigit(*it); + } + + if (!onlyDigit) + throw exceptions::malformed_url("Port can only contain digits"); + + std::istringstream iss(port); + port_t portNum = 0; + + iss >> portNum; + + // Now, save URL parts + m_protocol = proto; + + m_username = urlUtils::decode(username); + m_password = urlUtils::decode(password); + + m_host = urlUtils::decode(host); + m_port = portNum; + + m_path = urlUtils::decode(path); +} + + +const string& url::getProtocol() const +{ + return (m_protocol); +} + + +void url::setProtocol(const string& protocol) +{ + m_protocol = protocol; +} + + +const string& url::getUsername() const +{ + return (m_username); +} + + +void url::setUsername(const string& username) +{ + m_username = username; +} + + +const string& url::getPassword() const +{ + return (m_password); +} + + +void url::setPassword(const string& password) +{ + m_password = password; +} + + +const string& url::getHost() const +{ + return (m_host); +} + + +void url::setHost(const string& host) +{ + m_host = host; +} + + +const port_t url::getPort() const +{ + return (m_port); +} + + +void url::setPort(const port_t port) +{ + m_port = port; +} + + +const string& url::getPath() const +{ + return (m_path); +} + + +void url::setPath(const string& path) +{ + m_path = path; +} + + +} // utility +} // vmime diff --git a/src/utility/urlUtils.cpp b/src/utility/urlUtils.cpp new file mode 100644 index 00000000..6099c19b --- /dev/null +++ b/src/utility/urlUtils.cpp @@ -0,0 +1,94 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2005 Vincent Richard <[email protected]> +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#include "vmime/utility/urlUtils.hpp" +#include "vmime/parserHelpers.hpp" + + +namespace vmime { +namespace utility { + + +const string urlUtils::encode(const string& s) +{ + string result; + result.reserve(s.length()); + + for (string::const_iterator it = s.begin() ; it != s.end() ; ++it) + { + const char_t c = *it; + + if (parserHelpers::isPrint(c) && c != '%') + { + result += c; + } + else + { + char hex[4]; + + hex[0] = '%'; + hex[1] = c / 16; + hex[2] = c % 16; + hex[3] = 0; + + result += hex; + } + } + + return (result); +} + + +const string urlUtils::decode(const string& s) +{ + string result; + result.reserve(s.length()); + + for (string::const_iterator it = s.begin() ; it != s.end() ; ) + { + const char_t c = *it; + + switch (c) + { + case '%': + { + const char_t p = (++it != s.end() ? *it : 0); + const char_t q = (++it != s.end() ? *it : 0); + + result += static_cast <string::value_type>(p * 16 + q); + + if (it != s.end()) + ++it; + + break; + } + default: + + result += c; + ++it; + break; + } + } + + return (result); +} + + +} // utility +} // vmime |
