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