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/scheduler.h>
00024 #include <klocale.h>
00025 #include <kprocess.h>
00026 #include <kstringhandler.h>
00027 #include <kuserprofile.h>
00028 #include <ktempfile.h>
00029 #include <kdebug.h>
00030 #include <kstandarddirs.h>
00031 #include <assert.h>
00032
00033 using namespace KParts;
00034
00035 class BrowserRun::BrowserRunPrivate
00036 {
00037 public:
00038 bool m_bHideErrorDialog;
00039 QString contentDisposition;
00040 };
00041
00042 BrowserRun::BrowserRun( const KURL& url, const KParts::URLArgs& args,
00043 KParts::ReadOnlyPart *part, QWidget* window,
00044 bool removeReferrer, bool trustedSource )
00045 : KRun( url, window, 0 , false , false ),
00046 m_args( args ), m_part( part ), m_window( window ),
00047 m_bRemoveReferrer( removeReferrer ), m_bTrustedSource( trustedSource )
00048 {
00049 d = new BrowserRunPrivate;
00050 d->m_bHideErrorDialog = false;
00051 }
00052
00053
00054 BrowserRun::BrowserRun( const KURL& url, const KParts::URLArgs& args,
00055 KParts::ReadOnlyPart *part, QWidget* window,
00056 bool removeReferrer, bool trustedSource, bool hideErrorDialog )
00057 : KRun( url, window, 0 , false , false ),
00058 m_args( args ), m_part( part ), m_window( window ),
00059 m_bRemoveReferrer( removeReferrer ), m_bTrustedSource( trustedSource )
00060 {
00061 d = new BrowserRunPrivate;
00062 d->m_bHideErrorDialog = hideErrorDialog;
00063 }
00064
00065 BrowserRun::~BrowserRun()
00066 {
00067 delete d;
00068 }
00069
00070 void BrowserRun::init()
00071 {
00072 if ( d->m_bHideErrorDialog )
00073 {
00074
00075
00076
00077 if ( !m_strURL.isValid() ) {
00078 redirectToError( KIO::ERR_MALFORMED_URL, m_strURL.url() );
00079 return;
00080 }
00081 if ( !m_bIsLocalFile && !m_bFault && m_strURL.isLocalFile() )
00082 m_bIsLocalFile = true;
00083
00084 if ( m_bIsLocalFile ) {
00085 struct stat buff;
00086 if ( stat( QFile::encodeName(m_strURL.path()), &buff ) == -1 )
00087 {
00088 kdDebug(1000) << "BrowserRun::init : " << m_strURL.prettyURL() << " doesn't exist." << endl;
00089 redirectToError( KIO::ERR_DOES_NOT_EXIST, m_strURL.path() );
00090 return;
00091 }
00092 m_mode = buff.st_mode;
00093 }
00094 }
00095 KRun::init();
00096 }
00097
00098 void BrowserRun::scanFile()
00099 {
00100 kdDebug(1000) << "BrowserRun::scanfile " << m_strURL.prettyURL() << endl;
00101
00102
00103
00104
00105 if ( m_strURL.query().isEmpty() && !m_strURL.protocol().startsWith("http") )
00106 {
00107 KMimeType::Ptr mime = KMimeType::findByURL( m_strURL );
00108 assert( mime != 0L );
00109 if ( mime->name() != "application/octet-stream" || m_bIsLocalFile )
00110 {
00111 kdDebug(1000) << "Scanfile: MIME TYPE is " << mime->name() << endl;
00112 foundMimeType( mime->name() );
00113 return;
00114 }
00115 }
00116
00117 if ( m_part )
00118 {
00119 QString proto = m_part->url().protocol().lower();
00120
00121 if (proto == "https" || proto == "webdavs") {
00122 m_args.metaData().insert("main_frame_request", "TRUE" );
00123 m_args.metaData().insert("ssl_was_in_use", "TRUE" );
00124 m_args.metaData().insert("ssl_activate_warnings", "TRUE" );
00125 } else if (proto == "http" || proto == "webdav") {
00126 m_args.metaData().insert("ssl_activate_warnings", "TRUE" );
00127 m_args.metaData().insert("ssl_was_in_use", "FALSE" );
00128 }
00129
00130
00131 if (!m_args.metaData().contains("PropagateHttpHeader"))
00132 m_args.metaData().insert("PropagateHttpHeader", "TRUE");
00133 }
00134
00135 KIO::TransferJob *job;
00136 if ( m_args.doPost() && m_strURL.protocol().startsWith("http"))
00137 {
00138 job = KIO::http_post( m_strURL, m_args.postData, false );
00139 job->addMetaData( "content-type", m_args.contentType() );
00140 }
00141 else
00142 job = KIO::get(m_strURL, m_args.reload, false);
00143
00144 if ( m_bRemoveReferrer )
00145 m_args.metaData().remove("referrer");
00146
00147 job->addMetaData( m_args.metaData() );
00148 job->setWindow( m_window );
00149 connect( job, SIGNAL( result( KIO::Job *)),
00150 this, SLOT( slotBrowserScanFinished(KIO::Job *)));
00151 connect( job, SIGNAL( mimetype( KIO::Job *, const QString &)),
00152 this, SLOT( slotBrowserMimetype(KIO::Job *, const QString &)));
00153 m_job = job;
00154 }
00155
00156 void BrowserRun::slotBrowserScanFinished(KIO::Job *job)
00157 {
00158 kdDebug(1000) << "BrowserRun::slotBrowserScanFinished" << endl;
00159 if ( job->error() == KIO::ERR_IS_DIRECTORY )
00160 {
00161
00162
00163
00164 kdDebug(1000) << "It is in fact a directory!" << endl;
00165
00166 m_strURL = static_cast<KIO::TransferJob *>(job)->url();
00167 m_job = 0;
00168 foundMimeType( "inode/directory" );
00169 }
00170 else
00171 {
00172 if ( job->error() )
00173 handleError( job );
00174 else
00175 KRun::slotScanFinished(job);
00176 }
00177 }
00178
00179 void BrowserRun::slotBrowserMimetype( KIO::Job *_job, const QString &type )
00180 {
00181 Q_ASSERT( _job == m_job );
00182 KIO::TransferJob *job = static_cast<KIO::TransferJob *>(m_job);
00183
00184
00185
00186 m_strURL = job->url();
00187 kdDebug(1000) << "slotBrowserMimetype: found " << type << " for " << m_strURL.prettyURL() << endl;
00188
00189 m_suggestedFilename = job->queryMetaData("content-disposition-filename");
00190 d->contentDisposition = job->queryMetaData("content-disposition-type");
00191
00192
00193
00194 QString _type = type;
00195 job->putOnHold();
00196 m_job = 0;
00197
00198 KRun::setSuggestedFileName(m_suggestedFilename);
00199
00200 foundMimeType( _type );
00201 }
00202
00203 BrowserRun::NonEmbeddableResult BrowserRun::handleNonEmbeddable( const QString& _mimeType )
00204 {
00205 QString mimeType( _mimeType );
00206 Q_ASSERT( !m_bFinished );
00207
00208 if ( mimeType != "inode/directory" &&
00209 !m_strURL.isLocalFile() )
00210 {
00211 if ( isTextExecutable(mimeType) )
00212 mimeType = QString::fromLatin1("text/plain");
00213 kdDebug(1000) << "BrowserRun: ask for saving" << endl;
00214 KService::Ptr offer = KServiceTypeProfile::preferredService(mimeType, "Application");
00215
00216 KParts::BrowserRun::AskSaveResult res = askSave( m_strURL, offer, mimeType, m_suggestedFilename );
00217 if ( res == KParts::BrowserRun::Save ) {
00218 save( m_strURL, m_suggestedFilename );
00219 kdDebug(1000) << "BrowserRun::handleNonEmbeddable: Save: returning Handled" << endl;
00220 m_bFinished = true;
00221 return Handled;
00222 }
00223 else if ( res == KParts::BrowserRun::Cancel ) {
00224
00225 kdDebug(1000) << "BrowserRun::handleNonEmbeddable: Cancel: returning Handled" << endl;
00226 m_bFinished = true;
00227 return Handled;
00228 }
00229 else
00230 {
00231
00232
00233 if ( m_args.doPost() )
00234 {
00235 kdDebug(1000) << "BrowserRun: request comes from a POST, can't pass a URL to another app, need to save" << endl;
00236 m_sMimeType = mimeType;
00237 QString extension;
00238 QString fileName = m_suggestedFilename.isEmpty() ? m_strURL.fileName() : m_suggestedFilename;
00239 int extensionPos = fileName.findRev( '.' );
00240 if ( extensionPos != -1 )
00241 extension = fileName.mid( extensionPos );
00242 KTempFile tempFile( QString::null, extension );
00243 KURL destURL;
00244 destURL.setPath( tempFile.name() );
00245 KIO::Job *job = KIO::file_copy( m_strURL, destURL, 0600, true , false , true );
00246 job->setWindow (m_window);
00247 connect( job, SIGNAL( result( KIO::Job *)),
00248 this, SLOT( slotCopyToTempFileResult(KIO::Job *)) );
00249 return Delayed;
00250 }
00251 }
00252 }
00253
00254
00255 if ( !m_bTrustedSource &&
00256 !allowExecution( mimeType, m_strURL ) )
00257 {
00258 m_bFinished = true;
00259 return Handled;
00260 }
00261
00262 KIO::SimpleJob::removeOnHold();
00263 return NotHandled;
00264 }
00265
00266
00267 bool BrowserRun::allowExecution( const QString &serviceType, const KURL &url )
00268 {
00269 if ( !isExecutable( serviceType ) )
00270 return true;
00271
00272 if ( !url.isLocalFile() )
00273 return false;
00274
00275 return ( KMessageBox::warningContinueCancel( 0, i18n( "Do you really want to execute '%1'? " ).arg( url.prettyURL() ),
00276 i18n("Execute File?"), i18n("Execute") ) == KMessageBox::Continue );
00277 }
00278
00279 static QString makeQuestion( const KURL& url, const QString& mimeType, const QString& suggestedFilename )
00280 {
00281 QString surl = KStringHandler::csqueeze( url.prettyURL() );
00282 KMimeType::Ptr mime = KMimeType::mimeType( mimeType );
00283 QString comment = mimeType;
00284
00285
00286
00287 if (mime->name() != KMimeType::defaultMimeType()) {
00288
00289 comment = mime->comment();
00290 }
00291
00292
00293 if ( suggestedFilename.isEmpty() )
00294 return i18n("Open '%2'?\nType: %1").arg(comment, surl);
00295 else
00296 return i18n("Open '%3'?\nName: %2\nType: %1").arg(comment, suggestedFilename, surl);
00297 }
00298
00299
00300 BrowserRun::AskSaveResult BrowserRun::askSave( const KURL & url, KService::Ptr offer, const QString& mimeType, const QString & suggestedFilename )
00301 {
00302
00303
00304
00305
00306 QString question = makeQuestion( url, mimeType, suggestedFilename );
00307
00308
00309 QString openText = (offer && !offer->name().isEmpty())
00310 ? i18n("&Open with '%1'").arg(offer->name())
00311 : i18n("&Open With...");
00312
00313 int choice = KMessageBox::questionYesNoCancel(
00314 0L, question, url.host(),
00315 KStdGuiItem::saveAs(), openText,
00316 QString::fromLatin1("askSave")+ mimeType );
00317
00318 return choice == KMessageBox::Yes ? Save : ( choice == KMessageBox::No ? Open : Cancel );
00319
00320 }
00321
00322
00323 BrowserRun::AskSaveResult BrowserRun::askEmbedOrSave( const KURL & url, const QString& mimeType, const QString & suggestedFilename, int flags )
00324 {
00325
00326
00327
00328
00329 KMimeType::Ptr mime = KMimeType::mimeType( mimeType );
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339 if (flags != (int)AttachmentDisposition && (
00340 mime->is( "text/html" ) ||
00341 mime->is( "text/xml" ) ||
00342 mime->is( "inode/directory" ) ||
00343 mimeType.startsWith( "image" ) ||
00344 mime->is( "multipart/x-mixed-replace" ) ||
00345 mime->is( "multipart/replace" ) ||
00346 mimeType.startsWith( "print" ) ) )
00347 return Open;
00348
00349 QString question = makeQuestion( url, mimeType, suggestedFilename );
00350
00351 int choice = KMessageBox::questionYesNoCancel(
00352 0L, question, url.host(),
00353 KStdGuiItem::saveAs(), KGuiItem( i18n( "&Open" ), "fileopen"),
00354 QString::fromLatin1("askEmbedOrSave")+ mimeType );
00355 return choice == KMessageBox::Yes ? Save : ( choice == KMessageBox::No ? Open : Cancel );
00356
00357 }
00358
00359
00360 void BrowserRun::save( const KURL & url, const QString & suggestedFilename )
00361 {
00362 simpleSave( url, suggestedFilename, m_window );
00363 }
00364
00365
00366 void BrowserRun::simpleSave( const KURL & url, const QString & suggestedFilename )
00367 {
00368 simpleSave (url, suggestedFilename, 0);
00369 }
00370
00371 void BrowserRun::simpleSave( const KURL & url, const QString & suggestedFilename,
00372 QWidget* window )
00373 {
00374
00375
00376
00377
00378 if ( !url.isLocalFile() )
00379 {
00380 KConfig cfg("konquerorrc", false, false);
00381 cfg.setGroup("HTML Settings");
00382 QString downloadManger = cfg.readPathEntry("DownloadManager");
00383 if (!downloadManger.isEmpty())
00384 {
00385
00386 kdDebug(1000) << "Using: "<<downloadManger <<" as Download Manager" <<endl;
00387 QString cmd=KStandardDirs::findExe(downloadManger);
00388 if (cmd.isEmpty())
00389 {
00390 QString errMsg=i18n("The Download Manager (%1) could not be found in your $PATH ").arg(downloadManger);
00391 QString errMsgEx= i18n("Try to reinstall it \n\nThe integration with Konqueror will be disabled!");
00392 KMessageBox::detailedSorry(0,errMsg,errMsgEx);
00393 cfg.writePathEntry("DownloadManager",QString::null);
00394 cfg.sync ();
00395 }
00396 else
00397 {
00398
00399
00400
00401
00402 cmd += " " + KProcess::quote(url.url());
00403 if ( !suggestedFilename.isEmpty() )
00404 cmd +=" " + KProcess::quote(suggestedFilename);
00405
00406 kdDebug(1000) << "Calling command " << cmd << endl;
00407
00408 KIO::Scheduler::publishSlaveOnHold();
00409 KRun::runCommand(cmd);
00410 return;
00411 }
00412 }
00413 }
00414
00415
00416 KFileDialog *dlg = new KFileDialog( QString::null, QString::null ,
00417 window , "filedialog", true );
00418 dlg->setOperationMode( KFileDialog::Saving );
00419 dlg->setCaption(i18n("Save As"));
00420
00421 dlg->setSelection( suggestedFilename.isEmpty() ? url.fileName() : suggestedFilename );
00422 if ( dlg->exec() )
00423 {
00424 KURL destURL( dlg->selectedURL() );
00425 if ( destURL.isValid() )
00426 {
00427 KIO::Job *job = KIO::copy( url, destURL );
00428 job->setWindow (window);
00429 job->setAutoErrorHandlingEnabled( true );
00430 }
00431 }
00432 delete dlg;
00433 }
00434
00435 void BrowserRun::slotStatResult( KIO::Job *job )
00436 {
00437 if ( job->error() ) {
00438 kdDebug(1000) << "BrowserRun::slotStatResult : " << job->errorString() << endl;
00439 handleError( job );
00440 } else
00441 KRun::slotStatResult( job );
00442 }
00443
00444 void BrowserRun::handleError( KIO::Job * job )
00445 {
00446 if ( !job ) {
00447 kdWarning(1000) << "BrowserRun::handleError called with job=0! hideErrorDialog=" << d->m_bHideErrorDialog << endl;
00448 return;
00449 }
00450
00451 if (d->m_bHideErrorDialog && job->error() != KIO::ERR_NO_CONTENT)
00452 {
00453 redirectToError( job->error(), job->errorText() );
00454 return;
00455 }
00456
00457
00458 KRun::slotStatResult( job );
00459 }
00460
00461 void BrowserRun::redirectToError( int error, const QString& errorText )
00462 {
00473 KURL newURL(QString("error:/?error=%1&errText=%2")
00474 .arg( error ).arg( KURL::encode_string(errorText) ), 106 );
00475 m_strURL.setPass( QString::null );
00476
00477 KURL::List lst;
00478 lst << newURL << m_strURL;
00479 m_strURL = KURL::join( lst );
00480
00481
00482 m_job = 0;
00483 foundMimeType( "text/html" );
00484 }
00485
00486 void BrowserRun::slotCopyToTempFileResult(KIO::Job *job)
00487 {
00488 if ( job->error() ) {
00489 job->showErrorDialog( m_window );
00490 } else {
00491
00492 (void) (KRun::runURL( static_cast<KIO::FileCopyJob *>(job)->destURL(), m_sMimeType ));
00493 }
00494 m_bFault = true;
00495 m_bFinished = true;
00496 m_timer.start( 0, true );
00497 }
00498
00499 bool BrowserRun::isTextExecutable( const QString &serviceType )
00500 {
00501 return ( serviceType == "application/x-desktop" ||
00502 serviceType == "application/x-shellscript" );
00503 }
00504
00505 bool BrowserRun::isExecutable( const QString &serviceType )
00506 {
00507 return KRun::isExecutable( serviceType );
00508 }
00509
00510 bool BrowserRun::hideErrorDialog() const
00511 {
00512 return d->m_bHideErrorDialog;
00513 }
00514
00515 QString BrowserRun::contentDisposition() const {
00516 return d->contentDisposition;
00517 }
00518
00519 #include "browserrun.moc"