• Skip to content
  • Skip to link menu
KDE 4.6 API Reference
  • KDE API Reference
  • kdelibs
  • KDE Home
  • Contact Us
 

KIO

accessmanager.cpp

Go to the documentation of this file.
00001 /*
00002  * This file is part of the KDE project.
00003  *
00004  * Copyright (C) 2009,2010 Dawit Alemayehu <adawit @ kde.org>
00005  * Copyright (C) 2008 - 2009 Urs Wolfer <uwolfer @ kde.org>
00006  * Copyright (C) 2007 Trolltech ASA
00007  *
00008  * This library is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU Library General Public
00010  * License as published by the Free Software Foundation; either
00011  * version 2 of the License, or (at your option) any later version.
00012  *
00013  * This library is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016  * Library General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU Library General Public License
00019  * along with this library; see the file COPYING.LIB.  If not, write to
00020  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00021  * Boston, MA 02110-1301, USA.
00022  *
00023  */
00024 
00025 #include "accessmanager.h"
00026 #include "accessmanagerreply_p.h"
00027 
00028 #include <kdebug.h>
00029 #include <kio/job.h>
00030 #include <kio/scheduler.h>
00031 #include <kconfiggroup.h>
00032 #include <ksharedconfig.h>
00033 #include <kprotocolinfo.h>
00034 #include <klocalizedstring.h>
00035 
00036 #include <QtCore/QUrl>
00037 #include <QtCore/QWeakPointer>
00038 #include <QtDBus/QDBusInterface>
00039 #include <QtDBus/QDBusConnection>
00040 #include <QtDBus/QDBusReply>
00041 #include <QtNetwork/QNetworkReply>
00042 #include <QtNetwork/QNetworkRequest>
00043 #include <QtNetwork/QSslCipher>
00044 #include <QtNetwork/QSslCertificate>
00045 #include <QtNetwork/QSslConfiguration>
00046 
00047 #define QL1S(x)   QLatin1String(x)
00048 #define QL1C(x)   QLatin1Char(x)
00049 
00050 static bool isLocalRequest(const KUrl& url)
00051 {
00052     const QString scheme (url.protocol());
00053     return (KProtocolInfo::isKnownProtocol(scheme) && 
00054             KProtocolInfo::protocolClass(scheme).compare(QL1S(":local"), Qt::CaseInsensitive) == 0);
00055 }
00056 
00057 namespace KIO {
00058 
00059 class AccessManager::AccessManagerPrivate
00060 {
00061 public:
00062     AccessManagerPrivate() 
00063     : externalContentAllowed(true)
00064     {}
00065 
00066     void setMetaDataForRequest(QNetworkRequest request, KIO::MetaData& metaData);
00067     
00068     bool externalContentAllowed;    
00069     KIO::MetaData requestMetaData;
00070     KIO::MetaData sessionMetaData;
00071 };
00072 
00073 namespace Integration {
00074 
00075 class CookieJar::CookieJarPrivate
00076 {
00077 public:
00078   CookieJarPrivate()
00079     : windowId((WId)-1), 
00080       isEnabled(true),
00081       isStorageDisabled(false)
00082   {}
00083 
00084   WId windowId;
00085   bool isEnabled;
00086   bool isStorageDisabled;
00087 };
00088 
00089 }
00090 
00091 }
00092 
00093 using namespace KIO;
00094 
00095 AccessManager::AccessManager(QObject *parent)
00096               :QNetworkAccessManager(parent), d(new AccessManager::AccessManagerPrivate())
00097 {
00098     // KDE Cookiejar (KCookieJar) integration...
00099     setCookieJar(new KIO::Integration::CookieJar);
00100 }
00101 
00102 AccessManager::~AccessManager()
00103 {
00104     delete d;
00105 }
00106 
00107 void AccessManager::setExternalContentAllowed(bool allowed)
00108 {
00109     d->externalContentAllowed = allowed;
00110 }
00111 
00112 bool AccessManager::isExternalContentAllowed() const
00113 {
00114     return d->externalContentAllowed;
00115 }
00116 
00117 void AccessManager::setCookieJarWindowId(WId id)
00118 {
00119     KIO::Integration::CookieJar *jar = qobject_cast<KIO::Integration::CookieJar *> (cookieJar());
00120     if (jar) {
00121         jar->setWindowId(id);
00122         d->sessionMetaData.insert(QL1S("window-id"), QString::number((qlonglong)id));
00123     }
00124 }
00125 
00126 WId AccessManager::cookieJarWindowid() const
00127 {
00128     KIO::Integration::CookieJar *jar = qobject_cast<KIO::Integration::CookieJar *> (cookieJar());
00129     if (jar)
00130         return jar->windowId();
00131 
00132     return 0;
00133 }
00134 
00135 KIO::MetaData& AccessManager::requestMetaData()
00136 {
00137     return d->requestMetaData;
00138 }
00139 
00140 KIO::MetaData& AccessManager::sessionMetaData()
00141 {
00142     return d->sessionMetaData;
00143 }
00144 
00145 void AccessManager::putReplyOnHold(QNetworkReply* reply)
00146 {
00147     KDEPrivate::AccessManagerReply* r = qobject_cast<KDEPrivate::AccessManagerReply*>(reply);
00148     if (!r)
00149       return;
00150 
00151     r->putOnHold();
00152 }
00153 
00154 QNetworkReply *AccessManager::createRequest(Operation op, const QNetworkRequest &req, QIODevice *outgoingData)
00155 {
00156     KIO::SimpleJob *kioJob = 0;
00157     const KUrl reqUrl (req.url());
00158     
00159     if (!d->externalContentAllowed && !isLocalRequest(reqUrl)) {
00160         kDebug( 7044 ) << "Blocked: " << reqUrl;
00161         KDEPrivate::AccessManagerReply* reply = new KDEPrivate::AccessManagerReply(op, req, kioJob, this);
00162         reply->setStatus(i18n("Blocked request."),QNetworkReply::ContentAccessDenied);
00163         return reply;
00164     }
00165 
00166     switch (op) {
00167         case HeadOperation: {
00168             //kDebug( 7044 ) << "HeadOperation:" << reqUrl;
00169             kioJob = KIO::mimetype(reqUrl, KIO::HideProgressInfo);
00170             break;
00171         }
00172         case GetOperation: {
00173             //kDebug( 7044 ) << "GetOperation:" << reqUrl;
00174             if (!reqUrl.path().isEmpty() || reqUrl.host().isEmpty())
00175                 kioJob = KIO::get(reqUrl, KIO::NoReload, KIO::HideProgressInfo);
00176             else
00177                 kioJob = KIO::stat(reqUrl, KIO::HideProgressInfo);
00178             break;
00179         }
00180         case PutOperation: {
00181             //kDebug( 7044 ) << "PutOperation:" << reqUrl;
00182             if (outgoingData)
00183                 kioJob = KIO::storedPut(outgoingData->readAll(), reqUrl, -1, KIO::HideProgressInfo);
00184             else
00185                 kioJob = KIO::put(reqUrl, -1, KIO::HideProgressInfo);
00186             break;
00187         }
00188         case PostOperation: {
00189             //kDebug( 7044 ) << "PostOperation:" << reqUrl;
00190             kioJob = KIO::http_post(reqUrl, outgoingData->readAll(), KIO::HideProgressInfo);
00191             break;
00192         }
00193         case DeleteOperation: {
00194             //kDebug(7044) << "DeleteOperation:" << reqUrl;
00195             kioJob = KIO::file_delete(reqUrl, KIO::HideProgressInfo);
00196             break;
00197         }
00198         case CustomOperation: {
00199             const QByteArray& method = req.attribute(QNetworkRequest::CustomVerbAttribute).toByteArray();
00200             //kDebug(7044) << "CustomOperation:" << reqUrl << "method:" << method << "outgoing data:" << outgoingData;
00201             if (method.isEmpty()) {
00202                 KDEPrivate::AccessManagerReply* reply = new KDEPrivate::AccessManagerReply(op, req, kioJob, this);
00203                 reply->setStatus(i18n("Unknown HTTP verb."), QNetworkReply::ProtocolUnknownError);
00204                 return reply;
00205             }
00206             if (outgoingData)
00207                 kioJob = KIO::http_post(reqUrl, outgoingData->readAll(), KIO::HideProgressInfo);
00208             else
00209                 kioJob = KIO::get(reqUrl, KIO::NoReload, KIO::HideProgressInfo);
00210             kioJob->metaData().insert(QL1S("CustomHTTPMethod"), method);
00211             break;
00212         }
00213         default: {
00214             kWarning(7044) << "Unsupported KIO operation requested! Defering to QNetworkAccessManager...";
00215             return QNetworkAccessManager::createRequest(op, req, outgoingData);
00216         }
00217     }
00218 
00219     kioJob->setRedirectionHandlingEnabled(false);
00220     
00221     switch (req.priority()) {
00222     case QNetworkRequest::HighPriority:
00223         KIO::Scheduler::setJobPriority(kioJob, -5);
00224         break;
00225     case QNetworkRequest::LowPriority:
00226         KIO::Scheduler::setJobPriority(kioJob, 5);
00227         break;
00228     default:
00229         break;
00230     }
00231 
00232     KDEPrivate::AccessManagerReply *reply = new KDEPrivate::AccessManagerReply(op, req, kioJob, this);
00233     if (req.hasRawHeader("x-kdewebkit-ignore-disposition")) {
00234         kDebug(7044) << "Content-Disposition WILL BE IGNORED!";
00235         reply->setIgnoreContentDisposition(true);
00236     }
00237     
00238     KIO::MetaData metaData;
00239     d->setMetaDataForRequest(req, metaData);
00240     kioJob->addMetaData(metaData);
00241     
00242     if ( op == PostOperation && !kioJob->metaData().contains(QL1S("content-type")))  {
00243         const QVariant header = req.header(QNetworkRequest::ContentTypeHeader);
00244         if (header.isValid())
00245           kioJob->addMetaData(QL1S("content-type"),
00246                               (QL1S("Content-Type: ") + header.toString()));
00247         else
00248           kioJob->addMetaData(QL1S("content-type"),
00249                               QL1S("Content-Type: application/x-www-form-urlencoded"));
00250     }
00251 
00252     return reply;
00253 }
00254 
00255 void AccessManager::AccessManagerPrivate::setMetaDataForRequest(QNetworkRequest request, KIO::MetaData& metaData)
00256 {
00257     // Add any meta data specified within request...
00258     QVariant userMetaData = request.attribute (static_cast<QNetworkRequest::Attribute>(MetaData));
00259     if (userMetaData.isValid() && userMetaData.type() == QVariant::Map) {
00260       metaData += userMetaData.toMap();
00261     }
00262 
00263     metaData.insert("PropagateHttpHeader", "true");
00264 
00265     if (request.hasRawHeader("User-Agent")) {
00266         metaData.insert("UserAgent", request.rawHeader("User-Agent"));
00267         request.setRawHeader("User-Agent", QByteArray());
00268     }
00269 
00270     if (request.hasRawHeader("Accept")) {
00271         metaData.insert("accept", request.rawHeader("Accept"));
00272         request.setRawHeader("Accept", QByteArray());
00273     }
00274 
00275     if (request.hasRawHeader("Referer")) {
00276         metaData.insert(QL1S("referrer"), request.rawHeader("Referer"));
00277         request.setRawHeader("Referer", QByteArray());
00278     }
00279 
00280     if (request.hasRawHeader("Content-Type")) {
00281         metaData.insert(QL1S("content-type"), request.rawHeader("Content-Type"));
00282         request.setRawHeader("Content-Type", QByteArray());
00283     }
00284 
00285     request.setRawHeader("content-length", QByteArray());
00286     request.setRawHeader("Connection", QByteArray());
00287     request.setRawHeader("If-None-Match", QByteArray());
00288     request.setRawHeader("If-Modified-Since", QByteArray());
00289     request.setRawHeader("x-kdewebkit-ignore-disposition", QByteArray());
00290 
00291     QStringList customHeaders;
00292     Q_FOREACH(const QByteArray &key, request.rawHeaderList()) {
00293         const QByteArray value = request.rawHeader(key);
00294         if (value.length())
00295             customHeaders << (key + QL1S(": ") + value);
00296     }
00297 
00298     if (!customHeaders.isEmpty())
00299         metaData.insert("customHTTPHeader", customHeaders.join("\r\n"));
00300 
00301     // Append per request meta data, if any...
00302     if (!requestMetaData.isEmpty()) {
00303         metaData += requestMetaData;
00304         // Clear per request meta data...
00305         requestMetaData.clear();
00306     }
00307 
00308     // Append per session meta data, if any...
00309     if (!sessionMetaData.isEmpty())
00310         metaData += sessionMetaData;
00311 }
00312 
00313 
00314 using namespace KIO::Integration;
00315 
00316 static QSsl::SslProtocol qSslProtocolFromString(const QString& str)
00317 {
00318     if (str.compare(QLatin1String("SSLv3"), Qt::CaseInsensitive) == 0)
00319         return QSsl::SslV3;
00320 
00321     if (str.compare(QLatin1String("SSLv2"), Qt::CaseInsensitive) == 0)
00322         return QSsl::SslV2;
00323 
00324     if (str.compare(QLatin1String("TLSv1"), Qt::CaseInsensitive) == 0)
00325         return QSsl::TlsV1;
00326 
00327     return QSsl::AnyProtocol;
00328 }
00329 
00330 bool KIO::Integration::sslConfigFromMetaData(const KIO::MetaData& metadata, QSslConfiguration& sslconfig)
00331 {
00332     bool success = false;
00333 
00334     if (metadata.contains(QL1S("ssl_in_use"))) {
00335         const QSsl::SslProtocol sslProto = qSslProtocolFromString(metadata.value("ssl_protocol_version"));
00336         QList<QSslCipher> cipherList;
00337         cipherList << QSslCipher(metadata.value("ssl_cipher_name"), sslProto);
00338         sslconfig.setCaCertificates(QSslCertificate::fromData(metadata.value("ssl_peer_chain").toUtf8()));
00339         sslconfig.setCiphers(cipherList);
00340         sslconfig.setProtocol(sslProto);
00341         success = sslconfig.isNull();
00342     }
00343 
00344     return success;
00345 }
00346 
00347 CookieJar::CookieJar(QObject* parent)
00348           :QNetworkCookieJar(parent), d(new CookieJar::CookieJarPrivate) {
00349     reparseConfiguration();
00350 }
00351 
00352 CookieJar::~CookieJar() {
00353     delete d;
00354 }
00355 
00356 WId CookieJar::windowId() const {
00357     return d->windowId;
00358 }
00359 
00360 bool CookieJar::isCookieStorageDisabled() const {
00361    return d->isStorageDisabled;
00362 }
00363 
00364 QList<QNetworkCookie> CookieJar::cookiesForUrl(const QUrl &url) const {
00365     QList<QNetworkCookie> cookieList;
00366 
00367     if (d->isEnabled) {
00368         QDBusInterface kcookiejar("org.kde.kded", "/modules/kcookiejar", "org.kde.KCookieServer");
00369         QDBusReply<QString> reply = kcookiejar.call("findDOMCookies", url.toString(QUrl::RemoveUserInfo), (qlonglong)d->windowId);
00370 
00371         if (reply.isValid()) {
00372             const QString cookieStr = reply.value();
00373             const QStringList cookies = cookieStr.split(QL1S("; "), QString::SkipEmptyParts);
00374             Q_FOREACH(const QString& cookie, cookies) {
00375                 const int index = cookie.indexOf(QL1C('='));
00376                 const QString name = cookie.left(index);
00377                 const QString value = cookie.right((cookie.length() - index - 1));
00378                 cookieList << QNetworkCookie(name.toUtf8(), value.toUtf8());
00379                 //kDebug(7044) << "cookie: name=" << name << ", value=" << value;
00380             }
00381             //kDebug(7044) << "cookie for" << url.host() << ":" << cookieStr;
00382         } else {
00383             kWarning(7044) << "Unable to communicate with the cookiejar!";
00384         }
00385     }
00386 
00387     return cookieList;
00388 }
00389 
00390 bool CookieJar::setCookiesFromUrl(const QList<QNetworkCookie> &cookieList, const QUrl &url) {
00391     if (d->isEnabled) {
00392         QDBusInterface kcookiejar("org.kde.kded", "/modules/kcookiejar", "org.kde.KCookieServer");
00393         Q_FOREACH(const QNetworkCookie &cookie, cookieList) {
00394             QByteArray cookieHeader ("Set-Cookie: ");
00395             if (d->isStorageDisabled && !cookie.isSessionCookie()) {
00396                 QNetworkCookie sessionCookie(cookie);
00397                 sessionCookie.setExpirationDate(QDateTime());
00398                 cookieHeader += sessionCookie.toRawForm();
00399             } else
00400                 cookieHeader += cookie.toRawForm();
00401             kcookiejar.call("addCookies", url.toString(QUrl::RemoveUserInfo), cookieHeader, (qlonglong)d->windowId);
00402             //kDebug(7044) << "[" << d->windowId << "]" << cookieHeader << " from " << url;
00403         }
00404 
00405         return !kcookiejar.lastError().isValid();
00406     }
00407 
00408     return false;
00409 }
00410 
00411 void CookieJar::setDisableCookieStorage(bool disable) {
00412     d->isStorageDisabled = disable;
00413 }
00414 
00415 void CookieJar::setWindowId(WId id) {
00416     d->windowId = id;
00417 }
00418 
00419 void CookieJar::reparseConfiguration() {
00420     KConfigGroup cfg = KSharedConfig::openConfig("kcookiejarrc", KConfig::NoGlobals)->group("Cookie Policy");
00421     d->isEnabled = cfg.readEntry("Cookies", true);
00422 }
00423 
00424 #include "accessmanager.moc"

KIO

Skip menu "KIO"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.7.3
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal