2
This file is part of KDE.
4
Copyright (c) 2009 Eckhart Wörner <ewoerner@kde.org>
5
Copyright (c) 2009 Frederik Gladhorn <gladhorn@kde.org>
7
This library is free software; you can redistribute it and/or
8
modify it under the terms of the GNU Lesser General Public
9
License as published by the Free Software Foundation; either
10
version 2.1 of the License, or (at your option) version 3, or any
11
later version accepted by the membership of KDE e.V. (or its
12
successor approved by the membership of KDE e.V.), which shall
13
act as a proxy defined in Section 6 of version 3 of the license.
15
This library is distributed in the hope that it will be useful,
16
but WITHOUT ANY WARRANTY; without even the implied warranty of
17
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18
Lesser General Public License for more details.
20
You should have received a copy of the GNU Lesser General Public
21
License along with this library. If not, see <http://www.gnu.org/licenses/>.
25
#include "providermanager.h"
27
#include <QtCore/QDebug>
28
#include <QtCore/QFile>
29
#include <QtCore/QPluginLoader>
30
#include <QtCore/QSet>
31
#include <QtCore/QSignalMapper>
32
#include <QtCore/QTimer>
33
#include <QtCore/QProcess>
34
#include <QtNetwork/QAuthenticator>
35
#include <QtNetwork/QNetworkReply>
36
#if QT_VERSION >= 0x050000
37
#include <QtCore/QXmlStreamReader>
39
#include <QtXml/QXmlStreamReader>
42
#include "platformdependent.h"
43
#include "qtplatformdependent_p.h"
44
#include <QLibraryInfo>
46
using namespace Attica;
48
#if QT_VERSION < 0x040700
49
uint qHash(const QUrl &key)
51
return qHash(key.toString());
55
class ProviderManager::Private
58
PlatformDependent *m_internals;
59
QHash<QUrl, Provider> m_providers;
60
QHash<QUrl, QList<QString> > m_providerFiles;
61
QSignalMapper m_downloadMapping;
62
QHash<QString, QNetworkReply *> m_downloads;
63
QPluginLoader m_pluginLoader;
64
bool m_authenticationSuppressed;
68
, m_authenticationSuppressed(false)
73
// do not delete m_internals: it is the root component of a plugin!
77
PlatformDependent *ProviderManager::loadPlatformDependent(const ProviderFlags &flags)
81
#define PATH_SEPARATOR ';'
82
#define LIB_EXTENSION "dll"
84
#define PATH_SEPARATOR ':'
85
#define LIB_EXTENSION "so"
88
if (flags & ProviderManager::DisablePlugins) {
89
//qDebug() << "Disabling provider plugins per application request";
90
return new QtPlatformDependent;
93
// use qt plugin dir, if that is not found, fall back to kde plugin path (the old way)
95
paths.append(QLibraryInfo::location(QLibraryInfo::PluginsPath));
97
// old plugin location, required for attica < 0.1.5
98
QString program(QLatin1String("kde4-config"));
99
QStringList arguments;
100
arguments << QLatin1String("--path") << QLatin1String("lib");
103
process.start(program, arguments);
104
process.waitForFinished();
106
/* Try to find the KDE plugin. This can be extended to include other platform specific plugins. */
107
paths.append(QString(QLatin1String(process.readAllStandardOutput())).trimmed().split(QLatin1Char(PATH_SEPARATOR)));
108
//qDebug() << "Plugin paths: " << paths;
110
QString pluginName(QLatin1String("attica_kde"));
112
foreach (const QString &path, paths) {
113
QString libraryPath(path + QLatin1Char('/') + pluginName + QLatin1Char('.') + QLatin1String(LIB_EXTENSION));
114
//qDebug() << "Trying to load Attica plugin: " << libraryPath;
115
if (QFile::exists(libraryPath)) {
116
d->m_pluginLoader.setFileName(libraryPath);
117
QObject *plugin = d->m_pluginLoader.instance();
119
PlatformDependent *platformDependent = qobject_cast<PlatformDependent *>(plugin);
120
if (platformDependent) {
121
//qDebug() << "Using Attica with KDE support";
122
return platformDependent;
127
//qDebug() << "Using Attica without KDE support";
128
return new QtPlatformDependent;
131
ProviderManager::ProviderManager(const ProviderFlags &flags)
134
d->m_internals = loadPlatformDependent(flags);
135
connect(d->m_internals->nam(), SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)), SLOT(authenticate(QNetworkReply*,QAuthenticator*)));
136
connect(&d->m_downloadMapping, SIGNAL(mapped(QString)), SLOT(fileFinished(QString)));
139
void ProviderManager::loadDefaultProviders()
141
QTimer::singleShot(0, this, SLOT(slotLoadDefaultProvidersInternal()));
144
void ProviderManager::setAuthenticationSuppressed(bool suppressed)
146
d->m_authenticationSuppressed = suppressed;
149
void ProviderManager::clear()
151
d->m_providerFiles.clear();
152
d->m_providers.clear();
155
void ProviderManager::slotLoadDefaultProvidersInternal()
157
foreach (const QUrl &url, d->m_internals->getDefaultProviderFiles()) {
158
addProviderFile(url);
160
if (d->m_downloads.isEmpty()) {
161
emit defaultProvidersLoaded();
165
QList<QUrl> ProviderManager::defaultProviderFiles()
167
return d->m_internals->getDefaultProviderFiles();
170
ProviderManager::~ProviderManager()
175
void ProviderManager::addProviderFileToDefaultProviders(const QUrl &url)
177
d->m_internals->addDefaultProviderFile(url);
178
addProviderFile(url);
181
void ProviderManager::removeProviderFileFromDefaultProviders(const QUrl &url)
183
d->m_internals->removeDefaultProviderFile(url);
186
void ProviderManager::addProviderFile(const QUrl &url)
188
QString localFile = url.toLocalFile();
189
if (!localFile.isEmpty()) {
190
QFile file(localFile);
191
if (!file.open(QIODevice::ReadOnly)) {
192
qWarning() << "ProviderManager::addProviderFile: could not open provider file: " << url.toString();
195
addProviderFromXml(QLatin1String(file.readAll()));
197
if (!d->m_downloads.contains(url.toString())) {
198
QNetworkReply *reply = d->m_internals->get(QNetworkRequest(url));
199
connect(reply, SIGNAL(finished()), &d->m_downloadMapping, SLOT(map()));
200
d->m_downloadMapping.setMapping(reply, url.toString());
201
d->m_downloads.insert(url.toString(), reply);
206
void ProviderManager::fileFinished(const QString &url)
208
QNetworkReply *reply = d->m_downloads.take(url);
209
parseProviderFile(QLatin1String(reply->readAll()), url);
210
reply->deleteLater();
213
void ProviderManager::addProviderFromXml(const QString &providerXml)
215
parseProviderFile(providerXml, QString());
218
void ProviderManager::parseProviderFile(const QString &xmlString, const QString &url)
220
QXmlStreamReader xml(xmlString);
221
while (!xml.atEnd() && xml.readNext()) {
222
if (xml.isStartElement() && xml.name() == QLatin1String("provider")) {
234
QString knowledgebase;
239
while (!xml.atEnd() && xml.readNext()) {
240
if (xml.isStartElement()) {
241
if (xml.name() == QLatin1String("location")) {
242
baseUrl = QUrl(xml.readElementText());
243
} else if (xml.name() == QLatin1String("name")) {
244
name = xml.readElementText();
245
} else if (xml.name() == QLatin1String("icon")) {
246
icon = QUrl(xml.readElementText());
247
} else if (xml.name() == QLatin1String("person")) {
248
person = xml.attributes().value(QLatin1String("ocsversion")).toString();
249
} else if (xml.name() == QLatin1String("friend")) {
250
friendV = xml.attributes().value(QLatin1String("ocsversion")).toString();
251
} else if (xml.name() == QLatin1String("message")) {
252
message = xml.attributes().value(QLatin1String("ocsversion")).toString();
253
} else if (xml.name() == QLatin1String("achievement")) {
254
achievement = xml.attributes().value(QLatin1String("ocsversion")).toString();
255
} else if (xml.name() == QLatin1String("activity")) {
256
activity = xml.attributes().value(QLatin1String("ocsversion")).toString();
257
} else if (xml.name() == QLatin1String("content")) {
258
content = xml.attributes().value(QLatin1String("ocsversion")).toString();
259
} else if (xml.name() == QLatin1String("fan")) {
260
fan = xml.attributes().value(QLatin1String("ocsversion")).toString();
261
} else if (xml.name() == QLatin1String("forum")) {
262
forum = xml.attributes().value(QLatin1String("ocsversion")).toString();
263
} else if (xml.name() == QLatin1String("knowledgebase")) {
264
knowledgebase = xml.attributes().value(QLatin1String("ocsversion")).toString();
265
} else if (xml.name() == QLatin1String("event")) {
266
event = xml.attributes().value(QLatin1String("ocsversion")).toString();
267
} else if (xml.name() == QLatin1String("comment")) {
268
comment = xml.attributes().value(QLatin1String("ocsversion")).toString();
269
} else if (xml.name() == QLatin1String("register")) {
270
registerUrl = xml.readElementText();
272
} else if (xml.isEndElement() && xml.name() == QLatin1String("provider")) {
276
if (!baseUrl.isEmpty()) {
277
//qDebug() << "Adding provider" << baseUrl;
278
d->m_providers.insert(baseUrl, Provider(d->m_internals, baseUrl, name, icon,
279
person, friendV, message, achievement, activity, content, fan, forum, knowledgebase,
280
event, comment, registerUrl));
281
emit providerAdded(d->m_providers.value(baseUrl));
286
if (d->m_downloads.isEmpty()) {
287
emit defaultProvidersLoaded();
291
Provider ProviderManager::providerByUrl(const QUrl &url) const
293
return d->m_providers.value(url);
296
QList<Provider> ProviderManager::providers() const
298
return d->m_providers.values();
301
bool ProviderManager::contains(const QString &provider) const
303
return d->m_providers.contains(QUrl(provider));
306
QList<QUrl> ProviderManager::providerFiles() const
308
return d->m_providerFiles.keys();
311
void ProviderManager::authenticate(QNetworkReply *reply, QAuthenticator *auth)
314
QList<QUrl> urls = d->m_providers.keys();
315
foreach (const QUrl &url, urls) {
316
if (url.isParentOf(reply->url())) {
322
//qDebug() << "ProviderManager::authenticate" << baseUrl;
326
if (auth->user().isEmpty() && auth->password().isEmpty()) {
327
if (d->m_internals->hasCredentials(baseUrl)) {
328
if (d->m_internals->loadCredentials(baseUrl, user, password)) {
329
//qDebug() << "ProviderManager::authenticate: loading authentication";
331
auth->setPassword(password);
337
if (!d->m_authenticationSuppressed && d->m_internals->askForCredentials(baseUrl, user, password)) {
338
//qDebug() << "ProviderManager::authenticate: asking internals for new credentials";
339
//auth->setUser(user);
340
//auth->setPassword(password);
344
qWarning() << "ProviderManager::authenticate: No authentication credentials provided, aborting." << reply->url().toString();
345
emit authenticationCredentialsMissing(d->m_providers.value(baseUrl));
349
void ProviderManager::proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *authenticator)
353
void ProviderManager::initNetworkAccesssManager()
355
connect(d->m_internals->nam(), SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)), this, SLOT(authenticate(QNetworkReply*,QAuthenticator*)));
356
connect(d->m_internals->nam(), SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)), this, SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
359
#include "providermanager.moc"