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 "platformdependent_v3.h"
28#include "qtplatformdependent_p.h"
29#include <QLibraryInfo>
30
31using namespace Attica;
32
33class Q_DECL_HIDDEN ProviderManager::Private
34{
35public:
36 PlatformDependent *m_internals;
37 QHash<QUrl, Provider> m_providers;
38 QHash<QUrl, QUrl> m_providerTargets;
40 bool m_authenticationSuppressed;
41
42 Private()
43 : m_internals(nullptr)
44 , m_authenticationSuppressed(false)
45 {
46 }
47 ~Private()
48 {
49 // do not delete m_internals: it is the root component of a plugin!
50 }
51};
52
53PlatformDependent *ProviderManager::loadPlatformDependent(const ProviderFlags &flags)
54{
55 if (flags & ProviderManager::DisablePlugins) {
56 return new QtPlatformDependent;
57 }
58
59 QPluginLoader loader(QStringLiteral("attica_kde"));
60 PlatformDependent *ret = qobject_cast<PlatformDependent *>(loader.instance());
61
62 return ret ? ret : new QtPlatformDependent;
63}
64
65ProviderManager::ProviderManager(const ProviderFlags &flags)
66 : d(new Private)
67{
68 d->m_internals = loadPlatformDependent(flags);
69 connect(d->m_internals->nam(), &QNetworkAccessManager::authenticationRequired, this, &ProviderManager::authenticate);
70}
71
73{
74 auto platformDependentV3 = dynamic_cast<Attica::PlatformDependentV3 *>(d->m_internals);
75 if (platformDependentV3 && !platformDependentV3->isReady()) {
76 connect(platformDependentV3,
78 this,
79 &ProviderManager::slotLoadDefaultProvidersInternal,
81 return;
82 }
83
84 QTimer::singleShot(0, this, &ProviderManager::slotLoadDefaultProvidersInternal);
85}
86
88{
89 d->m_authenticationSuppressed = suppressed;
90}
91
93{
94 d->m_providerTargets.clear();
95 d->m_providers.clear();
96}
97
98void ProviderManager::slotLoadDefaultProvidersInternal()
99{
100 const auto providerFiles = d->m_internals->getDefaultProviderFiles();
101 for (const QUrl &url : providerFiles) {
102 addProviderFile(url);
103 }
104 if (d->m_downloads.isEmpty()) {
105 Q_EMIT defaultProvidersLoaded();
106 }
107}
108
110{
111 return d->m_internals->getDefaultProviderFiles();
112}
113
114ProviderManager::~ProviderManager()
115{
116 delete d;
117}
118
120{
121 d->m_internals->addDefaultProviderFile(url);
122 addProviderFile(url);
123}
124
125void ProviderManager::removeProviderFileFromDefaultProviders(const QUrl &url)
126{
127 d->m_internals->removeDefaultProviderFile(url);
128}
129
130void ProviderManager::addProviderFile(const QUrl &url)
131{
132 if (url.isLocalFile()) {
133 QFile file(url.toLocalFile());
134 if (!file.open(QIODevice::ReadOnly)) {
135 qWarning() << "ProviderManager::addProviderFile: could not open provider file: " << url.toString();
136 return;
137 }
138 parseProviderFile(QLatin1String(file.readAll()), url);
139 } else {
140 if (!d->m_downloads.contains(url.toString())) {
141 QNetworkRequest req(url);
142 req.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::RedirectPolicy::NoLessSafeRedirectPolicy);
143 QNetworkReply *reply = d->m_internals->get(req);
144 qCDebug(ATTICA) << "executing" << Utils::toString(reply->operation()) << "for" << reply->url();
145 connect(reply, &QNetworkReply::finished, this, [this, url]() {
146 fileFinished(url.toString());
147 });
148 d->m_downloads.insert(url.toString(), reply);
149 }
150 }
151}
152
153void ProviderManager::fileFinished(const QString &url)
154{
155 QNetworkReply *reply = d->m_downloads.take(url);
156 if (reply) {
157 if (reply->error()) {
158 Q_EMIT failedToLoad(QUrl(url), reply->error());
159 } else {
160 parseProviderFile(QLatin1String(reply->readAll()), QUrl(url));
161 }
162 reply->deleteLater();
163 } else {
165 }
166}
167
169{
170 parseProviderFile(providerXml, QUrl());
171}
172
173void ProviderManager::parseProviderFile(const QString &xmlString, const QUrl &url)
174{
175 QXmlStreamReader xml(xmlString);
176 while (!xml.atEnd() && xml.readNext()) {
177 if (xml.isStartElement() && xml.name() == QLatin1String("provider")) {
178 QUrl baseUrl;
179 QString name;
180 QUrl icon;
181 QString person;
182 QString friendV;
183 QString message;
184 QString achievement;
185 QString activity;
186 QString content;
187 QString fan;
188 QString forum;
189 QString knowledgebase;
191 QString comment;
192 QString registerUrl;
193
194 while (!xml.atEnd() && xml.readNext()) {
195 if (xml.isStartElement()) {
196 if (xml.name() == QLatin1String("location")) {
197 baseUrl = QUrl(xml.readElementText());
198 } else if (xml.name() == QLatin1String("name")) {
199 name = xml.readElementText();
200 } else if (xml.name() == QLatin1String("icon")) {
201 icon = QUrl(xml.readElementText());
202 } else if (xml.name() == QLatin1String("person")) {
203 person = xml.attributes().value(QLatin1String("ocsversion")).toString();
204 } else if (xml.name() == QLatin1String("friend")) {
205 friendV = xml.attributes().value(QLatin1String("ocsversion")).toString();
206 } else if (xml.name() == QLatin1String("message")) {
207 message = xml.attributes().value(QLatin1String("ocsversion")).toString();
208 } else if (xml.name() == QLatin1String("achievement")) {
209 achievement = xml.attributes().value(QLatin1String("ocsversion")).toString();
210 } else if (xml.name() == QLatin1String("activity")) {
211 activity = xml.attributes().value(QLatin1String("ocsversion")).toString();
212 } else if (xml.name() == QLatin1String("content")) {
213 content = xml.attributes().value(QLatin1String("ocsversion")).toString();
214 } else if (xml.name() == QLatin1String("fan")) {
215 fan = xml.attributes().value(QLatin1String("ocsversion")).toString();
216 } else if (xml.name() == QLatin1String("forum")) {
217 forum = xml.attributes().value(QLatin1String("ocsversion")).toString();
218 } else if (xml.name() == QLatin1String("knowledgebase")) {
219 knowledgebase = xml.attributes().value(QLatin1String("ocsversion")).toString();
220 } else if (xml.name() == QLatin1String("event")) {
221 event = xml.attributes().value(QLatin1String("ocsversion")).toString();
222 } else if (xml.name() == QLatin1String("comment")) {
223 comment = xml.attributes().value(QLatin1String("ocsversion")).toString();
224 } else if (xml.name() == QLatin1String("register")) {
225 registerUrl = xml.readElementText();
226 }
227 } else if (xml.isEndElement() && xml.name() == QLatin1String("provider")) {
228 break;
229 }
230 }
231 if (!baseUrl.isEmpty()) {
232 // qCDebug(ATTICA) << "Adding provider" << baseUrl;
233 d->m_providers.insert(baseUrl,
234 Provider(d->m_internals,
235 baseUrl,
236 name,
237 icon,
238 person,
239 friendV,
240 message,
241 achievement,
242 activity,
243 content,
244 fan,
245 forum,
246 knowledgebase,
247 event,
248 comment,
249 registerUrl));
250 d->m_providerTargets[url] = baseUrl;
251 Q_EMIT providerAdded(d->m_providers.value(baseUrl));
252 }
253 }
254 }
255
256 if (xml.error() != QXmlStreamReader::NoError) {
257 qCDebug(ATTICA) << "error:" << xml.errorString() << "in" << url;
258 }
259
260 if (d->m_downloads.isEmpty()) {
261 Q_EMIT defaultProvidersLoaded();
262 }
263}
264
266{
267 return providerByUrl(d->m_providerTargets.value(url));
268}
269
271{
272 return d->m_providers.value(url);
273}
274
276{
277 return d->m_providers.values();
278}
279
280QList<QUrl> ProviderManager::providerFiles() const
281{
282 return d->m_providerTargets.keys();
283}
284
285void ProviderManager::authenticate(QNetworkReply *reply, QAuthenticator *auth)
286{
287 QUrl baseUrl;
288 const QList<QUrl> urls = d->m_providers.keys();
289 for (const QUrl &url : urls) {
290 if (url.isParentOf(reply->url())) {
291 baseUrl = url;
292 break;
293 }
294 }
295
296 // qCDebug(ATTICA) << "ProviderManager::authenticate" << baseUrl;
297
298 QString user;
299 QString password;
300 if (auth->user().isEmpty() && auth->password().isEmpty()) {
301 if (d->m_internals->hasCredentials(baseUrl)) {
302 if (d->m_internals->loadCredentials(baseUrl, user, password)) {
303 // qCDebug(ATTICA) << "ProviderManager::authenticate: loading authentication";
304 auth->setUser(user);
305 auth->setPassword(password);
306 return;
307 }
308 }
309 }
310
311 if (!d->m_authenticationSuppressed && d->m_internals->askForCredentials(baseUrl, user, password)) {
312 // qCDebug(ATTICA) << "ProviderManager::authenticate: asking internals for new credentials";
313 // auth->setUser(user);
314 // auth->setPassword(password);
315 return;
316 }
317
318 qWarning() << "ProviderManager::authenticate: No authentication credentials provided, aborting." << reply->url().toString();
319 Q_EMIT authenticationCredentialsMissing(d->m_providers.value(baseUrl));
320 reply->abort();
321}
322
323void ProviderManager::proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *authenticator)
324{
325 Q_UNUSED(proxy)
326 Q_UNUSED(authenticator)
327}
328
329#include "moc_providermanager.cpp"
Platform integration plugin v3.
void readyChanged()
Emit this when the ready state changes.
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)
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)
T qobject_cast(QObject *object)
bool isEmpty() const const
QueuedConnection
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 Mon Nov 18 2024 12:17:36 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.