blob: df38265974dcd0157f8f19e4a568e0ffebb8eb85 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "URI.h"
#include <decaf/lang/Integer.h>
#include <decaf/lang/Character.h>
#include <decaf/net/URL.h>
#include <decaf/internal/net/URIHelper.h>
#include <decaf/internal/util/StringUtils.h>
#include <decaf/internal/net/URIEncoderDecoder.h>
using namespace std;
using namespace decaf;
using namespace decaf::net;
using namespace decaf::internal;
using namespace decaf::internal::net;
using namespace decaf::internal::util;
using namespace decaf::lang;
using namespace decaf::lang::exceptions;
////////////////////////////////////////////////////////////////////////////////
const std::string URI::unreserved = "_-!.~\'()*";
const std::string URI::punct = ",;:$&+=";
const std::string URI::reserved = punct + "?/[]@";
const std::string URI::someLegal = unreserved + punct;
const std::string URI::allLegal = unreserved + reserved;
////////////////////////////////////////////////////////////////////////////////
URI::URI() : uri(), uriString() {
}
////////////////////////////////////////////////////////////////////////////////
URI::URI(const URI& uri) : uri(uri.uri), uriString(uri.uriString) {
}
////////////////////////////////////////////////////////////////////////////////
URI::URI(const std::string& uri) : uri(), uriString(uri) {
this->parseURI(uri, false);
}
////////////////////////////////////////////////////////////////////////////////
URI::URI(const std::string& scheme, const std::string& ssp, const std::string& fragment) : uri(), uriString() {
std::string uri = "";
if (scheme != "") {
uri.append(scheme);
uri.append(":");
}
if (ssp != "") {
// QUOTE ILLEGAL CHARACTERS
uri.append(quoteComponent(ssp, allLegal));
}
if (fragment != "") {
uri.append("#");
// QUOTE ILLEGAL CHARACTERS
uri.append(quoteComponent(fragment, allLegal));
}
// Now hand of to the main parse function.
this->parseURI(uri, false);
}
////////////////////////////////////////////////////////////////////////////////
URI::URI(const std::string& scheme, const std::string& userInfo,
const std::string& host, int port,
const std::string& path, const std::string& query,
const std::string& fragment) : uri(), uriString() {
if (scheme == "" && userInfo == "" && host == "" && path == "" && query == "" && fragment == "") {
return;
}
if (scheme != "" && !path.empty() && path.at(0) != '/') {
throw URISyntaxException(
__FILE__, __LINE__, path,
"URI::URI - Path string: %s starts with invalid char '/'" );
}
std::string uri = "";
if (scheme != "") {
uri.append(scheme);
uri.append(":");
}
uri.append("//");
if (userInfo != "") {
// QUOTE ILLEGAL CHARACTERS in userinfo
uri.append(quoteComponent(userInfo, someLegal));
uri.append("@");
}
if (host != "") {
std::string newHost = host;
// check for ipv6 addresses that hasn't been enclosed
// in square brackets
if (host.find(":") != std::string::npos &&
host.find("]") == std::string::npos &&
host.find("[") == std::string::npos) {
newHost = std::string("[") + host + "]";
}
uri.append(newHost);
}
if (port != -1) {
uri.append(":");
uri.append(Integer::toString(port));
}
if (path != "") {
// QUOTE ILLEGAL CHARS
uri.append(quoteComponent(path, "/@" + someLegal));
}
if (query != "") {
uri.append("?");
// QUOTE ILLEGAL CHARS
uri.append(quoteComponent(query, allLegal));
}
if (fragment != "") {
// QUOTE ILLEGAL CHARS
uri.append("#");
uri.append(quoteComponent(fragment, allLegal));
}
this->parseURI(uri, true);
}
////////////////////////////////////////////////////////////////////////////////
URI::URI(const std::string& scheme, const std::string& host,
const std::string& path, const std::string& fragment) : uri(), uriString() {
if (scheme == "" && host == "" && path == "" && fragment == "") {
return;
}
if (scheme != "" && !path.empty() && path.at(0) != '/') {
throw URISyntaxException(
__FILE__, __LINE__, path,
"URI::URI - Path string: %s starts with invalid char '/'" );
}
std::string uri = "";
if (scheme != "") {
uri.append(scheme);
uri.append(":");
}
if (host != "") {
uri.append("//");
}
if (host != "") {
std::string newHost = host;
// check for ipv6 addresses that hasn't been enclosed
// in square brackets
if (host.find(":") != std::string::npos &&
host.find("]") == std::string::npos &&
host.find("[") == std::string::npos) {
newHost = std::string("[") + host + "]";
}
uri.append(newHost);
}
if (path != "") {
// QUOTE ILLEGAL CHARS
uri.append(quoteComponent(path, "/@" + someLegal));
}
if (fragment != "") {
// QUOTE ILLEGAL CHARS
uri.append("#");
uri.append(quoteComponent(fragment, allLegal));
}
this->parseURI(uri, true);
}
////////////////////////////////////////////////////////////////////////////////
URI::URI(const std::string& scheme, const std::string& authority,
const std::string& path, const std::string& query,
const std::string& fragment) : uri(), uriString() {
if (scheme != "" && !path.empty() && path.at(0) != '/') {
throw URISyntaxException(
__FILE__, __LINE__, path,
"URI::URI - Path String %s must start with a '/'" );
}
std::string uri = "";
if (scheme != "") {
uri.append(scheme);
uri.append(":");
}
uri.append("//");
if (authority != "") {
// QUOTE ILLEGAL CHARS
uri.append(quoteComponent(authority, "@[]" + someLegal));
}
if (path != "") {
// QUOTE ILLEGAL CHARS
uri.append(quoteComponent(path, "/@" + someLegal));
}
if (query != "") {
// QUOTE ILLEGAL CHARS
uri.append("?");
uri.append(quoteComponent(query, allLegal));
}
if (fragment != "") {
// QUOTE ILLEGAL CHARS
uri.append("#");
uri.append(quoteComponent(fragment, allLegal));
}
this->parseURI(uri, false);
}
////////////////////////////////////////////////////////////////////////////////
void URI::parseURI(const std::string& uri, bool forceServer) {
try {
this->uri = URIHelper().parseURI(uri, forceServer);
}
DECAF_CATCH_RETHROW(URISyntaxException)
DECAF_CATCHALL_THROW(URISyntaxException)
}
////////////////////////////////////////////////////////////////////////////////
int URI::compareTo( const URI& uri ) const {
int ret = 0;
// compare schemes
if (this->uri.getScheme() == "" && uri.getScheme() != "") {
return -1;
} else if (this->uri.getScheme() != "" && uri.getScheme() == "") {
return 1;
} else if (this->uri.getScheme() != "" && uri.getScheme() != "") {
ret = StringUtils::compareIgnoreCase(this->uri.getScheme().c_str(), uri.getScheme().c_str());
if (ret != 0) {
return ret > 0 ? 1 : -1;
}
}
// compare opacities
if (!this->uri.isOpaque() && uri.isOpaque()) {
return -1;
} else if (this->uri.isOpaque() && !uri.isOpaque()) {
return 1;
} else if (this->uri.isOpaque() && uri.isOpaque()) {
ret = StringUtils::compare(this->getSchemeSpecificPart().c_str(),
uri.getSchemeSpecificPart().c_str());
if (ret != 0) {
return ret > 0 ? 1 : -1;
}
} else {
// otherwise both must be hierarchical
// compare authorities
if (this->uri.getAuthority() != "" && uri.getAuthority() == "") {
return 1;
} else if (this->uri.getAuthority() == "" && uri.getAuthority() != "") {
return -1;
} else if (this->uri.getAuthority() != "" && uri.getAuthority() != "") {
if (this->uri.getHost() != "" && uri.getHost() != "") {
// both are server based, so compare userinfo, host, port
if (this->getUserInfo() != "" && uri.getUserInfo() == "") {
return 1;
} else if (this->getUserInfo() == "" && uri.getUserInfo() != "") {
return -1;
} else if (this->getUserInfo() != "" && uri.getUserInfo() != "") {
ret = StringUtils::compare(this->getUserInfo().c_str(),
uri.getUserInfo().c_str());
if (ret != 0) {
return ret > 0 ? 1 : -1;
}
}
// userinfo's are the same, compare hostname
ret = StringUtils::compareIgnoreCase(this->uri.getHost().c_str(), uri.getHost().c_str());
if (ret != 0) {
return ret > 0 ? 1 : -1;
}
// compare port
if (this->getPort() != uri.getPort()) {
return (getPort() - uri.getPort()) > 0 ? 1 : -1;
}
} else {
// one or both are registry based, compare the whole authority
ret = StringUtils::compare(this->uri.getAuthority().c_str(), uri.getAuthority().c_str());
if (ret != 0) {
return ret > 0 ? 1 : -1;
}
}
}
// authorities are the same, compare paths
ret = StringUtils::compare(this->getPath().c_str(), uri.getPath().c_str());
if (ret != 0) {
return ret > 0 ? 1 : -1;
}
// compare queries
if (this->getQuery() != "" && uri.getQuery() == "") {
return 1;
} else if (this->getQuery() == "" && uri.getQuery() != "") {
return -1;
} else if (this->getQuery() != "" && uri.getQuery() != "") {
ret = StringUtils::compare(this->getQuery().c_str(), uri.getQuery().c_str());
if (ret != 0) {
return ret > 0 ? 1 : -1;
}
}
}
// everything else is identical, so compare fragments
if (this->getFragment() != "" && uri.getFragment() == "") {
return 1;
} else if (this->getFragment() == "" && uri.getFragment() != "") {
return -1;
} else if (this->getFragment() != "" && uri.getFragment() != "") {
ret = StringUtils::compare(this->getFragment().c_str(), uri.getFragment().c_str());
if (ret != 0) {
return ret > 0 ? 1 : -1;
}
}
// identical
return 0;
}
////////////////////////////////////////////////////////////////////////////////
bool URI::equals( const URI& uri ) const {
if ((uri.uri.getFragment() == "" && this->uri.getFragment() != "") ||
(uri.uri.getFragment() != "" && this->uri.getFragment() == "")) {
return false;
} else if (uri.uri.getFragment() != "" && this->uri.getFragment() != "") {
if (!equalsHexCaseInsensitive(uri.uri.getFragment(), this->uri.getFragment())) {
return false;
}
}
if ((uri.uri.getScheme() == "" && this->uri.getScheme() != "") ||
(uri.uri.getScheme() != "" && this->uri.getScheme() == "")) {
return false;
} else if (uri.uri.getScheme() != "" && this->uri.getScheme() != "") {
if (StringUtils::compareIgnoreCase(uri.uri.getScheme().c_str(), this->uri.getScheme().c_str()) != 0) {
return false;
}
}
if (uri.uri.isOpaque() && this->uri.isOpaque()) {
return equalsHexCaseInsensitive(
uri.uri.getSchemeSpecificPart(), this->uri.getSchemeSpecificPart());
} else if (!uri.uri.isOpaque() && !this->uri.isOpaque()) {
if (!equalsHexCaseInsensitive(this->uri.getPath(), uri.uri.getPath())) {
return false;
}
if ((uri.uri.getQuery() != "" && this->uri.getQuery() == "") ||
(uri.uri.getQuery() == "" && this->uri.getQuery() != "")) {
return false;
} else if(uri.uri.getQuery() != "" && this->uri.getQuery() != "") {
if (!equalsHexCaseInsensitive(uri.uri.getQuery(), this->uri.getQuery())) {
return false;
}
}
if( ( uri.uri.getAuthority() != "" && this->uri.getAuthority() == "" ) ||
( uri.uri.getAuthority() == "" && this->uri.getAuthority() != "" ) ) {
return false;
} else if (uri.uri.getAuthority() != "" && this->uri.getAuthority() != "") {
if ((uri.uri.getHost() != "" && this->uri.getHost() == "") ||
(uri.uri.getHost() == "" && this->uri.getHost() != "")) {
return false;
} else if (uri.uri.getHost() == "" && this->uri.getHost() == "") {
// both are registry based, so compare the whole authority
return equalsHexCaseInsensitive(
uri.uri.getAuthority(), this->uri.getAuthority());
} else { // uri.host != "" && host != "", so server-based
if (StringUtils::compareIgnoreCase(uri.uri.getHost().c_str(), this->uri.getHost().c_str()) != 0) {
return false;
}
if (this->uri.getPort() != uri.uri.getPort()) {
return false;
}
if ((uri.uri.getUserInfo() != "" && this->uri.getUserInfo() == "") ||
(uri.uri.getUserInfo() == "" && this->uri.getUserInfo() != "")) {
return false;
} else if (uri.uri.getUserInfo() != "" && this->uri.getUserInfo() != "") {
return equalsHexCaseInsensitive(this->uri.getUserInfo(), uri.uri.getUserInfo());
} else {
return true;
}
}
} else {
// no authority
return true;
}
} else {
// one is opaque, the other hierarchical
return false;
}
}
////////////////////////////////////////////////////////////////////////////////
bool URI::operator==(const URI& value) const {
return compareTo(value) == 0 ? true : false;
}
////////////////////////////////////////////////////////////////////////////////
bool URI::operator<(const URI& value) const {
return compareTo(value) == -1 ? true : false;
}
////////////////////////////////////////////////////////////////////////////////
URI URI::create(const std::string uri) {
try {
return URI(uri);
} catch (URISyntaxException& e) {
throw IllegalArgumentException(e);
}
}
////////////////////////////////////////////////////////////////////////////////
std::string URI::quoteComponent(const std::string& component, const std::string& legalset) {
try {
/*
* Use a different encoder than URLEncoder since: 1. chars like "/",
* "#", "@" etc needs to be preserved instead of being encoded, 2.
* UTF-8 char set needs to be used for encoding instead of default
* platform one
*/
return URIEncoderDecoder::quoteIllegal(component, legalset);
}
DECAF_CATCH_RETHROW(decaf::lang::Exception)
DECAF_CATCHALL_THROW(decaf::lang::Exception)
}
////////////////////////////////////////////////////////////////////////////////
std::string URI::encodeOthers(const std::string& src) const {
try {
/*
* Use a different encoder than URLEncoder since: 1. chars like "/",
* "#", "@" etc needs to be preserved instead of being encoded, 2.
* UTF-8 char set needs to be used for encoding instead of default
* platform one 3. Only other chars need to be converted
*/
return URIEncoderDecoder::encodeOthers(src);
}
DECAF_CATCH_RETHROW(decaf::lang::Exception)
DECAF_CATCHALL_THROW(decaf::lang::Exception)
}
////////////////////////////////////////////////////////////////////////////////
std::string URI::decode(const std::string& src) const {
if (src == "") {
return src;
}
try {
return URIEncoderDecoder::decode(src);
}
DECAF_CATCH_RETHROW(decaf::lang::Exception)
DECAF_CATCHALL_THROW(decaf::lang::Exception)
}
////////////////////////////////////////////////////////////////////////////////
bool URI::equalsHexCaseInsensitive(const std::string& first, const std::string& second) const {
if (first.find('%') != second.find('%')) {
return StringUtils::compare(first.c_str(), second.c_str()) == 0;
}
std::size_t index = 0;
std::size_t previndex = 0;
while ((index = first.find('%', previndex)) != string::npos && second.find('%', previndex) == index) {
bool match = first.substr(previndex, index - previndex) ==
second.substr(previndex, index - previndex);
if (!match) {
return false;
}
match = StringUtils::compareIgnoreCase(
first.substr(index + 1, 3).c_str(), second.substr(index + 1, 3).c_str()) == 0;
if (!match) {
return false;
}
index += 3;
previndex = index;
}
return first.substr(previndex) == second.substr(previndex);
}
////////////////////////////////////////////////////////////////////////////////
std::string URI::convertHexToLowerCase(const std::string& s) const {
string result = "";
if (s.find('%') == string::npos) {
return s;
}
std::size_t index = 0;
std::size_t previndex = 0;
while ((index = s.find('%', previndex)) != string::npos) {
result.append(s.substr(previndex, (index - previndex) + 1));
string temp = s.substr(index + 1, 3);
for (size_t i = 0; i < temp.length(); ++i) {
result.append(1, Character::toLowerCase(temp.at(i)));
}
index += 3;
previndex = index;
}
return result;
}
////////////////////////////////////////////////////////////////////////////////
std::string URI::normalize(const std::string& path) const {
if (path == "") {
return path;
}
// count the number of '/'s, to determine number of segments
std::size_t index = -1;
std::size_t pathlen = path.length();
unsigned int size = 0;
if (pathlen > 0 && path.at(0) != '/') {
size++;
}
while ((index = path.find('/', index + 1)) != string::npos) {
if (index + 1 < pathlen && path.at(index + 1) != '/') {
size++;
}
}
std::vector<string> seglist(size);
std::vector<bool> include(size);
// break the path into segments and store in the list
std::size_t current = 0;
std::size_t index2 = 0;
index = (pathlen > 0 && path.at(0) == '/') ? 1 : 0;
while ((index2 = path.find('/', index + 1)) != string::npos) {
seglist[current++] = path.substr(index, index2 - index);
index = index2 + 1;
}
// if current==size, then the last character was a slash
// and there are no more segments
if (current < size) {
seglist[current] = path.substr(index);
}
// determine which segments get included in the normalized path
for (unsigned int i = 0; i < size; i++) {
include[i] = true;
if (seglist[i] == "..") {
int remove = i - 1;
// search back to find a segment to remove, if possible
while (remove > -1 && !include[remove]) {
remove--;
}
// if we find a segment to remove, remove it and the ".."
// segment
if (remove > -1 && !(seglist[remove] == "..")) {
include[remove] = false;
include[i] = false;
}
} else if (seglist[i] == ".") {
include[i] = false;
}
}
// put the path back together
string newpath;
if (path.at(0) == '/') {
newpath.append("/");
}
for (unsigned int i = 0; i < seglist.size(); i++) {
if (include[i]) {
newpath.append(seglist[i]);
newpath.append("/");
}
}
// if we used at least one segment and the path previously ended with
// a slash and the last segment is still used, then delete the extra
// trailing '/'
if (path.at(path.length() - 1) != '/' && seglist.size() > 0 && include[seglist.size() - 1]) {
newpath.erase(newpath.length() - 1, 1);
}
string result = newpath;
// check for a ':' in the first segment if one exists,
// prepend "./" to normalize
index = result.find(':');
index2 = result.find('/');
if (index != string::npos && (index < index2 || index2 == string::npos)) {
newpath.insert(0, "./");
result = newpath;
}
return result;
}
////////////////////////////////////////////////////////////////////////////////
URI URI::normalize() const {
if (isOpaque()) {
return *this;
}
string normalizedPath = normalize(this->uri.getPath());
// if the path is already normalized, return this
if (this->uri.getPath() == normalizedPath) {
return *this;
}
// get an exact copy of the URI re-calculate the scheme specific part
// since the path of the normalized URI is different from this URI.
URI result = *this;
result.uri.setPath(normalizedPath);
result.setSchemeSpecificPart();
return result;
}
////////////////////////////////////////////////////////////////////////////////
void URI::setSchemeSpecificPart() {
// ssp = [//authority][path][?query]
string ssp;
if (this->uri.getAuthority() != "") {
ssp.append(string("//") + this->uri.getAuthority());
}
if (this->uri.getPath() != "") {
ssp.append(this->uri.getPath());
}
if (this->uri.getQuery() != "") {
ssp.append("?" + this->uri.getQuery());
}
this->uri.setSchemeSpecificPart(ssp);
// reset string, so that it can be re-calculated correctly when asked.
this->uriString = "";
}
////////////////////////////////////////////////////////////////////////////////
URI URI::parseServerAuthority() const {
URI newURI = *this;
if (!newURI.uri.isServerAuthority()) {
newURI.uri = URIHelper().parseAuthority(true, this->uri.getAuthority());
}
return newURI;
}
////////////////////////////////////////////////////////////////////////////////
URI URI::relativize( const URI& relative ) const {
if (relative.isOpaque() || this->isOpaque()) {
return relative;
}
if (this->uri.getScheme() == "" ? relative.uri.getScheme() != "" :
this->uri.getScheme() != relative.uri.getScheme()) {
return relative;
}
if (this->uri.getAuthority() == "" ? relative.uri.getAuthority() != "" :
this->uri.getAuthority() != relative.uri.getAuthority()) {
return relative;
}
// normalize both paths
string thisPath = normalize( this->uri.getPath() );
string relativePath = normalize( relative.uri.getPath() );
/*
* if the paths aren't equal, then we need to determine if this URI's
* path is a parent path (begins with) the relative URI's path
*/
if (thisPath != relativePath) {
// if this URI's path doesn't end in a '/', add one
if (thisPath.empty() || thisPath.at(thisPath.length() - 1) != '/') {
thisPath = thisPath + '/';
}
/*
* if the relative URI's path doesn't start with this URI's path,
* then just return the relative URI; the URIs have nothing in
* common
*/
if (relativePath.find(thisPath) != 0) {
return relative;
}
}
URI result;
result.uri.setFragment(relative.uri.getFragment());
result.uri.setQuery(relative.uri.getQuery());
// the result URI is the remainder of the relative URI's path
result.uri.setPath(relativePath.substr(thisPath.length()));
result.setSchemeSpecificPart();
return result;
}
////////////////////////////////////////////////////////////////////////////////
URI URI::resolve(const URI& relative) const {
if (relative.isAbsolute() || this->isOpaque()) {
return relative;
}
URI result;
if (relative.uri.getPath() == "" && relative.uri.getScheme() == "" && relative.uri.getAuthority() == ""
&& relative.uri.getQuery() == "" && relative.uri.getFragment() != "") {
// if the relative URI only consists of fragment,
// the resolved URI is very similar to this URI,
// except that it has the fragment from the relative URI.
result = *this;
result.uri.setFragment(relative.uri.getFragment());
result.uriString = "";
// no need to re-calculate the scheme specific part,
// since fragment is not part of scheme specific part.
return result;
}
if (relative.uri.getAuthority() != "") {
// if the relative URI has authority,
// the resolved URI is almost the same as the relative URI,
// except that it has the scheme of this URI.
result = relative;
result.uri.setScheme(this->uri.getScheme());
result.uri.setAbsolute(this->uri.isAbsolute());
result.uriString = "";
} else {
// since relative URI has no authority,
// the resolved URI is very similar to this URI,
// except that it has the query and fragment of the relative URI,
// and the path is different.
result = *this;
result.uri.setFragment(relative.uri.getFragment());
result.uri.setQuery(relative.uri.getQuery());
result.uriString = "";
if (relative.uri.getPath().at(0) == '/') {
result.uri.setPath(relative.uri.getPath());
} else {
// resolve a relative reference
std::size_t endindex = this->uri.getPath().find_last_of('/') + 1;
result.uri.setPath(normalize(
this->uri.getPath().substr(0, endindex) + relative.uri.getPath()));
}
// re-calculate the scheme specific part since
// query and path of the resolved URI is different from this URI.
result.setSchemeSpecificPart();
}
return result;
}
////////////////////////////////////////////////////////////////////////////////
URI URI::resolve(const std::string& relative) const {
return resolve(create(relative));
}
////////////////////////////////////////////////////////////////////////////////
string URI::toString() const {
if (this->uriString == "") {
string result = "";
if (this->uri.getScheme() != "") {
result.append(this->uri.getScheme());
result.append(":");
}
if (this->isOpaque()) {
result.append(this->uri.getSchemeSpecificPart());
} else {
if (this->uri.getAuthority() != "") {
result.append("//");
result.append(this->uri.getAuthority());
}
if (this->uri.getPath() != "") {
result.append(this->uri.getPath());
}
if (this->uri.getQuery() != "") {
result.append("?");
result.append(this->uri.getQuery());
}
}
if (this->uri.getFragment() != "") {
result.append("#");
result.append(this->uri.getFragment());
}
this->uriString = result;
}
return this->uriString;
}
////////////////////////////////////////////////////////////////////////////////
URL URI::toURL() const {
if (!this->isAbsolute()) {
throw IllegalArgumentException(
__FILE__, __LINE__, "URI is not absolute, cannot convert to an URL.");
}
return URL(this->toString());
}
////////////////////////////////////////////////////////////////////////////////
std::string URI::getAuthority() const {
return this->decode(this->uri.getAuthority());
}
////////////////////////////////////////////////////////////////////////////////
std::string URI::getFragment() const {
return this->decode(this->uri.getFragment());
}
////////////////////////////////////////////////////////////////////////////////
std::string URI::getHost() const {
return this->uri.getHost();
}
////////////////////////////////////////////////////////////////////////////////
std::string URI::getPath() const {
return this->decode(this->uri.getPath());
}
////////////////////////////////////////////////////////////////////////////////
int URI::getPort() const {
return this->uri.getPort();
}
////////////////////////////////////////////////////////////////////////////////
std::string URI::getQuery() const {
return this->decode(this->uri.getQuery());
}
////////////////////////////////////////////////////////////////////////////////
std::string URI::getRawAuthority() const {
return this->uri.getAuthority();
}
////////////////////////////////////////////////////////////////////////////////
std::string URI::getRawFragment() const {
return this->uri.getFragment();
}
////////////////////////////////////////////////////////////////////////////////
std::string URI::getRawPath() const {
return this->uri.getPath();
}
////////////////////////////////////////////////////////////////////////////////
std::string URI::getRawQuery() const {
return this->uri.getQuery();
}
////////////////////////////////////////////////////////////////////////////////
std::string URI::getRawSchemeSpecificPart() const {
return this->uri.getSchemeSpecificPart();
}
////////////////////////////////////////////////////////////////////////////////
std::string URI::getRawUserInfo() const {
return this->uri.getUserInfo();
}
////////////////////////////////////////////////////////////////////////////////
std::string URI::getScheme() const {
return this->uri.getScheme();
}
////////////////////////////////////////////////////////////////////////////////
std::string URI::getSchemeSpecificPart() const {
return this->decode(this->uri.getSchemeSpecificPart());
}
////////////////////////////////////////////////////////////////////////////////
std::string URI::getUserInfo() const {
return this->decode(this->uri.getUserInfo());
}
////////////////////////////////////////////////////////////////////////////////
bool URI::isAbsolute() const {
return this->uri.isAbsolute();
}
////////////////////////////////////////////////////////////////////////////////
bool URI::isOpaque() const {
return this->uri.isOpaque();
}