diff options
Diffstat (limited to 'src/webpage.cpp')
-rw-r--r-- | src/webpage.cpp | 380 |
1 files changed, 212 insertions, 168 deletions
diff --git a/src/webpage.cpp b/src/webpage.cpp index 507263cc..00745445 100644 --- a/src/webpage.cpp +++ b/src/webpage.cpp @@ -97,6 +97,72 @@ static bool domainSchemeMatch(const QUrl& u1, const QUrl& u2) } +// NOTE +// This is heavily based on the one from KdeWebKit and +// extended to provide the extra functionality we need: +// 1. KGet Integration +// 2. Save downloads history +static bool downloadResource (const KUrl& srcUrl, const KIO::MetaData& metaData = KIO::MetaData(), + QWidget* parent = 0, const QString& suggestedName = QString()) +{ + KUrl destUrl; + + int result = KIO::R_OVERWRITE; + const QUrl fileName ((suggestedName.isEmpty() ? srcUrl.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?"), 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(); + } + } + } + while (result == KIO::R_CANCEL && destUrl.isValid()); + + // Save download on history manager + Application::historyManager()->addDownload(srcUrl.pathOrUrl() , destUrl.pathOrUrl()); + + if (ReKonfig::kgetDownload()) + { + //KGet integration: + if (!QDBusConnection::sessionBus().interface()->isServiceRegistered("org.kde.kget")) + { + KToolInvocation::kdeinitExecWait("kget"); + } + QDBusInterface kget("org.kde.kget", "/KGet", "org.kde.kget.main"); + if (kget.isValid()) + { + kget.call("addTransfer", srcUrl.prettyUrl(), destUrl.prettyUrl(), true); + return true; + } + return false; + } + + 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; + +} + + // --------------------------------------------------------------------------------- @@ -246,111 +312,151 @@ void WebPage::handleUnsupportedContent(QNetworkReply *reply) if (_protHandler.postHandling(reply->request(), mainFrame())) return; - if (reply->error() == QNetworkReply::NoError) - { - KUrl replyUrl = reply->url(); + if (reply->error() != QNetworkReply::NoError) + return; + + KUrl replyUrl = reply->url(); - // HACK ------------------------------------------- - QString mimeType; - QString suggestedFileName; - - QString app = reply->header(QNetworkRequest::ContentTypeHeader).toString(); - QStringList headerList = app.split( ';' ); - - if(headerList.count() > 0) + // HACK ------------------------------------------- + // This is done to fix #231204 && #212808 + + QString mimeType; + QString suggestedFileName; + + QString app = reply->header(QNetworkRequest::ContentTypeHeader).toString(); + QStringList headerList = app.split( ';' ); + + if(headerList.count() > 0) + { + mimeType = headerList.takeFirst().trimmed(); + Q_FOREACH(const QString &head, headerList) { - mimeType = headerList.takeFirst().trimmed(); - Q_FOREACH(const QString &head, headerList) + if( head.contains( QL1S("name") ) ) { - if( head.contains( QL1S("name") ) ) - { - // this is not so sure.. :) - suggestedFileName = head; - suggestedFileName = suggestedFileName.remove( QL1S("name=") ); - suggestedFileName = suggestedFileName.remove( '"' ); - suggestedFileName = suggestedFileName.trimmed(); - break; - } + // this is not so sure.. :) + suggestedFileName = head; + suggestedFileName = suggestedFileName.remove( QL1S("name=") ); + suggestedFileName = suggestedFileName.remove( '"' ); + suggestedFileName = suggestedFileName.trimmed(); + break; } } - else + } + else + { + mimeType = reply->header(QNetworkRequest::ContentTypeHeader).toString(); + } + + // NOTE + // This part has been copied from KWebPage::downloadResponse code + if (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 { - mimeType = reply->header(QNetworkRequest::ContentTypeHeader).toString(); + 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(); + } + } + } } - // ------------------------------------------------ - - KService::Ptr appService = KMimeTypeTrader::self()->preferredService(mimeType); - - bool isLocal = replyUrl.isLocalFile(); + } + + kDebug() << "Detected MimeType = " << mimeType; + kDebug() << "Suggested File Name = " << suggestedFileName; + // ------------------------------------------------ + + KService::Ptr appService = KMimeTypeTrader::self()->preferredService(mimeType); - if (appService.isNull()) // no service can handle this. We can just download it.. - { - kDebug() << "no service can handle this. We can just download it.."; + bool isLocal = replyUrl.isLocalFile(); - isLocal - ? KMessageBox::sorry(view(), i18n("No service can handle this :(")) - : downloadThings(reply->request(), suggestedFileName); + if (appService.isNull()) // no service can handle this. We can just download it.. + { + kDebug() << "no service can handle this. We can just download it.."; - return; - } + isLocal + ? KMessageBox::sorry(view(), i18n("No service can handle this :(")) + : downloadReply(reply, suggestedFileName); - if (!isLocal) - { + return; + } - KParts::BrowserOpenOrSaveQuestion dlg(Application::instance()->mainWindow(), replyUrl, mimeType); - if(!suggestedFileName.isEmpty()) - dlg.setSuggestedFileName(suggestedFileName); - - switch (dlg.askEmbedOrSave()) - { - case KParts::BrowserOpenOrSaveQuestion::Save: - kDebug() << "user choice: no services, just download!"; - downloadThings(reply->request(), suggestedFileName); - return; + if (!isLocal) + { - case KParts::BrowserOpenOrSaveQuestion::Cancel: - return; + KParts::BrowserOpenOrSaveQuestion dlg(Application::instance()->mainWindow(), replyUrl, mimeType); + if(!suggestedFileName.isEmpty()) + dlg.setSuggestedFileName(suggestedFileName); + + switch (dlg.askEmbedOrSave()) + { + case KParts::BrowserOpenOrSaveQuestion::Save: + kDebug() << "user choice: no services, just download!"; + downloadReply(reply, suggestedFileName); + return; - default: // non extant case - break; - } - } + case KParts::BrowserOpenOrSaveQuestion::Cancel: + return; - // case KParts::BrowserRun::Embed - KService::List partServices = KMimeTypeTrader::self()->query(mimeType, QL1S("KParts/ReadOnlyPart")); - if (partServices.count() > 0) - { - QString p = replyUrl.pathOrUrl(); - - // A part can handle this. Embed it! - QString html; - html += "<html>"; - html += "<head>"; - html += "<title>"; - html += p; - html += "</title>"; - html += "<style type=\"text/css\">"; - html += "* { border: 0; padding: 0; margin: 0; }"; - html += "</style>"; - html += "</head>"; - html += "<body>"; - html += "<object type=\"" + mimeType + "\" data=\"" + p + "\" width=\"100%\" height=\"100%\" />"; - html += "</body>"; - html += "</html>"; - - mainFrame()->setHtml(html); - _isOnRekonqPage = true; - Application::instance()->mainWindow()->mainView()->urlBar()->setQUrl(replyUrl); - Application::instance()->mainWindow()->updateActions(); - } - else - { - // No parts, just app services. Load it! - KRun::run(*appService, replyUrl, 0); + default: // non extant case + break; } + } - return; + // case KParts::BrowserRun::Embed + KService::List partServices = KMimeTypeTrader::self()->query(mimeType, QL1S("KParts/ReadOnlyPart")); + if (partServices.count() > 0) + { + QString p = replyUrl.pathOrUrl(); + + // A part can handle this. Embed it! + QString html; + html += "<html>"; + html += "<head>"; + html += "<title>"; + html += p; + html += "</title>"; + html += "<style type=\"text/css\">"; + html += "* { border: 0; padding: 0; margin: 0; }"; + html += "</style>"; + html += "</head>"; + html += "<body>"; + html += "<object type=\"" + mimeType + "\" data=\"" + p + "\" width=\"100%\" height=\"100%\" />"; + html += "</body>"; + html += "</html>"; + + mainFrame()->setHtml(html); + _isOnRekonqPage = true; + Application::instance()->mainWindow()->mainView()->urlBar()->setQUrl(replyUrl); + Application::instance()->mainWindow()->updateActions(); } + else + { + // No parts, just app services. Load it! + KRun::run(*appService, replyUrl, 0); + } + + return; } @@ -402,24 +508,28 @@ void WebPage::manageNetworkErrors(QNetworkReply *reply) } break; + case QNetworkReply::OperationCanceledError: // operation canceled via abort() or close() calls + // ignore this.. + return; + case QNetworkReply::ContentAccessDenied: // access to remote content denied (similar to HTTP error 401) kDebug() << "We (hopefully) are managing this through the adblock :)"; break; case QNetworkReply::UnknownNetworkError: // unknown network-related error detected - if (_protHandler.postHandling(reply->request(), mainFrame())) - break; + _protHandler.postHandling(reply->request(), mainFrame()); + return; case QNetworkReply::ConnectionRefusedError: // remote server refused connection case QNetworkReply::HostNotFoundError: // invalid hostname case QNetworkReply::TimeoutError: // connection time out - case QNetworkReply::OperationCanceledError: // operation canceled via abort() or close() calls case QNetworkReply::ProxyNotFoundError: // invalid proxy hostname case QNetworkReply::ContentOperationNotPermittedError: // operation requested on remote content not permitted case QNetworkReply::ContentNotFoundError: // remote content not found on server (similar to HTTP error 404) case QNetworkReply::ProtocolUnknownError: // Unknown protocol case QNetworkReply::ProtocolInvalidOperationError: // requested operation is invalid for this protocol + kDebug() << "ERROR " << reply->error() << ": " << reply->errorString(); if (reply->url() == _loadingUrl) { mainFrame()->setHtml(errorPage(reply)); @@ -478,89 +588,23 @@ QString WebPage::errorPage(QNetworkReply *reply) } -// WARNING -// this code is actually copied from KWebPage::downloadRequest to save -// downloads data before. If you have some better ideas about, -// feel free to let us know about :) -void WebPage::downloadThings(const QNetworkRequest &request, const QString &suggestedFileName) +void WebPage::downloadReply(const QNetworkReply *reply, const QString &suggestedFileName) { - KUrl destUrl; - KUrl srcUrl(request.url()); - - if( !ReKonfig::kgetDownload() && suggestedFileName.isEmpty() ) - { - kDebug() << "Using KWebPage downloadRequest.."; - Application::historyManager()->addDownload(srcUrl.pathOrUrl() , destUrl.pathOrUrl()); - KWebPage::downloadRequest(request); - return; - } - - int result = KIO::R_OVERWRITE; - - do - { - QString fName = suggestedFileName.isEmpty() - ? srcUrl.fileName() - : suggestedFileName; - - destUrl = KFileDialog::getSaveFileName(fName, QString(), view()); - - if (destUrl.isLocalFile()) - { - QFileInfo finfo(destUrl.toLocalFile()); - if (finfo.exists()) - { - QDateTime now = QDateTime::currentDateTime(); - QPointer<KIO::RenameDialog> dlg = new KIO::RenameDialog(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(); - delete dlg; - } - } - } - while (result == KIO::R_CANCEL && destUrl.isValid()); + downloadResource( reply->url(), KIO::MetaData(), view(), suggestedFileName); +} - if (result == KIO::R_OVERWRITE && destUrl.isValid()) - { - // now store data - // now, destUrl, srcUrl - Application::historyManager()->addDownload(srcUrl.pathOrUrl() , destUrl.pathOrUrl()); - if (ReKonfig::kgetDownload()) - { - //KGet integration: - if (!QDBusConnection::sessionBus().interface()->isServiceRegistered("org.kde.kget")) - { - KToolInvocation::kdeinitExecWait("kget"); - } - QDBusInterface kget("org.kde.kget", "/KGet", "org.kde.kget.main"); - if (kget.isValid()) - { - kget.call("addTransfer", srcUrl.prettyUrl(), destUrl.prettyUrl(), true); - return; - } - } +void WebPage::downloadRequest(const QNetworkRequest &request) +{ + downloadResource(request.url(), + request.attribute(static_cast<QNetworkRequest::Attribute>(KIO::AccessManager::MetaData)).toMap(), + view()); +} - // else, use KIO or fallback to it - 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())); - 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); - } +void WebPage::downloadUrl(const KUrl &url) +{ + downloadResource( url, KIO::MetaData(), view() ); } |