[WebKit-devel] KDE/kdelibs/kdewebkit

Dawit Alemayehu adawit at kde.org
Wed May 19 02:08:45 CEST 2010


SVN commit 1128338 by adawit:

- Added a slot that properly handles the downloading of replies that might contain
  "content-disposition" headers.

  Note this new API was added this late in anticipation of fixing a critical 
  issue that is awaiting a pending patch upstream in QtWebKit. See
  https://bugs.webkit.org/show_bug.cgi?id=37880

CCMAIL:kde-bindings at kde.org
CCMAIL:rekonq at kde.org
CCMAIL:webkit-devel at kde.org


 M  +88 -35    kwebpage.cpp  
 M  +16 -5     kwebpage.h  


--- trunk/KDE/kdelibs/kdewebkit/kwebpage.cpp #1128337:1128338
@@ -4,7 +4,7 @@
  * Copyright (C) 2008 Dirk Mueller <mueller at kde.org>
  * Copyright (C) 2008 Urs Wolfer <uwolfer @ kde.org>
  * Copyright (C) 2008 Michael Howell <mhowell123 at gmail.com>
- * Copyright (C) 2009 Dawit Alemayehu <adawit at kde.org>
+ * Copyright (C) 2009,2010 Dawit Alemayehu <adawit at kde.org>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -49,18 +49,63 @@
 #include <QtCore/QPointer>
 #include <QtCore/QFileInfo>
 #include <QtWebKit/QWebFrame>
+#include <QtNetwork/QNetworkReply>
 
 
-#define QL1(x)  QLatin1String(x)
+#define QL1S(x)  QLatin1String(x)
+#define QL1C(x)  QLatin1Char(x)
 
+static KUrl promptUser (QWidget *parent, const KUrl& url, const QString& suggestedName)
+{
+    KUrl destUrl;
+    int result = KIO::R_OVERWRITE;
+    const QUrl fileName ((suggestedName.isEmpty() ? url.fileName() : suggestedName));
 
+    do {
+        destUrl = KFileDialog::getSaveFileName(fileName, QString(), parent);
+
+        if (destUrl.isLocalFile()) {
+            QFileInfo finfo (destUrl.toLocalFile());
+            if (finfo.exists()) {
+                QDateTime now = QDateTime::currentDateTime();
+                KIO::RenameDialog dlg (parent, i18n("Overwrite File?"), url, destUrl,
+                                       KIO::RenameDialog_Mode(KIO::M_OVERWRITE | KIO::M_SKIP),
+                                       -1, finfo.size(),
+                                       now.toTime_t(), finfo.created().toTime_t(),
+                                       now.toTime_t(), finfo.lastModified().toTime_t());
+                result = dlg.exec();
+            }
+        }
+    } while (result == KIO::R_CANCEL && destUrl.isValid());
+
+    return destUrl;
+}
+
+static bool downloadResource (const KUrl& srcUrl, const KIO::MetaData& metaData = KIO::MetaData(),
+                              QWidget* parent = 0, const QString& suggestedName = QString())
+{
+    const KUrl& destUrl = promptUser(parent, srcUrl, suggestedName);
+
+    if (destUrl.isValid()) {
+        KIO::Job *job = KIO::file_copy(srcUrl, destUrl, -1, KIO::Overwrite);
+
+        if (!metaData.isEmpty())
+            job->setMetaData(metaData);
+
+        job->addMetaData(QL1S("MaxCacheSize"), QL1S("0")); // Don't store in http cache.
+        job->addMetaData(QL1S("cache"), QL1S("cache")); // Use entry from cache if available.
+        job->uiDelegate()->setAutoErrorHandlingEnabled(true);
+        return true;
+    }
+    return false;
+}
+
 class KWebPage::KWebPagePrivate
 {
 public:
     QPointer<KWebWallet> wallet;
 };
 
