Attica

providermanager.cpp
1/*
2 This file is part of KDE.
3
4 SPDX-FileCopyrightText: 2009 Eckhart Wörner <ewoerner@kde.org>
5 SPDX-FileCopyrightText: 2009 Frederik Gladhorn <gladhorn@kde.org>
6
7 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
8*/
9
10#include "providermanager.h"
11
12#include "attica_debug.h"
13#include "atticautils.h"
14
15#include <QAuthenticator>
16#include <QCoreApplication>
17#include <QDebug>
18#include <QFile>
19#include <QNetworkProxy>
20#include <QPluginLoader>
21#include <QSet>
22#include <QSignalMapper>
23#include <QTimer>
24#include <QXmlStreamReader>
25
26#include "platformdependent.h"
27#include "qtplatformdependent_p.h"
28#include <QLibraryInfo>
29
30using namespace Attica;
31
32class Q_DECL_HIDDEN ProviderManager::Private
33{
34public:
35 PlatformDependent *m_internals;
36 QHash<QUrl, Provider> m_providers;
37 QHash<QUrl, QUrl> m_providerTargets;
39 bool m_authenticationSuppressed;
40
41 Private()
42 : m_internals(nullptr)
43 , m_authenticationSuppressed(false)
44 {
45 }
46 ~Private()
47 {
48 // do not delete m_internals: it is the root component of a plugin!
49 }
50};
51
52PlatformDependent *ProviderManager::loadPlatformDependent(const ProviderFlags &flags)
53{
54 if (flags & ProviderManager::DisablePlugins) {
55 return new QtPlatformDependent;
56 }
57
58 QPluginLoader loader(QStringLiteral("attica_kde"));
59 PlatformDependent *ret = qobject_cast<PlatformDependent *>(loader.instance());
60
61 return ret ? ret : new QtPlatformDependent;
62}
63
64ProviderManager::ProviderManager(const ProviderFlags &flags)
65 : d(new Private)
66{
67 d->m_internals = loadPlatformDependent(flags);
68 connect(d->m_internals->nam(), &QNetworkAccessManager::authenticationRequired, this, &ProviderManager::authenticate);
69}
70
72{
73 QTimer::singleShot(0, this, &ProviderManager::slotLoadDefaultProvidersInternal);
74}
75
77{
78 d->m_authenticationSuppressed = suppressed;
79}
80
82{
83 d->m_providerTargets.clear();
84 d->m_providers.clear();
85}
86
87void ProviderManager::slotLoadDefaultProvidersInternal()
88{
89 const auto providerFiles = d->m_internals->getDefaultProviderFiles();
90 for (const QUrl &url : providerFiles) {
91 addProviderFile(url);
92 }
93 if (d->m_downloads.isEmpty()) {
94 Q_EMIT defaultProvidersLoaded();
95 }
96}
97
99{
100 return d->m_internals->getDefaultProviderFiles();
101}
102
103ProviderManager::~ProviderManager()
104{
105 delete d;
106}
107
109{
110 d->m_internals->addDefaultProviderFile(url);
111 addProviderFile(url);
112}
113
114void ProviderManager::removeProviderFileFromDefaultProviders(const QUrl &url)
115{
116 d->m_internals->removeDefaultProviderFile(url);
117}
118
119void ProviderManager::addProviderFile(const QUrl &url)
120{
121 if (url.isLocalFile()) {
122 QFile file(url.toLocalFile());
123 if (!file.open(QIODevice::ReadOnly)) {
124 qWarning() << "ProviderManager::addProviderFile: could not open provider file: " << url.toString();
125 return;
126 }
127 parseProviderFile(QLatin1String(file.readAll()), url);
128 } else {
129 if (!d->m_downloads.contains(url.toString())) {
130 QNetworkRequest req(url);
131 req.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::RedirectPolicy::NoLessSafeRedirectPolicy);
132 QNetworkReply *reply = d->m_internals->get(req);
133 qCDebug(ATTICA) << "executing" << Utils::toString(reply->operation()) << "for" << reply->url();
134 connect(reply, &QNetworkReply::finished, this, [this, url]() {
135 fileFinished(url.toString());
136 });
137 d->m_downloads.insert(url.toString(), reply);
138 }
139 }
140}
141
142void ProviderManager::fileFinished(const QString &url)
143{
144 QNetworkReply *reply = d->m_downloads.take(url);
145 if (reply) {
146 if (reply->error()) {
147 Q_EMIT failedToLoad(QUrl(url), reply->error());
148 } else {
149 parseProviderFile(QLatin1String(reply->readAll()), QUrl(url));
150 }
151 reply->deleteLater();
152 } else {
154 }
155}
156
158{
159 parseProviderFile(providerXml, QUrl());
160}
161
162void ProviderManager::parseProviderFile(const QString &xmlString, const QUrl &url)
163{
165 while (!xml.atEnd() && xml.readNext()) {
166 if (xml.isStartElement() && xml.name() == QLatin1String("provider")) {
167 QUrl baseUrl;
168 QString name;
169 QUrl icon;
170 QString person;
172 QString message;
174 QString activity;
175 QString content;
176 QString fan;
180 QString comment;
182
183 while (!xml.atEnd() && xml.readNext()) {
184 if (xml.isStartElement()) {
185 if (xml.name() == QLatin1String("location")) {
186 baseUrl = QUrl(xml.readElementText());
187 } else if (xml.name() == QLatin1String("name")) {
188 name = xml.readElementText();
189 } else if (xml.name() == QLatin1String("icon")) {
190 icon = QUrl(xml.readElementText());
191 } else if (xml.name() == QLatin1String("person")) {
192 person = xml.attributes().value(QLatin1String("ocsversion")).toString();
193 } else if (xml.name() == QLatin1String("friend")) {
194 friendV = xml.attributes().value(QLatin1String("ocsversion")).toString();
195 } else if (xml.name() == QLatin1String("message")) {
196 message = xml.attributes().value(QLatin1String("ocsversion")).toString();
197 } else if (xml.name() == QLatin1String("achievement")) {
198 achievement = xml.attributes().value(QLatin1String("ocsversion")).toString();
199 } else if (xml.name() == QLatin1String("activity")) {
200 activity = xml.attributes().value(QLatin1String("ocsversion")).toString();
201 } else if (xml.name() == QLatin1String("content")) {
202 content = xml.attributes().value(QLatin1String("ocsversion")).toString();
203 } else if (xml.name() == QLatin1String("fan")) {
204 fan = xml.attributes().value(QLatin1String("ocsversion")).toString();
205 } else if (xml.name() == QLatin1String("forum")) {
206 forum = xml.attributes().value(QLatin1String("ocsversion")).toString();
207 } else if (xml.name() == QLatin1String("knowledgebase")) {
208 knowledgebase = xml.attributes().value(QLatin1String("ocsversion")).toString();
209 } else if (xml.name() == QLatin1String("event")) {
210 event = xml.attributes().value(QLatin1String("ocsversion")).toString();
211 } else if (xml.name() == QLatin1String("comment")) {
212 comment = xml.attributes().value(QLatin1String("ocsversion")).toString();
213 } else if (xml.name() == QLatin1String("register")) {
214 registerUrl = xml.readElementText();
215 }
216 } else if (xml.isEndElement() && xml.name() == QLatin1String("provider")) {
217 break;
218 }
219 }
220 if (!baseUrl.isEmpty()) {
221 // qCDebug(ATTICA) << "Adding provider" << baseUrl;
222 d->m_providers.insert(baseUrl,
223 Provider(d->m_internals,
224 baseUrl,
225 name,
226 icon,
227 person,
228 friendV,
229 message,
231 activity,
232 content,
233 fan,
234 forum,
236 event,
237 comment,
238 registerUrl));
239 d->m_providerTargets[url] = baseUrl;
240 Q_EMIT providerAdded(d->m_providers.value(baseUrl));
241 }
242 }
243 }
244
245 if (xml.error() != QXmlStreamReader::NoError) {
246 qCDebug(ATTICA) << "error:" << xml.errorString() << "in" << url;
247 }
248
249 if (d->m_downloads.isEmpty()) {
250 Q_EMIT defaultProvidersLoaded();
251 }
252}
253
255{
256 return providerByUrl(d->m_providerTargets.value(url));
257}
258
260{
261 return d->m_providers.value(url);
262}
263
265{
266 return d->m_providers.values();
267}
268
269QList<QUrl> ProviderManager::providerFiles() const
270{
271 return d->m_providerTargets.keys();
272}
273
274void ProviderManager::authenticate(QNetworkReply *reply, QAuthenticator *auth)
275{
276 QUrl baseUrl;
277 const QList<QUrl> urls = d->m_providers.keys();
278 for (const QUrl &url : urls) {
279 if (url.isParentOf(reply->url())) {
280 baseUrl = url;
281 break;
282 }
283 }
284
285 // qCDebug(ATTICA) << "ProviderManager::authenticate" << baseUrl;
286
287 QString user;
288 QString password;
289 if (auth->user().isEmpty() && auth->password().isEmpty()) {
290 if (d->m_internals->hasCredentials(baseUrl)) {
291 if (d->m_internals->loadCredentials(baseUrl, user, password)) {
292 // qCDebug(ATTICA) << "ProviderManager::authenticate: loading authentication";
293 auth->setUser(user);
294 auth->setPassword(password);
295 return;
296 }
297 }
298 }
299
300 if (!d->m_authenticationSuppressed && d->m_internals->askForCredentials(baseUrl, user, password)) {
301 // qCDebug(ATTICA) << "ProviderManager::authenticate: asking internals for new credentials";
302 // auth->setUser(user);
303 // auth->setPassword(password);
304 return;
305 }
306
307 qWarning() << "ProviderManager::authenticate: No authentication credentials provided, aborting." << reply->url().toString();
308 Q_EMIT authenticationCredentialsMissing(d->m_providers.value(baseUrl));
309 reply->abort();
310}
311
312void ProviderManager::proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *authenticator)
313{
314 Q_UNUSED(proxy)
316}
317
318void ProviderManager::initNetworkAccesssManager()
319{
320 connect(d->m_internals->nam(), &QNetworkAccessManager::authenticationRequired, this, &ProviderManager::authenticate);
321 connect(d->m_internals->nam(), &QNetworkAccessManager::proxyAuthenticationRequired, this, &ProviderManager::proxyAuthenticationRequired);
322}
323
324#include "moc_providermanager.cpp"
Represents an item post job.
Definition itemjob.h:66
Attica ProviderManager.
void addProviderFromXml(const QString &providerXml)
Parse a xml file containing a provider description.
void addProviderFileToDefaultProviders(const QUrl &url)
Add a provider file to the default providers (xml that contains provider descriptions).
void setAuthenticationSuppressed(bool suppressed)
Suppresses the authentication, so that the application can take care of authenticating itself.
QList< Provider > providers() const
Provider providerByUrl(const QUrl &url) const
void loadDefaultProviders()
Load available providers from configuration.
void clear()
Remove all providers and provider files that have been loaded.
QList< QUrl > defaultProviderFiles()
The list of provider files that get loaded by loadDefaultProviders.
Provider providerFor(const QUrl &url) const
The Provider class represents one Open Collaboration Service provider.
Definition provider.h:97
The Attica namespace,.
QString password() const const
void setPassword(const QString &password)
void setUser(const QString &user)
QString user() const const
void clear()
bool contains(const Key &key) const const
iterator insert(const Key &key, const T &value)
bool isEmpty() const const
QList< Key > keys() const const
T take(const Key &key)
T value(const Key &key) const const
QByteArray readAll()
void authenticationRequired(QNetworkReply *reply, QAuthenticator *authenticator)
void proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *authenticator)
virtual void abort()=0
NetworkError error() const const
QNetworkAccessManager::Operation operation() const const
QUrl url() const const
Q_EMITQ_EMIT
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
void deleteLater()
virtual bool event(QEvent *e)
bool isEmpty() const const
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
bool isEmpty() const const
bool isLocalFile() const const
bool isParentOf(const QUrl &childUrl) const const
QString toLocalFile() const const
QString toString(FormattingOptions options) const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:19:48 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.