• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

KIO

job.cpp

Go to the documentation of this file.
00001 /* This file is part of the KDE libraries
00002     Copyright (C) 2000 Stephan Kulow <coolo@kde.org>
00003                        David Faure <faure@kde.org>
00004                        Waldo Bastian <bastian@kde.org>
00005 
00006     This library is free software; you can redistribute it and/or
00007     modify it under the terms of the GNU Library General Public
00008     License as published by the Free Software Foundation; either
00009     version 2 of the License, or (at your option) any later version.
00010 
00011     This library is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014     Library General Public License for more details.
00015 
00016     You should have received a copy of the GNU Library General Public License
00017     along with this library; see the file COPYING.LIB.  If not, write to
00018     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00019     Boston, MA 02110-1301, USA.
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 //this will update the report dialog with 5 Hz, I think this is fast enough, aleXXX
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     //kDebug(7007) << "addSubjob(" << jobBase << ") this=" << this;
00107 
00108     bool ok = KCompositeJob::addSubjob( jobBase );
00109     KIO::Job *job = dynamic_cast<KIO::Job*>( jobBase );
00110     if (ok && job) {
00111         // Copy metadata into subjob (e.g. window-id, user-timestamp etc.)
00112         Q_D(Job);
00113         job->mergeMetaData(d->m_outgoingMetaData);
00114 
00115         // Forward information from that subjob.
00116         connect( job, SIGNAL(speed( KJob*, unsigned long )),
00117                  SLOT(slotSpeed(KJob*, unsigned long)) );
00118 
00119         if (ui() && job->ui()) {
00120             job->ui()->setWindow( ui()->window() );
00121             job->ui()->updateUserTimestamp( ui()->userTimestamp() );
00122         }
00123     }
00124     return ok;
00125 }
00126 
00127 bool Job::removeSubjob( KJob *jobBase )
00128 {
00129     //kDebug(7007) << "removeSubjob(" << jobBase << ") this=" << this << "subjobs=" << subjobs().count();
00130     return KCompositeJob::removeSubjob( jobBase );
00131 }
00132 
00133 void JobPrivate::emitMoving(KIO::Job * job, const KUrl &src, const KUrl &dest)
00134 {
00135     emit job->description(job, i18nc("@title job","Moving"),
00136                           qMakePair(i18n("Source"), src.prettyUrl()),
00137                           qMakePair(i18n("Destination"), dest.prettyUrl()));
00138 }
00139 
00140 void JobPrivate::emitCopying(KIO::Job * job, const KUrl &src, const KUrl &dest)
00141 {
00142     emit job->description(job, i18nc("@title job","Copying"),
00143                           qMakePair(i18n("Source"), src.prettyUrl()),
00144                           qMakePair(i18n("Destination"), dest.prettyUrl()));
00145 }
00146 
00147 void JobPrivate::emitCreatingDir(KIO::Job * job, const KUrl &dir)
00148 {
00149     emit job->description(job, i18nc("@title job","Creating directory"),
00150                           qMakePair(i18n("Directory"), dir.prettyUrl()));
00151 }
00152 
00153 void JobPrivate::emitDeleting(KIO::Job *job, const KUrl &url)
00154 {
00155     emit job->description(job, i18nc("@title job","Deleting"),
00156                           qMakePair(i18n("File"), url.prettyUrl()));
00157 }
00158 
00159 void JobPrivate::emitStating(KIO::Job *job, const KUrl &url)
00160 {
00161     emit job->description(job, i18nc("@title job","Stating"),
00162                           qMakePair(i18n("File"), url.prettyUrl()));
00163 }
00164 
00165 void JobPrivate::emitTransferring(KIO::Job *job, const KUrl &url)
00166 {
00167     emit job->description(job, i18nc("@title job","Transferring"),
00168                           qMakePair(i18n("Source"), url.prettyUrl()));
00169 }
00170 
00171 void JobPrivate::emitMounting(KIO::Job * job, const QString &dev, const QString &point)
00172 {
00173     emit job->description(job, i18nc("@title job","Mounting"),
00174                           qMakePair(i18n("Device"), dev),
00175                           qMakePair(i18n("Mountpoint"), point));
00176 }
00177 
00178 void JobPrivate::emitUnmounting(KIO::Job * job, const QString &point)
00179 {
00180     emit job->description(job, i18nc("@title job","Unmounting"),
00181                           qMakePair(i18n("Mountpoint"), point));
00182 }
00183 
00184 bool Job::doKill()
00185 {
00186   // kill all subjobs, without triggering their result slot
00187   Q_FOREACH( KJob* it, subjobs()) {
00188       it->kill( KJob::Quietly );
00189   }
00190   clearSubjobs();
00191 
00192   return true;
00193 }
00194 
00195 bool Job::doSuspend()
00196 {
00197     Q_FOREACH(KJob* it, subjobs()) {
00198         if (!it->suspend())
00199             return false;
00200     }
00201 
00202     return true;
00203 }
00204 
00205 bool Job::doResume()
00206 {
00207     Q_FOREACH ( KJob* it, subjobs() )
00208     {
00209         if (!it->resume())
00210             return false;
00211     }
00212 
00213     return true;
00214 }
00215 
00216 void JobPrivate::slotSpeed( KJob*, unsigned long speed )
00217 {
00218     //kDebug(7007) << speed;
00219     q_func()->emitSpeed( speed );
00220 }
00221 
00222 //Job::errorString is implemented in global.cpp
00223 
00224 void Job::showErrorDialog( QWidget *parent )
00225 {
00226     if ( ui() )
00227     {
00228         ui()->setWindow( parent );
00229         ui()->showErrorMessage();
00230     }
00231     else
00232     {
00233         kError() << errorString();
00234     }
00235 }
00236 
00237 bool Job::isInteractive() const
00238 {
00239   return uiDelegate() != 0;
00240 }
00241 
00242 void Job::setParentJob(Job* job)
00243 {
00244   Q_D(Job);
00245   Q_ASSERT(d->m_parentJob == 0L);
00246   Q_ASSERT(job);
00247   d->m_parentJob = job;
00248 }
00249 
00250 Job* Job::parentJob() const
00251 {
00252   return d_func()->m_parentJob;
00253 }
00254 
00255 MetaData Job::metaData() const
00256 {
00257     return d_func()->m_incomingMetaData;
00258 }
00259 
00260 QString Job::queryMetaData(const QString &key)
00261 {
00262     return d_func()->m_incomingMetaData.value(key, QString());
00263 }
00264 
00265 void Job::setMetaData( const KIO::MetaData &_metaData)
00266 {
00267     Q_D(Job);
00268     d->m_outgoingMetaData = _metaData;
00269 }
00270 
00271 void Job::addMetaData( const QString &key, const QString &value)
00272 {
00273     d_func()->m_outgoingMetaData.insert(key, value);
00274 }
00275 
00276 void Job::addMetaData( const QMap<QString,QString> &values)
00277 {
00278     Q_D(Job);
00279     QMap<QString,QString>::const_iterator it = values.begin();
00280     for(;it != values.end(); ++it)
00281         d->m_outgoingMetaData.insert(it.key(), it.value());
00282 }
00283 
00284 void Job::mergeMetaData( const QMap<QString,QString> &values)
00285 {
00286     Q_D(Job);
00287     QMap<QString,QString>::const_iterator it = values.begin();
00288     for(;it != values.end(); ++it)
00289         // there's probably a faster way
00290         if ( !d->m_outgoingMetaData.contains( it.key() ) )
00291             d->m_outgoingMetaData.insert( it.key(), it.value() );
00292 }
00293 
00294 MetaData Job::outgoingMetaData() const
00295 {
00296     return d_func()->m_outgoingMetaData;
00297 }
00298 
00299 SimpleJob::SimpleJob(SimpleJobPrivate &dd)
00300   : Job(dd)
00301 {
00302     d_func()->simpleJobInit();
00303 }
00304 
00305 void SimpleJobPrivate::simpleJobInit()
00306 {
00307     Q_Q(SimpleJob);
00308     if (!m_url.isValid())
00309     {
00310         q->setError( ERR_MALFORMED_URL );
00311         q->setErrorText( m_url.url() );
00312         QTimer::singleShot(0, q, SLOT(slotFinished()) );
00313         return;
00314     }
00315 
00316     Scheduler::doJob(q);
00317 }
00318 
00319 
00320 bool SimpleJob::doKill()
00321 {
00322     //kDebug() << this;
00323     Q_D(SimpleJob);
00324     Scheduler::cancelJob( this ); // deletes the slave if not 0
00325     d->m_slave = 0; // -> set to 0
00326     return Job::doKill();
00327 }
00328 
00329 bool SimpleJob::doSuspend()
00330 {
00331     Q_D(SimpleJob);
00332     if ( d->m_slave )
00333         d->m_slave->suspend();
00334     return Job::doSuspend();
00335 }
00336 
00337 bool SimpleJob::doResume()
00338 {
00339     Q_D(SimpleJob);
00340     if ( d->m_slave )
00341         d->m_slave->resume();
00342     return Job::doResume();
00343 }
00344 
00345 const KUrl& SimpleJob::url() const
00346 {
00347     return d_func()->m_url;
00348 }
00349 
00350 void SimpleJob::putOnHold()
00351 {
00352     Q_D(SimpleJob);
00353     Q_ASSERT( d->m_slave );
00354     if ( d->m_slave )
00355     {
00356         Scheduler::putSlaveOnHold(this, d->m_url);
00357         d->m_slave = 0;
00358     }
00359     kill( Quietly );
00360 }
00361 
00362 void SimpleJob::removeOnHold()
00363 {
00364     Scheduler::removeSlaveOnHold();
00365 }
00366 
00367 SimpleJob::~SimpleJob()
00368 {
00369     Q_D(SimpleJob);
00370     if (d->m_slave) // was running
00371     {
00372         kDebug(7007) << "Killing running job in destructor!"  << kBacktrace();
00373 #if 0
00374         d->m_slave->kill();
00375         Scheduler::jobFinished( this, d->m_slave ); // deletes the slave
00376 #endif
00377         Scheduler::cancelJob( this );
00378         d->m_slave = 0; // -> set to 0
00379     }
00380 }
00381 
00382 void SimpleJobPrivate::start(Slave *slave)
00383 {
00384     Q_Q(SimpleJob);
00385     m_slave = slave;
00386 
00387     q->connect( slave, SIGNAL( error( int , const QString & ) ),
00388                 SLOT( slotError( int , const QString & ) ) );
00389 
00390     q->connect( slave, SIGNAL( warning( const QString & ) ),
00391                 SLOT( slotWarning( const QString & ) ) );
00392 
00393     q->connect( slave, SIGNAL( infoMessage( const QString & ) ),
00394                 SLOT( _k_slotSlaveInfoMessage( const QString & ) ) );
00395 
00396     q->connect( slave, SIGNAL( connected() ),
00397                 SLOT( slotConnected() ) );
00398 
00399     q->connect( slave, SIGNAL( finished() ),
00400                 SLOT( slotFinished() ) );
00401 
00402     if ((m_extraFlags & EF_TransferJobDataSent) == 0)
00403     {
00404         q->connect( slave, SIGNAL( totalSize( KIO::filesize_t ) ),
00405                     SLOT( slotTotalSize( KIO::filesize_t ) ) );
00406 
00407         q->connect( slave, SIGNAL( processedSize( KIO::filesize_t ) ),
00408                     SLOT( slotProcessedSize( KIO::filesize_t ) ) );
00409 
00410         q->connect( slave, SIGNAL( speed( unsigned long ) ),
00411                     SLOT( slotSpeed( unsigned long ) ) );
00412     }
00413     q->connect( slave, SIGNAL(metaData( const KIO::MetaData& ) ),
00414                 SLOT( slotMetaData( const KIO::MetaData& ) ) );
00415 
00416     if (ui() && ui()->window())
00417     {
00418         m_outgoingMetaData.insert("window-id", QString::number((long)ui()->window()->winId()));
00419     }
00420 
00421     if (ui() && ui()->userTimestamp())
00422     {
00423         m_outgoingMetaData.insert("user-timestamp", QString::number(ui()->userTimestamp()));
00424     }
00425 
00426     QString sslSession = KSSLCSessionCache::getSessionForUrl(m_url);
00427     if ( !sslSession.isNull() )
00428     {
00429         m_outgoingMetaData.insert("ssl_session_id", sslSession);
00430     }
00431 
00432     if (ui() == 0)              // not interactive
00433     {
00434         m_outgoingMetaData.insert("no-auth-prompt", "true");
00435     }
00436 
00437     if (!m_outgoingMetaData.isEmpty())
00438     {
00439         KIO_ARGS << m_outgoingMetaData;
00440         slave->send( CMD_META_DATA, packedArgs );
00441     }
00442 
00443     if (!m_subUrl.isEmpty())
00444     {
00445        KIO_ARGS << m_subUrl;
00446        slave->send( CMD_SUBURL, packedArgs );
00447     }
00448 
00449     slave->send( m_command, m_packedArgs );
00450 }
00451 
00452 void SimpleJobPrivate::slaveDone()
00453 {
00454     Q_Q(SimpleJob);
00455     if (!m_slave) return;
00456     if (m_command == CMD_OPEN) m_slave->send(CMD_CLOSE);
00457     q->disconnect(m_slave); // Remove all signals between slave and job
00458     Scheduler::jobFinished( q, m_slave );
00459     m_slave = 0;
00460 }
00461 
00462 void SimpleJob::slotFinished( )
00463 {
00464     Q_D(SimpleJob);
00465     // Return slave to the scheduler
00466     d->slaveDone();
00467 
00468     if (!hasSubjobs())
00469     {
00470         if ( !error() && (d->m_command == CMD_MKDIR || d->m_command == CMD_RENAME ) )
00471         {
00472             if ( d->m_command == CMD_MKDIR )
00473             {
00474                 KUrl urlDir( url() );
00475                 urlDir.setPath( urlDir.directory() );
00476                 org::kde::KDirNotify::emitFilesAdded( urlDir.url() );
00477             }
00478             else /*if ( m_command == CMD_RENAME )*/
00479             {
00480                 KUrl src, dst;
00481                 QDataStream str( d->m_packedArgs );
00482                 str >> src >> dst;
00483                 if( src.directory() == dst.directory() ) // For the user, moving isn't renaming. Only renaming is.
00484                     org::kde::KDirNotify::emitFileRenamed( src.url(), dst.url() );
00485 
00486                 org::kde::KDirNotify::emitFileMoved( src.url(), dst.url() );
00487             }
00488         }
00489         emitResult();
00490     }
00491 }
00492 
00493 void SimpleJob::slotError( int err, const QString & errorText )
00494 {
00495     Q_D(SimpleJob);
00496     setError( err );
00497     setErrorText( errorText );
00498     if ((error() == ERR_UNKNOWN_HOST) && d->m_url.host().isEmpty())
00499        setErrorText( QString() );
00500     // error terminates the job
00501     slotFinished();
00502 }
00503 
00504 void SimpleJob::slotWarning( const QString & errorText )
00505 {
00506     emit warning( this, errorText );
00507 }
00508 
00509 void SimpleJobPrivate::_k_slotSlaveInfoMessage( const QString & msg )
00510 {
00511     emit q_func()->infoMessage( q_func(), msg );
00512 }
00513 
00514 void SimpleJobPrivate::slotConnected()
00515 {
00516     emit q_func()->connected( q_func() );
00517 }
00518 
00519 void SimpleJobPrivate::slotTotalSize( KIO::filesize_t size )
00520 {
00521     Q_Q(SimpleJob);
00522     if (size > q->totalAmount(KJob::Bytes))
00523     {
00524         q->setTotalAmount(KJob::Bytes, size);
00525     }
00526 }
00527 
00528 void SimpleJobPrivate::slotProcessedSize( KIO::filesize_t size )
00529 {
00530     Q_Q(SimpleJob);
00531     //kDebug(7007) << KIO::number(size);
00532     q->setProcessedAmount(KJob::Bytes, size);
00533 }
00534 
00535 void SimpleJobPrivate::slotSpeed( unsigned long speed )
00536 {
00537     //kDebug(7007) << speed;
00538     q_func()->emitSpeed( speed );
00539 }
00540 
00541 void SimpleJob::slotMetaData( const KIO::MetaData &_metaData )
00542 {
00543     Q_D(SimpleJob);
00544     d->m_incomingMetaData += _metaData;
00545 }
00546 
00547 void SimpleJob::storeSSLSessionFromJob(const KUrl &redirectionURL)
00548 {
00549     Q_D(SimpleJob);
00550     QString sslSession = queryMetaData("ssl_session_id");
00551 
00552     if ( !sslSession.isNull() ) {
00553         const KUrl &queryURL = redirectionURL.isEmpty() ? d->m_url : redirectionURL;
00554         KSSLCSessionCache::putSessionForUrl(queryURL, sslSession);
00555     }
00556 }
00557 
00559 class KIO::MkdirJobPrivate: public SimpleJobPrivate
00560 {
00561 public:
00562     MkdirJobPrivate(const KUrl& url, int command, const QByteArray &packedArgs)
00563         : SimpleJobPrivate(url, command, packedArgs)
00564         { }
00565     KUrl m_redirectionURL;
00566     void slotRedirection(const KUrl &url);
00567 
00574     virtual void start( Slave *slave );
00575 
00576     Q_DECLARE_PUBLIC(MkdirJob)
00577 
00578     static inline MkdirJob *newJob(const KUrl& url, int command, const QByteArray &packedArgs)
00579     {
00580         MkdirJob *job = new MkdirJob(*new MkdirJobPrivate(url, command, packedArgs));
00581         job->setUiDelegate(new JobUiDelegate);
00582         return job;
00583     }
00584 };
00585 
00586 MkdirJob::MkdirJob(MkdirJobPrivate &dd)
00587     : SimpleJob(dd)
00588 {
00589 }
00590 
00591 MkdirJob::~MkdirJob()
00592 {
00593 }
00594 
00595 void MkdirJobPrivate::start(Slave *slave)
00596 {
00597     Q_Q(MkdirJob);
00598     q->connect( slave, SIGNAL( redirection(const KUrl &) ),
00599                 SLOT( slotRedirection(const KUrl &) ) );
00600 
00601     SimpleJobPrivate::start(slave);
00602 }
00603 
00604 // Slave got a redirection request
00605 void MkdirJobPrivate::slotRedirection( const KUrl &url)
00606 {
00607      Q_Q(MkdirJob);
00608      kDebug(7007) << url;
00609      if (!KAuthorized::authorizeUrlAction("redirect", m_url, url))
00610      {
00611          kWarning(7007) << "Redirection from" << m_url << "to" << url << "REJECTED!";
00612          q->setError( ERR_ACCESS_DENIED );
00613          q->setErrorText( url.prettyUrl() );
00614          return;
00615      }
00616      m_redirectionURL = url; // We'll remember that when the job finishes
00617      if (m_url.hasUser() && !url.hasUser() && (m_url.host().toLower() == url.host().toLower()))
00618          m_redirectionURL.setUser(m_url.user()); // Preserve user
00619      // Tell the user that we haven't finished yet
00620      emit q->redirection(q, m_redirectionURL);
00621 }
00622 
00623 void MkdirJob::slotFinished()
00624 {
00625     Q_D(MkdirJob);
00626     if ( d->m_redirectionURL.isEmpty() || !d->m_redirectionURL.isValid())
00627     {
00628         // Return slave to the scheduler
00629         SimpleJob::slotFinished();
00630     } else {
00631         //kDebug(7007) << "MkdirJob: Redirection to " << m_redirectionURL;
00632         if (queryMetaData("permanent-redirect")=="true")
00633             emit permanentRedirection(this, d->m_url, d->m_redirectionURL);
00634         KUrl dummyUrl;
00635         int permissions;
00636         QDataStream istream( d->m_packedArgs );
00637         istream >> dummyUrl >> permissions;
00638 
00639         d->m_url = d->m_redirectionURL;
00640         d->m_redirectionURL = KUrl();
00641         d->m_packedArgs.truncate(0);
00642         QDataStream stream( &d->m_packedArgs, QIODevice::WriteOnly );
00643         stream << d->m_url << permissions;
00644 
00645         // Return slave to the scheduler
00646         d->slaveDone();
00647         Scheduler::doJob(this);
00648     }
00649 }
00650 
00651 SimpleJob *KIO::mkdir( const KUrl& url, int permissions )
00652 {
00653     //kDebug(7007) << "mkdir " << url;
00654     KIO_ARGS << url << permissions;
00655     return MkdirJobPrivate::newJob(url, CMD_MKDIR, packedArgs);
00656 }
00657 
00658 SimpleJob *KIO::rmdir( const KUrl& url )
00659 {
00660     //kDebug(7007) << "rmdir " << url;
00661     KIO_ARGS << url << qint8(false); // isFile is false
00662     return SimpleJobPrivate::newJob(url, CMD_DEL, packedArgs);
00663 }
00664 
00665 SimpleJob *KIO::chmod( const KUrl& url, int permissions )
00666 {
00667     //kDebug(7007) << "chmod " << url;
00668     KIO_ARGS << url << permissions;
00669     return SimpleJobPrivate::newJob(url, CMD_CHMOD, packedArgs);
00670 }
00671 
00672 SimpleJob *KIO::chown( const KUrl& url, const QString& owner, const QString& group )
00673 {
00674     KIO_ARGS << url << owner << group;
00675     return SimpleJobPrivate::newJob(url, CMD_CHOWN, packedArgs);
00676 }
00677 
00678 SimpleJob *KIO::setModificationTime( const KUrl& url, const QDateTime& mtime )
00679 {
00680     //kDebug(7007) << "setModificationTime " << url << " " << mtime;
00681     KIO_ARGS << url << mtime;
00682     return SimpleJobPrivate::newJobNoUi(url, CMD_SETMODIFICATIONTIME, packedArgs);
00683 }
00684 
00685 SimpleJob *KIO::rename( const KUrl& src, const KUrl & dest, JobFlags flags )
00686 {
00687     //kDebug(7007) << "rename " << src << " " << dest;
00688     KIO_ARGS << src << dest << (qint8) (flags & Overwrite);
00689     return SimpleJobPrivate::newJob(src, CMD_RENAME, packedArgs);
00690 }
00691 
00692 SimpleJob *KIO::symlink( const QString& target, const KUrl & dest, JobFlags flags )
00693 {
00694     //kDebug(7007) << "symlink target=" << target << " " << dest;
00695     KIO_ARGS << target << dest << (qint8) (flags & Overwrite);
00696     return SimpleJobPrivate::newJob(dest, CMD_SYMLINK, packedArgs, flags);
00697 }
00698 
00699 SimpleJob *KIO::special(const KUrl& url, const QByteArray & data, JobFlags flags)
00700 {
00701     //kDebug(7007) << "special " << url;
00702     return SimpleJobPrivate::newJob(url, CMD_SPECIAL, data, flags);
00703 }
00704 
00705 SimpleJob *KIO::mount( bool ro, const QByteArray& fstype, const QString& dev, const QString& point, JobFlags flags )
00706 {
00707     KIO_ARGS << int(1) << qint8( ro ? 1 : 0 )
00708              << QString::fromLatin1(fstype) << dev << point;
00709     SimpleJob *job = special( KUrl("file:/"), packedArgs, flags );
00710     if (!(flags & HideProgressInfo)) {
00711         KIO::JobPrivate::emitMounting(job, dev, point);
00712     }
00713     return job;
00714 }
00715 
00716 SimpleJob *KIO::unmount( const QString& point, JobFlags flags )
00717 {
00718     KIO_ARGS << int(2) << point;
00719     SimpleJob *job = special( KUrl("file:/"), packedArgs, flags );
00720     if (!(flags & HideProgressInfo)) {
00721         KIO::JobPrivate::emitUnmounting(job, point);
00722     }
00723     return job;
00724 }
00725 
00726 
00727 
00729 
00730 class KIO::StatJobPrivate: public SimpleJobPrivate
00731 {
00732 public:
00733     inline StatJobPrivate(const KUrl& url, int command, const QByteArray &packedArgs)
00734         : SimpleJobPrivate(url, command, packedArgs), m_bSource(true), m_details(2)
00735         {}
00736 
00737     UDSEntry m_statResult;
00738     KUrl m_redirectionURL;
00739     bool m_bSource;
00740     short int m_details;
00741     void slotStatEntry( const KIO::UDSEntry & entry );
00742     void slotRedirection( const KUrl &url);
00743 
00750     virtual void start( Slave *slave );
00751 
00752     Q_DECLARE_PUBLIC(StatJob)
00753 
00754     static inline StatJob *newJob(const KUrl& url, int command, const QByteArray &packedArgs,
00755         JobFlags flags )
00756     {
00757         StatJob *job = new StatJob(*new StatJobPrivate(url, command, packedArgs));
00758         job->setUiDelegate(new JobUiDelegate);
00759         if (!(flags & HideProgressInfo)) {
00760             KIO::getJobTracker()->registerJob(job);
00761             emitStating(job, url);
00762         }
00763         return job;
00764     }
00765 };
00766 
00767 StatJob::StatJob(StatJobPrivate &dd)
00768     : SimpleJob(dd)
00769 {
00770 }
00771 
00772 StatJob::~StatJob()
00773 {
00774 }
00775 
00776 void StatJob::setSide( bool source )
00777 {
00778     d_func()->m_bSource = source;
00779 }
00780 
00781 void StatJob::setSide( StatSide side )
00782 {
00783     d_func()->m_bSource = side == SourceSide;
00784 }
00785 
00786 void StatJob::setDetails( short int details )
00787 {
00788     d_func()->m_details = details;
00789 }
00790 
00791 const UDSEntry & StatJob::statResult() const
00792 {
00793     return d_func()->m_statResult;
00794 }
00795 
00796 void StatJobPrivate::start(Slave *slave)
00797 {
00798     Q_Q(StatJob);
00799     m_outgoingMetaData.insert( "statSide", m_bSource ? "source" : "dest" );
00800     m_outgoingMetaData.insert( "details", QString::number(m_details) );
00801 
00802     q->connect( slave, SIGNAL( statEntry( const KIO::UDSEntry& ) ),
00803              SLOT( slotStatEntry( const KIO::UDSEntry & ) ) );
00804     q->connect( slave, SIGNAL( redirection(const KUrl &) ),
00805              SLOT( slotRedirection(const KUrl &) ) );
00806 
00807     SimpleJobPrivate::start(slave);
00808 }
00809 
00810 void StatJobPrivate::slotStatEntry( const KIO::UDSEntry & entry )
00811 {
00812     //kDebug(7007);
00813     m_statResult = entry;
00814 }
00815 
00816 // Slave got a redirection request
00817 void StatJobPrivate::slotRedirection( const KUrl &url)
00818 {
00819      Q_Q(StatJob);
00820      kDebug(7007) << url;
00821      if (!KAuthorized::authorizeUrlAction("redirect", m_url, url))
00822      {
00823        kWarning(7007) << "Redirection from " << m_url << " to " << url << " REJECTED!";
00824        q->setError( ERR_ACCESS_DENIED );
00825        q->setErrorText( url.prettyUrl() );
00826        return;
00827      }
00828      m_redirectionURL = url; // We'll remember that when the job finishes
00829      if (m_url.hasUser() && !url.hasUser() && (m_url.host().toLower() == url.host().toLower()))
00830         m_redirectionURL.setUser(m_url.user()); // Preserve user
00831      // Tell the user that we haven't finished yet
00832      emit q->redirection(q, m_redirectionURL);
00833 }
00834 
00835 void StatJob::slotFinished()
00836 {
00837     Q_D(StatJob);
00838     if ( d->m_redirectionURL.isEmpty() || !d->m_redirectionURL.isValid())
00839     {
00840         // Return slave to the scheduler
00841         SimpleJob::slotFinished();
00842     } else {
00843         //kDebug(7007) << "StatJob: Redirection to " << m_redirectionURL;
00844         if (queryMetaData("permanent-redirect")=="true")
00845             emit permanentRedirection(this, d->m_url, d->m_redirectionURL);
00846         d->m_url = d->m_redirectionURL;
00847         d->m_redirectionURL = KUrl();
00848         d->m_packedArgs.truncate(0);
00849         QDataStream stream( &d->m_packedArgs, QIODevice::WriteOnly );
00850         stream << d->m_url;
00851 
00852         // Return slave to the scheduler
00853         d->slaveDone();
00854         Scheduler::doJob(this);
00855     }
00856 }
00857 
00858 void StatJob::slotMetaData( const KIO::MetaData &_metaData)
00859 {
00860     Q_D(StatJob);
00861     SimpleJob::slotMetaData(_metaData);
00862     storeSSLSessionFromJob(d->m_redirectionURL);
00863 }
00864 
00865 StatJob *KIO::stat(const KUrl& url, JobFlags flags)
00866 {
00867     // Assume sideIsSource. Gets are more common than puts.
00868     return stat( url, StatJob::SourceSide, 2, flags );
00869 }
00870 
00871 StatJob *KIO::stat(const KUrl& url, bool sideIsSource, short int details, JobFlags flags )
00872 {
00873     //kDebug(7007) << "stat" << url;
00874     KIO_ARGS << url;
00875     StatJob * job = StatJobPrivate::newJob(url, CMD_STAT, packedArgs, flags);
00876     job->setSide( sideIsSource ? StatJob::SourceSide : StatJob::DestinationSide );
00877     job->setDetails( details );
00878     return job;
00879 }
00880 
00881 StatJob *KIO::stat(const KUrl& url, KIO::StatJob::StatSide side, short int details, JobFlags flags )
00882 {
00883     //kDebug(7007) << "stat" << url;
00884     KIO_ARGS << url;
00885     StatJob * job = StatJobPrivate::newJob(url, CMD_STAT, packedArgs, flags);
00886     job->setSide( side );
00887     job->setDetails( details );
00888     return job;
00889 }
00890 
00891 SimpleJob *KIO::http_update_cache( const KUrl& url, bool no_cache, time_t expireDate)
00892 {
00893     assert( (url.protocol() == "http") || (url.protocol() == "https") );
00894     // Send http update_cache command (2)
00895     KIO_ARGS << (int)2 << url << no_cache << qlonglong(expireDate);
00896     SimpleJob * job = SimpleJobPrivate::newJob(url, CMD_SPECIAL, packedArgs);
00897     job->