00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "browserrun.h"
00020 #include <kmessagebox.h>
00021 #include <kfiledialog.h>
00022 #include <kio/job.h>
00023 #include <kio/jobuidelegate.h>
00024 #include <kio/scheduler.h>
00025 #include <kio/copyjob.h>
00026 #include <klocale.h>
00027 #include <kshell.h>
00028 #include <kstringhandler.h>
00029 #include <kmimetypetrader.h>
00030 #include <ktemporaryfile.h>
00031 #include <kdebug.h>
00032 #include <kde_file.h>
00033 #include <kstandarddirs.h>
00034 #include <assert.h>
00035
00036 using namespace KParts;
00037
00038 class BrowserRun::BrowserRunPrivate
00039 {
00040 public:
00041 bool m_bHideErrorDialog;
00042 bool m_bRemoveReferrer;
00043 bool m_bTrustedSource;
00044 KParts::OpenUrlArguments m_args;
00045 KParts::BrowserArguments m_browserArgs;
00046
00047 KParts::ReadOnlyPart *m_part;
00048 QPointer<QWidget> m_window;
00049 QString m_mimeType;
00050 QString m_contentDisposition;
00051 };
00052
00053 BrowserRun::BrowserRun( const KUrl& url, const KParts::OpenUrlArguments& args,
00054 const KParts::BrowserArguments& browserArgs,
00055 KParts::ReadOnlyPart *part, QWidget* window,
00056 bool removeReferrer, bool trustedSource, bool hideErrorDialog )
00057 : KRun( url, window, 0 , false , false ),
00058 d(new BrowserRunPrivate)
00059 {
00060 d->m_bHideErrorDialog = hideErrorDialog;
00061 d->m_bRemoveReferrer = removeReferrer;
00062 d->m_bTrustedSource = trustedSource;
00063 d->m_args = args;
00064 d->m_browserArgs = browserArgs;
00065 d->m_part = part;
00066 d->m_window = window;
00067 }
00068
00069 BrowserRun::~BrowserRun()
00070 {
00071 delete d;
00072 }
00073
00074 KParts::ReadOnlyPart* BrowserRun::part() const
00075 {
00076 return d->m_part;
00077 }
00078
00079 KUrl BrowserRun::url() const
00080 {
00081 return KRun::url();
00082 }
00083
00084 void BrowserRun::init()
00085 {
00086 if ( d->m_bHideErrorDialog )
00087 {
00088
00089
00090
00091 if ( !KRun::url().isValid() ) {
00092 redirectToError( KIO::ERR_MALFORMED_URL, KRun::url().url() );
00093 return;
00094 }
00095 if ( !isLocalFile() && !hasError() && KRun::url().isLocalFile() )
00096 setIsLocalFile( true );
00097
00098 if ( isLocalFile() ) {
00099 KDE_struct_stat buff;
00100 if ( KDE_stat( QFile::encodeName(KRun::url().toLocalFile()), &buff ) == -1 )
00101 {
00102 kDebug(1000) << KRun::url().toLocalFile() << "doesn't exist.";
00103 redirectToError( KIO::ERR_DOES_NOT_EXIST, KRun::url().toLocalFile() );
00104 return;
00105 }
00106 setMode( buff.st_mode );
00107 }
00108 }
00109 KRun::init();
00110 }
00111
00112 void BrowserRun::scanFile()
00113 {
00114 kDebug(1000) << KRun::url();
00115
00116
00117
00118
00119 if ( KRun::url().query().isEmpty() && !KRun::url().protocol().startsWith("http") )
00120 {
00121 KMimeType::Ptr mime = KMimeType::findByUrl( KRun::url() );
00122 assert( mime );
00123 if ( mime->name() != "application/octet-stream" || isLocalFile() )
00124 {
00125 kDebug(1000) << "MIME TYPE is" << mime->name();
00126 mimeTypeDetermined( mime->name() );
00127 return;
00128 }
00129 }
00130
00131 QMap<QString, QString>& metaData = d->m_args.metaData();
00132 if ( d->m_part ) {
00133 const QString proto = d->m_part->url().protocol().toLower();
00134
00135 if (proto == "https" || proto == "webdavs") {
00136 metaData.insert("main_frame_request", "TRUE" );
00137 metaData.insert("ssl_was_in_use", "TRUE" );
00138 metaData.insert("ssl_activate_warnings", "TRUE" );
00139 } else if (proto == "http" || proto == "webdav") {
00140 metaData.insert("ssl_activate_warnings", "TRUE" );
00141 metaData.insert("ssl_was_in_use", "FALSE" );
00142 }
00143
00144
00145 if (!metaData.contains("PropagateHttpHeader"))
00146 metaData.insert("PropagateHttpHeader", "TRUE");
00147 }
00148
00149 KIO::TransferJob *job;
00150 if ( d->m_browserArgs.doPost() && KRun::url().protocol().startsWith("http")) {
00151 job = KIO::http_post( KRun::url(), d->m_browserArgs.postData, KIO::HideProgressInfo );
00152 job->addMetaData( "content-type", d->m_browserArgs.contentType() );
00153 } else {
00154 job = KIO::get(KRun::url(),
00155 d->m_args.reload() ? KIO::Reload : KIO::NoReload,
00156 KIO::HideProgressInfo);
00157 }
00158
00159 if ( d->m_bRemoveReferrer )
00160 metaData.remove("referrer");
00161
00162 job->addMetaData( metaData );
00163 job->ui()->setWindow( d->m_window );
00164 connect( job, SIGNAL( result( KJob *)),
00165 this, SLOT( slotBrowserScanFinished(KJob *)));
00166 connect( job, SIGNAL( mimetype( KIO::Job *, const QString &)),
00167 this, SLOT( slotBrowserMimetype(KIO::Job *, const QString &)));
00168 setJob( job );
00169 }
00170
00171 void BrowserRun::slotBrowserScanFinished(KJob *job)
00172 {
00173 kDebug(1000) << job->error();
00174 if ( job->error() == KIO::ERR_IS_DIRECTORY )
00175 {
00176
00177
00178
00179 kDebug(1000) << "It is in fact a directory!";
00180
00181 KRun::setUrl( static_cast<KIO::TransferJob *>(job)->url() );
00182 setJob( 0 );
00183 mimeTypeDetermined( "inode/directory" );
00184 }
00185 else
00186 {
00187 if ( job->error() )
00188 handleError( job );
00189 else
00190 KRun::slotScanFinished(job);
00191 }
00192 }
00193
00194 void BrowserRun::slotBrowserMimetype( KIO::Job *_job, const QString &type )
00195 {
00196 Q_ASSERT( _job == KRun::job() );
00197 KIO::TransferJob *job = static_cast<KIO::TransferJob *>(KRun::job());
00198
00199
00200
00201 setUrl( job->url() );
00202
00203 if (job->isErrorPage()) {
00204 d->m_mimeType = type;
00205 handleError(job);
00206 setJob( 0 );
00207 } else {
00208 kDebug(1000) << "found" << type << "for" << KRun::url();
00209
00210
00211
00212 const QString suggestedFileName = job->queryMetaData("content-disposition-filename");
00213 setSuggestedFileName(suggestedFileName);
00214
00215 d->m_contentDisposition = job->queryMetaData("content-disposition-type");
00216
00217
00218 QString _type = type;
00219 job->putOnHold();
00220 setJob( 0 );
00221
00222 mimeTypeDetermined( _type );
00223 }
00224 }
00225
00226 BrowserRun::NonEmbeddableResult BrowserRun::handleNonEmbeddable( const QString& _mimeType )
00227 {
00228 QString mimeType( _mimeType );
00229 Q_ASSERT( !hasFinished() );
00230
00231 if ( mimeType != "inode/directory" &&
00232 !KRun::url().isLocalFile() )
00233 {
00234 if ( isTextExecutable(mimeType) )
00235 mimeType = QLatin1String("text/plain");
00236 kDebug(1000) << "ask for saving";
00237 KService::Ptr offer = KMimeTypeTrader::self()->preferredService(mimeType, "Application");
00238
00239 KParts::BrowserRun::AskSaveResult res = askSave( KRun::url(), offer, mimeType, suggestedFileName() );
00240 if ( res == KParts::BrowserRun::Save ) {
00241 save( KRun::url(), suggestedFileName() );
00242 kDebug(1000) << "Save: returning Handled";
00243 setFinished( true );
00244 return Handled;
00245 }
00246 else if ( res == KParts::BrowserRun::Cancel ) {
00247
00248 kDebug(1000) << "Cancel: returning Handled";
00249 setFinished( true );
00250 return Handled;
00251 }
00252 else
00253 {
00254
00255
00256 if ( d->m_browserArgs.doPost() )
00257 {
00258 kDebug(1000) << "request comes from a POST, can't pass a URL to another app, need to save";
00259 d->m_mimeType = mimeType;
00260 QString extension;
00261 QString fileName = suggestedFileName().isEmpty() ? KRun::url().fileName() : suggestedFileName();
00262 int extensionPos = fileName.lastIndexOf( '.' );
00263 if ( extensionPos != -1 )
00264 extension = fileName.mid( extensionPos );
00265 KTemporaryFile tempFile;
00266 tempFile.setSuffix(extension);
00267 tempFile.setAutoRemove(false);
00268 tempFile.open();
00269 KUrl destURL;
00270 destURL.setPath( tempFile.fileName() );
00271 KIO::Job *job = KIO::file_copy( KRun::url(), destURL, 0600, KIO::Overwrite );
00272 job->ui()->setWindow(d->m_window);
00273 connect( job, SIGNAL(result(KJob *)),
00274 this, SLOT(slotCopyToTempFileResult(KJob *)) );
00275 return Delayed;
00276 }
00277 }
00278 }
00279
00280
00281 if ( !d->m_bTrustedSource &&
00282 !allowExecution( mimeType, KRun::url() ) )
00283 {
00284 setFinished( true );
00285 return Handled;
00286 }
00287
00288 KIO::SimpleJob::removeOnHold();
00289 return NotHandled;
00290 }
00291
00292
00293 bool BrowserRun::allowExecution( const QString &mimeType, const KUrl &url )
00294 {
00295 if ( !KRun::isExecutable( mimeType ) )
00296 return true;
00297
00298 if ( !url.isLocalFile() )
00299 return false;
00300
00301 return ( KMessageBox::warningContinueCancel( 0,
00302 i18n( "Do you really want to execute '%1'?", url.prettyUrl() ),
00303 i18n("Execute File?"), KGuiItem(i18n("Execute")) ) == KMessageBox::Continue );
00304 }
00305
00306 static QString makeQuestion( const KUrl& url, const QString& mimeType, const QString& suggestedFileName )
00307 {
00308 QString surl = url.prettyUrl();
00309 KMimeType::Ptr mime = KMimeType::mimeType(mimeType, KMimeType::ResolveAliases);
00310 QString comment = mimeType;
00311
00312
00313
00314 if (mime && mime->name() != KMimeType::defaultMimeType()) {
00315
00316 comment = mime->comment();
00317 }
00318
00319
00320 if ( suggestedFileName.isEmpty() )
00321 return i18n("Open '%2'?\nType: %1", comment, surl);
00322 else
00323 return i18n("Open '%3'?\nName: %2\nType: %1", comment, suggestedFileName, surl);
00324 }
00325
00326
00327
00328 BrowserRun::AskSaveResult BrowserRun::askSave( const KUrl & url, KService::Ptr offer, const QString& mimeType, const QString & suggestedFileName )
00329 {
00330
00331
00332
00333
00334 QString question = makeQuestion( url, mimeType, suggestedFileName );
00335
00336
00337 QString openText = (offer && !offer->name().isEmpty())
00338 ? i18n("&Open with '%1'", offer->name())
00339 : i18n("&Open With...");
00340
00341 int choice = KMessageBox::questionYesNoCancel(
00342 0, question, url.host(),
00343 KStandardGuiItem::saveAs(), KGuiItem(openText), KStandardGuiItem::cancel(),
00344 QLatin1String("askSave")+ mimeType );
00345
00346 return choice == KMessageBox::Yes ? Save : ( choice == KMessageBox::No ? Open : Cancel );
00347
00348 }
00349
00350
00351
00352 BrowserRun::AskSaveResult BrowserRun::askEmbedOrSave( const KUrl & url, const QString& mimeType, const QString & suggestedFileName, int flags )
00353 {
00354
00355
00356
00357
00358
00359 KMimeType::Ptr mime = KMimeType::mimeType(mimeType, KMimeType::ResolveAliases);
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369 if (flags != (int)AttachmentDisposition && mime && (
00370 mime->is( "text/html" ) ||
00371 mime->is( "application/xml" ) ||
00372 mime->is( "inode/directory" ) ||
00373 mimeType.startsWith( "image" ) ||
00374 mime->is( "multipart/x-mixed-replace" ) ||
00375 mime->is( "multipart/replace" ) ||
00376 mimeType.startsWith( "print" ) ) )
00377 return Open;
00378
00379 QString question = makeQuestion( url, mimeType, suggestedFileName );
00380
00381
00382 int choice = KMessageBox::questionYesNoCancel(
00383 0, question, url.host(),
00384 KStandardGuiItem::saveAs(), KGuiItem( i18n( "&Open" ), "document-open"), KStandardGuiItem::cancel(),
00385 QLatin1String("askEmbedOrSave")+ mimeType );
00386 return choice == KMessageBox::Yes ? Save : ( choice == KMessageBox::No ? Open : Cancel );
00387
00388 }
00389
00390
00391 void BrowserRun::save( const KUrl & url, const QString & suggestedFileName )
00392 {
00393 simpleSave( url, suggestedFileName, d->m_window );
00394 }
00395
00396
00397 void BrowserRun::simpleSave( const KUrl & url, const QString & suggestedFileName,
00398 QWidget* window )
00399 {
00400
00401
00402
00403
00404 if ( !url.isLocalFile() )
00405 {
00406 KConfigGroup cfg = KSharedConfig::openConfig("konquerorrc", KConfig::NoGlobals)->group("HTML Settings");
00407 QString downloadManger = cfg.readPathEntry("DownloadManager", QString());
00408 if (!downloadManger.isEmpty())
00409 {
00410
00411 kDebug(1000) << "Using: "<<downloadManger <<" as Download Manager";
00412 QString cmd=KStandardDirs::findExe(downloadManger);
00413 if (cmd.isEmpty())
00414 {
00415 QString errMsg=i18n("The Download Manager (%1) could not be found in your $PATH ", downloadManger);
00416 QString errMsgEx= i18n("Try to reinstall it \n\nThe integration with Konqueror will be disabled.");
00417 KMessageBox::detailedSorry(0,errMsg,errMsgEx);
00418 cfg.writePathEntry("DownloadManager",QString());
00419 cfg.sync ();
00420 }
00421 else
00422 {
00423
00424
00425
00426
00427 cmd += " " + KShell::quoteArg(url.url());
00428 if ( !suggestedFileName.isEmpty() )
00429 cmd +=" " + KShell::quoteArg(suggestedFileName);
00430
00431 kDebug(1000) << "Calling command" << cmd;
00432
00433 KIO::Scheduler::publishSlaveOnHold();
00434 KRun::runCommand(cmd, window);
00435 return;
00436 }
00437 }
00438 }
00439
00440
00441 KFileDialog *dlg = new KFileDialog( QString(), QString() ,
00442 window);
00443 dlg->setOperationMode( KFileDialog::Saving );
00444 dlg->setCaption(i18n("Save As"));
00445
00446 dlg->setSelection( suggestedFileName.isEmpty() ? url.fileName() : suggestedFileName );
00447 if ( dlg->exec() )
00448 {
00449 KUrl destURL( dlg->selectedUrl() );
00450 if ( destURL.isValid() )
00451 {
00452 KIO::Job *job = KIO::copy( url, destURL );
00453 job->ui()->setWindow (window);
00454 job->ui()->setAutoErrorHandlingEnabled( true );
00455 }
00456 }
00457 delete dlg;
00458 }
00459
00460 void BrowserRun::slotStatResult( KJob *job )
00461 {
00462 if ( job->error() ) {
00463 kDebug(1000) << job->errorString();
00464 handleError( job );
00465 } else
00466 KRun::slotStatResult( job );
00467 }
00468
00469 void BrowserRun::handleError( KJob * job )
00470 {
00471 if ( !job ) {
00472 kWarning(1000) << "handleError called with job=0! hideErrorDialog=" << d->m_bHideErrorDialog;
00473 return;
00474 }
00475
00476 KIO::TransferJob *tjob = qobject_cast<KIO::TransferJob *>(job);
00477 if (tjob && tjob->isErrorPage() && !job->error()) {
00478
00479
00480 tjob->putOnHold();
00481 setJob(0);
00482 if (!d->m_mimeType.isEmpty())
00483 mimeTypeDetermined(d->m_mimeType);
00484 return;
00485 }
00486
00487 if (d->m_bHideErrorDialog && job->error() != KIO::ERR_NO_CONTENT)
00488 {
00489 redirectToError( job->error(), job->errorText() );
00490 return;
00491 }
00492
00493
00494 KRun::slotStatResult( job );
00495 }
00496
00497 void BrowserRun::redirectToError( int error, const QString& errorText )
00498 {
00509 KUrl newURL(QString("error:/?error=%1&errText=%2")
00510 .arg( error )
00511 .arg( QString::fromUtf8( QUrl::toPercentEncoding( errorText ) ) ) );
00512 KUrl runURL = KRun::url();
00513 runURL.setPass( QString() );
00514
00515 KUrl::List lst;
00516 lst << newURL << runURL;
00517 KRun::setUrl( KUrl::join( lst ) );
00518
00519 setJob( 0 );
00520 mimeTypeDetermined( "text/html" );
00521 }
00522
00523 void BrowserRun::slotCopyToTempFileResult(KJob *job)
00524 {
00525 if ( job->error() ) {
00526 job->uiDelegate()->showErrorMessage();
00527 } else {
00528
00529 (void) (KRun::runUrl( static_cast<KIO::FileCopyJob *>(job)->destUrl(), d->m_mimeType, d->m_window ));
00530 }
00531 setError( true );
00532 setFinished( true );
00533 timer().start( 0 );
00534 }
00535
00536 bool BrowserRun::isTextExecutable( const QString &mimeType )
00537 {
00538 return ( mimeType == "application/x-desktop" ||
00539 mimeType == "application/x-shellscript" );
00540 }
00541
00542 bool BrowserRun::hideErrorDialog() const
00543 {
00544 return d->m_bHideErrorDialog;
00545 }
00546
00547 QString BrowserRun::contentDisposition() const {
00548 return d->m_contentDisposition;
00549 }
00550
00551 KParts::OpenUrlArguments& KParts::BrowserRun::arguments()
00552 {
00553 return d->m_args;
00554 }
00555
00556 KParts::BrowserArguments& KParts::BrowserRun::browserArguments()
00557 {
00558 return d->m_browserArgs;
00559 }
00560
00561 #include "browserrun.moc"