Example #1
0
bool KWebPage::handleReply(QNetworkReply* reply, QString* contentType, KIO::MetaData* metaData)
{
    // Reply url...
    const KUrl replyUrl (reply->url());

    // Get suggested file name...
    const KIO::MetaData& data = reply->attribute(static_cast<QNetworkRequest::Attribute>(KIO::AccessManager::MetaData)).toMap();
    const QString suggestedFileName = data.value(QL1S("content-disposition-filename"));
    if (metaData) {
        *metaData = data;
    }

    // Get the mime-type...
    QString mimeType;
    extractMimeType(reply, mimeType);
    if (contentType) {
        *contentType = mimeType;
    }

    // Let the calling function deal with handling empty or inode/* mimetypes...
    if (mimeType.isEmpty() || mimeType.startsWith(QL1S("inode/"), Qt::CaseInsensitive)) {
        return false;
    }

    // Convert executable text files to plain text...
    if (KParts::BrowserRun::isTextExecutable(mimeType))
        mimeType = QL1S("text/plain");

    //kDebug(800) << "Content-disposition:" << suggestedFileName;
    //kDebug(800) << "Got unsupported content of type:" << mimeType << "URL:" << replyUrl;
    //kDebug(800) << "Error code:" << reply->error() << reply->errorString();

    if (isReplyStatusOk(reply)) {
        while (true) {
            KParts::BrowserOpenOrSaveQuestion::Result result;
            KParts::BrowserOpenOrSaveQuestion dlg(d->windowWidget(), replyUrl, mimeType);
            dlg.setSuggestedFileName(suggestedFileName);
            dlg.setFeatures(KParts::BrowserOpenOrSaveQuestion::ServiceSelection);
            result = dlg.askOpenOrSave();

            switch (result) {
            case KParts::BrowserOpenOrSaveQuestion::Open:
                // Handle Post operations that return content...
                if (reply->operation() == QNetworkAccessManager::PostOperation) {
                    d->mimeType = mimeType;
                    QFileInfo finfo (suggestedFileName.isEmpty() ? replyUrl.fileName() : suggestedFileName);
                    KTemporaryFile tempFile;
                    tempFile.setSuffix(QL1C('.') + finfo.suffix());
                    tempFile.setAutoRemove(false);
                    tempFile.open();
                    KUrl destUrl;
                    destUrl.setPath(tempFile.fileName());
                    KIO::Job *job = KIO::file_copy(replyUrl, destUrl, 0600, KIO::Overwrite);
                    job->ui()->setWindow(d->windowWidget());
                    job->ui()->setAutoErrorHandlingEnabled(true);
                    connect(job, SIGNAL(result(KJob*)),
                            this, SLOT(_k_copyResultToTempFile(KJob*)));
                    return true;
                }

                // Ask before running any executables...
                if (KParts::BrowserRun::allowExecution(mimeType, replyUrl)) {
                    KService::Ptr offer = dlg.selectedService();
                    // HACK: The check below is necessary to break an infinite
                    // recursion that occurs whenever this function is called as a result
                    // of receiving content that can be rendered by the app using this engine.
                    // For example a text/html header that containing a content-disposition
                    // header is received by the app using this class.
                    if (isMimeTypeAssociatedWithSelf(offer)) {
                        reloadRequestWithoutDisposition(reply);
                    } else {
                        KUrl::List list;
                        list.append(replyUrl);
                        bool success = false;
                        // kDebug(800) << "Suggested file name:" << suggestedFileName;
                        if (offer) {
                            success = KRun::run(*offer, list, d->windowWidget() , false, suggestedFileName);
                        } else {
                            success = KRun::displayOpenWithDialog(list, d->windowWidget(), false, suggestedFileName);
                            if (!success)
                                break;
                        }
                        // For non KIO apps and cancelled Open With dialog, remove slave on hold.
                        if (!success || (offer && !offer->categories().contains(QL1S("KDE")))) {
                            KIO::SimpleJob::removeOnHold(); // Remove any slave-on-hold...
                        }
                    }
                    return true;
                }
                // TODO: Instead of silently failing when allowExecution fails, notify
                // the user why the requested action cannot be fulfilled...
                return false;
            case KParts::BrowserOpenOrSaveQuestion::Save:
                // Do not download local files...
                if (!replyUrl.isLocalFile()) {
                    QString downloadCmd (reply->property("DownloadManagerExe").toString());
                    if (!downloadCmd.isEmpty()) {
                        downloadCmd += QLatin1Char(' ');
                        downloadCmd += KShell::quoteArg(replyUrl.url());
                        if (!suggestedFileName.isEmpty()) {
                            downloadCmd += QLatin1Char(' ');
                            downloadCmd += KShell::quoteArg(suggestedFileName);
                        }
                        // kDebug(800) << "download command:" << downloadCmd;
                        if (KRun::runCommand(downloadCmd, view()))
                            return true;
                    }
                    if (!downloadResource(replyUrl, suggestedFileName, d->windowWidget()))
                        break;
                }
                return true;
            case KParts::BrowserOpenOrSaveQuestion::Cancel:
            default:
                KIO::SimpleJob::removeOnHold(); // Remove any slave-on-hold...
                return true;
            }
        }
    } else {