-
 KWebPage::KWebPage(QObject *parent, Integration flags)
          :QWebPage(parent), d(new KWebPagePrivate)
 {   
@@ -162,43 +207,51 @@
 
 void KWebPage::downloadRequest(const QNetworkRequest &request)
 {
-    KUrl destUrl;
-    KUrl srcUrl (request.url());
-    int result = KIO::R_OVERWRITE;
+    downloadResource(request.url(),
+                     request.attribute(static_cast<QNetworkRequest::Attribute>(KIO::AccessManager::MetaData)).toMap(),
+                     view());
+}
 
-    do {
-        destUrl = KFileDialog::getSaveFileName(srcUrl.fileName(), QString(), view());
-
-        if (destUrl.isLocalFile()) {
-            QFileInfo finfo (destUrl.toLocalFile());
-            if (finfo.exists()) {
-                QDateTime now = QDateTime::currentDateTime();
-                KIO::RenameDialog dlg (view(), i18n("Overwrite File?"), srcUrl, destUrl,
-                                       KIO::RenameDialog_Mode(KIO::M_OVERWRITE | KIO::M_SKIP),
-                                       -1, finfo.size(),
-                                       now.toTime_t(), finfo.created().toTime_t(),
-                                       now.toTime_t(), finfo.lastModified().toTime_t());
-                result = dlg.exec();
+void KWebPage::downloadUrl(const KUrl &url)
+{
+    downloadResource(url, KIO::MetaData(), view());
             }
-        }
-    } while (result == KIO::R_CANCEL && destUrl.isValid());
 
-    if (result == KIO::R_OVERWRITE && destUrl.isValid()) {
-        KIO::Job *job = KIO::file_copy(srcUrl, destUrl, -1, KIO::Overwrite);
-        QVariant attr = request.attribute(static_cast<QNetworkRequest::Attribute>(KIO::AccessManager::MetaData));
-        if (attr.isValid() && attr.type() == QVariant::Map)
-            job->setMetaData(KIO::MetaData(attr.toMap()));
+void KWebPage::downloadResponse(QNetworkReply *reply)
+{
+    // FIXME: Remove the next line of code once support for putting an ioslave is
+    // implemented in KIO::AccessManager which is waiting for an upstream fix.
+    // See https://bugs.webkit.org/show_bug.cgi?id=37880.
+    reply->abort();
 
-        job->addMetaData(QL1("MaxCacheSize"), QL1("0")); // Don't store in http cache.
-        job->addMetaData(QL1("cache"), QL1("cache")); // Use entry from cache if available.
-        job->uiDelegate()->setAutoErrorHandlingEnabled(true);
+    QString suggestedFileName;
+    if (reply && reply->hasRawHeader("Content-Disposition")) {
+        KIO::MetaData metaData = reply->attribute(static_cast<QNetworkRequest::Attribute>(KIO::AccessManager::MetaData)).toMap();
+        if (metaData.value(QL1S("content-disposition-type")).compare(QL1S("attachment"), Qt::CaseInsensitive) == 0) {
+            suggestedFileName = metaData.value(QL1S("content-disposition-filename"));
+        } else {
+            const QString value = QL1S(reply->rawHeader("Content-Disposition").simplified());
+            if (value.startsWith(QL1S("attachment"), Qt::CaseInsensitive)) {
+                const int length = value.size();
+                int pos = value.indexOf(QL1S("filename"), 0, Qt::CaseInsensitive);
+                if (pos > -1) {
+                    pos += 9;
+                    while (pos < length && (value.at(pos) == QL1C(' ') || value.at(pos) == QL1C('=') || value.at(pos) == QL1C('"')))
+                        pos++;
+
+                    int endPos = pos;
+                    while (endPos < length && value.at(endPos) != QL1C('"') && value.at(endPos) != QL1C(';'))
+                        endPos++;
+
+                    if (endPos > pos) {
+                        suggestedFileName = value.mid(pos, (endPos-pos)).trimmed();
     }
 }
+            }
+        }
+    }
 
-void KWebPage::downloadUrl(const KUrl &url)
-{
-    QNetworkRequest request (url);
-    downloadRequest(request);
+    downloadResource(reply->url(), KIO::MetaData(), this->view(), suggestedFileName);
 }
 
 QString KWebPage::sessionMetaData(const QString &key) const
@@ -254,7 +307,7 @@
 QString KWebPage::userAgentForUrl(const QUrl& _url) const
 {
     const KUrl url(_url);
-    QString userAgent = KProtocolManager::userAgentForHost((url.isLocalFile() ? "localhost" : url.host()));
+    const QString userAgent = KProtocolManager::userAgentForHost((url.isLocalFile() ? QL1S("localhost") : url.host()));
 
     if (userAgent == KProtocolManager::defaultUserAgent())
         return QWebPage::userAgentForUrl(_url);
@@ -275,7 +328,7 @@
         meta-data value to the current url for proper integration with KCookieJar...
       */
     if (frame == mainFrame() && type != QWebPage::NavigationTypeReload) {
-        setSessionMetaData(QL1("cross-domain"), request.url().toString());
+        setSessionMetaData(QL1S("cross-domain"), request.url().toString());
     }
 
     return QWebPage::acceptNavigationRequest(frame, request, type);
--- trunk/KDE/kdelibs/kdewebkit/kwebpage.h #1128337:1128338
@@ -4,7 +4,7 @@
  * Copyright (C) 2008 Dirk Mueller <mueller at kde.org>
  * Copyright (C) 2008 Urs Wolfer <uwolfer @ kde.org>
  * Copyright (C) 2008 Michael Howell <mhowell123 at gmail.com>
- * Copyright (C) 2009 Dawit Alemayehu <adawit @ kde.org>
+ * Copyright (C) 2009,2010 Dawit Alemayehu <adawit @ kde.org>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -126,7 +126,7 @@
      * Downloads @p request using KIO.
      *
      * This slot first prompts the user where to put/save the requested
-     * resource and then downloads using KIO::file_copy.
+     * resource and then downloads it using KIO.
      */
     virtual void downloadRequest(const QNetworkRequest &request);
 
@@ -134,10 +134,20 @@
      * Downloads @p url using KIO.
      *
      * This slot first prompts the user where to put/save the requested
-     * resource and then downloads using KIO::file_copy.
+     * resource and then downloads it using KIO.     
      */
     virtual void downloadUrl(const KUrl &url);
 
+    /**
+     * Downloads the resource specified by @p reply using KIO.
+     *
+     * This slot first prompts the user where to save the requested resource
+     * and then downloads it using KIO.
+     *
+     * @since 4.5
+     */
+    void downloadResponse(QNetworkReply *reply);
+
 protected:
     /**
      * Returns the value of the permanent (per session) meta data for the given @p key.
@@ -184,10 +194,11 @@
     void removeRequestMetaData(const QString &key);
 
     /**
-     * Reimplemented for internal reasons, the API is not affected.
+     * This function is re-implemented to provide KDE user-agent management
+     * integration through KProtocolManager.
      *
+     * @see KProtocolManager::userAgentForUrl.
      * @see QWebPage::userAgentForUrl.
-     * @internal
      */
     virtual QString userAgentForUrl(const QUrl& url) const;
 


More information about the WebKit-devel mailing list