00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "job.h"
00023 #include "job_p.h"
00024
00025 #include <config.h>
00026
00027 #include <sys/types.h>
00028 #include <sys/wait.h>
00029 #include <sys/stat.h>
00030
00031 #include <assert.h>
00032
00033 #include <signal.h>
00034 #include <stdlib.h>
00035 #include <stdio.h>
00036 #include <time.h>
00037 #include <unistd.h>
00038 extern "C" {
00039 #include <pwd.h>
00040 #include <grp.h>
00041 }
00042 #include <QtCore/QTimer>
00043 #include <QtCore/QFile>
00044
00045 #include <kapplication.h>
00046 #include <kauthorized.h>
00047 #include <kglobal.h>
00048 #include <klocale.h>
00049 #include <kconfig.h>
00050 #include <kdebug.h>
00051 #include <kde_file.h>
00052
00053 #include <errno.h>
00054
00055 #include "jobuidelegate.h"
00056 #include "kmimetype.h"
00057 #include "slave.h"
00058 #include "scheduler.h"
00059 #include "kdirwatch.h"
00060 #include "kprotocolinfo.h"
00061 #include "kprotocolmanager.h"
00062 #include "filejob.h"
00063
00064 #include "kssl/ksslcsessioncache.h"
00065
00066 #include <kdirnotify.h>
00067 #include <ktemporaryfile.h>
00068
00069 #ifdef Q_OS_UNIX
00070 #include <utime.h>
00071 #endif
00072
00073 using namespace KIO;
00074
00075 static inline Slave *jobSlave(SimpleJob *job)
00076 {
00077 return SimpleJobPrivate::get(job)->m_slave;
00078 }
00079
00080
00081 #define REPORT_TIMEOUT 200
00082
00083 #define KIO_ARGS QByteArray packedArgs; QDataStream stream( &packedArgs, QIODevice::WriteOnly ); stream
00084
00085 Job::Job() : KCompositeJob(*new JobPrivate, 0)
00086 {
00087 setCapabilities( KJob::Killable | KJob::Suspendable );
00088 }
00089
00090 Job::Job(JobPrivate &dd) : KCompositeJob(dd, 0)
00091 {
00092 setCapabilities( KJob::Killable | KJob::Suspendable );
00093 }
00094
00095 Job::~Job()
00096 {
00097 }
00098
00099 JobUiDelegate *Job::ui() const
00100 {
00101 return static_cast<JobUiDelegate*>( uiDelegate() );
00102 }
00103
00104 bool Job::addSubjob(KJob *jobBase)
00105 {
00106
00107
00108 bool ok = KCompositeJob::addSubjob( jobBase );
00109 KIO::Job *job = dynamic_cast<KIO::Job*>( jobBase );
00110 if (ok && job) {
00111
00112 connect( job, SIGNAL(speed( KJob*, unsigned long )),
00113 SLOT(slotSpeed(KJob*, unsigned long)) );
00114
00115 if (ui() && job->ui()) {
00116 job->ui()->setWindow( ui()->window() );
00117 job->ui()->updateUserTimestamp( ui()->userTimestamp() );
00118 }
00119 }
00120 return ok;
00121 }
00122
00123 bool Job::removeSubjob( KJob *jobBase )
00124 {
00125
00126 return KCompositeJob::removeSubjob( jobBase );
00127 }
00128
00129 void JobPrivate::emitMoving(KIO::Job * job, const KUrl &src, const KUrl &dest)
00130 {
00131 emit job->description(job, i18nc("@title job","Moving"),
00132 qMakePair(i18n("Source"), src.prettyUrl()),
00133 qMakePair(i18n("Destination"), dest.prettyUrl()));
00134 }
00135
00136 void JobPrivate::emitCopying(KIO::Job * job, const KUrl &src, const KUrl &dest)
00137 {
00138 emit job->description(job, i18nc("@title job","Copying"),
00139 qMakePair(i18n("Source"), src.prettyUrl()),
00140 qMakePair(i18n("Destination"), dest.prettyUrl()));
00141 }
00142
00143 void JobPrivate::emitCreatingDir(KIO::Job * job, const KUrl &dir)
00144 {
00145 emit job->description(job, i18nc("@title job","Creating directory"),
00146 qMakePair(i18n("Directory"), dir.prettyUrl()));
00147 }
00148
00149 void JobPrivate::emitDeleting(KIO::Job *job, const KUrl &url)
00150 {
00151 emit job->description(job, i18nc("@title job","Deleting"),
00152 qMakePair(i18n("File"), url.prettyUrl()));
00153 }
00154
00155 void JobPrivate::emitStating(KIO::Job *job, const KUrl &url)
00156 {
00157 emit job->description(job, i18nc("@title job","Stating"),
00158 qMakePair(i18n("File"), url.prettyUrl()));
00159 }
00160
00161 void JobPrivate::emitTransferring(KIO::Job *job, const KUrl &url)
00162 {
00163 emit job->description(job, i18nc("@title job","Transferring"),
00164 qMakePair(i18n("Source"), url.prettyUrl()));
00165 }
00166
00167 void JobPrivate::emitMounting(KIO::Job * job, const QString &dev, const QString &point)
00168 {
00169 emit job->description(job, i18nc("@title job","Mounting"),
00170 qMakePair(i18n("Device"), dev),
00171 qMakePair(i18n("Mountpoint"), point));
00172 }
00173
00174 void JobPrivate::emitUnmounting(KIO::Job * job, const QString &point)
00175 {
00176 emit job->description(job, i18nc("@title job","Unmounting"),
00177 qMakePair(i18n("Mountpoint"), point));
00178 }
00179
00180 bool Job::doKill()
00181 {
00182 kDebug(7007) << "Job::kill this=" << this << " " << metaObject()->className();
00183
00184 const QList<KJob *> &jobs = subjobs();
00185 QList<KJob *>::const_iterator it = jobs.constBegin();
00186 const QList<KJob *>::const_iterator end = jobs.constEnd();
00187 for ( ; it != end ; ++it )
00188 (*it)->kill( KJob::Quietly );
00189 clearSubjobs();
00190
00191 return true;
00192 }
00193
00194 bool Job::doSuspend()
00195 {
00196 const QList<KJob *> &jobs = subjobs();
00197 QList<KJob *>::const_iterator it = jobs.constBegin();
00198 const QList<KJob *>::const_iterator end = jobs.constEnd();
00199 for ( ; it != end ; ++it )
00200 {
00201 if (!(*it)->suspend())
00202 return false;
00203 }
00204
00205 return true;
00206 }
00207
00208 bool Job::doResume()
00209 {
00210 const QList<KJob *> &jobs = subjobs();
00211 QList<KJob *>::const_iterator it = jobs.constBegin();
00212 const QList<KJob *>::const_iterator end = jobs.constEnd();
00213 for ( ; it != end ; ++it )
00214 {
00215 if (!(*it)->resume())
00216 return false;
00217 }
00218
00219 return true;
00220 }
00221
00222 void JobPrivate::slotSpeed( KJob*, unsigned long speed )
00223 {
00224
00225 q_func()->emitSpeed( speed );
00226 }
00227
00228
00229
00230 void Job::showErrorDialog( QWidget *parent )
00231 {
00232 if ( ui() )
00233 {
00234 ui()->setWindow( parent );
00235 ui()->showErrorMessage();
00236 }
00237 else
00238 {
00239 kError() << errorString() << endl;
00240 }
00241 }
00242
00243 bool Job::isInteractive() const
00244 {
00245 return uiDelegate() != 0;
00246 }
00247
00248 void Job::setParentJob(Job* job)
00249 {
00250 Q_D(Job);
00251 Q_ASSERT(d->m_parentJob == 0L);
00252 Q_ASSERT(job);
00253 d->m_parentJob = job;
00254 }
00255
00256 Job* Job::parentJob() const
00257 {
00258 return d_func()->m_parentJob;
00259 }
00260
00261 MetaData Job::metaData() const
00262 {
00263 return d_func()->m_incomingMetaData;
00264 }
00265
00266 QString Job::queryMetaData(const QString &key)
00267 {
00268 return d_func()->m_incomingMetaData.value(key, QString());
00269 }
00270
00271 void Job::setMetaData( const KIO::MetaData &_metaData)
00272 {
00273 Q_D(Job);
00274 d->m_outgoingMetaData = _metaData;
00275 }
00276
00277 void Job::addMetaData( const QString &key, const QString &value)
00278 {
00279 d_func()->m_outgoingMetaData.insert(key, value);
00280 }
00281
00282 void Job::addMetaData( const QMap<QString,QString> &values)
00283 {
00284 Q_D(Job);
00285 QMap<QString,QString>::const_iterator it = values.begin();
00286 for(;it != values.end(); ++it)
00287 d->m_outgoingMetaData.insert(it.key(), it.value());
00288 }
00289
00290 void Job::mergeMetaData( const QMap<QString,QString> &values)
00291 {
00292 Q_D(Job);
00293 QMap<QString,QString>::const_iterator it = values.begin();
00294 for(;it != values.end(); ++it)
00295
00296 if ( !d->m_outgoingMetaData.contains( it.key() ) )
00297 d->m_outgoingMetaData.insert( it.key(), it.value() );
00298 }
00299
00300 MetaData Job::outgoingMetaData() const
00301 {
00302 return d_func()->m_outgoingMetaData;
00303 }
00304
00305 SimpleJob::SimpleJob(SimpleJobPrivate &dd)
00306 : Job(dd)
00307 {
00308 d_func()->simpleJobInit();
00309 }
00310
00311 void SimpleJobPrivate::simpleJobInit()
00312 {
00313 Q_Q(SimpleJob);
00314 if (!m_url.isValid())
00315 {
00316 q->setError( ERR_MALFORMED_URL );
00317 q->setErrorText( m_url.url() );
00318 QTimer::singleShot(0, q, SLOT(slotFinished()) );
00319 return;
00320 }
00321
00322 Scheduler::doJob(q);
00323 }
00324
00325
00326 bool SimpleJob::doKill()
00327 {
00328 Q_D(SimpleJob);
00329 Scheduler::cancelJob( this );
00330 d->m_slave = 0;
00331 return Job::doKill();
00332 }
00333
00334 bool SimpleJob::doSuspend()
00335 {
00336 Q_D(SimpleJob);
00337 if ( d->m_slave )
00338 d->m_slave->suspend();
00339 return Job::doSuspend();
00340 }
00341
00342 bool SimpleJob::doResume()
00343 {
00344 Q_D(SimpleJob);
00345 if ( d->m_slave )
00346 d->m_slave->resume();
00347 return Job::doResume();
00348 }
00349
00350 const KUrl& SimpleJob::url() const
00351 {
00352 return d_func()->m_url;
00353 }
00354
00355 void SimpleJob::putOnHold()
00356 {
00357 Q_D(SimpleJob);
00358 Q_ASSERT( d->m_slave );
00359 if ( d->m_slave )
00360 {
00361 Scheduler::putSlaveOnHold(this, d->m_url);
00362 d->m_slave = 0;
00363 }
00364 kill( Quietly );
00365 }
00366
00367 void SimpleJob::removeOnHold()
00368 {
00369 Scheduler::removeSlaveOnHold();
00370 }
00371
00372 SimpleJob::~SimpleJob()
00373 {
00374 Q_D(SimpleJob);
00375 if (d->m_slave)
00376 {
00377 kDebug(7007) << "SimpleJob::~SimpleJob: Killing running job in destructor!" << kBacktrace();
00378 #if 0
00379 d->m_slave->kill();
00380 Scheduler::jobFinished( this, d->m_slave );
00381 #endif
00382 Scheduler::cancelJob( this );
00383 d->m_slave = 0;
00384 }
00385 }
00386
00387 void SimpleJobPrivate::start(Slave *slave)
00388 {
00389 Q_Q(SimpleJob);
00390 m_slave = slave;
00391
00392 q->connect( slave, SIGNAL( error( int , const QString & ) ),
00393 SLOT( slotError( int , const QString & ) ) );
00394
00395 q->connect( slave, SIGNAL( warning( const QString & ) ),
00396 SLOT( slotWarning( const QString & ) ) );
00397
00398 q->connect( slave, SIGNAL( infoMessage( const QString & ) ),
00399 SLOT( _k_slotSlaveInfoMessage( const QString & ) ) );
00400
00401 q->connect( slave, SIGNAL( connected() ),
00402 SLOT( slotConnected() ) );
00403
00404 q->connect( slave, SIGNAL( finished() ),
00405 SLOT( slotFinished() ) );
00406
00407 if ((m_extraFlags & EF_TransferJobDataSent) == 0)
00408 {
00409 q->connect( slave, SIGNAL( totalSize( KIO::filesize_t ) ),
00410 SLOT( slotTotalSize( KIO::filesize_t ) ) );
00411
00412 q->connect( slave, SIGNAL( processedSize( KIO::filesize_t ) ),
00413 SLOT( slotProcessedSize( KIO::filesize_t ) ) );
00414
00415 q->connect( slave, SIGNAL( speed( unsigned long ) ),
00416 SLOT( slotSpeed( unsigned long ) ) );
00417 }
00418 q->connect( slave, SIGNAL(metaData( const KIO::MetaData& ) ),
00419 SLOT( slotMetaData( const KIO::MetaData& ) ) );
00420
00421 if (ui() && ui()->window())
00422 {
00423 m_outgoingMetaData.insert("window-id", QString::number((long)ui()->window()->winId()));
00424 }
00425
00426 if (ui() && ui()->userTimestamp())
00427 {
00428 m_outgoingMetaData.insert("user-timestamp", QString::number(ui()->userTimestamp()));
00429 }
00430
00431 QString sslSession = KSSLCSessionCache::getSessionForUrl(m_url);
00432 if ( !sslSession.isNull() )
00433 {
00434 m_outgoingMetaData.insert("ssl_session_id", sslSession);
00435 }
00436
00437 if (ui() == 0)
00438 {
00439 m_outgoingMetaData.insert("no-auth-prompt", "true");
00440 }
00441
00442 if (!m_outgoingMetaData.isEmpty())
00443 {
00444 KIO_ARGS << m_outgoingMetaData;
00445 slave->send( CMD_META_DATA, packedArgs );
00446 }
00447
00448 if (!m_subUrl.isEmpty())
00449 {
00450 KIO_ARGS << m_subUrl;
00451 slave->send( CMD_SUBURL, packedArgs );
00452 }
00453
00454 slave->send( m_command, m_packedArgs );
00455 }
00456
00457 void SimpleJobPrivate::slaveDone()
00458 {
00459 Q_Q(SimpleJob);
00460 if (!m_slave) return;
00461 q->disconnect(m_slave);
00462 Scheduler::jobFinished( q, m_slave );
00463 m_slave = 0;
00464 }
00465
00466 void SimpleJob::slotFinished( )
00467 {
00468 Q_D(SimpleJob);
00469
00470 d->slaveDone();
00471
00472 if (!hasSubjobs())
00473 {
00474 if ( !error() && (d->m_command == CMD_MKDIR || d->m_command == CMD_RENAME ) )
00475 {
00476 if ( d->m_command == CMD_MKDIR )
00477 {
00478 KUrl urlDir( url() );
00479 urlDir.setPath( urlDir.directory() );
00480 org::kde::KDirNotify::emitFilesAdded( urlDir.url() );
00481 }
00482 else
00483 {
00484 KUrl src, dst;
00485 QDataStream str( d->m_packedArgs );
00486 str >> src >> dst;
00487 if( src.directory() == dst.directory() )
00488 org::kde::KDirNotify::emitFileRenamed( src.url(), dst.url() );
00489 }
00490 }
00491 emitResult();
00492 }
00493 }
00494
00495 void SimpleJob::slotError( int err, const QString & errorText )
00496 {
00497 Q_D(SimpleJob);
00498 setError( err );
00499 setErrorText( errorText );
00500 if ((error() == ERR_UNKNOWN_HOST) && d->m_url.host().isEmpty())
00501 setErrorText( QString() );
00502
00503 slotFinished();
00504 }
00505
00506 void SimpleJob::slotWarning( const QString & errorText )
00507 {
00508 emit warning( this, errorText );
00509 }
00510
00511 void SimpleJobPrivate::_k_slotSlaveInfoMessage( const QString & msg )
00512 {
00513 emit q_func()->infoMessage( q_func(), msg );
00514 }
00515
00516 void SimpleJobPrivate::slotConnected()
00517 {
00518 emit q_func()->connected( q_func() );
00519 }
00520
00521 void SimpleJobPrivate::slotTotalSize( KIO::filesize_t size )
00522 {
00523 Q_Q(SimpleJob);
00524 if (size > q->totalAmount(KJob::Bytes))
00525 {
00526 q->setTotalAmount(KJob::Bytes, size);
00527 }
00528 }
00529
00530 void SimpleJobPrivate::slotProcessedSize( KIO::filesize_t size )
00531 {
00532 Q_Q(SimpleJob);
00533
00534 q->setProcessedAmount(KJob::Bytes, size);
00535 }
00536
00537 void SimpleJobPrivate::slotSpeed( unsigned long speed )
00538 {
00539
00540 q_func()->emitSpeed( speed );
00541 }
00542
00543 void SimpleJob::slotMetaData( const KIO::MetaData &_metaData )
00544 {
00545 Q_D(SimpleJob);
00546 d->m_incomingMetaData += _metaData;
00547 }
00548
00549 void SimpleJob::storeSSLSessionFromJob(const KUrl &redirectionURL)
00550 {
00551 Q_D(SimpleJob);
00552 QString sslSession = queryMetaData("ssl_session_id");
00553
00554 if ( !sslSession.isNull() ) {
00555 const KUrl &queryURL = redirectionURL.isEmpty() ? d->m_url : redirectionURL;
00556 KSSLCSessionCache::putSessionForUrl(queryURL, sslSession);
00557 }
00558 }
00559
00561 class KIO::MkdirJobPrivate: public SimpleJobPrivate
00562 {
00563 public:
00564 MkdirJobPrivate(const KUrl& url, int command, const QByteArray &packedArgs)
00565 : SimpleJobPrivate(url, command, packedArgs)
00566 { }
00567 KUrl m_redirectionURL;
00568 void slotRedirection(const KUrl &url);
00569
00576 virtual void start( Slave *slave );
00577
00578 Q_DECLARE_PUBLIC(MkdirJob)
00579
00580 static inline MkdirJob *newJob(const KUrl& url, int command, const QByteArray &packedArgs)
00581 {
00582 MkdirJob *job = new MkdirJob(*new MkdirJobPrivate(url, command, packedArgs));
00583 job->setUiDelegate(new JobUiDelegate);
00584 return job;
00585 }
00586 };
00587
00588 MkdirJob::MkdirJob(MkdirJobPrivate &dd)
00589 : SimpleJob(dd)
00590 {
00591 }
00592
00593 MkdirJob::~MkdirJob()
00594 {
00595 }
00596
00597 void MkdirJobPrivate::start(Slave *slave)
00598 {
00599 Q_Q(MkdirJob);
00600 q->connect( slave, SIGNAL( redirection(const KUrl &) ),
00601 SLOT( slotRedirection(const KUrl &) ) );
00602
00603 SimpleJobPrivate::start(slave);
00604 }
00605
00606
00607 void MkdirJobPrivate::slotRedirection( const KUrl &url)
00608 {
00609 Q_Q(MkdirJob);
00610 kDebug(7007) << "MkdirJob::slotRedirection(" << url << ")";
00611 if (!KAuthorized::authorizeUrlAction("redirect", m_url, url))
00612 {
00613 kWarning(7007) << "MkdirJob: Redirection from " << m_url << " to " << url << " REJECTED!";
00614 q->setError( ERR_ACCESS_DENIED );
00615 q->setErrorText( url.prettyUrl() );
00616 return;
00617 }
00618 m_redirectionURL = url;
00619 if (m_url.hasUser() && !url.hasUser() && (m_url.host().toLower() == url.host().toLower()))
00620 m_redirectionURL.setUser(m_url.user());
00621
00622 emit q->redirection(q, m_redirectionURL);
00623 }
00624
00625 void MkdirJob::slotFinished()
00626 {
00627 Q_D(MkdirJob);
00628 if ( d->m_redirectionURL.isEmpty() || !d->m_redirectionURL.isValid())
00629 {
00630
00631 SimpleJob::slotFinished();
00632 } else {
00633
00634 if (queryMetaData("permanent-redirect")=="true")
00635 emit permanentRedirection(this, d->m_url, d->m_redirectionURL);
00636 KUrl dummyUrl;
00637 int permissions;
00638 QDataStream istream( d->m_packedArgs );
00639 istream >> dummyUrl >> permissions;
00640
00641 d->m_url = d->m_redirectionURL;
00642 d->m_redirectionURL = KUrl();
00643 d->m_packedArgs.truncate(0);
00644 QDataStream stream( &d->m_packedArgs, QIODevice::WriteOnly );
00645 stream << d->m_url << permissions;
00646
00647
00648 d->slaveDone();
00649 Scheduler::doJob(this);
00650 }
00651 }
00652
00653 SimpleJob *KIO::mkdir( const KUrl& url, int permissions )
00654 {
00655
00656 KIO_ARGS << url << permissions;
00657 return MkdirJobPrivate::newJob(url, CMD_MKDIR, packedArgs);
00658 }
00659
00660 SimpleJob *KIO::rmdir( const KUrl& url )
00661 {
00662
00663 KIO_ARGS << url << qint8(false);
00664 return SimpleJobPrivate::newJob(url, CMD_DEL, packedArgs);
00665 }
00666
00667 SimpleJob *KIO::chmod( const KUrl& url, int permissions )
00668 {
00669
00670 KIO_ARGS << url << permissions;
00671 return SimpleJobPrivate::newJob(url, CMD_CHMOD, packedArgs);
00672 }
00673
00674 SimpleJob *KIO::chown( const KUrl& url, const QString& owner, const QString& group )
00675 {
00676 KIO_ARGS << url << owner << group;
00677 return SimpleJobPrivate::newJob(url, CMD_CHOWN, packedArgs);
00678 }
00679
00680 SimpleJob *KIO::setModificationTime( const KUrl& url, const QDateTime& mtime )
00681 {
00682
00683 KIO_ARGS << url << mtime;
00684 return SimpleJobPrivate::newJobNoUi(url, CMD_SETMODIFICATIONTIME, packedArgs);
00685 }
00686
00687 SimpleJob *KIO::rename( const KUrl& src, const KUrl & dest, JobFlags flags )
00688 {
00689
00690 KIO_ARGS << src << dest << (qint8) (flags & Overwrite);
00691 return SimpleJobPrivate::newJob(src, CMD_RENAME, packedArgs);
00692 }
00693
00694 SimpleJob *KIO::symlink( const QString& target, const KUrl & dest, JobFlags flags )
00695 {
00696
00697 KIO_ARGS << target << dest << (qint8) (flags & Overwrite);
00698 return SimpleJobPrivate::newJob(dest, CMD_SYMLINK, packedArgs, flags);
00699 }
00700
00701 SimpleJob *KIO::special(const KUrl& url, const QByteArray & data, JobFlags flags)
00702 {
00703
00704 return SimpleJobPrivate::newJob(url, CMD_SPECIAL, data, flags);
00705 }
00706
00707 SimpleJob *KIO::mount( bool ro, const QByteArray& fstype, const QString& dev, const QString& point, JobFlags flags )
00708 {
00709 KIO_ARGS << int(1) << qint8( ro ? 1 : 0 )
00710 << QString::fromLatin1(fstype) << dev << point;
00711 SimpleJob *job = special( KUrl("file:/"), packedArgs, flags );
00712 if (!(flags & HideProgressInfo)) {
00713 KIO::JobPrivate::emitMounting(job, dev, point);
00714 }
00715 return job;
00716 }
00717
00718 SimpleJob *KIO::unmount( const QString& point, JobFlags flags )
00719 {
00720 KIO_ARGS << int(2) << point;
00721 SimpleJob *job = special( KUrl("file:/"), packedArgs, flags );
00722 if (!(flags & HideProgressInfo)) {
00723 KIO::JobPrivate::emitUnmounting(job, point);
00724 }
00725 return job;
00726 }
00727
00728
00729
00731
00732 class KIO::StatJobPrivate: public SimpleJobPrivate
00733 {
00734 public:
00735 inline StatJobPrivate(const KUrl& url, int command, const QByteArray &packedArgs)
00736 : SimpleJobPrivate(url, command, packedArgs), m_bSource(true), m_details(2)
00737 {}
00738
00739 UDSEntry m_statResult;
00740 KUrl m_redirectionURL;
00741 bool m_bSource;
00742 short int m_details;
00743 void slotStatEntry( const KIO::UDSEntry & entry );
00744 void slotRedirection( const KUrl &url);
00745
00752 virtual void start( Slave *slave );
00753
00754 Q_DECLARE_PUBLIC(StatJob)
00755
00756 static inline StatJob *newJob(const KUrl& url, int command, const QByteArray &packedArgs,
00757 JobFlags flags )
00758 {
00759 StatJob *job = new StatJob(*new StatJobPrivate(url, command, packedArgs));
00760 job->setUiDelegate(new JobUiDelegate);
00761 if (!(flags & HideProgressInfo)) {
00762 KIO::getJobTracker()->registerJob(job);
00763 emitStating(job, url);
00764 }
00765 return job;
00766 }
00767 };
00768
00769 StatJob::StatJob(StatJobPrivate &dd)
00770 : SimpleJob(dd)
00771 {
00772 }
00773
00774 StatJob::~StatJob()
00775 {
00776 }
00777
00778 void StatJob::setSide( bool source )
00779 {
00780 d_func()->m_bSource = source;
00781 }
00782
00783 void StatJob::setSide( StatSide side )
00784 {
00785 d_func()->m_bSource = side == SourceSide;
00786 }
00787
00788 void StatJob::setDetails( short int details )
00789 {
00790 d_func()->m_details = details;
00791 }
00792
00793 const UDSEntry & StatJob::statResult() const
00794 {
00795 return d_func()->m_statResult;
00796 }
00797
00798 void StatJobPrivate::start(Slave *slave)
00799 {
00800 Q_Q(StatJob);
00801 m_outgoingMetaData.insert( "statSide", m_bSource ? "source" : "dest" );
00802 m_outgoingMetaData.insert( "details", QString::number(m_details) );
00803
00804 q->connect( slave, SIGNAL( statEntry( const KIO::UDSEntry& ) ),
00805 SLOT( slotStatEntry( const KIO::UDSEntry & ) ) );
00806 q->connect( slave, SIGNAL( redirection(const KUrl &) ),
00807 SLOT( slotRedirection(const KUrl &) ) );
00808
00809 SimpleJobPrivate::start(slave);
00810 }
00811
00812 void StatJobPrivate::slotStatEntry( const KIO::UDSEntry & entry )
00813 {
00814
00815 m_statResult = entry;
00816 }
00817
00818
00819 void StatJobPrivate::slotRedirection( const KUrl &url)
00820 {
00821 Q_Q(StatJob);
00822 kDebug(7007) << "StatJob::slotRedirection(" << url << ")";
00823 if (!KAuthorized::authorizeUrlAction("redirect", m_url, url))
00824 {
00825 kWarning(7007) << "StatJob: Redirection from " << m_url << " to " << url << " REJECTED!";
00826 q->setError( ERR_ACCESS_DENIED );
00827 q->setErrorText( url.prettyUrl() );
00828 return;
00829 }
00830 m_redirectionURL = url;
00831 if (m_url.hasUser() && !url.hasUser() && (m_url.host().toLower() == url.host().toLower()))
00832 m_redirectionURL.setUser(m_url.user());
00833
00834 emit q->redirection(q, m_redirectionURL);
00835 }
00836
00837 void StatJob::slotFinished()
00838 {
00839 Q_D(StatJob);
00840 if ( d->m_redirectionURL.isEmpty() || !d->m_redirectionURL.isValid())
00841 {
00842
00843 SimpleJob::slotFinished();
00844 } else {
00845
00846 if (queryMetaData("permanent-redirect")=="true")
00847 emit permanentRedirection(this, d->m_url, d->m_redirectionURL);
00848 d->m_url = d->m_redirectionURL;
00849 d->m_redirectionURL = KUrl();
00850 d->m_packedArgs.truncate(0);
00851 QDataStream stream( &d->m_packedArgs, QIODevice::WriteOnly );
00852 stream << d->m_url;
00853
00854
00855 d->slaveDone();
00856 Scheduler::doJob(this);
00857 }
00858 }
00859
00860 void StatJob::slotMetaData( const KIO::MetaData &_metaData)
00861 {
00862 Q_D(StatJob);
00863 SimpleJob::slotMetaData(_metaData);
00864 storeSSLSessionFromJob(d->m_redirectionURL);
00865 }
00866
00867 StatJob *KIO::stat(const KUrl& url, JobFlags flags)
00868 {
00869
00870 return stat( url, StatJob::SourceSide, 2, flags );
00871 }
00872
00873 StatJob *KIO::stat(const KUrl& url, bool sideIsSource, short int details, JobFlags flags )
00874 {
00875 kDebug(7007) << "stat " << url;
00876 KIO_ARGS << url;
00877 StatJob * job = StatJobPrivate::newJob(url, CMD_STAT, packedArgs, flags);
00878 job->setSide( sideIsSource ? StatJob::SourceSide : StatJob::DestinationSide );
00879 job->setDetails( details );
00880 return job;
00881 }
00882
00883 StatJob *KIO::stat(const KUrl& url, KIO::StatJob::StatSide side, short int details, JobFlags flags )
00884 {
00885 kDebug(7007) << "stat " << url;
00886 KIO_ARGS << url;
00887 StatJob * job = StatJobPrivate::newJob(url, CMD_STAT, packedArgs, flags);
00888 job->