/* Copyright (C) 2015 * swift project Community / Contributors * * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level * directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project, * including this file, may be copied, modified, propagated, or distributed except according to the terms * contained in the LICENSE file. */ #include "blackmisc/network/url.h" #include "blackmisc/network/networkutils.h" #include "blackmisc/propertyindex.h" #include #include #include namespace BlackMisc { namespace Network { CUrl::CUrl(const QString &fullUrl) { if (!fullUrl.isEmpty()) { setFullUrl(fullUrl); } } CUrl::CUrl(const QUrl &url) { this->setQUrl(url); } CUrl::CUrl(const QString &address, int port) : CUrl("", address, port, "") { } CUrl::CUrl(const QString &scheme, const QString &address, int port, const QString &path) : m_host(address.trimmed()), m_port(port), m_path(path.trimmed()) { this->setScheme(scheme); } void CUrl::setScheme(const QString &protocol) { m_scheme = protocol.trimmed().toLower().replace("://", ""); } void CUrl::setPath(const QString &path) { m_path = path.simplified(); } QString CUrl::appendPath(const QString &pathToAppend) { QString p(getPath()); p = p.append("/").append(pathToAppend.trimmed()).replace("//", "/"); this->setPath(p); return m_path; } int CUrl::getPort() const { if (m_port > 0) { return m_port; } return protocolToDefaultPort(this->getScheme()); } bool CUrl::hasPort() const { return m_port >= 0; } bool CUrl::isEmpty() const { return m_host.isEmpty(); } bool CUrl::hasDefaultPort() const { return isDefaultPort(m_scheme, m_port); } void CUrl::setQuery(const QString &query) { const QString q(stripQueryString(query)); m_query = q; } bool CUrl::hasQuery() const { return !m_query.isEmpty(); } QString CUrl::appendQuery(const QString &queryToAppend) { const QString q(stripQueryString(queryToAppend)); if (q.isEmpty()) { return m_query; } if (!hasQuery()) { this->setQuery(q); } else { m_query = m_query + "&" + q; } return m_query; } QString CUrl::getFullUrl(bool withQuery) const { if (m_host.isEmpty()) { return ""; } QString qn(m_host); if (!hasDefaultPort() && hasPort()) { qn = qn.append(":").append(QString::number(m_port)); } if (hasPath()) { qn = qn.append("/").append(m_path).replace("//", "/"); } if (hasQuery() && withQuery) { qn = qn.append("?").append(m_query); } if (hasScheme()) { qn = QString(this->getScheme()).append("://").append(qn); } return qn; } void CUrl::setFullUrl(const QString &fullUrl) { setQUrl(QUrl(fullUrl)); } QString CUrl::getFileName() const { return toQUrl().fileName(); } QUrl CUrl::toQUrl() const { return QUrl(getFullUrl()); } void CUrl::setQUrl(const QUrl &url) { this->setPort(url.port()); this->setHost(url.host()); this->setScheme(url.scheme()); this->setPath(url.path()); this->setQuery(url.query()); } QNetworkRequest CUrl::toNetworkRequest() const { return CNetworkUtils::getNetworkRequest(*this); } CUrl CUrl::withAppendedPath(const QString &path) const { if (path.isEmpty()) { return *this; } CUrl url(*this); url.appendPath(path); return url; } CUrl CUrl::withSwitchedScheme(const QString &scheme, int port) const { if (getPort() == port && getScheme() == scheme) { return *this; } QUrl qurl(this->toQUrl()); qurl.setPort(port); qurl.setScheme(scheme); CUrl url(qurl); return url; } bool CUrl::pathEndsWith(const QString &ending, Qt::CaseSensitivity cs) const { return m_path.endsWith(ending, cs); } CUrl CUrl::withAppendedQuery(const QString &query) const { if (query.isEmpty()) { return *this; } CUrl url(*this); url.appendQuery(query); return url; } QString CUrl::convertToQString(bool i18n) const { Q_UNUSED(i18n); return getFullUrl(); } QJsonObject CUrl::toJson() const { QPair v("url", getFullUrl()); QJsonObject json({ v }); return json; } void CUrl::convertFromJson(const QJsonObject &json) { const QJsonValue value = json.value("url"); if (value.isUndefined()) { throw CJsonException("Missing 'url'"); } this->setFullUrl(value.toString()); } int CUrl::protocolToDefaultPort(const QString &protocol) { const QString p(protocol.trimmed().toLower()); if (p == "ftp") return 20; if (p == "https") return 443; if (p == "http") return 80; return -1; } bool CUrl::isDefaultPort(const QString &protocol, int port) { int p = protocolToDefaultPort(protocol); if (p < 0) { return false; } return port == p; } CUrl CUrl::fromLocalFile(const QString &localFile) { return QUrl::fromLocalFile(localFile); } QString CUrl::stripQueryString(const QString &query) { QString q(query.trimmed()); if (q.startsWith("?") || q.startsWith("&")) { q = q.mid(1); } if (q.endsWith("?") || q.endsWith("&")) { q = q.left(q.size() - 1); } return q; } CVariant CUrl::propertyByIndex(const BlackMisc::CPropertyIndex &index) const { if (index.isMyself()) { return CVariant::from(*this); } ColumnIndex i = index.frontCasted(); switch (i) { case IndexHost: return CVariant::fromValue(this->m_host); case IndexPort: return CVariant::fromValue(this->m_port); case IndexScheme: return CVariant::fromValue(this->m_scheme); case IndexPath: return CVariant::fromValue(this->m_path); default: return CValueObject::propertyByIndex(index); } } void CUrl::setPropertyByIndex(const CPropertyIndex &index, const CVariant &variant) { if (index.isMyself()) { (*this) = variant.to(); return; } ColumnIndex i = index.frontCasted(); switch (i) { case IndexHost: this->setHost(variant.value()); break; case IndexPort: this->setPort(variant.value()); break; case IndexPath: this->setPath(variant.value()); break; case IndexScheme: this->setScheme(variant.value()); break; default: CValueObject::setPropertyByIndex(index, variant); break; } } } // namespace } // namespace