diff --git a/src/atticabasejob.cpp b/src/atticabasejob.cpp index 00b35da..2121b00 100644 --- a/src/atticabasejob.cpp +++ b/src/atticabasejob.cpp @@ -1,180 +1,196 @@ /* This file is part of KDE. Copyright (c) 2008 Cornelius Schumacher This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #include "atticabasejob.h" #include #include #include #include #include #include #include "platformdependent.h" using namespace Attica; class BaseJob::Private { public: Metadata m_metadata; PlatformDependent *m_internals; QNetworkReply *m_reply; Private(PlatformDependent *internals) : m_internals(internals), m_reply(nullptr) { } bool redirection(QUrl &newUrl) const { - if (m_reply == nullptr || m_reply->error() != QNetworkReply::NoError) { + if (m_reply == nullptr || + #if (QT_VERSION < QT_VERSION_CHECK(5, 15, 0)) + m_reply->error() + #else + m_reply->networkError() + #endif + != QNetworkReply::NoError) { return false; } int httpStatusCode = m_reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); if (httpStatusCode == 301 || // Moved Permanently httpStatusCode == 302 || // Found httpStatusCode == 303 || // See Other httpStatusCode == 307) { // Temporary Redirect QNetworkRequest request = m_reply->request(); QUrl redirectUrl(m_reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl()); if (redirectUrl.isRelative()) { QUrl baseUrl(request.url()); newUrl = baseUrl.resolved(redirectUrl); qCDebug(ATTICA) << "resolving relative URL redirection to" << newUrl.toString(); } else { newUrl = redirectUrl; qCDebug(ATTICA) << "resolving absolute URL redirection to" << newUrl.toString(); } return true; } return false; } }; BaseJob::BaseJob(PlatformDependent *internals) : d(new Private(internals)) { } BaseJob::~BaseJob() { delete d; } void BaseJob::dataFinished() { if (!d->m_reply) { return; } - bool error = (d->m_reply->error() != QNetworkReply::NoError); + bool error = ( + #if (QT_VERSION < QT_VERSION_CHECK(5, 15, 0)) + d->m_reply->error() + #else + d->m_reply->networkError() + #endif + != QNetworkReply::NoError); // handle redirections automatically QUrl newUrl; if (d->redirection(newUrl)) { //qCDebug(ATTICA) << "BaseJob::dataFinished" << newUrl; QNetworkRequest request = d->m_reply->request(); QNetworkAccessManager::Operation operation = d->m_reply->operation(); if (newUrl.isValid() && operation == QNetworkAccessManager::GetOperation) { d->m_reply->deleteLater(); // reissue same request with different Url request.setUrl(newUrl); d->m_reply = internals()->get(request); connect(d->m_reply, &QNetworkReply::finished, this, &BaseJob::dataFinished); return; } else { error = true; } } if (!error) { QByteArray data = d->m_reply->readAll(); //qCDebug(ATTICA) << "XML Returned:\n" << data; parse(QString::fromUtf8(data.constData())); if (d->m_metadata.statusCode() >= 100 && d->m_metadata.statusCode() < 200) { d->m_metadata.setError(Metadata::NoError); } else { d->m_metadata.setError(Metadata::OcsError); } } else { d->m_metadata.setError(Metadata::NetworkError); +#if (QT_VERSION < QT_VERSION_CHECK(5, 15, 0)) d->m_metadata.setStatusCode(d->m_reply->error()); +#else + d->m_metadata.setStatusCode(d->m_reply->networkError()); +#endif d->m_metadata.setStatusString(d->m_reply->errorString()); } emit finished(this); d->m_reply->deleteLater(); deleteLater(); } void BaseJob::start() { QTimer::singleShot(0, this, &BaseJob::doWork); } void BaseJob::doWork() { d->m_reply = executeRequest(); qCDebug(ATTICA) << "executing" << Utils::toString(d->m_reply->operation()) << "request for" << d->m_reply->url(); connect(d->m_reply, &QNetworkReply::finished, this, &BaseJob::dataFinished); connect(d->m_reply->manager(), &QNetworkAccessManager::authenticationRequired, this, &BaseJob::authenticationRequired); connect(d->m_reply, static_cast(&QNetworkReply::error), [](QNetworkReply::NetworkError code){ qCDebug(ATTICA) << "error found" << code; }); } void BaseJob::authenticationRequired(QNetworkReply *reply, QAuthenticator *auth) { auth->setUser(reply->request().attribute((QNetworkRequest::Attribute) BaseJob::UserAttribute).toString()); auth->setPassword(reply->request().attribute((QNetworkRequest::Attribute) BaseJob::PasswordAttribute).toString()); } void BaseJob::abort() { if (d->m_reply) { d->m_reply->abort(); d->m_reply->deleteLater(); } deleteLater(); } PlatformDependent *BaseJob::internals() { return d->m_internals; } Metadata BaseJob::metadata() const { return d->m_metadata; } void BaseJob::setMetadata(const Attica::Metadata &data) const { d->m_metadata = data; } diff --git a/src/providermanager.cpp b/src/providermanager.cpp index 00e5aec..aceca00 100644 --- a/src/providermanager.cpp +++ b/src/providermanager.cpp @@ -1,328 +1,333 @@ /* This file is part of KDE. Copyright (c) 2009 Eckhart Wörner Copyright (c) 2009 Frederik Gladhorn This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #include "providermanager.h" #include "attica_debug.h" #include "atticautils.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "platformdependent.h" #include "qtplatformdependent_p.h" #include using namespace Attica; class ProviderManager::Private { public: PlatformDependent *m_internals; QHash m_providers; QHash m_providerTargets; QHash m_downloads; bool m_authenticationSuppressed; Private() : m_internals(nullptr) , m_authenticationSuppressed(false) { } ~Private() { // do not delete m_internals: it is the root component of a plugin! } }; PlatformDependent *ProviderManager::loadPlatformDependent(const ProviderFlags &flags) { if (flags & ProviderManager::DisablePlugins) { return new QtPlatformDependent; } QPluginLoader loader(QStringLiteral("attica_kde")); PlatformDependent * ret = qobject_cast(loader.instance()); return ret ? ret : new QtPlatformDependent; } ProviderManager::ProviderManager(const ProviderFlags &flags) : d(new Private) { d->m_internals = loadPlatformDependent(flags); connect(d->m_internals->nam(), &QNetworkAccessManager::authenticationRequired, this, &ProviderManager::authenticate); } void ProviderManager::loadDefaultProviders() { QTimer::singleShot(0, this, &ProviderManager::slotLoadDefaultProvidersInternal); } void ProviderManager::setAuthenticationSuppressed(bool suppressed) { d->m_authenticationSuppressed = suppressed; } void ProviderManager::clear() { d->m_providerTargets.clear(); d->m_providers.clear(); } void ProviderManager::slotLoadDefaultProvidersInternal() { const auto providerFiles = d->m_internals->getDefaultProviderFiles(); for (const QUrl &url : providerFiles) { addProviderFile(url); } if (d->m_downloads.isEmpty()) { emit defaultProvidersLoaded(); } } QList ProviderManager::defaultProviderFiles() { return d->m_internals->getDefaultProviderFiles(); } ProviderManager::~ProviderManager() { delete d; } void ProviderManager::addProviderFileToDefaultProviders(const QUrl &url) { d->m_internals->addDefaultProviderFile(url); addProviderFile(url); } void ProviderManager::removeProviderFileFromDefaultProviders(const QUrl &url) { d->m_internals->removeDefaultProviderFile(url); } void ProviderManager::addProviderFile(const QUrl &url) { if (url.isLocalFile()) { QFile file(url.toLocalFile()); if (!file.open(QIODevice::ReadOnly)) { qWarning() << "ProviderManager::addProviderFile: could not open provider file: " << url.toString(); return; } parseProviderFile(QLatin1String(file.readAll()), url); } else { if (!d->m_downloads.contains(url.toString())) { QNetworkRequest req(url); req.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); QNetworkReply *reply = d->m_internals->get(req); qCDebug(ATTICA) << "executing" << Utils::toString(reply->operation()) << "for" << reply->url(); connect(reply, &QNetworkReply::finished, this, [this, url]() { fileFinished(url.toString()); }); d->m_downloads.insert(url.toString(), reply); } } } void ProviderManager::fileFinished(const QString &url) { QNetworkReply *reply = d->m_downloads.take(url); +#if (QT_VERSION < QT_VERSION_CHECK(5, 15, 0)) if (reply->error()) Q_EMIT failedToLoad(QUrl(url), reply->error()); +#else + if (reply->networkError()) + Q_EMIT failedToLoad(QUrl(url), reply->networkError()); +#endif else parseProviderFile(QLatin1String(reply->readAll()), QUrl(url)); reply->deleteLater(); } void ProviderManager::addProviderFromXml(const QString &providerXml) { parseProviderFile(providerXml, QUrl()); } void ProviderManager::parseProviderFile(const QString &xmlString, const QUrl &url) { QXmlStreamReader xml(xmlString); while (!xml.atEnd() && xml.readNext()) { if (xml.isStartElement() && xml.name() == QLatin1String("provider")) { QUrl baseUrl; QString name; QUrl icon; QString person; QString friendV; QString message; QString achievement; QString activity; QString content; QString fan; QString forum; QString knowledgebase; QString event; QString comment; QString registerUrl; while (!xml.atEnd() && xml.readNext()) { if (xml.isStartElement()) { if (xml.name() == QLatin1String("location")) { baseUrl = QUrl(xml.readElementText()); } else if (xml.name() == QLatin1String("name")) { name = xml.readElementText(); } else if (xml.name() == QLatin1String("icon")) { icon = QUrl(xml.readElementText()); } else if (xml.name() == QLatin1String("person")) { person = xml.attributes().value(QLatin1String("ocsversion")).toString(); } else if (xml.name() == QLatin1String("friend")) { friendV = xml.attributes().value(QLatin1String("ocsversion")).toString(); } else if (xml.name() == QLatin1String("message")) { message = xml.attributes().value(QLatin1String("ocsversion")).toString(); } else if (xml.name() == QLatin1String("achievement")) { achievement = xml.attributes().value(QLatin1String("ocsversion")).toString(); } else if (xml.name() == QLatin1String("activity")) { activity = xml.attributes().value(QLatin1String("ocsversion")).toString(); } else if (xml.name() == QLatin1String("content")) { content = xml.attributes().value(QLatin1String("ocsversion")).toString(); } else if (xml.name() == QLatin1String("fan")) { fan = xml.attributes().value(QLatin1String("ocsversion")).toString(); } else if (xml.name() == QLatin1String("forum")) { forum = xml.attributes().value(QLatin1String("ocsversion")).toString(); } else if (xml.name() == QLatin1String("knowledgebase")) { knowledgebase = xml.attributes().value(QLatin1String("ocsversion")).toString(); } else if (xml.name() == QLatin1String("event")) { event = xml.attributes().value(QLatin1String("ocsversion")).toString(); } else if (xml.name() == QLatin1String("comment")) { comment = xml.attributes().value(QLatin1String("ocsversion")).toString(); } else if (xml.name() == QLatin1String("register")) { registerUrl = xml.readElementText(); } } else if (xml.isEndElement() && xml.name() == QLatin1String("provider")) { break; } } if (!baseUrl.isEmpty()) { //qCDebug(ATTICA) << "Adding provider" << baseUrl; d->m_providers.insert(baseUrl, Provider(d->m_internals, baseUrl, name, icon, person, friendV, message, achievement, activity, content, fan, forum, knowledgebase, event, comment, registerUrl)); d->m_providerTargets[url] = baseUrl; emit providerAdded(d->m_providers.value(baseUrl)); } } } if (xml.error() != QXmlStreamReader::NoError) { qCDebug(ATTICA) << "error:" << xml.errorString() << "in" << url; } if (d->m_downloads.isEmpty()) { emit defaultProvidersLoaded(); } } Provider ProviderManager::providerFor(const QUrl &url) const { return providerByUrl(d->m_providerTargets.value(url)); } Provider ProviderManager::providerByUrl(const QUrl &url) const { return d->m_providers.value(url); } QList ProviderManager::providers() const { return d->m_providers.values(); } #if ATTICA_BUILD_DEPRECATED_SINCE(5, 23) bool ProviderManager::contains(const QString &provider) const { return d->m_providers.contains(QUrl(provider)); } #endif QList ProviderManager::providerFiles() const { return d->m_providerTargets.keys(); } void ProviderManager::authenticate(QNetworkReply *reply, QAuthenticator *auth) { QUrl baseUrl; const QList urls = d->m_providers.keys(); for (const QUrl &url : urls) { if (url.isParentOf(reply->url())) { baseUrl = url; break; } } //qCDebug(ATTICA) << "ProviderManager::authenticate" << baseUrl; QString user; QString password; if (auth->user().isEmpty() && auth->password().isEmpty()) { if (d->m_internals->hasCredentials(baseUrl)) { if (d->m_internals->loadCredentials(baseUrl, user, password)) { //qCDebug(ATTICA) << "ProviderManager::authenticate: loading authentication"; auth->setUser(user); auth->setPassword(password); return; } } } if (!d->m_authenticationSuppressed && d->m_internals->askForCredentials(baseUrl, user, password)) { //qCDebug(ATTICA) << "ProviderManager::authenticate: asking internals for new credentials"; //auth->setUser(user); //auth->setPassword(password); return; } qWarning() << "ProviderManager::authenticate: No authentication credentials provided, aborting." << reply->url().toString(); emit authenticationCredentialsMissing(d->m_providers.value(baseUrl)); reply->abort(); } void ProviderManager::proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *authenticator) { Q_UNUSED(proxy) Q_UNUSED(authenticator) } void ProviderManager::initNetworkAccesssManager() { connect(d->m_internals->nam(), &QNetworkAccessManager::authenticationRequired, this, &ProviderManager::authenticate); connect(d->m_internals->nam(), &QNetworkAccessManager::proxyAuthenticationRequired, this, &ProviderManager::proxyAuthenticationRequired); }