00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "kio/job.h"
00023
00024 #include <config.h>
00025
00026 #include <sys/types.h>
00027 #include <sys/wait.h>
00028 #include <sys/stat.h>
00029
00030 #include <assert.h>
00031
00032 #include <signal.h>
00033 #include <stdlib.h>
00034 #include <stdio.h>
00035 #include <time.h>
00036 #include <unistd.h>
00037 extern "C" {
00038 #include <pwd.h>
00039 #include <grp.h>
00040 }
00041 #include <qtimer.h>
00042 #include <qfile.h>
00043
00044 #include <kapplication.h>
00045 #include <kglobal.h>
00046 #include <klocale.h>
00047 #include <ksimpleconfig.h>
00048 #include <kdebug.h>
00049 #include <kdialog.h>
00050 #include <kmessagebox.h>
00051 #include <kdatastream.h>
00052 #include <kmainwindow.h>
00053 #include <kde_file.h>
00054
00055 #include <errno.h>
00056
00057 #include "kmimetype.h"
00058 #include "slave.h"
00059 #include "scheduler.h"
00060 #include "kdirwatch.h"
00061 #include "kmimemagic.h"
00062 #include "kprotocolinfo.h"
00063 #include "kprotocolmanager.h"
00064
00065 #include "kio/observer.h"
00066
00067 #include "kssl/ksslcsessioncache.h"
00068
00069 #include <kdirnotify_stub.h>
00070 #include <ktempfile.h>
00071 #include <dcopclient.h>
00072
00073 #ifdef Q_OS_UNIX
00074 #include <utime.h>
00075 #endif
00076
00077 using namespace KIO;
00078 template class QPtrList<KIO::Job>;
00079
00080
00081 #define REPORT_TIMEOUT 200
00082
00083 #define KIO_ARGS QByteArray packedArgs; QDataStream stream( packedArgs, IO_WriteOnly ); stream
00084
00085 class Job::JobPrivate
00086 {
00087 public:
00088 JobPrivate() : m_autoErrorHandling( false ), m_autoWarningHandling( true ),
00089 m_interactive( true ), m_parentJob( 0L ), m_extraFlags(0),
00090 m_processedSize(0)
00091 {}
00092
00093 bool m_autoErrorHandling;
00094 bool m_autoWarningHandling;
00095 bool m_interactive;
00096 QGuardedPtr<QWidget> m_errorParentWidget;
00097
00098
00099 Job* m_parentJob;
00100 int m_extraFlags;
00101 KIO::filesize_t m_processedSize;
00102 };
00103
00104 Job::Job(bool showProgressInfo) : QObject(0, "job"), m_error(0), m_percent(0)
00105 , m_progressId(0), m_speedTimer(0), d( new JobPrivate )
00106 {
00107
00108
00109
00110 if ( showProgressInfo )
00111 {
00112 m_progressId = Observer::self()->newJob( this, true );
00113
00114
00115 connect( this, SIGNAL( percent( KIO::Job*, unsigned long ) ),
00116 Observer::self(), SLOT( slotPercent( KIO::Job*, unsigned long ) ) );
00117 connect( this, SIGNAL( infoMessage( KIO::Job*, const QString & ) ),
00118 Observer::self(), SLOT( slotInfoMessage( KIO::Job*, const QString & ) ) );
00119 connect( this, SIGNAL( totalSize( KIO::Job*, KIO::filesize_t ) ),
00120 Observer::self(), SLOT( slotTotalSize( KIO::Job*, KIO::filesize_t ) ) );
00121 connect( this, SIGNAL( processedSize( KIO::Job*, KIO::filesize_t ) ),
00122 Observer::self(), SLOT( slotProcessedSize( KIO::Job*, KIO::filesize_t ) ) );
00123 connect( this, SIGNAL( speed( KIO::Job*, unsigned long ) ),
00124 Observer::self(), SLOT( slotSpeed( KIO::Job*, unsigned long ) ) );
00125 }
00126
00127 if (kapp)
00128 kapp->ref();
00129 }
00130
00131 Job::~Job()
00132 {
00133 delete m_speedTimer;
00134 delete d;
00135 if (kapp)
00136 kapp->deref();
00137 }
00138
00139 int& Job::extraFlags()
00140 {
00141 return d->m_extraFlags;
00142 }
00143
00144 void Job::setProcessedSize(KIO::filesize_t size)
00145 {
00146 d->m_processedSize = size;
00147 }
00148
00149 KIO::filesize_t Job::getProcessedSize()
00150 {
00151 return d->m_processedSize;
00152 }
00153
00154 void Job::addSubjob(Job *job, bool inheritMetaData)
00155 {
00156
00157 subjobs.append(job);
00158
00159 connect( job, SIGNAL(result(KIO::Job*)),
00160 SLOT(slotResult(KIO::Job*)) );
00161
00162
00163 connect( job, SIGNAL(speed( KIO::Job*, unsigned long )),
00164 SLOT(slotSpeed(KIO::Job*, unsigned long)) );
00165
00166 connect( job, SIGNAL(infoMessage( KIO::Job*, const QString & )),
00167 SLOT(slotInfoMessage(KIO::Job*, const QString &)) );
00168
00169 if (inheritMetaData)
00170 job->mergeMetaData(m_outgoingMetaData);
00171
00172 job->setWindow( m_window );
00173 }
00174
00175 void Job::removeSubjob( Job *job )
00176 {
00177 removeSubjob( job, false, true );
00178 }
00179
00180 void Job::removeSubjob( Job *job, bool mergeMetaData, bool emitResultIfLast )
00181 {
00182
00183
00184 if ( mergeMetaData )
00185 m_incomingMetaData += job->metaData();
00186 subjobs.remove(job);
00187 if ( subjobs.isEmpty() && emitResultIfLast )
00188 emitResult();
00189 }
00190
00191 void Job::emitPercent( KIO::filesize_t processedSize, KIO::filesize_t totalSize )
00192 {
00193
00194 unsigned long ipercent = m_percent;
00195
00196 if ( totalSize == 0 )
00197 m_percent = 100;
00198 else
00199 m_percent = (unsigned long)(( (float)(processedSize) / (float)(totalSize) ) * 100.0);
00200
00201 if ( m_percent != ipercent || m_percent == 100 ) {
00202 emit percent( this, m_percent );
00203
00204 }
00205 }
00206
00207 void Job::emitSpeed( unsigned long bytes_per_second )
00208 {
00209
00210 if ( !m_speedTimer )
00211 {
00212 m_speedTimer = new QTimer();
00213 connect( m_speedTimer, SIGNAL( timeout() ), SLOT( slotSpeedTimeout() ) );
00214 }
00215 emit speed( this, bytes_per_second );
00216 m_speedTimer->start( 5000 );
00217 }
00218
00219 void Job::emitResult()
00220 {
00221
00222 if ( m_progressId )
00223 Observer::self()->jobFinished( m_progressId );
00224 if ( m_error && d->m_interactive && d->m_autoErrorHandling )
00225 showErrorDialog( d->m_errorParentWidget );
00226 emit result(this);
00227 deleteLater();
00228 }
00229
00230 void Job::kill( bool quietly )
00231 {
00232 kdDebug(7007) << "Job::kill this=" << this << " " << className() << " m_progressId=" << m_progressId << " quietly=" << quietly << endl;
00233
00234 QPtrListIterator<Job> it( subjobs );
00235 for ( ; it.current() ; ++it )
00236 (*it)->kill( true );
00237 subjobs.clear();
00238
00239 if ( ! quietly ) {
00240 m_error = ERR_USER_CANCELED;
00241 emit canceled( this );
00242 emitResult();
00243 } else
00244 {
00245 if ( m_progressId )
00246 Observer::self()->jobFinished( m_progressId );
00247 deleteLater();
00248 }
00249 }
00250
00251 void Job::slotResult( Job *job )
00252 {
00253
00254 if ( job->error() && !m_error )
00255 {
00256
00257 m_error = job->error();
00258 m_errorText = job->errorText();
00259 }
00260 removeSubjob(job);
00261 }
00262
00263 void Job::slotSpeed( KIO::Job*, unsigned long speed )
00264 {
00265
00266 emitSpeed( speed );
00267 }
00268
00269 void Job::slotInfoMessage( KIO::Job*, const QString & msg )
00270 {
00271 emit infoMessage( this, msg );
00272 }
00273
00274 void Job::slotSpeedTimeout()
00275 {
00276
00277
00278
00279 emit speed( this, 0 );
00280 m_speedTimer->stop();
00281 }
00282
00283
00284
00285 void Job::showErrorDialog( QWidget * parent )
00286 {
00287
00288 kapp->enableStyles();
00289
00290 if ( (m_error != ERR_USER_CANCELED) && (m_error != ERR_NO_CONTENT) ) {
00291
00292
00293 if ( 1 )
00294 KMessageBox::queuedMessageBox( parent, KMessageBox::Error, errorString() );
00295 #if 0
00296 } else {
00297 QStringList errors = detailedErrorStrings();
00298 QString caption, err, detail;
00299 QStringList::const_iterator it = errors.begin();
00300 if ( it != errors.end() )
00301 caption = *(it++);
00302 if ( it != errors.end() )
00303 err = *(it++);
00304 if ( it != errors.end() )
00305 detail = *it;
00306 KMessageBox::queuedDetailedError( parent, err, detail, caption );
00307 }
00308 #endif
00309 }
00310 }
00311
00312 void Job::setAutoErrorHandlingEnabled( bool enable, QWidget *parentWidget )
00313 {
00314 d->m_autoErrorHandling = enable;
00315 d->m_errorParentWidget = parentWidget;
00316 }
00317
00318 bool Job::isAutoErrorHandlingEnabled() const
00319 {
00320 return d->m_autoErrorHandling;
00321 }
00322
00323 void Job::setAutoWarningHandlingEnabled( bool enable )
00324 {
00325 d->m_autoWarningHandling = enable;
00326 }
00327
00328 bool Job::isAutoWarningHandlingEnabled() const
00329 {
00330 return d->m_autoWarningHandling;
00331 }
00332
00333 void Job::setInteractive(bool enable)
00334 {
00335 d->m_interactive = enable;
00336 }
00337
00338 bool Job::isInteractive() const
00339 {
00340 return d->m_interactive;
00341 }
00342
00343 void Job::setWindow(QWidget *window)
00344 {
00345 m_window = window;
00346 KIO::Scheduler::registerWindow(window);
00347 }
00348
00349 QWidget *Job::window() const
00350 {
00351 return m_window;
00352 }
00353
00354 void Job::setParentJob(Job* job)
00355 {
00356 Q_ASSERT(d->m_parentJob == 0L);
00357 Q_ASSERT(job);
00358 d->m_parentJob = job;
00359 }
00360
00361 Job* Job::parentJob() const
00362 {
00363 return d->m_parentJob;
00364 }
00365
00366 MetaData Job::metaData() const
00367 {
00368 return m_incomingMetaData;
00369 }
00370
00371 QString Job::queryMetaData(const QString &key)
00372 {
00373 if (!m_incomingMetaData.contains(key))
00374 return QString::null;
00375 return m_incomingMetaData[key];
00376 }
00377
00378 void Job::setMetaData( const KIO::MetaData &_metaData)
00379 {
00380 m_outgoingMetaData = _metaData;
00381 }
00382
00383 void Job::addMetaData( const QString &key, const QString &value)
00384 {
00385 m_outgoingMetaData.insert(key, value);
00386 }
00387
00388 void Job::addMetaData( const QMap<QString,QString> &values)
00389 {
00390 QMapConstIterator<QString,QString> it = values.begin();
00391 for(;it != values.end(); ++it)
00392 m_outgoingMetaData.insert(it.key(), it.data());
00393 }
00394
00395 void Job::mergeMetaData( const QMap<QString,QString> &values)
00396 {
00397 QMapConstIterator<QString,QString> it = values.begin();
00398 for(;it != values.end(); ++it)
00399 m_outgoingMetaData.insert(it.key(), it.data(), false);
00400 }
00401
00402 MetaData Job::outgoingMetaData() const
00403 {
00404 return m_outgoingMetaData;
00405 }
00406
00407
00408 SimpleJob::SimpleJob(const KURL& url, int command, const QByteArray &packedArgs,
00409 bool showProgressInfo )
00410 : Job(showProgressInfo), m_slave(0), m_packedArgs(packedArgs),
00411 m_url(url), m_command(command), m_totalSize(0)
00412 {
00413 if (!m_url.isValid())
00414 {
00415 m_error = ERR_MALFORMED_URL;
00416 m_errorText = m_url.url();
00417 QTimer::singleShot(0, this, SLOT(slotFinished()) );
00418 return;
00419 }
00420
00421
00422 if (m_url.hasSubURL())
00423 {
00424 KURL::List list = KURL::split(m_url);
00425 KURL::List::Iterator it = list.fromLast();
00426 list.remove(it);
00427 m_subUrl = KURL::join(list);
00428
00429
00430 }
00431
00432 Scheduler::doJob(this);
00433 }
00434
00435 void SimpleJob::kill( bool quietly )
00436 {
00437 Scheduler::cancelJob( this );
00438 m_slave = 0;
00439 Job::kill( quietly );
00440 }
00441
00442 void SimpleJob::putOnHold()
00443 {
00444 Q_ASSERT( m_slave );
00445 if ( m_slave )
00446 {
00447 Scheduler::putSlaveOnHold(this, m_url);
00448 m_slave = 0;
00449 }
00450 kill(true);
00451 }
00452
00453 void SimpleJob::removeOnHold()
00454 {
00455 Scheduler::removeSlaveOnHold();
00456 }
00457
00458 SimpleJob::~SimpleJob()
00459 {
00460 if (m_slave)
00461 {
00462 kdDebug(7007) << "SimpleJob::~SimpleJob: Killing running job in destructor!" << endl;
00463 #if 0
00464 m_slave->kill();
00465 Scheduler::jobFinished( this, m_slave );
00466 #endif
00467 Scheduler::cancelJob( this );
00468 m_slave = 0;
00469 }
00470 }
00471
00472 void SimpleJob::start(Slave *slave)
00473 {
00474 m_slave = slave;
00475
00476 connect( m_slave, SIGNAL( error( int , const QString & ) ),
00477 SLOT( slotError( int , const QString & ) ) );
00478
00479 connect( m_slave, SIGNAL( warning( const QString & ) ),
00480 SLOT( slotWarning( const QString & ) ) );
00481
00482 connect( m_slave, SIGNAL( infoMessage( const QString & ) ),
00483 SLOT( slotInfoMessage( const QString & ) ) );
00484
00485 connect( m_slave, SIGNAL( connected() ),
00486 SLOT( slotConnected() ) );
00487
00488 connect( m_slave, SIGNAL( finished() ),
00489 SLOT( slotFinished() ) );
00490
00491 if ((extraFlags() & EF_TransferJobDataSent) == 0)
00492 {
00493 connect( m_slave, SIGNAL( totalSize( KIO::filesize_t ) ),
00494 SLOT( slotTotalSize( KIO::filesize_t ) ) );
00495
00496 connect( m_slave, SIGNAL( processedSize( KIO::filesize_t ) ),
00497 SLOT( slotProcessedSize( KIO::filesize_t ) ) );
00498
00499 connect( m_slave, SIGNAL( speed( unsigned long ) ),
00500 SLOT( slotSpeed( unsigned long ) ) );
00501 }
00502
00503 connect( slave, SIGNAL( needProgressId() ),
00504 SLOT( slotNeedProgressId() ) );
00505
00506 connect( slave, SIGNAL(metaData( const KIO::MetaData& ) ),
00507 SLOT( slotMetaData( const KIO::MetaData& ) ) );
00508
00509 if (m_window)
00510 {
00511 QString id;
00512 addMetaData("window-id", id.setNum((ulong)m_window->winId()));
00513 }
00514
00515 QString sslSession = KSSLCSessionCache::getSessionForURL(m_url);
00516 if ( !sslSession.isNull() )
00517 {
00518 addMetaData("ssl_session_id", sslSession);
00519 }
00520
00521 if (!isInteractive())
00522 {
00523 addMetaData("no-auth-prompt", "true");
00524 }
00525
00526 if (!m_outgoingMetaData.isEmpty())
00527 {
00528 KIO_ARGS << m_outgoingMetaData;
00529 slave->send( CMD_META_DATA, packedArgs );
00530 }
00531
00532 if (!m_subUrl.isEmpty())
00533 {
00534 KIO_ARGS << m_subUrl;
00535 m_slave->send( CMD_SUBURL, packedArgs );
00536 }
00537
00538 m_slave->send( m_command, m_packedArgs );
00539 }
00540
00541 void SimpleJob::slaveDone()
00542 {
00543 if (!m_slave) return;
00544 disconnect(m_slave);
00545 Scheduler::jobFinished( this, m_slave );
00546 m_slave = 0;
00547 }
00548
00549 void SimpleJob::slotFinished( )
00550 {
00551
00552 slaveDone();
00553
00554 if (subjobs.isEmpty())
00555 {
00556 if ( !m_error && (m_command == CMD_MKDIR || m_command == CMD_RENAME ) )
00557 {
00558 KDirNotify_stub allDirNotify( "*", "KDirNotify*" );
00559 if ( m_command == CMD_MKDIR )
00560 {
00561 KURL urlDir( url() );
00562 urlDir.setPath( urlDir.directory() );
00563 allDirNotify.FilesAdded( urlDir );
00564 }
00565 else
00566 {
00567 KURL src, dst;
00568 QDataStream str( m_packedArgs, IO_ReadOnly );
00569 str >> src >> dst;
00570 if ( src.directory() == dst.directory() )
00571 allDirNotify.FileRenamed( src, dst );
00572 }
00573 }
00574 emitResult();
00575 }
00576 }
00577
00578 void SimpleJob::slotError( int error, const QString & errorText )
00579 {
00580 m_error = error;
00581 m_errorText = errorText;
00582 if ((m_error == ERR_UNKNOWN_HOST) && m_url.host().isEmpty())
00583 m_errorText = QString::null;
00584
00585 slotFinished();
00586 }
00587
00588 void SimpleJob::slotWarning( const QString & errorText )
00589 {
00590 QGuardedPtr<SimpleJob> guard( this );
00591 if (isInteractive() && isAutoWarningHandlingEnabled())
00592 {
00593 static uint msgBoxDisplayed = 0;
00594 if ( msgBoxDisplayed == 0 )
00595 {
00596 msgBoxDisplayed++;
00597 KMessageBox::information( 0L, errorText );
00598 msgBoxDisplayed--;
00599 }
00600
00601 }
00602
00603 if ( !guard.isNull() )
00604 emit warning( this, errorText );
00605 }
00606
00607 void SimpleJob::slotInfoMessage( const QString & msg )
00608 {
00609 emit infoMessage( this, msg );
00610 }
00611
00612 void SimpleJob::slotConnected()
00613 {
00614 emit connected( this );
00615 }
00616
00617 void SimpleJob::slotNeedProgressId()
00618 {
00619 if ( !m_progressId )
00620 m_progressId = Observer::self()->newJob( this, false );
00621 m_slave->setProgressId( m_progressId );
00622 }
00623
00624 void SimpleJob::slotTotalSize( KIO::filesize_t size )
00625 {
00626 if (size > m_totalSize)
00627 {
00628 m_totalSize = size;
00629 emit totalSize( this, size );
00630 }
00631 }
00632
00633 void SimpleJob::slotProcessedSize( KIO::filesize_t size )
00634 {
00635
00636 setProcessedSize(size);
00637 emit processedSize( this, size );
00638 if ( size > m_totalSize ) {
00639 slotTotalSize(size);
00640 }
00641 emitPercent( size, m_totalSize );
00642 }
00643
00644 void SimpleJob::slotSpeed( unsigned long speed )
00645 {
00646
00647 emitSpeed( speed );
00648 }
00649
00650 void SimpleJob::slotMetaData( const KIO::MetaData &_metaData)
00651 {
00652 m_incomingMetaData += _metaData;
00653 }
00654
00655 void SimpleJob::storeSSLSessionFromJob(const KURL &m_redirectionURL) {
00656 QString sslSession = queryMetaData("ssl_session_id");
00657
00658 if ( !sslSession.isNull() ) {
00659 const KURL &queryURL = m_redirectionURL.isEmpty()?m_url:m_redirectionURL;
00660 KSSLCSessionCache::putSessionForURL(queryURL, sslSession);
00661 }
00662 }
00663
00665 MkdirJob::MkdirJob( const KURL& url, int command,
00666 const QByteArray &packedArgs, bool showProgressInfo )
00667 : SimpleJob(url, command, packedArgs, showProgressInfo)
00668 {
00669 }
00670
00671 void MkdirJob::start(Slave *slave)
00672 {
00673 connect( slave, SIGNAL( redirection(const KURL &) ),
00674 SLOT( slotRedirection(const KURL &) ) );
00675
00676 SimpleJob::start(slave);
00677 }
00678
00679
00680 void MkdirJob::slotRedirection( const KURL &url)
00681 {
00682 kdDebug(7007) << "MkdirJob::slotRedirection(" << url << ")" << endl;
00683 if (!kapp->authorizeURLAction("redirect", m_url, url))
00684 {
00685 kdWarning(7007) << "MkdirJob: Redirection from " << m_url << " to " << url << " REJECTED!" << endl;
00686 m_error = ERR_ACCESS_DENIED;
00687 m_errorText = url.prettyURL();
00688 return;
00689 }
00690 m_redirectionURL = url;
00691 if (m_url.hasUser() && !url.hasUser() && (m_url.host().lower() == url.host().lower()))
00692 m_redirectionURL.setUser(m_url.user());
00693
00694 emit redirection(this, m_redirectionURL);
00695 }
00696
00697 void MkdirJob::slotFinished()
00698 {
00699 if ( m_redirectionURL.isEmpty() || !m_redirectionURL.isValid())
00700 {
00701
00702 SimpleJob::slotFinished();
00703 } else {
00704
00705 if (queryMetaData("permanent-redirect")=="true")
00706 emit permanentRedirection(this, m_url, m_redirectionURL);
00707 KURL dummyUrl;
00708 int permissions;
00709 QDataStream istream( m_packedArgs, IO_ReadOnly );
00710 istream >> dummyUrl >> permissions;
00711
00712 m_url = m_redirectionURL;
00713 m_redirectionURL = KURL();
00714 m_packedArgs.truncate(0);
00715 QDataStream stream( m_packedArgs, IO_WriteOnly );
00716 stream << m_url << permissions;
00717
00718
00719 slaveDone();
00720 Scheduler::doJob(this);
00721 }
00722 }
00723
00724 SimpleJob *KIO::mkdir( const KURL& url, int permissions )
00725 {
00726
00727 KIO_ARGS << url << permissions;
00728 return new MkdirJob(url, CMD_MKDIR, packedArgs, false);
00729 }
00730
00731 SimpleJob *KIO::rmdir( const KURL& url )
00732 {
00733
00734 KIO_ARGS << url << Q_INT8(false);
00735 return new SimpleJob(url, CMD_DEL, packedArgs, false);
00736 }
00737
00738 SimpleJob *KIO::chmod( const KURL& url, int permissions )
00739 {
00740
00741 KIO_ARGS << url << permissions;
00742 return new SimpleJob(url, CMD_CHMOD, packedArgs, false);
00743 }
00744
00745 SimpleJob *KIO::rename( const KURL& src, const KURL & dest, bool overwrite )
00746 {
00747
00748 KIO_ARGS << src << dest << (Q_INT8) overwrite;
00749 return new SimpleJob(src, CMD_RENAME, packedArgs, false);
00750 }
00751
00752 SimpleJob *KIO::symlink( const QString& target, const KURL & dest, bool overwrite, bool showProgressInfo )
00753 {
00754
00755 KIO_ARGS << target << dest << (Q_INT8) overwrite;
00756 return new SimpleJob(dest, CMD_SYMLINK, packedArgs, showProgressInfo);
00757 }
00758
00759 SimpleJob *KIO::special(const KURL& url, const QByteArray & data, bool showProgressInfo)
00760 {
00761
00762 return new SimpleJob(url, CMD_SPECIAL, data, showProgressInfo);
00763 }
00764
00765 SimpleJob *KIO::mount( bool ro, const char *fstype, const QString& dev, const QString& point, bool showProgressInfo )
00766 {
00767 KIO_ARGS << int(1) << Q_INT8( ro ? 1 : 0 )
00768 << QString::fromLatin1(fstype) << dev << point;
00769 SimpleJob *job = special( KURL("file:/"), packedArgs, showProgressInfo );
00770 if ( showProgressInfo )
00771 Observer::self()->mounting( job, dev, point );
00772 return job;
00773 }
00774
00775 SimpleJob *KIO::unmount( const QString& point, bool showProgressInfo )
00776 {
00777 KIO_ARGS << int(2) << point;
00778 SimpleJob *job = special( KURL("file:/"), packedArgs, showProgressInfo );
00779 if ( showProgressInfo )
00780 Observer::self()->unmounting( job, point );
00781 return job;
00782 }
00783
00784
00785
00787
00788 StatJob::StatJob( const KURL& url, int command,
00789 const QByteArray &packedArgs, bool showProgressInfo )
00790 : SimpleJob(url, command, packedArgs, showProgressInfo),
00791 m_bSource(true), m_details(2)
00792 {
00793 }
00794
00795 void StatJob::start(Slave *slave)
00796 {
00797 m_outgoingMetaData.replace( "statSide", m_bSource ? "source" : "dest" );
00798 m_outgoingMetaData.replace( "details", QString::number(m_details) );
00799
00800 connect( slave, SIGNAL( statEntry( const KIO::UDSEntry& ) ),
00801 SLOT( slotStatEntry( const KIO::UDSEntry & ) ) );
00802 connect( slave, SIGNAL( redirection(const KURL &) ),
00803 SLOT( slotRedirection(const KURL &) ) );
00804
00805 SimpleJob::start(slave);
00806 }
00807
00808 void StatJob::slotStatEntry( const KIO::UDSEntry & entry )
00809 {
00810
00811 m_statResult = entry;
00812 }
00813
00814
00815 void StatJob::slotRedirection( const KURL &url)
00816 {
00817 kdDebug(7007) << "StatJob::slotRedirection(" << url << ")" << endl;
00818 if (!kapp->authorizeURLAction("redirect", m_url, url))
00819 {
00820 kdWarning(7007) << "StatJob: Redirection from " << m_url << " to " << url << " REJECTED!" << endl;
00821 m_error = ERR_ACCESS_DENIED;
00822 m_errorText = url.prettyURL();
00823 return;
00824 }
00825 m_redirectionURL = url;
00826 if (m_url.hasUser() && !url.hasUser() && (m_url.host().lower() == url.host().lower()))
00827 m_redirectionURL.setUser(m_url.user());
00828
00829 emit redirection(this, m_redirectionURL);
00830 }
00831
00832 void StatJob::slotFinished()
00833 {
00834 if ( m_redirectionURL.isEmpty() || !m_redirectionURL.isValid())
00835 {
00836
00837 SimpleJob::slotFinished();
00838 } else {
00839
00840 if (queryMetaData("permanent-redirect")=="true")
00841 emit permanentRedirection(this, m_url, m_redirectionURL);
00842 m_url = m_redirectionURL;
00843 m_redirectionURL = KURL();
00844 m_packedArgs.truncate(0);
00845 QDataStream stream( m_packedArgs, IO_WriteOnly );
00846 stream << m_url;
00847
00848
00849 slaveDone();
00850 Scheduler::doJob(this);
00851 }
00852 }
00853
00854 void StatJob::slotMetaData( const KIO::MetaData &_metaData) {
00855 SimpleJob::slotMetaData(_metaData);
00856 storeSSLSessionFromJob(m_redirectionURL);
00857 }
00858
00859 StatJob *KIO::stat(const KURL& url, bool showProgressInfo)
00860 {
00861
00862 return stat( url, true, 2, showProgressInfo );
00863 }
00864
00865 StatJob *KIO::stat(const KURL& url, bool sideIsSource, short int details, bool showProgressInfo)
00866 {
00867 kdDebug(7007) << "stat " << url << endl;
00868 KIO_ARGS << url;
00869 StatJob * job = new StatJob(url, CMD_STAT, packedArgs, showProgressInfo );
00870 job->setSide( sideIsSource );
00871 job->setDetails( details );
00872 if ( showProgressInfo )
00873 Observer::self()->stating( job, url );
00874 return job;
00875 }
00876
00877 SimpleJob *KIO::http_update_cache( const KURL& url, bool no_cache, time_t expireDate)
00878 {
00879 assert( (url.protocol() == "http") || (url.protocol() == "https") );
00880
00881 KIO_ARGS << (int)2 << url << no_cache << expireDate;
00882 SimpleJob * job = new SimpleJob( url, CMD_SPECIAL, packedArgs, false );
00883 Scheduler::scheduleJob(job);
00884 return job;
00885 }
00886
00888
00889 TransferJob::TransferJob( const KURL& url, int command,
00890 const QByteArray &packedArgs,
00891 const QByteArray &_staticData,
00892 bool showProgressInfo)
00893 : SimpleJob(url, command, packedArgs, showProgressInfo), staticData( _staticData)
00894 {
00895 m_suspended = false;
00896 m_errorPage = false;
00897 m_subJob = 0L;
00898 if ( showProgressInfo )
00899 Observer::self()->slotTransferring( this, url );
00900 }
00901
00902
00903 void TransferJob::slotData( const QByteArray &_data)
00904 {
00905 if(m_redirectionURL.isEmpty() || !m_redirectionURL.isValid() || m_error)
00906 emit data( this, _data);
00907 }
00908
00909
00910 void TransferJob::slotRedirection( const KURL &url)
00911 {
00912 kdDebug(7007) << "TransferJob::slotRedirection(" << url << ")" << endl;
00913 if (!kapp->authorizeURLAction("redirect", m_url, url))
00914 {
00915 kdWarning(7007) << "TransferJob: Redirection from " << m_url << " to " << url << " REJECTED!" << endl;
00916 return;
00917 }
00918
00919
00920
00921
00922 if (m_redirectionList.contains(url) > 5)
00923 {
00924 kdDebug(7007) << "TransferJob::slotRedirection: CYCLIC REDIRECTION!" << endl;
00925 m_error = ERR_CYCLIC_LINK;
00926 m_errorText = m_url.prettyURL();
00927 }
00928 else
00929 {
00930 m_redirectionURL = url;
00931 if (m_url.hasUser() && !url.hasUser() && (m_url.host().lower() == url.host().lower()))
00932 m_redirectionURL.setUser(m_url.user());
00933 m_redirectionList.append(url);
00934 m_outgoingMetaData["ssl_was_in_use"] = m_incomingMetaData["ssl_in_use"];
00935
00936 emit redirection(this, m_redirectionURL);
00937 }
00938 }
00939
00940 void TransferJob::slotFinished()
00941 {
00942
00943 if (m_redirectionURL.isEmpty() || !m_redirectionURL.isValid())
00944 SimpleJob::slotFinished();
00945 else {
00946
00947 if (queryMetaData("permanent-redirect")=="true")
00948 emit permanentRedirection(this, m_url, m_redirectionURL);
00949
00950
00951
00952
00953 staticData.truncate(0);
00954 m_incomingMetaData.clear();
00955 if (queryMetaData("cache") != "reload")
00956 addMetaData("cache","refresh");
00957 m_suspended = false;
00958 m_url = m_redirectionURL;
00959 m_redirectionURL = KURL();
00960
00961 QString dummyStr;
00962 KURL dummyUrl;
00963 QDataStream istream( m_packedArgs, IO_ReadOnly );
00964 switch( m_command ) {
00965 case CMD_GET: {
00966 m_packedArgs.truncate(0);
00967 QDataStream stream( m_packedArgs, IO_WriteOnly );
00968 stream << m_url;
00969 break;
00970 }
00971 case CMD_PUT: {
00972 int permissions;
00973 Q_INT8 iOverwrite, iResume;
00974 istream >> dummyUrl >> iOverwrite >> iResume >> permissions;
00975 m_packedArgs.truncate(0);
00976 QDataStream stream( m_packedArgs, IO_WriteOnly );
00977 stream << m_url << iOverwrite << iResume << permissions;
00978 break;
00979 }
00980 case CMD_SPECIAL: {
00981 int specialcmd;
00982 istream >> specialcmd;
00983 if (specialcmd == 1)
00984 {
00985 addMetaData("cache","reload");
00986 m_packedArgs.truncate(0);
00987 QDataStream stream( m_packedArgs, IO_WriteOnly );
00988 stream << m_url;
00989 m_command = CMD_GET;
00990 }
00991 break;
00992 }
00993 }
00994
00995
00996 slaveDone();
00997 Scheduler::doJob(this);
00998 }
00999 }
01000
01001 void TransferJob::setAsyncDataEnabled(bool enabled)
01002 {
01003 if (enabled)
01004 extraFlags() |= EF_TransferJobAsync;
01005 else
01006 extraFlags() &= ~EF_TransferJobAsync;
01007 }
01008
01009 void TransferJob::sendAsyncData(const QByteArray &dataForSlave)
01010 {
01011 if (extraFlags() & EF_TransferJobNeedData)
01012 {
01013 m_slave->send( MSG_DATA, dataForSlave );
01014 if (extraFlags() & EF_TransferJobDataSent)
01015 {
01016 KIO::filesize_t size = getProcessedSize()+dataForSlave.size();
01017 setProcessedSize(size);
01018 emit processedSize( this, size );
01019 if ( size > m_totalSize ) {
01020 slotTotalSize(size);
01021 }
01022 emitPercent( size, m_totalSize );
01023 }
01024 }
01025
01026 extraFlags() &= ~EF_TransferJobNeedData;
01027 }
01028
01029 void TransferJob::setReportDataSent(bool enabled)
01030 {
01031 if (enabled)
01032 extraFlags() |= EF_TransferJobDataSent;
01033 else
01034 extraFlags() &= ~EF_TransferJobDataSent;
01035 }
01036
01037 bool TransferJob::reportDataSent()
01038 {
01039 return (extraFlags() & EF_TransferJobDataSent);
01040 }
01041
01042
01043
01044 void TransferJob::slotDataReq()
01045 {
01046 QByteArray dataForSlave;
01047
01048 extraFlags() |= EF_TransferJobNeedData;
01049
01050 if (!staticData.isEmpty())
01051 {
01052 dataForSlave = staticData;
01053 staticData = QByteArray();
01054 }
01055 else
01056 {
01057 emit dataReq( this, dataForSlave);
01058
01059 if (extraFlags() & EF_TransferJobAsync)
01060 return;
01061 }
01062
01063 static const size_t max_size = 14 * 1024 * 1024;
01064 if (dataForSlave.size() > max_size)
01065 {
01066 kdDebug(7007) << "send " << dataForSlave.size() / 1024 / 1024 << "MB of data in TransferJob::dataReq. This needs to be splitted, which requires a copy. Fix the application.\n";
01067 staticData.duplicate(dataForSlave.data() + max_size , dataForSlave.size() - max_size);
01068 dataForSlave.truncate(max_size);
01069 }
01070
01071 sendAsyncData(dataForSlave);
01072
01073 if (m_subJob)
01074 {
01075
01076 suspend();
01077 m_subJob->resume();
01078 }
01079 }
01080
01081 void TransferJob::slotMimetype( const QString& type )
01082 {
01083 m_mimetype = type;
01084 emit mimetype( this, m_mimetype);
01085 }
01086
01087
01088 void TransferJob::suspend()
01089 {
01090 m_suspended = true;
01091 if (m_slave)
01092 m_slave->suspend();
01093 }
01094
01095 void TransferJob::resume()
01096 {
01097 m_suspended = false;
01098 if (m_slave)
01099 m_slave->resume();
01100 }
01101
01102 void TransferJob::start(Slave *slave)
01103 {
01104 assert(slave);
01105 connect( slave, SIGNAL( data( const QByteArray & ) ),
01106 SLOT( slotData( const QByteArray & ) ) );
01107
01108 connect( slave, SIGNAL( dataReq() ),
01109 SLOT( slotDataReq() ) );
01110
01111 connect( slave, SIGNAL( redirection(const KURL &) ),
01112 SLOT( slotRedirection(const KURL &) ) );
01113
01114 connect( slave, SIGNAL(mimeType( const QString& ) ),
01115 SLOT( slotMimetype( const QString& ) ) );
01116
01117 connect( slave, SIGNAL(errorPage() ),
01118 SLOT( slotErrorPage() ) );
01119
01120 connect( slave, SIGNAL( needSubURLData() ),
01121 SLOT( slotNeedSubURLData() ) );
01122
01123 connect( slave, SIGNAL(canResume( KIO::filesize_t ) ),
01124 SLOT( slotCanResume( KIO::filesize_t ) ) );
01125
01126 if (slave->suspended())
01127 {
01128 m_mimetype = "unknown";
01129
01130 slave->resume();
01131 }
01132
01133 SimpleJob::start(slave);
01134 if (m_suspended)
01135 slave->suspend();
01136 }
01137
01138 void TransferJob::slotNeedSubURLData()
01139 {
01140
01141 m_subJob = KIO::get( m_subUrl, false, false);
01142 suspend();
01143 connect(m_subJob, SIGNAL( data(KIO::Job*,const QByteArray &)),
01144 SLOT( slotSubURLData(KIO::Job*,const QByteArray &)));
01145 addSubjob(m_subJob);
01146 }
01147
01148 void TransferJob::slotSubURLData(KIO::Job*, const QByteArray &data)
01149 {
01150
01151 staticData = data;
01152 m_subJob->suspend();
01153 resume();
01154 }
01155
01156 void TransferJob::slotMetaData( const KIO::MetaData &_metaData) {
01157 SimpleJob::slotMetaData(_metaData);
01158 storeSSLSessionFromJob(m_redirectionURL);
01159 }
01160
01161 void TransferJob::slotErrorPage()
01162 {
01163 m_errorPage = true;
01164 }
01165
01166 void TransferJob::slotCanResume( KIO::filesize_t offset )
01167 {
01168 emit canResume(this, offset);
01169 }
01170
01171 void TransferJob::slotResult( KIO::Job *job)
01172 {
01173
01174 assert(job == m_subJob);
01175
01176 if ( job->error() )
01177 {
01178 m_error = job->error();
01179 m_errorText = job->errorText();
01180
01181 emitResult();
01182 return;
01183 }
01184
01185 if (job == m_subJob)
01186 {
01187 m_subJob = 0;
01188 resume();
01189 }
01190 removeSubjob( job, false, false );
01191 }
01192
01193 TransferJob *KIO::get( const KURL& url, bool reload, bool showProgressInfo )
01194 {
01195
01196 KIO_ARGS << url;
01197 TransferJob * job = new TransferJob( url, CMD_GET, packedArgs, QByteArray(), showProgressInfo );
01198 if (reload)
01199 job->addMetaData("cache", "reload");
01200 return job;
01201 }
01202
01203 class PostErrorJob : public TransferJob
01204 {
01205 public:
01206
01207 PostErrorJob(int _error, const QString& url, const QByteArray &packedArgs, const QByteArray &postData, bool showProgressInfo)
01208 : TransferJob(KURL(), CMD_SPECIAL, packedArgs, postData, showProgressInfo)
01209 {
01210 m_error = _error;
01211 m_errorText = url;
01212 }
01213
01214 };
01215
01216 TransferJob *KIO::http_post( const KURL& url, const QByteArray &postData, bool showProgressInfo )
01217 {
01218 int _error = 0;
01219
01220
01221 static const int bad_ports[] = {
01222 1,
01223 7,
01224 9,
01225 11,
01226 13,
01227 15,
01228 17,
01229 19,
01230 20,
01231 21,
01232 22,
01233 23,
01234 25,
01235 37,
01236 42,
01237 43,
01238 53,
01239 77,
01240 79,
01241 87,
01242 95,
01243 101,
01244 102,
01245 103,
01246 104,
01247 109,
01248 110,
01249 111,
01250 113,
01251 115,
01252 117,
01253 119,
01254 123,
01255 135,
01256 139,
01257 143,
01258 179,
01259 389,
01260 512,
01261 513,
01262 514,
01263 515,
01264 526,
01265 530,
01266 531,
01267 532,
01268 540,
01269 556,
01270 587,
01271 601,
01272 989,
01273 990,
01274 992,
01275 993,
01276 995,
01277 1080,
01278 2049,
01279 4045,
01280 6000,
01281 6667,
01282 0};
01283 for (int cnt=0; bad_ports[cnt]; ++cnt)
01284 if (url.port() == bad_ports[cnt])
01285 {
01286 _error = KIO::ERR_POST_DENIED;
01287 break;
01288 }
01289
01290 if( _error )
01291 {
01292 static bool override_loaded = false;
01293 static QValueList< int >* overriden_ports = NULL;
01294 if( !override_loaded )
01295 {
01296 KConfig cfg( "kio_httprc", true );
01297 overriden_ports = new QValueList< int >;
01298 *overriden_ports = cfg.readIntListEntry( "OverriddenPorts" );
01299 override_loaded = true;
01300 }
01301 for( QValueList< int >::ConstIterator it = overriden_ports->begin();
01302 it != overriden_ports->end();
01303 ++it )
01304 if( overriden_ports->contains( url.port()))
01305 _error = 0;
01306 }
01307
01308
01309 if ((url.protocol() != "http") && (url.protocol() != "https" ))
01310 _error = KIO::ERR_POST_DENIED;
01311
01312 bool redirection = false;
01313 KURL _url(url);
01314 if (_url.path().isEmpty())
01315 {
01316 redirection = true;
01317 _url.setPath("/");
01318 }
01319
01320 if (!_error && !kapp->authorizeURLAction("open", KURL(), _url))
01321 _error = KIO::ERR_ACCESS_DENIED;
01322
01323
01324 if (_error)
01325 {
01326 KIO_ARGS << (int)1 << url;
01327 TransferJob * job = new PostErrorJob(_error, url.prettyURL(), packedArgs, postData, showProgressInfo);
01328 return job;
01329 }
01330
01331
01332 KIO_ARGS << (int)1 << _url;
01333 TransferJob * job = new TransferJob( _url, CMD_SPECIAL,
01334 packedArgs, postData, showProgressInfo );
01335
01336 if (redirection)
01337 QTimer::singleShot(0, job, SLOT(slotPostRedirection()) );
01338
01339 return job;
01340 }
01341
01342
01343
01344
01345 void TransferJob::slotPostRedirection()
01346 {
01347 kdDebug(7007) << "TransferJob::slotPostRedirection(" << m_url << ")" << endl;
01348
01349 emit redirection(this, m_url);
01350 }
01351
01352
01353 TransferJob *KIO::put( const KURL& url, int permissions,
01354 bool overwrite, bool resume, bool showProgressInfo )
01355 {
01356 KIO_ARGS << url << Q_INT8( overwrite ? 1 : 0 ) << Q_INT8( resume ? 1 : 0 ) << permissions;
01357 TransferJob * job = new TransferJob( url, CMD_PUT, packedArgs, QByteArray(), showProgressInfo );
01358 return job;
01359 }
01360
01362
01363 StoredTransferJob::StoredTransferJob(const KURL& url, int command,
01364 const QByteArray &packedArgs,
01365 const QByteArray &_staticData,
01366 bool showProgressInfo)
01367 : TransferJob( url, command, packedArgs, _staticData, showProgressInfo ),
01368 m_uploadOffset( 0 )
01369 {
01370 connect( this, SIGNAL( data( KIO::Job *, const QByteArray & ) ),
01371 SLOT( slotStoredData( KIO::Job *, const QByteArray & ) ) );
01372 connect( this, SIGNAL( dataReq( KIO::Job *, QByteArray & ) ),
01373 SLOT( slotStoredDataReq( KIO::Job *, QByteArray & ) ) );
01374 }
01375
01376 void StoredTransferJob::setData( const QByteArray& arr )
01377 {
01378 Q_ASSERT( m_data.isNull() );
01379 Q_ASSERT( m_uploadOffset == 0 );
01380 m_data = arr;
01381 }
01382
01383 void StoredTransferJob::slotStoredData( KIO::Job *, const QByteArray &data )
01384 {
01385
01386 if ( data.size() == 0 )
01387 return;
01388 unsigned int oldSize = m_data.size();
01389 m_data.resize( oldSize + data.size(), QGArray::SpeedOptim );
01390 memcpy( m_data.data() + oldSize, data.data(), data.size() );
01391 }
01392
01393 void StoredTransferJob::slotStoredDataReq( KIO::Job *, QByteArray &data )
01394 {
01395
01396
01397 const int MAX_CHUNK_SIZE = 64*1024;
01398 int remainingBytes = m_data.size() - m_uploadOffset;
01399 if( remainingBytes > MAX_CHUNK_SIZE ) {
01400
01401 data.duplicate( m_data.data() + m_uploadOffset, MAX_CHUNK_SIZE );
01402 m_uploadOffset += MAX_CHUNK_SIZE;
01403
01404
01405 } else {
01406
01407 data.duplicate( m_data.data() + m_uploadOffset, remainingBytes );
01408 m_data = QByteArray();
01409 m_uploadOffset = 0;
01410
01411 }
01412 }
01413
01414 StoredTransferJob *KIO::storedGet( const KURL& url, bool reload, bool showProgressInfo )
01415 {
01416
01417 KIO_ARGS << url;
01418 StoredTransferJob * job = new StoredTransferJob( url, CMD_GET, packedArgs, QByteArray(), showProgressInfo );
01419 if (reload)
01420 job->addMetaData("cache", "reload");
01421 return job;
01422 }
01423
01424 StoredTransferJob *KIO::storedPut( const QByteArray& arr, const KURL& url, int permissions,
01425 bool overwrite, bool resume, bool showProgressInfo )
01426 {
01427 KIO_ARGS << url << Q_INT8( overwrite ? 1 : 0 ) << Q_INT8( resume ? 1 : 0 ) << permissions;
01428 StoredTransferJob * job = new StoredTransferJob( url, CMD_PUT, packedArgs, QByteArray(), showProgressInfo );
01429 job->setData( arr );
01430 return job;
01431 }
01432
01434
01435 MimetypeJob::MimetypeJob( const KURL& url, int command,
01436 const QByteArray &packedArgs, bool showProgressInfo )
01437 : TransferJob(url, command, packedArgs, QByteArray(), showProgressInfo)
01438 {
01439 }
01440
01441 void MimetypeJob::start(Slave *slave)
01442 {
01443 TransferJob::start(slave);
01444 }
01445
01446
01447 void MimetypeJob::slotFinished( )
01448 {
01449
01450 if ( m_error == KIO::ERR_IS_DIRECTORY )
01451 {
01452
01453
01454
01455 kdDebug(7007) << "It is in fact a directory!" << endl;
01456 m_mimetype = QString::fromLatin1("inode/directory");
01457 emit TransferJob::mimetype( this, m_mimetype );
01458 m_error = 0;
01459 }
01460 if ( m_redirectionURL.isEmpty() || !m_redirectionURL.isValid() || m_error )
01461 {
01462
01463 TransferJob::slotFinished();
01464 } else {
01465
01466 if (queryMetaData("permanent-redirect")=="true")
01467 emit permanentRedirection(this, m_url, m_redirectionURL);
01468 staticData.truncate(0);
01469 m_suspended = false;
01470 m_url = m_redirectionURL;
01471 m_redirectionURL = KURL();
01472 m_packedArgs.truncate(0);
01473 QDataStream stream( m_packedArgs, IO_WriteOnly );
01474 stream << m_url;
01475
01476
01477 slaveDone();
01478 Scheduler::doJob(this);
01479 }
01480 }
01481
01482 MimetypeJob *KIO::mimetype(const KURL& url, bool showProgressInfo )
01483 {
01484 KIO_ARGS << url;
01485 MimetypeJob * job = new MimetypeJob(url, CMD_MIMETYPE, packedArgs, showProgressInfo);
01486 if ( showProgressInfo )
01487 Observer::self()->stating( job, url );
01488 return job;
01489 }
01490
01492
01493 DirectCopyJob::DirectCopyJob( const KURL& url, int command,
01494 const QByteArray &packedArgs, bool showProgressInfo )
01495 : SimpleJob(url, command, packedArgs, showProgressInfo)
01496 {
01497 }
01498
01499 void DirectCopyJob::start( Slave* slave )
01500 {
01501 connect( slave, SIGNAL(canResume( KIO::filesize_t ) ),
01502 SLOT( slotCanResume( KIO::filesize_t ) ) );
01503 SimpleJob::start(slave);
01504 }
01505
01506 void DirectCopyJob::slotCanResume( KIO::filesize_t offset )
01507 {
01508 emit canResume(this, offset);
01509 }
01510
01512
01513
01514 class FileCopyJob::FileCopyJobPrivate
01515 {
01516 public:
01517 KIO::filesize_t m_sourceSize;
01518 time_t m_modificationTime;
01519 SimpleJob *m_delJob;
01520 };
01521
01522
01523
01524
01525
01526
01527
01528
01529 FileCopyJob::FileCopyJob( const KURL& src, const KURL& dest, int permissions,
01530 bool move, bool overwrite, bool resume, bool showProgressInfo)
01531 : Job(showProgressInfo), m_src(src), m_dest(dest),
01532 m_permissions(permissions), m_move(move), m_overwrite(overwrite), m_resume(resume),
01533 m_totalSize(0)
01534 {
01535 if (showProgressInfo && !move)
01536 Observer::self()->slotCopying( this, src, dest );
01537 else if (showProgressInfo && move)
01538 Observer::self()->slotMoving( this, src, dest );
01539
01540
01541 m_moveJob = 0;
01542 m_copyJob = 0;
01543 m_getJob = 0;
01544 m_putJob = 0;
01545 d = new FileCopyJobPrivate;
01546 d->m_delJob = 0;
01547 d->m_sourceSize = (KIO::filesize_t) -1;
01548 d->m_modificationTime = static_cast<time_t>( -1 );
01549 QTimer::singleShot(0, this, SLOT(slotStart()));
01550 }
01551
01552 void FileCopyJob::slotStart()
01553 {
01554 if ( m_move )
01555 {
01556
01557 if ((m_src.protocol() == m_dest.protocol()) &&
01558 (m_src.host() == m_dest.host()) &&
01559 (m_src.port() == m_dest.port()) &&
01560 (m_src.user() == m_dest.user()) &&
01561 (m_src.pass() == m_dest.pass()) &&
01562 !m_src.hasSubURL() && !m_dest.hasSubURL())
01563 {
01564 startRenameJob(m_src);
01565 return;
01566 }
01567 else if (m_src.isLocalFile() && KProtocolInfo::canRenameFromFile(m_dest))
01568 {
01569 startRenameJob(m_dest);
01570 return;
01571 }
01572 else if (m_dest.isLocalFile() && KProtocolInfo::canRenameToFile(m_src))
01573 {
01574 startRenameJob(m_src);
01575 return;
01576 }
01577
01578 }
01579 startBestCopyMethod();
01580 }
01581
01582 void FileCopyJob::startBestCopyMethod()
01583 {
01584 if ((m_src.protocol() == m_dest.protocol()) &&
01585 (m_src.host() == m_dest.host()) &&
01586 (m_src.port() == m_dest.port()) &&
01587 (m_src.user() == m_dest.user()) &&
01588 (m_src.pass() == m_dest.pass()) &&
01589 !m_src.hasSubURL() && !m_dest.hasSubURL())
01590 {
01591 startCopyJob();
01592 }
01593 else if (m_src.isLocalFile() && KProtocolInfo::canCopyFromFile(m_dest))
01594 {
01595 startCopyJob(m_dest);
01596 }
01597 else if (m_dest.isLocalFile() && KProtocolInfo::canCopyToFile(m_src))
01598 {
01599 startCopyJob(m_src);
01600 }
01601 else
01602 {
01603 startDataPump();
01604 }
01605 }
01606
01607 FileCopyJob::~FileCopyJob()
01608 {
01609 delete d;
01610 }
01611
01612 void FileCopyJob::setSourceSize( off_t size )
01613 {
01614 d->m_sourceSize = size;
01615 if (size != (off_t) -1)
01616 m_totalSize = size;
01617 }
01618
01619 void FileCopyJob::setSourceSize64( KIO::filesize_t size )
01620 {
01621 d->m_sourceSize = size;
01622 if (size != (KIO::filesize_t) -1)
01623 m_totalSize = size;
01624 }
01625
01626 void FileCopyJob::setModificationTime( time_t mtime )
01627 {
01628 d->m_modificationTime = mtime;
01629 }
01630
01631 void FileCopyJob::startCopyJob()
01632 {
01633 startCopyJob(m_src);
01634 }
01635
01636 void FileCopyJob::startCopyJob(const KURL &slave_url)
01637 {
01638
01639 KIO_ARGS << m_src << m_dest << m_permissions << (Q_INT8) m_overwrite;
01640 m_copyJob = new DirectCopyJob(slave_url, CMD_COPY, packedArgs, false);
01641 addSubjob( m_copyJob );
01642 connectSubjob( m_copyJob );
01643 connect( m_copyJob, SIGNAL(canResume(KIO::Job *, KIO::filesize_t)),
01644 SLOT( slotCanResume(KIO::Job *, KIO::filesize_t)));
01645 }
01646
01647 void FileCopyJob::startRenameJob(const KURL &slave_url)
01648 {
01649 KIO_ARGS << m_src << m_dest << (Q_INT8) m_overwrite;
01650 m_moveJob = new SimpleJob(slave_url, CMD_RENAME, packedArgs, false);
01651 addSubjob( m_moveJob );
01652 connectSubjob( m_moveJob );
01653 }
01654
01655 void FileCopyJob::connectSubjob( SimpleJob * job )
01656 {
01657 connect( job, SIGNAL(totalSize( KIO::Job*, KIO::filesize_t )),
01658 this, SLOT( slotTotalSize(KIO::Job*, KIO::filesize_t)) );
01659
01660 connect( job, SIGNAL(processedSize( KIO::Job*, KIO::filesize_t )),
01661 this, SLOT( slotProcessedSize(KIO::Job*, KIO::filesize_t)) );
01662
01663 connect( job, SIGNAL(percent( KIO::Job*, unsigned long )),
01664 this, SLOT( slotPercent(KIO::Job*, unsigned long)) );
01665
01666 }
01667
01668 void FileCopyJob::slotProcessedSize( KIO::Job *, KIO::filesize_t size )
01669 {
01670 setProcessedSize(size);
01671 emit processedSize( this, size );
01672 if ( size > m_totalSize ) {
01673 slotTotalSize( this, size );
01674 }
01675 emitPercent( size, m_totalSize );
01676 }
01677
01678 void FileCopyJob::slotTotalSize( KIO::Job*, KIO::filesize_t size )
01679 {
01680 if (size > m_totalSize)
01681 {
01682 m_totalSize = size;
01683 emit totalSize( this, m_totalSize );
01684 }
01685 }
01686
01687 void FileCopyJob::slotPercent( KIO::Job*, unsigned long pct )
01688 {
01689 if ( pct > m_percent )
01690 {
01691 m_percent = pct;
01692 emit percent( this, m_percent );
01693 }
01694 }
01695
01696 void FileCopyJob::startDataPump()
01697 {
01698
01699
01700 m_canResume = false;
01701 m_resumeAnswerSent = false;
01702 m_getJob = 0L;
01703 m_putJob = put( m_dest, m_permissions, m_overwrite, m_resume, false );
01704 if ( d->m_modificationTime != static_cast<time_t>( -1 ) ) {
01705 QDateTime dt; dt.setTime_t( d->m_modificationTime );
01706 m_putJob->addMetaData( "modified", dt.toString( Qt::ISODate ) );
01707 }
01708
01709
01710
01711
01712 connect( m_putJob, SIGNAL(canResume(KIO::Job *, KIO::filesize_t)),
01713 SLOT( slotCanResume(KIO::Job *, KIO::filesize_t)));
01714 connect( m_putJob, SIGNAL(dataReq(KIO::Job *, QByteArray&)),
01715 SLOT( slotDataReq(KIO::Job *, QByteArray&)));
01716 addSubjob( m_putJob );
01717 }
01718
01719 void FileCopyJob::slotCanResume( KIO::Job* job, KIO::filesize_t offset )
01720 {
01721 if ( job == m_putJob || job == m_copyJob )
01722 {
01723
01724 if (offset)
01725 {
01726 RenameDlg_Result res = R_RESUME;
01727
01728 if (!KProtocolManager::autoResume() && !m_overwrite)
01729 {
01730 QString newPath;
01731 KIO::Job* job = ( !m_progressId && parentJob() ) ? parentJob() : this;
01732
01733 res = Observer::self()->open_RenameDlg(
01734 job, i18n("File Already Exists"),
01735 m_src.url(),
01736 m_dest.url(),
01737 (RenameDlg_Mode) (M_OVERWRITE | M_RESUME | M_NORENAME), newPath,
01738 d->m_sourceSize, offset );
01739 }
01740
01741 if ( res == R_OVERWRITE || m_overwrite )
01742 offset = 0;
01743 else if ( res == R_CANCEL )
01744 {
01745 if ( job == m_putJob )
01746 m_putJob->kill(true);
01747 else
01748 m_copyJob->kill(true);
01749 m_error = ERR_USER_CANCELED;
01750 emitResult();
01751 return;
01752 }
01753 }
01754 else
01755 m_resumeAnswerSent = true;
01756
01757 if ( job == m_putJob )
01758 {
01759 m_getJob = get( m_src, false, false );
01760
01761 m_getJob->addMetaData( "errorPage", "false" );
01762 m_getJob->addMetaData( "AllowCompressedPage", "false" );
01763
01764 if ( d->m_sourceSize != (KIO::filesize_t)-1 )
01765 m_getJob->slotTotalSize( d->m_sourceSize );
01766 if (offset)
01767 {
01768
01769
01770
01771 m_getJob->addMetaData( "resume", KIO::number(offset) );
01772
01773
01774 connect( m_getJob, SIGNAL(canResume(KIO::Job *, KIO::filesize_t)),
01775 SLOT( slotCanResume(KIO::Job *, KIO::filesize_t)));
01776 }
01777 m_putJob->slave()->setOffset( offset );
01778
01779 m_putJob->suspend();
01780 addSubjob( m_getJob );
01781 connectSubjob( m_getJob );
01782 m_getJob->resume();
01783
01784 connect( m_getJob, SIGNAL(data(KIO::Job *, const QByteArray&)),
01785 SLOT( slotData(KIO::Job *, const QByteArray&)));
01786 }
01787 else
01788 {
01789 m_copyJob->slave()->sendResumeAnswer( offset != 0 );
01790 }
01791 }
01792 else if ( job == m_getJob )
01793 {
01794
01795 m_canResume = true;
01796
01797
01798 m_getJob->slave()->setOffset( m_putJob->slave()->offset() );
01799 }
01800 else
01801 kdWarning(7007) << "FileCopyJob::slotCanResume from unknown job=" << job
01802 << " m_getJob=" << m_getJob << " m_putJob=" << m_putJob << endl;
01803 }
01804
01805 void FileCopyJob::slotData( KIO::Job * , const QByteArray &data)
01806 {
01807
01808
01809 assert(m_putJob);
01810 if (!m_putJob) return;
01811 m_getJob->suspend();
01812 m_putJob->resume();
01813 m_buffer = data;
01814
01815
01816
01817 if (!m_resumeAnswerSent)
01818 {
01819 m_resumeAnswerSent = true;
01820
01821 m_putJob->slave()->sendResumeAnswer( m_canResume );
01822 }
01823 }
01824
01825 void FileCopyJob::slotDataReq( KIO::Job * , QByteArray &data)
01826 {
01827
01828 if (!m_resumeAnswerSent && !m_getJob)
01829 {
01830
01831 m_error = ERR_INTERNAL;
01832 m_errorText = "'Put' job didn't send canResume or 'Get' job didn't send data!";
01833 m_putJob->kill(true);
01834 emitResult();
01835 return;
01836 }
01837 if (m_getJob)
01838 {
01839 m_getJob->resume();
01840 m_putJob->suspend();
01841 }
01842 data = m_buffer;
01843 m_buffer = QByteArray();
01844 }
01845
01846 void FileCopyJob::slotResult( KIO::Job *job)
01847 {
01848
01849
01850 if ( job->error() )
01851 {
01852 if ((job == m_moveJob) && (job->error() == ERR_UNSUPPORTED_ACTION))
01853 {
01854 m_moveJob = 0;
01855 startBestCopyMethod();
01856 removeSubjob(job);
01857 return;
01858 }
01859 else if ((job == m_copyJob) && (job->error() == ERR_UNSUPPORTED_ACTION))
01860 {
01861 m_copyJob = 0;
01862 startDataPump();
01863 removeSubjob(job);
01864 return;
01865 }
01866 else if (job == m_getJob)
01867 {
01868 m_getJob = 0L;
01869 if (m_putJob)
01870 m_putJob->kill(true);
01871 }
01872 else if (job == m_putJob)
01873 {
01874 m_putJob = 0L;
01875 if (m_getJob)
01876 m_getJob->kill(true);
01877 }
01878 m_error = job->error();
01879 m_errorText = job->errorText();
01880 emitResult();
01881 return;
01882 }
01883
01884 if (job == m_moveJob)
01885 {
01886 m_moveJob = 0;
01887 }
01888
01889 if (job == m_copyJob)
01890 {
01891 m_copyJob = 0;
01892 if (m_move)
01893 {
01894 d->m_delJob = file_delete( m_src, false );
01895 addSubjob(d->m_delJob);
01896 }
01897 }
01898
01899 if (job == m_getJob)
01900 {
01901 m_getJob = 0;
01902 if (m_putJob)
01903 m_putJob->resume();
01904 }
01905
01906 if (job == m_putJob)
01907 {
01908
01909 m_putJob = 0;
01910 if (m_getJob)
01911 {
01912 kdWarning(7007) << "WARNING ! Get still going on..." << endl;
01913 m_getJob->resume();
01914 }
01915 if (m_move)
01916 {
01917 d->m_delJob = file_delete( m_src, false );
01918 addSubjob(d->m_delJob);
01919 }
01920 }
01921
01922 if (job == d->m_delJob)
01923 {
01924 d->m_delJob = 0;
01925 }
01926 removeSubjob(job);
01927 }
01928
01929 FileCopyJob *KIO::file_copy( const KURL& src, const KURL& dest, int permissions,
01930 bool overwrite, bool resume, bool showProgressInfo)
01931 {
01932 return new FileCopyJob( src, dest, permissions, false, overwrite, resume, showProgressInfo );
01933 }
01934
01935 FileCopyJob *KIO::file_move( const KURL& src, const KURL& dest, int permissions,
01936 bool overwrite, bool resume, bool showProgressInfo)
01937 {
01938 return new FileCopyJob( src, dest, permissions, true, overwrite, resume, showProgressInfo );
01939 }
01940
01941 SimpleJob *KIO::file_delete( const KURL& src, bool showProgressInfo)
01942 {
01943 KIO_ARGS << src << Q_INT8(true);
01944 return new SimpleJob(src, CMD_DEL, packedArgs, showProgressInfo );
01945 }
01946
01948
01949
01950 ListJob::ListJob(const KURL& u, bool showProgressInfo, bool _recursive, QString _prefix, bool _includeHidden) :
01951 SimpleJob(u, CMD_LISTDIR, QByteArray(), showProgressInfo),
01952 recursive(_recursive), includeHidden(_includeHidden), prefix(_prefix), m_processedEntries(0)
01953 {
01954
01955
01956 QDataStream stream( m_packedArgs, IO_WriteOnly );
01957 stream << u;
01958 }
01959
01960 void ListJob::slotListEntries( const KIO::UDSEntryList& list )
01961 {
01962
01963 m_processedEntries += list.count();
01964 slotProcessedSize( m_processedEntries );
01965
01966 if (recursive) {
01967 UDSEntryListConstIterator it = list.begin();
01968 UDSEntryListConstIterator end = list.end();
01969
01970 for (; it != end; ++it) {
01971 bool isDir = false;
01972 bool isLink = false;
01973 KURL itemURL;
01974
01975 UDSEntry::ConstIterator it2 = (*it).begin();
01976 UDSEntry::ConstIterator end2 = (*it).end();
01977 for( ; it2 != end2; it2++ ) {
01978 switch( (*it2).m_uds ) {
01979 case UDS_FILE_TYPE:
01980 isDir = S_ISDIR((*it2).m_long);
01981 break;
01982 case UDS_NAME:
01983 if( itemURL.isEmpty() ) {
01984 itemURL = url();
01985 itemURL.addPath( (*it2).m_str );
01986 }
01987 break;
01988 case UDS_URL:
01989 itemURL = (*it2).m_str;
01990 break;
01991 case UDS_LINK_DEST:
01992
01993 isLink = !(*it2).m_str.isEmpty();
01994 break;
01995 default:
01996 break;
01997 }
01998 }
01999 if (isDir && !isLink) {
02000 const QString filename = itemURL.fileName();
02001
02002 if (filename != ".." && filename != "." && (includeHidden || filename[0] != '.')) {
02003 ListJob *job = new ListJob(itemURL,
02004 false ,
02005 true ,
02006 prefix + filename + "/",
02007 includeHidden);
02008 Scheduler::scheduleJob(job);
02009 connect(job, SIGNAL(entries( KIO::Job *,
02010 const KIO::UDSEntryList& )),
02011 SLOT( gotEntries( KIO::Job*,
02012 const KIO::UDSEntryList& )));
02013 addSubjob(job);
02014 }
02015 }
02016 }
02017 }
02018
02019
02020
02021
02022 if (prefix.isNull() && includeHidden) {
02023 emit entries(this, list);
02024 } else {
02025
02026 UDSEntryList newlist;
02027
02028 UDSEntryListConstIterator it = list.begin();
02029 UDSEntryListConstIterator end = list.end();
02030 for (; it != end; ++it) {
02031
02032 UDSEntry newone = *it;
02033 UDSEntry::Iterator it2 = newone.begin();
02034 QString filename;
02035 for( ; it2 != newone.end(); it2++ ) {
02036 if ((*it2).m_uds == UDS_NAME) {
02037 filename = (*it2).m_str;
02038 (*it2).m_str = prefix + filename;
02039 }
02040 }
02041
02042
02043 if ( (prefix.isNull() || (filename != ".." && filename != ".") )
02044 && (includeHidden || (filename[0] != '.') ) )
02045 newlist.append(newone);
02046 }
02047
02048 emit entries(this, newlist);
02049 }
02050 }
02051
02052 void ListJob::gotEntries(KIO::Job *, const KIO::UDSEntryList& list )
02053 {
02054
02055 emit entries(this, list);
02056 }
02057
02058 void ListJob::slotResult( KIO::Job * job )
02059 {
02060
02061
02062 removeSubjob( job );
02063 }
02064
02065 void ListJob::slotRedirection( const KURL & url )
02066 {
02067 if (!kapp->authorizeURLAction("redirect", m_url, url))
02068 {
02069 kdWarning(7007) << "ListJob: Redirection from " << m_url << " to " << url << " REJECTED!" << endl;
02070 return;
02071 }
02072 m_redirectionURL = url;
02073 if (m_url.hasUser() && !url.hasUser() && (m_url.host().lower() == url.host().lower()))
02074 m_redirectionURL.setUser(m_url.user());
02075 emit redirection( this, m_redirectionURL );
02076 }
02077
02078 void ListJob::slotFinished()
02079 {
02080
02081 if ( m_error == KIO::ERR_IS_FILE && m_url.isLocalFile() ) {
02082 KMimeType::Ptr ptr = KMimeType::findByURL( m_url, 0, true, true );
02083 if ( ptr ) {
02084 QString proto = ptr->property("X-KDE-LocalProtocol").toString();
02085 if ( !proto.isEmpty() ) {
02086 m_redirectionURL = m_url;
02087 m_redirectionURL.setProtocol( proto );
02088 m_error = 0;
02089 emit redirection(this,m_redirectionURL);
02090 }
02091 }
02092 }
02093 if ( m_redirectionURL.isEmpty() || !m_redirectionURL.isValid() || m_error ) {
02094
02095 SimpleJob::slotFinished();
02096 } else {
02097
02098
02099 if (queryMetaData("permanent-redirect")=="true")
02100 emit permanentRedirection(this, m_url, m_redirectionURL);
02101 m_url = m_redirectionURL;
02102 m_redirectionURL = KURL();
02103 m_packedArgs.truncate(0);
02104 QDataStream stream( m_packedArgs, IO_WriteOnly );
02105 stream << m_url;
02106
02107
02108 slaveDone();
02109 Scheduler::doJob(this);
02110 }
02111 }
02112
02113 void ListJob::slotMetaData( const KIO::MetaData &_metaData) {
02114 SimpleJob::slotMetaData(_metaData);
02115 storeSSLSessionFromJob(m_redirectionURL);
02116 }
02117
02118 ListJob *KIO::listDir( const KURL& url, bool showProgressInfo, bool includeHidden )
02119 {
02120 ListJob * job = new ListJob(url, showProgressInfo,false,QString::null,includeHidden);
02121 return job;
02122 }
02123
02124 ListJob *KIO::listRecursive( const KURL& url, bool showProgressInfo, bool includeHidden )
02125 {
02126 ListJob * job = new ListJob(url, showProgressInfo, true,QString::null,includeHidden);
02127 return job;
02128 }
02129
02130 void ListJob::setUnrestricted(bool unrestricted)
02131 {
02132 if (unrestricted)
02133 extraFlags() |= EF_ListJobUnrestricted;
02134 else
02135 extraFlags() &= ~EF_ListJobUnrestricted;
02136 }
02137
02138 void ListJob::start(Slave *slave)
02139 {
02140 if (kapp && !kapp->authorizeURLAction("list", m_url, m_url) && !(extraFlags() & EF_ListJobUnrestricted))
02141 {
02142 m_error = ERR_ACCESS_DENIED;
02143 m_errorText = m_url.url();
02144 QTimer::singleShot(0, this, SLOT(slotFinished()) );
02145 return;
02146 }
02147 connect( slave, SIGNAL( listEntries( const KIO::UDSEntryList& )),
02148 SLOT( slotListEntries( const KIO::UDSEntryList& )));
02149 connect( slave, SIGNAL( totalSize( KIO::filesize_t ) ),
02150 SLOT( slotTotalSize( KIO::filesize_t ) ) );
02151 connect( slave, SIGNAL( redirection(const KURL &) ),
02152 SLOT( slotRedirection(const KURL &) ) );
02153
02154 SimpleJob::start(slave);
02155 }
02156
02157 class CopyJob::CopyJobPrivate
02158 {
02159 public:
02160 CopyJobPrivate() {
02161 m_defaultPermissions = false;
02162 m_bURLDirty = false;
02163 }
02164
02165
02166
02167
02168 KURL m_globalDest;
02169
02170 CopyJob::DestinationState m_globalDestinationState;
02171
02172 bool m_defaultPermissions;
02173
02174 bool m_bURLDirty;
02175
02176
02177 QValueList<CopyInfo> m_directoriesCopied;
02178 };
02179
02180 CopyJob::CopyJob( const KURL::List& src, const KURL& dest, CopyMode mode, bool asMethod, bool showProgressInfo )
02181 : Job(showProgressInfo), m_mode(mode), m_asMethod(asMethod),
02182 destinationState(DEST_NOT_STATED), state(STATE_STATING),
02183 m_totalSize(0), m_processedSize(0), m_fileProcessedSize(0),
02184 m_processedFiles(0), m_processedDirs(0),
02185 m_srcList(src), m_currentStatSrc(m_srcList.begin()),
02186 m_bCurrentOperationIsLink(false), m_bSingleFileCopy(false), m_bOnlyRenames(mode==Move),
02187 m_dest(dest), m_bAutoSkip( false ), m_bOverwriteAll( false ),
02188 m_conflictError(0), m_reportTimer(0)
02189 {
02190 d = new CopyJobPrivate;
02191 d->m_globalDest = dest;
02192 d->m_globalDestinationState = destinationState;
02193
02194 if ( showProgressInfo ) {
02195 connect( this, SIGNAL( totalFiles( KIO::Job*, unsigned long ) ),
02196 Observer::self(), SLOT( slotTotalFiles( KIO::Job*, unsigned long ) ) );
02197
02198 connect( this, SIGNAL( totalDirs( KIO::Job*, unsigned long ) ),
02199 Observer::self(), SLOT( slotTotalDirs( KIO::Job*, unsigned long ) ) );
02200 }
02201 QTimer::singleShot(0, this, SLOT(slotStart()));
02216 }
02217
02218 CopyJob::~CopyJob()
02219 {
02220 delete d;
02221 }
02222
02223 void CopyJob::slotStart()
02224 {
02230 m_reportTimer = new QTimer(this);
02231
02232 connect(m_reportTimer,SIGNAL(timeout()),this,SLOT(slotReport()));
02233 m_reportTimer->start(REPORT_TIMEOUT,false);
02234
02235
02236 KIO::Job * job = KIO::stat( m_dest, false, 2, false );
02237
02238 addSubjob(job);
02239 }
02240
02241
02242 KIO_EXPORT bool kio_resolve_local_urls = true;
02243
02244 void CopyJob::slotResultStating( Job *job )
02245 {
02246
02247
02248 if (job->error() && destinationState != DEST_NOT_STATED )
02249 {
02250 KURL srcurl = ((SimpleJob*)job)->url();
02251 if ( !srcurl.isLocalFile() )
02252 {
02253
02254
02255
02256 kdDebug(7007) << "Error while stating source. Activating hack" << endl;
02257 subjobs.remove( job );
02258 assert ( subjobs.isEmpty() );
02259 struct CopyInfo info;
02260 info.permissions = (mode_t) -1;
02261 info.mtime = (time_t) -1;
02262 info.ctime = (time_t) -1;
02263 info.size = (KIO::filesize_t)-1;
02264 info.uSource = srcurl;
02265 info.uDest = m_dest;
02266
02267 if ( destinationState == DEST_IS_DIR && !m_asMethod )
02268 info.uDest.addPath( srcurl.fileName() );
02269
02270 files.append( info );
02271 statNextSrc();
02272 return;
02273 }
02274
02275 Job::slotResult( job );
02276 return;
02277 }
02278
02279
02280 UDSEntry entry = ((StatJob*)job)->statResult();
02281 bool bDir = false;
02282 bool bLink = false;
02283 QString sName;
02284 QString sLocalPath;
02285 UDSEntry::ConstIterator it2 = entry.begin();
02286 for( ; it2 != entry.end(); it2++ ) {
02287 if ( ((*it2).m_uds) == UDS_FILE_TYPE )
02288 bDir = S_ISDIR( (mode_t)(*it2).m_long );
02289 else if ( ((*it2).m_uds) == UDS_LINK_DEST )
02290 bLink = !((*it2).m_str.isEmpty());
02291 else if ( ((*it2).m_uds) == UDS_NAME )
02292 sName = (*it2).m_str;
02293 else if ( ((*it2).m_uds) == UDS_LOCAL_PATH )
02294 sLocalPath = (*it2).m_str;
02295 }
02296
02297 if ( destinationState == DEST_NOT_STATED )
02298
02299 {
02300 if (job->error())
02301 destinationState = DEST_DOESNT_EXIST;
02302 else {
02303
02304 destinationState = bDir ? DEST_IS_DIR : DEST_IS_FILE;
02305
02306 }
02307 if ( m_dest == d->m_globalDest )
02308 d->m_globalDestinationState = destinationState;
02309
02310 if ( !sLocalPath.isEmpty() && kio_resolve_local_urls ) {
02311 m_dest = KURL();
02312 m_dest.setPath(sLocalPath);
02313 }
02314
02315 subjobs.remove( job );
02316 assert ( subjobs.isEmpty() );
02317
02318
02319 statCurrentSrc();
02320 return;
02321 }
02322
02323 m_currentDest = m_dest;
02324
02325 UDSEntryList lst;
02326 lst.append(entry);
02327
02328
02329
02330
02331
02332
02333
02334
02335
02336
02337
02338
02339
02340 m_bCurrentSrcIsDir = false;
02341 slotEntries(job, lst);
02342
02343 KURL srcurl;
02344 if (!sLocalPath.isEmpty())
02345 srcurl.setPath(sLocalPath);
02346 else
02347 srcurl = ((SimpleJob*)job)->url();
02348
02349 subjobs.remove( job );
02350 assert ( subjobs.isEmpty() );
02351
02352 if ( bDir
02353 && !bLink
02354 && m_mode != Link )
02355 {
02356
02357
02358 m_bCurrentSrcIsDir = true;
02359 if ( destinationState == DEST_IS_DIR )
02360 {
02361 if ( !m_asMethod )
02362 {
02363
02364 QString directory = srcurl.fileName();
02365 if ( !sName.isEmpty() && KProtocolInfo::fileNameUsedForCopying( srcurl ) == KProtocolInfo::Name )
02366 {
02367 directory = sName;
02368 }
02369 m_currentDest.addPath( directory );
02370 }
02371 }
02372 else if ( destinationState == DEST_IS_FILE )
02373 {
02374 m_error = ERR_IS_FILE;
02375 m_errorText = m_dest.prettyURL();
02376 emitResult();
02377 return;
02378 }
02379 else
02380 {
02381
02382
02383
02384
02385 destinationState = DEST_IS_DIR;
02386 if ( m_dest == d->m_globalDest )
02387 d->m_globalDestinationState = destinationState;
02388 }
02389
02390 startListing( srcurl );
02391 }
02392 else
02393 {
02394
02395 statNextSrc();
02396 }
02397 }
02398
02399 void CopyJob::slotReport()
02400 {
02401
02402 Observer * observer = m_progressId ? Observer::self() : 0L;
02403 switch (state) {
02404 case STATE_COPYING_FILES:
02405 emit processedFiles( this, m_processedFiles );
02406 if (observer) observer->slotProcessedFiles(this, m_processedFiles);
02407 if (d->m_bURLDirty)
02408 {
02409
02410 d->m_bURLDirty = false;
02411 if (m_mode==Move)
02412 {
02413 if (observer) observer->slotMoving( this, m_currentSrcURL, m_currentDestURL);
02414 emit moving( this, m_currentSrcURL, m_currentDestURL);
02415 }
02416 else if (m_mode==Link)
02417 {
02418 if (observer) observer->slotCopying( this, m_currentSrcURL, m_currentDestURL );
02419 emit linking( this, m_currentSrcURL.path(), m_currentDestURL );
02420 }
02421 else
02422 {
02423 if (observer) observer->slotCopying( this, m_currentSrcURL, m_currentDestURL );
02424 emit copying( this, m_currentSrcURL, m_currentDestURL );
02425 }
02426 }
02427 break;
02428
02429 case STATE_CREATING_DIRS:
02430 if (observer) observer->slotProcessedDirs( this, m_processedDirs );
02431 emit processedDirs( this, m_processedDirs );
02432 if (d->m_bURLDirty)
02433 {
02434 d->m_bURLDirty = false;
02435 emit creatingDir( this, m_currentDestURL );
02436 if (observer) observer->slotCreatingDir( this, m_currentDestURL);
02437 }
02438 break;
02439
02440 case STATE_STATING:
02441 case STATE_LISTING:
02442 if (d->m_bURLDirty)
02443 {
02444 d->m_bURLDirty = false;
02445 if (observer) observer->slotCopying( this, m_currentSrcURL, m_currentDestURL );
02446 }
02447 emit totalSize( this, m_totalSize );
02448 emit totalFiles( this, files.count() );
02449 emit totalDirs( this, dirs.count() );
02450 break;
02451
02452 default:
02453 break;
02454 }
02455 }
02456
02457 void CopyJob::slotEntries(KIO::Job* job, const UDSEntryList& list)
02458 {
02459 UDSEntryListConstIterator it = list.begin();
02460 UDSEntryListConstIterator end = list.end();
02461 for (; it != end; ++it) {
02462 UDSEntry::ConstIterator it2 = (*it).begin();
02463 struct CopyInfo info;
02464 info.permissions = -1;
02465 info.mtime = (time_t) -1;
02466 info.ctime = (time_t) -1;
02467 info.size = (KIO::filesize_t)-1;
02468 QString displayName;
02469 KURL url;
02470 QString localPath;
02471 bool isDir = false;
02472 for( ; it2 != (*it).end(); it2++ ) {
02473 switch ((*it2).m_uds) {
02474 case UDS_FILE_TYPE:
02475
02476 isDir = S_ISDIR( (mode_t)((*it2).m_long) );
02477 break;
02478 case UDS_NAME:
02479 displayName = (*it2).m_str;
02480 break;
02481 case UDS_URL:
02482 url = KURL((*it2).m_str);
02483 break;
02484 case UDS_LOCAL_PATH:
02485 localPath = (*it2).m_str;
02486 break;
02487 case UDS_LINK_DEST:
02488 info.linkDest = (*it2).m_str;
02489 break;
02490 case UDS_ACCESS:
02491 info.permissions = ((*it2).m_long);
02492 break;
02493 case UDS_SIZE:
02494 info.size = (KIO::filesize_t)((*it2).m_long);
02495 m_totalSize += info.size;
02496 break;
02497 case UDS_MODIFICATION_TIME:
02498 info.mtime = (time_t)((*it2).m_long);
02499 break;
02500 case UDS_CREATION_TIME:
02501 info.ctime = (time_t)((*it2).m_long);
02502 default:
02503 break;
02504 }
02505 }
02506 if (displayName != ".." && displayName != ".")
02507 {
02508 bool hasCustomURL = !url.isEmpty() || !localPath.isEmpty();
02509 if( !hasCustomURL ) {
02510
02511 url = ((SimpleJob *)job)->url();
02512 if ( m_bCurrentSrcIsDir ) {
02513
02514 url.addPath( displayName );
02515 }
02516 }
02517
02518 if (!localPath.isEmpty() && kio_resolve_local_urls) {
02519 url = KURL();
02520 url.setPath(localPath);
02521 }
02522
02523 info.uSource = url;
02524 info.uDest = m_currentDest;
02525
02526
02527 if ( destinationState == DEST_IS_DIR &&
02528
02529
02530 ( ! ( m_asMethod && state == STATE_STATING ) ) )
02531 {
02532 QString destFileName;
02533 if ( hasCustomURL &&
02534 KProtocolInfo::fileNameUsedForCopying( url ) == KProtocolInfo::FromURL ) {
02535
02536
02537 int numberOfSlashes = displayName.contains( '/' );
02538 QString path = url.path();
02539 int pos = 0;
02540 for ( int n = 0; n < numberOfSlashes + 1; ++n ) {
02541 pos = path.findRev( '/', pos - 1 );
02542 if ( pos == -1 ) {
02543 kdWarning(7007) << "kioslave bug: not enough slashes in UDS_URL " << path << " - looking for " << numberOfSlashes << " slashes" << endl;
02544 break;
02545 }
02546 }
02547 if ( pos >= 0 ) {
02548 destFileName = path.mid( pos + 1 );
02549 }
02550
02551 } else {
02552 destFileName = displayName;
02553 }
02554
02555
02556
02557
02558 if ( destFileName.isEmpty() )
02559 destFileName = KIO::encodeFileName( info.uSource.prettyURL() );
02560
02561
02562 info.uDest.addPath( destFileName );
02563 }
02564
02565
02566 if ( info.linkDest.isEmpty() && isDir && m_mode != Link )
02567 {
02568 dirs.append( info );
02569 if (m_mode == Move)
02570 dirsToRemove.append( info.uSource );
02571 }
02572 else {
02573 files.append( info );
02574 }
02575 }
02576 }
02577 }
02578
02579 void CopyJob::skipSrc()
02580 {
02581 m_dest = d->m_globalDest;
02582 destinationState = d->m_globalDestinationState;
02583 ++m_currentStatSrc;
02584 skip( m_currentSrcURL );
02585 statCurrentSrc();
02586 }
02587
02588 void CopyJob::statNextSrc()
02589 {
02590 m_dest = d->m_globalDest;
02591 destinationState = d->m_globalDestinationState;
02592 ++m_currentStatSrc;
02593 statCurrentSrc();
02594 }
02595
02596 void CopyJob::statCurrentSrc()
02597 {
02598 if ( m_currentStatSrc != m_srcList.end() )
02599 {
02600 m_currentSrcURL = (*m_currentStatSrc);
02601 d->m_bURLDirty = true;
02602 if ( m_mode == Link )
02603 {
02604
02605 m_currentDest = m_dest;
02606 struct CopyInfo info;
02607 info.permissions = -1;
02608 info.mtime = (time_t) -1;
02609 info.ctime = (time_t) -1;
02610 info.size = (KIO::filesize_t)-1;
02611 info.uSource = m_currentSrcURL;
02612 info.uDest = m_currentDest;
02613
02614 if ( destinationState == DEST_IS_DIR && !m_asMethod )
02615 {
02616 if (
02617 (m_currentSrcURL.protocol() == info.uDest.protocol()) &&
02618 (m_currentSrcURL.host() == info.uDest.host()) &&
02619 (m_currentSrcURL.port() == info.uDest.port()) &&
02620 (m_currentSrcURL.user() == info.uDest.user()) &&
02621 (m_currentSrcURL.pass() == info.uDest.pass()) )
02622 {
02623
02624 info.uDest.addPath( m_currentSrcURL.fileName() );
02625 }
02626 else
02627 {
02628
02629
02630
02631 info.uDest.addPath( KIO::encodeFileName( m_currentSrcURL.prettyURL() )+".desktop" );
02632 }
02633 }
02634 files.append( info );
02635 statNextSrc();
02636 return;
02637 }
02638 else if ( m_mode == Move && (
02639
02640 KProtocolInfo::fileNameUsedForCopying( m_currentSrcURL ) == KProtocolInfo::FromURL ||
02641 destinationState != DEST_IS_DIR || m_asMethod )
02642 )
02643 {
02644
02645
02646 if ( (m_currentSrcURL.protocol() == m_dest.protocol()) &&
02647 (m_currentSrcURL.host() == m_dest.host()) &&
02648 (m_currentSrcURL.port() == m_dest.port()) &&
02649 (m_currentSrcURL.user() == m_dest.user()) &&
02650 (m_currentSrcURL.pass() == m_dest.pass()) )
02651 {
02652 startRenameJob( m_currentSrcURL );
02653 return;
02654 }
02655 else if ( m_currentSrcURL.isLocalFile() && KProtocolInfo::canRenameFromFile( m_dest ) )
02656 {
02657 startRenameJob( m_dest );
02658 return;
02659 }
02660 else if ( m_dest.isLocalFile() && KProtocolInfo::canRenameToFile( m_currentSrcURL ) )
02661 {
02662 startRenameJob( m_currentSrcURL );
02663 return;
02664 }
02665 }
02666
02667
02668 if (m_mode == Move && !KProtocolInfo::supportsDeleting(m_currentSrcURL)) {
02669 QGuardedPtr<CopyJob> that = this;
02670 if (isInteractive())
02671 KMessageBox::information( 0, buildErrorString(ERR_CANNOT_DELETE, m_currentSrcURL.prettyURL()));
02672 if (that)
02673 statNextSrc();
02674 return;
02675 }
02676
02677
02678 Job * job = KIO::stat( m_currentSrcURL, true, 2, false );
02679
02680 state = STATE_STATING;
02681 addSubjob(job);
02682 m_currentDestURL=m_dest;
02683 m_bOnlyRenames = false;
02684 d->m_bURLDirty = true;
02685 }
02686 else
02687 {
02688
02689
02690 state = STATE_STATING;
02691 d->m_bURLDirty = true;
02692 slotReport();
02693 if (!dirs.isEmpty())
02694 emit aboutToCreate( this, dirs );
02695 if (!files.isEmpty())
02696 emit aboutToCreate( this, files );
02697
02698 m_bSingleFileCopy = ( files.count() == 1 && dirs.isEmpty() );
02699
02700 state = STATE_CREATING_DIRS;
02701 createNextDir();
02702 }
02703 }
02704
02705 void CopyJob::startRenameJob( const KURL& slave_url )
02706 {
02707 KURL dest = m_dest;
02708
02709 if ( destinationState == DEST_IS_DIR && !m_asMethod )
02710 dest.addPath( m_currentSrcURL.fileName() );
02711 kdDebug(7007) << "This seems to be a suitable case for trying to rename before stat+[list+]copy+del" << endl;
02712 state = STATE_RENAMING;
02713
02714 struct CopyInfo info;
02715 info.permissions = -1;
02716 info.mtime = (time_t) -1;
02717 info.ctime = (time_t) -1;
02718 info.size = (KIO::filesize_t)-1;
02719 info.uSource = m_currentSrcURL;
02720 info.uDest = dest;
02721 QValueList<CopyInfo> files;
02722 files.append(info);
02723 emit aboutToCreate( this, files );
02724
02725 KIO_ARGS << m_currentSrcURL << dest << (Q_INT8) false ;
02726 SimpleJob * newJob = new SimpleJob(slave_url, CMD_RENAME, packedArgs, false);
02727 Scheduler::scheduleJob(newJob);
02728 addSubjob( newJob );
02729 if ( m_currentSrcURL.directory() != dest.directory() )
02730 m_bOnlyRenames = false;
02731 }
02732
02733 void CopyJob::startListing( const KURL & src )
02734 {
02735 state = STATE_LISTING;
02736 d->m_bURLDirty = true;
02737 ListJob * newjob = listRecursive( src, false );
02738 newjob->setUnrestricted(true);
02739 connect(newjob, SIGNAL(entries( KIO::Job *,
02740 const KIO::UDSEntryList& )),
02741 SLOT( slotEntries( KIO::Job*,
02742 const KIO::UDSEntryList& )));
02743 addSubjob( newjob );
02744 }
02745
02746 void CopyJob::skip( const KURL & sourceUrl )
02747 {
02748
02749
02750
02751 KURL::List::Iterator sit = m_srcList.find( sourceUrl );
02752 if ( sit != m_srcList.end() )
02753 {
02754
02755 m_srcList.remove( sit );
02756 }
02757 dirsToRemove.remove( sourceUrl );
02758 }
02759
02760 bool CopyJob::shouldOverwrite( const QString& path ) const
02761 {
02762 if ( m_bOverwriteAll )
02763 return true;
02764 QStringList::ConstIterator sit = m_overwriteList.begin();
02765 for( ; sit != m_overwriteList.end(); ++sit )
02766 if ( path.startsWith( *sit ) )
02767 return true;
02768 return false;
02769 }
02770
02771 bool CopyJob::shouldSkip( const QString& path ) const
02772 {
02773 QStringList::ConstIterator sit = m_skipList.begin();
02774 for( ; sit != m_skipList.end(); ++sit )
02775 if ( path.startsWith( *sit ) )
02776 return true;
02777 return false;
02778 }
02779
02780 void CopyJob::slotResultCreatingDirs( Job * job )
02781 {
02782
02783 QValueList<CopyInfo>::Iterator it = dirs.begin();
02784
02785 if ( job->error() )
02786 {
02787 m_conflictError = job->error();
02788 if ( (m_conflictError == ERR_DIR_ALREADY_EXIST)
02789 || (m_conflictError == ERR_FILE_ALREADY_EXIST) )
02790 {
02791 KURL oldURL = ((SimpleJob*)job)->url();
02792
02793 if ( m_bAutoSkip ) {
02794
02795 m_skipList.append( oldURL.path( 1 ) );
02796 skip( oldURL );
02797 dirs.remove( it );
02798 } else {
02799
02800 const QString destFile = (*it).uDest.path();
02801 if ( shouldOverwrite( destFile ) ) {
02802 emit copyingDone( this, ( *it ).uSource, ( *it ).uDest, true , false );
02803 dirs.remove( it );
02804 } else {
02805 if ( !isInteractive() ) {
02806 Job::slotResult( job );
02807 return;
02808 }
02809
02810 assert( ((SimpleJob*)job)->url().url() == (*it).uDest.url() );
02811 subjobs.remove( job );
02812 assert ( subjobs.isEmpty() );
02813
02814
02815 KURL existingDest( (*it).uDest );
02816 SimpleJob * newJob = KIO::stat( existingDest, false, 2, false );
02817 Scheduler::scheduleJob(newJob);
02818 kdDebug(7007) << "KIO::stat for resolving conflict on " << existingDest << endl;
02819 state = STATE_CONFLICT_CREATING_DIRS;
02820 addSubjob(newJob);
02821 return;
02822 }
02823 }
02824 }
02825 else
02826 {
02827
02828 Job::slotResult( job );
02829 return;
02830 }
02831 }
02832 else
02833 {
02834
02835 emit copyingDone( this, (*it).uSource, (*it).uDest, true, false );
02836 d->m_directoriesCopied.append( *it );
02837 dirs.remove( it );
02838 }
02839
02840 m_processedDirs++;
02841
02842 subjobs.remove( job );
02843 assert( subjobs.isEmpty() );
02844 createNextDir();
02845 }
02846
02847 void CopyJob::slotResultConflictCreatingDirs( KIO::Job * job )
02848 {
02849
02850
02851
02852 QValueList<CopyInfo>::Iterator it = dirs.begin();
02853
02854 time_t destmtime = (time_t)-1;
02855 time_t destctime = (time_t)-1;
02856 KIO::filesize_t destsize = 0;
02857 QString linkDest;
02858
02859 UDSEntry entry = ((KIO::StatJob*)job)->statResult();
02860 KIO::UDSEntry::ConstIterator it2 = entry.begin();
02861 for( ; it2 != entry.end(); it2++ ) {
02862 switch ((*it2).m_uds) {
02863 case UDS_MODIFICATION_TIME:
02864 destmtime = (time_t)((*it2).m_long);
02865 break;
02866 case UDS_CREATION_TIME:
02867 destctime = (time_t)((*it2).m_long);
02868 break;
02869 case UDS_SIZE:
02870 destsize = (*it2).m_long;
02871 break;
02872 case UDS_LINK_DEST:
02873 linkDest = (*it2).m_str;
02874 break;
02875 }
02876 }
02877 subjobs.remove( job );
02878 assert ( subjobs.isEmpty() );
02879
02880
02881 RenameDlg_Mode mode = (RenameDlg_Mode)( M_MULTI | M_SKIP );
02882
02883 if ( m_conflictError == ERR_DIR_ALREADY_EXIST )
02884 {
02885 if( (*it).uSource == (*it).uDest ||
02886 ((*it).uSource.protocol() == (*it).uDest.protocol() &&
02887 (*it).uSource.path(-1) == linkDest) )
02888 mode = (RenameDlg_Mode)( mode | M_OVERWRITE_ITSELF);
02889 else
02890 mode = (RenameDlg_Mode)( mode | M_OVERWRITE );
02891 }
02892
02893 QString existingDest = (*it).uDest.path();
02894 QString newPath;
02895 if (m_reportTimer)
02896 m_reportTimer->stop();
02897 RenameDlg_Result r = Observer::self()->open_RenameDlg( this, i18n("Folder Already Exists"),
02898 (*it).uSource.url(),
02899 (*it).uDest.url(),
02900 mode, newPath,
02901 (*it).size, destsize,
02902 (*it).ctime, destctime,
02903 (*it).mtime, destmtime );
02904 if (m_reportTimer)
02905 m_reportTimer->start(REPORT_TIMEOUT,false);
02906 switch ( r ) {
02907 case R_CANCEL:
02908 m_error = ERR_USER_CANCELED;
02909 emitResult();
02910 return;
02911 case R_RENAME:
02912 {
02913 QString oldPath = (*it).uDest.path( 1 );
02914 KURL newUrl( (*it).uDest );
02915 newUrl.setPath( newPath );
02916 emit renamed( this, (*it).uDest, newUrl );
02917
02918
02919 (*it).uDest.setPath( newUrl.path( -1 ) );
02920 newPath = newUrl.path( 1 );
02921 QValueList<CopyInfo>::Iterator renamedirit = it;
02922 ++renamedirit;
02923
02924 for( ; renamedirit != dirs.end() ; ++renamedirit )
02925 {
02926 QString path = (*renamedirit).uDest.path();
02927 if ( path.left(oldPath.length()) == oldPath ) {
02928 QString n = path;
02929 n.replace( 0, oldPath.length(), newPath );
02930 kdDebug(7007) << "dirs list: " << (*renamedirit).uSource.path()
02931 << " was going to be " << path
02932 << ", changed into " << n << endl;
02933 (*renamedirit).uDest.setPath( n );
02934 }
02935 }
02936
02937 QValueList<CopyInfo>::Iterator renamefileit = files.begin();
02938 for( ; renamefileit != files.end() ; ++renamefileit )
02939 {
02940 QString path = (*renamefileit).uDest.path();
02941 if ( path.left(oldPath.length()) == oldPath ) {
02942 QString n = path;
02943 n.replace( 0, oldPath.length(), newPath );
02944 kdDebug(7007) << "files list: " << (*renamefileit).uSource.path()
02945 << " was going to be " << path
02946 << ", changed into " << n << endl;
02947 (*renamefileit).uDest.setPath( n );
02948 }
02949 }
02950 if (!dirs.isEmpty())
02951 emit aboutToCreate( this, dirs );
02952 if (!files.isEmpty())
02953 emit aboutToCreate( this, files );
02954 }
02955 break;
02956 case R_AUTO_SKIP:
02957 m_bAutoSkip = true;
02958
02959 case R_SKIP:
02960 m_skipList.append( existingDest );
02961 skip( (*it).uSource );
02962
02963 dirs.remove( it );
02964 m_processedDirs++;
02965 break;
02966 case R_OVERWRITE:
02967 m_overwriteList.append( existingDest );
02968 emit copyingDone( this, ( *it ).uSource, ( *it ).uDest, true , false );
02969
02970 dirs.remove( it );
02971 m_processedDirs++;
02972 break;
02973 case R_OVERWRITE_ALL:
02974 m_bOverwriteAll = true;
02975 emit copyingDone( this, ( *it ).uSource, ( *it ).uDest, true , false );
02976
02977 dirs.remove( it );
02978 m_processedDirs++;
02979 break;
02980 default:
02981 assert( 0 );
02982 }
02983 state = STATE_CREATING_DIRS;
02984
02985 createNextDir();
02986 }
02987
02988 void CopyJob::createNextDir()
02989 {
02990 KURL udir;
02991 if ( !dirs.isEmpty() )
02992 {
02993
02994 QValueList<CopyInfo>::Iterator it = dirs.begin();
02995
02996 while( it != dirs.end() && udir.isEmpty() )
02997 {
02998 const QString dir = (*it).uDest.path();
02999 if ( shouldSkip( dir ) ) {
03000 dirs.remove( it );
03001 it = dirs.begin();
03002 } else
03003 udir = (*it).uDest;
03004 }
03005 }
03006 if ( !udir.isEmpty() )
03007 {
03008
03009
03010 KIO::SimpleJob *newjob = KIO::mkdir( udir, -1 );
03011 Scheduler::scheduleJob(newjob);
03012
03013 m_currentDestURL = udir;
03014 d->m_bURLDirty = true;
03015
03016 addSubjob(newjob);
03017 return;
03018 }
03019 else
03020 {
03021 emit processedDirs( this, m_processedDirs );
03022 if (m_progressId) Observer::self()->slotProcessedDirs( this, m_processedDirs );
03023
03024 state = STATE_COPYING_FILES;
03025 m_processedFiles++;
03026 copyNextFile();
03027 }
03028 }
03029
03030 void CopyJob::slotResultCopyingFiles( Job * job )
03031 {
03032
03033 QValueList<CopyInfo>::Iterator it = files.begin();
03034 if ( job->error() )
03035 {
03036
03037 if ( m_bAutoSkip )
03038 {
03039 skip( (*it).uSource );
03040 m_fileProcessedSize = (*it).size;
03041 files.remove( it );
03042 }
03043 else
03044 {
03045 if ( !isInteractive() ) {
03046 Job::slotResult( job );
03047 return;
03048 }
03049
03050 m_conflictError = job->error();
03051
03052 if ( ( m_conflictError == ERR_FILE_ALREADY_EXIST )
03053 || ( m_conflictError == ERR_DIR_ALREADY_EXIST ) )
03054 {
03055 subjobs.remove( job );
03056 assert ( subjobs.isEmpty() );
03057
03058 KURL existingFile( (*it).uDest );
03059 SimpleJob * newJob = KIO::stat( existingFile, false, 2, false );
03060 Scheduler::scheduleJob(newJob);
03061 kdDebug(7007) << "KIO::stat for resolving conflict on " << existingFile << endl;
03062 state = STATE_CONFLICT_COPYING_FILES;
03063 addSubjob(newJob);
03064 return;
03065 }
03066 else
03067 {
03068 if ( m_bCurrentOperationIsLink && ::qt_cast<KIO::DeleteJob*>( job ) )
03069 {
03070
03071
03072 m_fileProcessedSize = (*it).size;
03073 files.remove( it );
03074 } else {
03075
03076 slotResultConflictCopyingFiles( job );
03077 return;
03078 }
03079 }
03080 }
03081 } else
03082 {
03083
03084 if ( m_bCurrentOperationIsLink && m_mode == Move
03085 && !::qt_cast<KIO::DeleteJob *>( job )
03086 )
03087 {
03088 subjobs.remove( job );
03089 assert ( subjobs.isEmpty() );
03090
03091
03092 KIO::Job * newjob = KIO::del( (*it).uSource, false , false );
03093 addSubjob( newjob );
03094 return;
03095 }
03096
03097 if ( m_bCurrentOperationIsLink )
03098 {
03099 QString target = ( m_mode == Link ? (*it).uSource.path() : (*it).linkDest );
03100
03101 emit copyingLinkDone( this, (*it).uSource, target, (*it).uDest );
03102 }
03103 else
03104
03105 emit copyingDone( this, (*it).uSource, (*it).uDest, false, false );
03106
03107 files.remove( it );
03108 }
03109 m_processedFiles++;
03110
03111
03112 m_processedSize += m_fileProcessedSize;
03113 m_fileProcessedSize = 0;
03114
03115
03116
03117 removeSubjob( job, true, false );
03118 assert ( subjobs.isEmpty() );
03119 copyNextFile();
03120 }
03121
03122 void CopyJob::slotResultConflictCopyingFiles( KIO::Job * job )
03123 {
03124
03125
03126 QValueList<CopyInfo>::Iterator it = files.begin();
03127
03128 RenameDlg_Result res;
03129 QString newPath;
03130
03131 if (m_reportTimer)
03132 m_reportTimer->stop();
03133
03134 if ( ( m_conflictError == ERR_FILE_ALREADY_EXIST )
03135 || ( m_conflictError == ERR_DIR_ALREADY_EXIST ) )
03136 {
03137
03138 time_t destmtime = (time_t)-1;
03139 time_t destctime = (time_t)-1;
03140 KIO::filesize_t destsize = 0;
03141 QString linkDest;
03142 UDSEntry entry = ((KIO::StatJob*)job)->statResult();
03143 KIO::UDSEntry::ConstIterator it2 = entry.begin();
03144 for( ; it2 != entry.end(); it2++ ) {
03145 switch ((*it2).m_uds) {
03146 case UDS_MODIFICATION_TIME:
03147 destmtime = (time_t)((*it2).m_long);
03148 break;
03149 case UDS_CREATION_TIME:
03150 destctime = (time_t)((*it2).m_long);
03151 break;
03152 case UDS_SIZE:
03153 destsize = (*it2).m_long;
03154 break;
03155 case UDS_LINK_DEST:
03156 linkDest = (*it2).m_str;
03157 break;
03158 }
03159 }
03160
03161
03162
03163 RenameDlg_Mode mode;
03164
03165 if( m_conflictError == ERR_DIR_ALREADY_EXIST )
03166 mode = (RenameDlg_Mode) 0;
03167 else
03168 {
03169 if ( (*it).uSource == (*it).uDest ||
03170 ((*it).uSource.protocol() == (*it).uDest.protocol() &&
03171 (*it).uSource.path(-1) == linkDest) )
03172 mode = M_OVERWRITE_ITSELF;
03173 else
03174 mode = M_OVERWRITE;
03175 }
03176
03177 if ( m_bSingleFileCopy )
03178 mode = (RenameDlg_Mode) ( mode | M_SINGLE );
03179 else
03180 mode = (RenameDlg_Mode) ( mode | M_MULTI | M_SKIP );
03181
03182 res = Observer::self()->open_RenameDlg( this, m_conflictError == ERR_FILE_ALREADY_EXIST ?
03183 i18n("File Already Exists") : i18n("Already Exists as Folder"),
03184 (*it).uSource.url(),
03185 (*it).uDest.url(),
03186 mode, newPath,
03187 (*it).size, destsize,
03188 (*it).ctime, destctime,
03189 (*it).mtime, destmtime );
03190
03191 }
03192 else
03193 {
03194 if ( job->error() == ERR_USER_CANCELED )
03195 res = R_CANCEL;
03196 else if ( !isInteractive() ) {
03197 Job::slotResult( job );
03198 return;
03199 }
03200 else
03201 {
03202 SkipDlg_Result skipResult = Observer::self()->open_SkipDlg( this, files.count() > 1,
03203 job->errorString() );
03204
03205
03206 res = ( skipResult == S_SKIP ) ? R_SKIP :
03207 ( skipResult == S_AUTO_SKIP ) ? R_AUTO_SKIP :
03208 R_CANCEL;
03209 }
03210 }
03211
03212 if (m_reportTimer)
03213 m_reportTimer->start(REPORT_TIMEOUT,false);
03214
03215 subjobs.remove( job );
03216 assert ( subjobs.isEmpty() );
03217 switch ( res ) {
03218 case R_CANCEL:
03219 m_error = ERR_USER_CANCELED;
03220 emitResult();
03221 return;
03222 case R_RENAME:
03223 {
03224 KURL newUrl( (*it).uDest );
03225 newUrl.setPath( newPath );
03226 emit renamed( this, (*it).uDest, newUrl );
03227 (*it).uDest = newUrl;
03228
03229 QValueList<CopyInfo> files;
03230 files.append(*it);
03231 emit aboutToCreate( this, files );
03232 }
03233 break;
03234 case R_AUTO_SKIP:
03235 m_bAutoSkip = true;
03236
03237 case R_SKIP:
03238
03239 skip( (*it).uSource );
03240 m_processedSize += (*it).size;
03241 files.remove( it );
03242 m_processedFiles++;
03243 break;
03244 case R_OVERWRITE_ALL:
03245 m_bOverwriteAll = true;
03246 break;
03247 case R_OVERWRITE:
03248
03249 m_overwriteList.append( (*it).uDest.path() );
03250 break;
03251 default:
03252 assert( 0 );
03253 }
03254 state = STATE_COPYING_FILES;
03255
03256 copyNextFile();
03257 }
03258
03259 void CopyJob::copyNextFile()
03260 {
03261 bool bCopyFile = false;
03262
03263
03264 QValueList<CopyInfo>::Iterator it = files.begin();
03265
03266 while (it != files.end() && !bCopyFile)
03267 {
03268 const QString destFile = (*it).uDest.path();
03269 bCopyFile = !shouldSkip( destFile );
03270 if ( !bCopyFile ) {
03271 files.remove( it );
03272 it = files.begin();
03273 }
03274 }
03275
03276 if (bCopyFile)
03277 {
03278
03279 bool bOverwrite;
03280 const QString destFile = (*it).uDest.path();
03281 kdDebug(7007) << "copying " << destFile << endl;
03282 if ( (*it).uDest == (*it).uSource )
03283 bOverwrite = false;
03284 else
03285 bOverwrite = shouldOverwrite( destFile );
03286
03287 m_bCurrentOperationIsLink = false;
03288 KIO::Job * newjob = 0L;
03289 if ( m_mode == Link )
03290 {
03291
03292 if (
03293 ((*it).uSource.protocol() == (*it).uDest.protocol()) &&
03294 ((*it).uSource.host() == (*it).uDest.host()) &&
03295 ((*it).uSource.port() == (*it).uDest.port()) &&
03296 ((*it).uSource.user() == (*it).uDest.user()) &&
03297 ((*it).uSource.pass() == (*it).uDest.pass()) )
03298 {
03299
03300 KIO::SimpleJob *newJob = KIO::symlink( (*it).uSource.path(), (*it).uDest, bOverwrite, false );
03301 newjob = newJob;
03302 Scheduler::scheduleJob(newJob);
03303
03304
03305 m_bCurrentOperationIsLink = true;
03306 m_currentSrcURL=(*it).uSource;
03307 m_currentDestURL=(*it).uDest;
03308 d->m_bURLDirty = true;
03309
03310 } else {
03311
03312 if ( (*it).uDest.isLocalFile() )
03313 {
03314 bool devicesOk=false;
03315
03316
03317 if ((*it).uSource.protocol()==QString::fromLatin1("devices"))
03318 {
03319 QByteArray data;
03320 QByteArray param;
03321 QCString retType;
03322 QDataStream streamout(param,IO_WriteOnly);
03323 streamout<<(*it).uSource;
03324 streamout<<(*it).uDest;
03325 if ( kapp && kapp->dcopClient()->call( "kded",
03326 "mountwatcher", "createLink(KURL, KURL)", param,retType,data,false ) )
03327 {
03328 QDataStream streamin(data,IO_ReadOnly);
03329 streamin>>devicesOk;
03330 }
03331 if (devicesOk)
03332 {
03333 files.remove( it );
03334 m_processedFiles++;
03335
03336 copyNextFile();
03337 return;
03338 }
03339 }
03340
03341 if (!devicesOk)
03342 {
03343 QString path = (*it).uDest.path();
03344
03345 QFile f( path );
03346 if ( f.open( IO_ReadWrite ) )
03347 {
03348 f.close();
03349 KSimpleConfig config( path );
03350 config.setDesktopGroup();
03351 KURL url = (*it).uSource;
03352 url.setPass( "" );
03353 config.writePathEntry( QString::fromLatin1("URL"), url.url() );
03354 config.writeEntry( QString::fromLatin1("Name"), url.url() );
03355 config.writeEntry( QString::fromLatin1("Type"), QString::fromLatin1("Link") );
03356 QString protocol = (*it).uSource.protocol();
03357 if ( protocol == QString::fromLatin1("ftp") )
03358 config.writeEntry( QString::fromLatin1("Icon"), QString::fromLatin1("ftp") );
03359 else if ( protocol == QString::fromLatin1("http") )
03360 config.writeEntry( QString::fromLatin1("Icon"), QString::fromLatin1("www") );
03361 else if ( protocol == QString::fromLatin1("info") )
03362 config.writeEntry( QString::fromLatin1("Icon"), QString::fromLatin1("info") );
03363 else if ( protocol == QString::fromLatin1("mailto") )
03364 config.writeEntry( QString::fromLatin1("Icon"), QString::fromLatin1("kmail") );
03365 else
03366 config.writeEntry( QString::fromLatin1("Icon"), QString::fromLatin1("unknown") );
03367 config.sync();
03368 files.remove( it );
03369 m_processedFiles++;
03370
03371 copyNextFile();
03372 return;
03373 }
03374 else
03375 {
03376 kdDebug(7007) << "CopyJob::copyNextFile ERR_CANNOT_OPEN_FOR_WRITING" << endl;
03377 m_error = ERR_CANNOT_OPEN_FOR_WRITING;
03378 m_errorText = (*it).uDest.path();
03379 emitResult();
03380 return;
03381 }
03382 }
03383 } else {
03384
03385 m_error = ERR_CANNOT_SYMLINK;
03386 m_errorText = (*it).uDest.prettyURL();
03387 emitResult();
03388 return;
03389 }
03390 }
03391 }
03392 else if ( !(*it).linkDest.isEmpty() &&
03393 ((*it).uSource.protocol() == (*it).uDest.protocol()) &&
03394 ((*it).uSource.host() == (*it).uDest.host()) &&
03395 ((*it).uSource.port() == (*it).uDest.port()) &&
03396 ((*it).uSource.user() == (*it).uDest.user()) &&
03397 ((*it).uSource.pass() == (*it).uDest.pass()))
03398
03399 {
03400 KIO::SimpleJob *newJob = KIO::symlink( (*it).linkDest, (*it).uDest, bOverwrite, false );
03401 Scheduler::scheduleJob(newJob);
03402 newjob = newJob;
03403
03404
03405 m_currentSrcURL=(*it).linkDest;
03406 m_currentDestURL=(*it).uDest;
03407 d->m_bURLDirty = true;
03408
03409 m_bCurrentOperationIsLink = true;
03410
03411 } else if (m_mode == Move)
03412 {
03413 KIO::FileCopyJob * moveJob = KIO::file_move( (*it).uSource, (*it).uDest, (*it).permissions, bOverwrite, false, false );
03414 moveJob->setSourceSize64( (*it).size );
03415 newjob = moveJob;
03416
03417
03418 m_currentSrcURL=(*it).uSource;
03419 m_currentDestURL=(*it).uDest;
03420 d->m_bURLDirty = true;
03421
03422 }
03423 else
03424 {
03425
03426
03427 bool remoteSource = !KProtocolInfo::supportsListing((*it).uSource);
03428 int permissions = (*it).permissions;
03429 if ( d->m_defaultPermissions || ( remoteSource && (*it).uDest.isLocalFile() ) )
03430 permissions = -1;
03431 KIO::FileCopyJob * copyJob = KIO::file_copy( (*it).uSource, (*it).uDest, permissions, bOverwrite, false, false );
03432 copyJob->setParentJob( this );
03433 copyJob->setSourceSize64( (*it).size );
03434 copyJob->setModificationTime( (*it).mtime );
03435 newjob = copyJob;
03436
03437 m_currentSrcURL=(*it).uSource;
03438 m_currentDestURL=(*it).uDest;
03439 d->m_bURLDirty = true;
03440 }
03441 addSubjob(newjob);
03442 connect( newjob, SIGNAL( processedSize( KIO::Job*, KIO::filesize_t ) ),
03443 this, SLOT( slotProcessedSize( KIO::Job*, KIO::filesize_t ) ) );
03444 connect( newjob, SIGNAL( totalSize( KIO::Job*, KIO::filesize_t ) ),
03445 this, SLOT( slotTotalSize( KIO::Job*, KIO::filesize_t ) ) );
03446 }
03447 else
03448 {
03449
03450
03451 deleteNextDir();
03452 }
03453 }
03454
03455 void CopyJob::deleteNextDir()
03456 {
03457 if ( m_mode == Move && !dirsToRemove.isEmpty() )
03458 {
03459 state = STATE_DELETING_DIRS;
03460 d->m_bURLDirty = true;
03461
03462 KURL::List::Iterator it = dirsToRemove.fromLast();
03463 SimpleJob *job = KIO::rmdir( *it );
03464 Scheduler::scheduleJob(job);
03465 dirsToRemove.remove(it);
03466 addSubjob( job );
03467 }
03468 else
03469 {
03470
03471 setNextDirAttribute();
03472 }
03473 }
03474
03475 void CopyJob::setNextDirAttribute()
03476 {
03477 if ( !d->m_directoriesCopied.isEmpty() )
03478 {
03479 state = STATE_SETTING_DIR_ATTRIBUTES;
03480 #ifdef Q_OS_UNIX
03481
03482 QValueList<CopyInfo>::Iterator it = d->m_directoriesCopied.begin();
03483 for ( ; it != d->m_directoriesCopied.end() ; ++it ) {
03484 const KURL& url = (*it).uDest;
03485 if ( url.isLocalFile() && (*it).mtime != (time_t)-1 ) {
03486 const QCString path = QFile::encodeName( url.path() );
03487 KDE_struct_stat statbuf;
03488 if (KDE_lstat(path, &statbuf) == 0) {
03489 struct utimbuf utbuf;
03490 utbuf.actime = statbuf.st_atime;
03491 utbuf.modtime = (*it).mtime;
03492 utime( path, &utbuf );
03493 }
03494
03495 }
03496 }
03497 #endif
03498 d->m_directoriesCopied.clear();
03499 }
03500
03501
03502
03503 {
03504
03505 if ( !m_bOnlyRenames )
03506 {
03507 KDirNotify_stub allDirNotify("*", "KDirNotify*");
03508 KURL url( d->m_globalDest );
03509 if ( d->m_globalDestinationState != DEST_IS_DIR || m_asMethod )
03510 url.setPath( url.directory() );
03511
03512 allDirNotify.FilesAdded( url );
03513
03514 if ( m_mode == Move && !m_srcList.isEmpty() ) {
03515
03516 allDirNotify.FilesRemoved( m_srcList );
03517 }
03518 }
03519 if (m_reportTimer)
03520 m_reportTimer->stop();
03521 --m_processedFiles;
03522 slotReport();
03523
03524 emitResult();
03525 }
03526 }
03527
03528 void CopyJob::slotProcessedSize( KIO::Job*, KIO::filesize_t data_size )
03529 {
03530
03531 m_fileProcessedSize = data_size;
03532 setProcessedSize(m_processedSize + m_fileProcessedSize);
03533
03534 if ( m_processedSize + m_fileProcessedSize > m_totalSize )
03535 {
03536 m_totalSize = m_processedSize + m_fileProcessedSize;
03537
03538 emit totalSize( this, m_totalSize );
03539 }
03540
03541 emit processedSize( this, m_processedSize + m_fileProcessedSize );
03542 emitPercent( m_processedSize + m_fileProcessedSize, m_totalSize );
03543 }
03544
03545 void CopyJob::slotTotalSize( KIO::Job*, KIO::filesize_t size )
03546 {
03547
03548
03549
03550
03551
03552 if ( m_bSingleFileCopy && size > m_totalSize)
03553 {
03554
03555 m_totalSize = size;
03556 emit totalSize( this, size );
03557 }
03558 }
03559
03560 void CopyJob::slotResultDeletingDirs( Job * job )
03561 {
03562 if (job->error())
03563 {
03564
03565
03566
03567 }
03568 subjobs.remove( job );
03569 assert ( subjobs.isEmpty() );
03570 deleteNextDir();
03571 }
03572
03573 #if 0 // TODO KDE4
03574 void CopyJob::slotResultSettingDirAttributes( Job * job )
03575 {
03576 if (job->error())
03577 {
03578
03579
03580
03581 }
03582 subjobs.remove( job );
03583 assert ( subjobs.isEmpty() );
03584 setNextDirAttribute();
03585 }
03586 #endif
03587
03588 void CopyJob::slotResultRenaming( Job* job )
03589 {
03590 int err = job->error();
03591 const QString errText = job->errorText();
03592 removeSubjob( job, true, false );
03593 assert ( subjobs.isEmpty() );
03594
03595 KURL dest = m_dest;
03596 if ( destinationState == DEST_IS_DIR && !m_asMethod )
03597 dest.addPath( m_currentSrcURL.fileName() );
03598 if ( err )
03599 {
03600
03601
03602
03603 if ( m_currentSrcURL.isLocalFile() && m_currentSrcURL.url(-1) != dest.url(-1) &&
03604 m_currentSrcURL.url(-1).lower() == dest.url(-1).lower() &&
03605 ( err == ERR_FILE_ALREADY_EXIST || err == ERR_DIR_ALREADY_EXIST ) )
03606 {
03607 kdDebug(7007) << "Couldn't rename directly, dest already exists. Detected special case of lower/uppercase renaming in same dir, try with 2 rename calls" << endl;
03608 QCString _src( QFile::encodeName(m_currentSrcURL.path()) );
03609 QCString _dest( QFile::encodeName(dest.path()) );
03610 KTempFile tmpFile( m_currentSrcURL.directory(false) );
03611 QCString _tmp( QFile::encodeName(tmpFile.name()) );
03612 kdDebug(7007) << "CopyJob::slotResult KTempFile status:" << tmpFile.status() << " using " << _tmp << " as intermediary" << endl;
03613 tmpFile.unlink();
03614 if ( ::rename( _src, _tmp ) == 0 )
03615 {
03616 if ( !QFile::exists( _dest ) && ::rename( _tmp, _dest ) == 0 )
03617 {
03618 kdDebug(7007) << "Success." << endl;
03619 err = 0;
03620 }
03621 else
03622 {
03623
03624 if ( ::rename( _tmp, _src ) != 0 ) {
03625 kdError(7007) << "Couldn't rename " << tmpFile.name() << " back to " << _src << " !" << endl;
03626
03627 Job::slotResult( job );
03628 return;
03629 }
03630 }
03631 }
03632 }
03633 }
03634 if ( err )
03635 {
03636
03637
03638
03639
03640
03641
03642
03643 Q_ASSERT( m_currentSrcURL == *m_currentStatSrc );
03644
03645
03646 if ( ( err == ERR_DIR_ALREADY_EXIST || err == ERR_FILE_ALREADY_EXIST )
03647 && isInteractive() )
03648 {
03649 if (m_reportTimer)
03650 m_reportTimer->stop();
03651
03652
03653 if ( m_bAutoSkip ) {
03654
03655 skipSrc();
03656 return;
03657 } else if ( m_bOverwriteAll ) {
03658 ;
03659 } else {
03660 QString newPath;
03661
03662 RenameDlg_Mode mode = (RenameDlg_Mode)
03663 ( ( m_currentSrcURL == dest ) ? M_OVERWRITE_ITSELF : M_OVERWRITE );
03664
03665 if ( m_srcList.count() > 1 )
03666 mode = (RenameDlg_Mode) ( mode | M_MULTI | M_SKIP );
03667 else
03668 mode = (RenameDlg_Mode) ( mode | M_SINGLE );
03669
03670
03671
03672
03673 KIO::filesize_t sizeSrc = (KIO::filesize_t) -1;
03674 KIO::filesize_t sizeDest = (KIO::filesize_t) -1;
03675 time_t ctimeSrc = (time_t) -1;
03676 time_t ctimeDest = (time_t) -1;
03677 time_t mtimeSrc = (time_t) -1;
03678 time_t mtimeDest = (time_t) -1;
03679
03680 KDE_struct_stat stat_buf;
03681 if ( m_currentSrcURL.isLocalFile() &&
03682 KDE_stat(QFile::encodeName(m_currentSrcURL.path()), &stat_buf) == 0 ) {
03683 sizeSrc = stat_buf.st_size;
03684 ctimeSrc = stat_buf.st_ctime;
03685 mtimeSrc = stat_buf.st_mtime;
03686 }
03687 if ( dest.isLocalFile() &&
03688 KDE_stat(QFile::encodeName(dest.path()), &stat_buf) == 0 ) {
03689 sizeDest = stat_buf.st_size;
03690 ctimeDest = stat_buf.st_ctime;
03691 mtimeDest = stat_buf.st_mtime;
03692 }
03693
03694 RenameDlg_Result r = Observer::self()->open_RenameDlg(
03695 this,
03696 err == ERR_FILE_ALREADY_EXIST ? i18n("File Already Exists") : i18n("Already Exists as Folder"),
03697 m_currentSrcURL.url(),
03698 dest.url(),
03699 mode, newPath,
03700 sizeSrc, sizeDest,
03701 ctimeSrc, ctimeDest,
03702 mtimeSrc, mtimeDest );
03703 if (m_reportTimer)
03704 m_reportTimer->start(REPORT_TIMEOUT,false);
03705
03706 switch ( r )
03707 {
03708 case R_CANCEL:
03709 {
03710 m_error = ERR_USER_CANCELED;
03711 emitResult();
03712 return;
03713 }
03714 case R_RENAME:
03715 {
03716
03717
03718 m_dest.setPath( newPath );
03719 KIO::Job* job = KIO::stat( m_dest, false, 2, false );
03720 state = STATE_STATING;
03721 destinationState = DEST_NOT_STATED;
03722 addSubjob(job);
03723 return;
03724 }
03725 case R_AUTO_SKIP:
03726 m_bAutoSkip = true;
03727
03728 case R_SKIP:
03729
03730 skipSrc();
03731 return;
03732 case R_OVERWRITE_ALL:
03733 m_bOverwriteAll = true;
03734 break;
03735 case R_OVERWRITE:
03736
03737
03738
03739
03740
03741 kdDebug(7007) << "adding to overwrite list: " << dest.path() << endl;
03742 m_overwriteList.append( dest.path() );
03743 break;
03744 default:
03745
03746 break;
03747 }
03748 }
03749 } else if ( err != KIO::ERR_UNSUPPORTED_ACTION ) {
03750 kdDebug(7007) << "Couldn't rename " << m_currentSrcURL << " to " << dest << ", aborting" << endl;
03751 m_error = err;
03752 m_errorText = errText;
03753 emitResult();
03754 return;
03755 }
03756 kdDebug(7007) << "Couldn't rename " << m_currentSrcURL << " to " << dest << ", reverting to normal way, starting with stat" << endl;
03757
03758 KIO::Job* job = KIO::stat( m_currentSrcURL, true, 2, false );
03759 state = STATE_STATING;
03760 addSubjob(job);
03761 m_bOnlyRenames = false;
03762 }
03763 else
03764 {
03765
03766 emit copyingDone( this, *m_currentStatSrc, dest, true, true );
03767 statNextSrc();
03768 }
03769 }
03770
03771 void CopyJob::slotResult( Job *job )
03772 {
03773
03774
03775
03776
03777
03778
03779 switch ( state ) {
03780 case STATE_STATING:
03781 slotResultStating( job );
03782 break;
03783 case STATE_RENAMING:
03784 {
03785 slotResultRenaming( job );
03786 break;
03787 }
03788 case STATE_LISTING:
03789
03790
03791 if (job->error())
03792 {
03793 Job::slotResult( job );
03794 return;
03795 }
03796
03797 subjobs.remove( job );
03798 assert ( subjobs.isEmpty() );
03799
03800 statNextSrc();
03801 break;
03802 case STATE_CREATING_DIRS:
03803 slotResultCreatingDirs( job );
03804 break;
03805 case STATE_CONFLICT_CREATING_DIRS:
03806 slotResultConflictCreatingDirs( job );
03807 break;
03808 case STATE_COPYING_FILES:
03809 slotResultCopyingFiles( job );
03810 break;
03811 case STATE_CONFLICT_COPYING_FILES:
03812 slotResultConflictCopyingFiles( job );
03813 break;
03814 case STATE_DELETING_DIRS:
03815 slotResultDeletingDirs( job );
03816 break;
03817 case STATE_SETTING_DIR_ATTRIBUTES:
03818 assert( 0 );
03819
03820 break;
03821 default:
03822 assert( 0 );
03823 }
03824 }
03825
03826 void KIO::CopyJob::setDefaultPermissions( bool b )
03827 {
03828 d->m_defaultPermissions = b;
03829 }
03830
03831
03832 void KIO::CopyJob::setInteractive( bool b )
03833 {
03834 Job::setInteractive( b );
03835 }
03836
03837 CopyJob *KIO::copy(const KURL& src, const KURL& dest, bool showProgressInfo )
03838 {
03839
03840 KURL::List srcList;
03841 srcList.append( src );
03842 return new CopyJob( srcList, dest, CopyJob::Copy, false, showProgressInfo );
03843 }
03844
03845 CopyJob *KIO::copyAs(const KURL& src, const KURL& dest, bool showProgressInfo )
03846 {
03847
03848 KURL::List srcList;
03849 srcList.append( src );
03850 return new CopyJob( srcList, dest, CopyJob::Copy, true, showProgressInfo );
03851 }
03852
03853 CopyJob *KIO::copy( const KURL::List& src, const KURL& dest, bool showProgressInfo )
03854 {
03855
03856 return new CopyJob( src, dest, CopyJob::Copy, false, showProgressInfo );
03857 }
03858
03859 CopyJob *KIO::move(const KURL& src, const KURL& dest, bool showProgressInfo )
03860 {
03861
03862 KURL::List srcList;
03863 srcList.append( src );
03864 return new CopyJob( srcList, dest, CopyJob::Move, false, showProgressInfo );
03865 }
03866
03867 CopyJob *KIO::moveAs(const KURL& src, const KURL& dest, bool showProgressInfo )
03868 {
03869
03870 KURL::List srcList;
03871 srcList.append( src );
03872 return new CopyJob( srcList, dest, CopyJob::Move, true, showProgressInfo );
03873 }
03874
03875 CopyJob *KIO::move( const KURL::List& src, const KURL& dest, bool showProgressInfo )
03876 {
03877
03878 return new CopyJob( src, dest, CopyJob::Move, false, showProgressInfo );
03879 }
03880
03881 CopyJob *KIO::link(const KURL& src, const KURL& destDir, bool showProgressInfo )
03882 {
03883 KURL::List srcList;
03884 srcList.append( src );
03885 return new CopyJob( srcList, destDir, CopyJob::Link, false, showProgressInfo );
03886 }
03887
03888 CopyJob *KIO::link(const KURL::List& srcList, const KURL& destDir, bool showProgressInfo )
03889 {
03890 return new CopyJob( srcList, destDir, CopyJob::Link, false, showProgressInfo );
03891 }
03892
03893 CopyJob *KIO::linkAs(const KURL& src, const KURL& destDir, bool showProgressInfo )
03894 {
03895 KURL::List srcList;
03896 srcList.append( src );
03897 return new CopyJob( srcList, destDir, CopyJob::Link, false, showProgressInfo );
03898 }
03899
03900 CopyJob *KIO::trash(const KURL& src, bool showProgressInfo )
03901 {
03902 KURL::List srcList;
03903 srcList.append( src );
03904 return new CopyJob( srcList, KURL( "trash:/" ), CopyJob::Move, false, showProgressInfo );
03905 }
03906
03907 CopyJob *KIO::trash(const KURL::List& srcList, bool showProgressInfo )
03908 {
03909 return new CopyJob( srcList, KURL( "trash:/" ), CopyJob::Move, false, showProgressInfo );
03910 }
03911
03913
03914 DeleteJob::DeleteJob( const KURL::List& src, bool , bool showProgressInfo )
03915 : Job(showProgressInfo), m_totalSize( 0 ), m_processedSize( 0 ), m_fileProcessedSize( 0 ),
03916 m_processedFiles( 0 ), m_processedDirs( 0 ), m_totalFilesDirs( 0 ),
03917 m_srcList(src), m_currentStat(m_srcList.begin()), m_reportTimer(0)
03918 {
03919 if ( showProgressInfo ) {
03920
03921 connect( this, SIGNAL( totalFiles( KIO::Job*, unsigned long ) ),
03922 Observer::self(), SLOT( slotTotalFiles( KIO::Job*, unsigned long ) ) );
03923
03924 connect( this, SIGNAL( totalDirs( KIO::Job*, unsigned long ) ),
03925 Observer::self(), SLOT( slotTotalDirs( KIO::Job*, unsigned long ) ) );
03926
03927
03928
03929
03930
03931
03932
03933
03934
03935
03936
03937 m_reportTimer=new QTimer(this);
03938 connect(m_reportTimer,SIGNAL(timeout()),this,SLOT(slotReport()));
03939
03940 m_reportTimer->start(REPORT_TIMEOUT,false);
03941 }
03942
03943 QTimer::singleShot(0, this, SLOT(slotStart()));
03944 }
03945
03946 void DeleteJob::slotStart()
03947 {
03948 statNextSrc();
03949 }
03950
03951
03952
03953
03954 void DeleteJob::slotReport()
03955 {
03956 if (m_progressId==0)
03957 return;
03958
03959 Observer * observer = Observer::self();
03960
03961 emit deleting( this, m_currentURL );
03962 observer->slotDeleting(this,m_currentURL);
03963
03964 switch( state ) {
03965 case STATE_STATING:
03966 case STATE_LISTING:
03967 emit totalSize( this, m_totalSize );
03968 emit totalFiles( this, files.count() );
03969 emit totalDirs( this, dirs.count() );
03970 break;
03971 case STATE_DELETING_DIRS:
03972 emit processedDirs( this, m_processedDirs );
03973 observer->slotProcessedDirs(this,m_processedDirs);
03974 emitPercent( m_processedFiles + m_processedDirs, m_totalFilesDirs );
03975 break;
03976 case STATE_DELETING_FILES:
03977 observer->slotProcessedFiles(this,m_processedFiles);
03978 emit processedFiles( this, m_processedFiles );
03979 emitPercent( m_processedFiles, m_totalFilesDirs );
03980 break;
03981 }
03982 }
03983
03984
03985 void DeleteJob::slotEntries(KIO::Job* job, const UDSEntryList& list)
03986 {
03987 UDSEntryListConstIterator it = list.begin();
03988 UDSEntryListConstIterator end = list.end();
03989 for (; it != end; ++it)
03990 {
03991 UDSEntry::ConstIterator it2 = (*it).begin();
03992 bool bDir = false;
03993 bool bLink = false;
03994 QString displayName;
03995 KURL url;
03996 int atomsFound(0);
03997 for( ; it2 != (*it).end(); it2++ )
03998 {
03999 switch ((*it2).m_uds)
04000 {
04001 case UDS_FILE_TYPE:
04002 bDir = S_ISDIR((*it2).m_long);
04003 atomsFound++;
04004 break;
04005 case UDS_NAME:
04006 displayName = (*it2).m_str;
04007 atomsFound++;
04008 break;
04009 case UDS_URL:
04010 url = KURL((*it2).m_str);
04011 atomsFound++;
04012 break;
04013 case UDS_LINK_DEST:
04014 bLink = !(*it2).m_str.isEmpty();
04015 atomsFound++;
04016 break;
04017 case UDS_SIZE:
04018 m_totalSize += (KIO::filesize_t)((*it2).m_long);
04019 atomsFound++;
04020 break;
04021 default:
04022 break;
04023 }
04024 if (atomsFound==5) break;
04025 }
04026 assert(!displayName.isEmpty());
04027 if (displayName != ".." && displayName != ".")
04028 {
04029 if( url.isEmpty() ) {
04030 url = ((SimpleJob *)job)->url();
04031 url.addPath( displayName );
04032 }
04033
04034 if ( bLink )
04035 symlinks.append( url );
04036 else if ( bDir )
04037 dirs.append( url );
04038 else
04039 files.append( url );
04040 }
04041 }
04042 }
04043
04044
04045 void DeleteJob::statNextSrc()
04046 {
04047
04048 if ( m_currentStat != m_srcList.end() )
04049 {
04050 m_currentURL = (*m_currentStat);
04051
04052
04053 if (!KProtocolInfo::supportsDeleting(m_currentURL)) {
04054 QGuardedPtr<DeleteJob> that = this;
04055 ++m_currentStat;
04056 if (isInteractive())
04057 KMessageBox::information( 0, buildErrorString(ERR_CANNOT_DELETE, m_currentURL.prettyURL()));
04058 if (that)
04059 statNextSrc();
04060 return;
04061 }
04062
04063 state = STATE_STATING;
04064 KIO::SimpleJob * job = KIO::stat( m_currentURL, true, 1, false );
04065 Scheduler::scheduleJob(job);
04066
04067 addSubjob(job);
04068
04069
04070 } else
04071 {
04072 m_totalFilesDirs = files.count()+symlinks.count() + dirs.count();
04073 slotReport();
04074
04075
04076
04077
04078 for ( QStringList::Iterator it = m_parentDirs.begin() ; it != m_parentDirs.end() ; ++it )
04079 KDirWatch::self()->stopDirScan( *it );
04080 state = STATE_DELETING_FILES;
04081 deleteNextFile();
04082 }
04083 }
04084
04085 void DeleteJob::deleteNextFile()
04086 {
04087
04088 if ( !files.isEmpty() || !symlinks.isEmpty() )
04089 {
04090 SimpleJob *job;
04091 do {
04092
04093 KURL::List::Iterator it = files.begin();
04094 bool isLink = false;
04095 if ( it == files.end() )
04096 {
04097 it = symlinks.begin();
04098 isLink = true;
04099 }
04100
04101
04102 if ( (*it).isLocalFile() && unlink( QFile::encodeName((*it).path()) ) == 0 ) {
04103
04104 job = 0;
04105 m_processedFiles++;
04106 if ( m_processedFiles % 300 == 0 || m_totalFilesDirs < 300) {
04107 m_currentURL = *it;
04108 slotReport();
04109 }
04110 } else
04111 {
04112 job = KIO::file_delete( *it, false );
04113 Scheduler::scheduleJob(job);
04114 m_currentURL=(*it);
04115 }
04116 if ( isLink )
04117 symlinks.remove(it);
04118 else
04119 files.remove(it);
04120 if ( job ) {
04121 addSubjob(job);
04122 return;
04123 }
04124
04125 } while (!job && (!files.isEmpty() || !symlinks.isEmpty()));
04126 }
04127 state = STATE_DELETING_DIRS;
04128 deleteNextDir();
04129 }
04130
04131 void DeleteJob::deleteNextDir()
04132 {
04133 if ( !dirs.isEmpty() )
04134 {
04135 do {
04136
04137 KURL::List::Iterator it = dirs.fromLast();
04138
04139 if ( (*it).isLocalFile() && ::rmdir( QFile::encodeName((*it).path()) ) == 0 ) {
04140
04141 m_processedDirs++;
04142 if ( m_processedDirs % 100 == 0 ) {
04143 m_currentURL = *it;
04144 slotReport();
04145 }
04146 } else {
04147 SimpleJob* job;
04148 if ( KProtocolInfo::canDeleteRecursive( *it ) ) {
04149
04150
04151 job = KIO::file_delete( *it, false );
04152 } else {
04153 job = KIO::rmdir( *it );
04154 }
04155 Scheduler::scheduleJob(job);
04156 dirs.remove(it);
04157 addSubjob( job );
04158 return;
04159 }
04160 dirs.remove(it);
04161 } while ( !dirs.isEmpty() );
04162 }
04163
04164
04165 for ( QStringList::Iterator it = m_parentDirs.begin() ; it != m_parentDirs.end() ; ++it )
04166 KDirWatch::self()->restartDirScan( *it );
04167
04168
04169 if ( !m_srcList.isEmpty() )
04170 {
04171 KDirNotify_stub allDirNotify("*", "KDirNotify*");
04172
04173 allDirNotify.FilesRemoved( m_srcList );
04174 }
04175 if (m_reportTimer!=0)
04176 m_reportTimer->stop();
04177 emitResult();
04178 }
04179
04180 void DeleteJob::slotProcessedSize( KIO::Job*, KIO::filesize_t data_size )
04181 {
04182
04183
04184
04185
04186 m_fileProcessedSize = data_size;
04187 setProcessedSize(m_processedSize + m_fileProcessedSize);
04188
04189
04190
04191 emit processedSize( this, m_processedSize + m_fileProcessedSize );
04192
04193
04194 unsigned long ipercent = m_percent;
04195
04196 if ( m_totalSize == 0 )
04197 m_percent = 100;
04198 else
04199 m_percent = (unsigned long)(( (float)(m_processedSize + m_fileProcessedSize) / (float)m_totalSize ) * 100.0);
04200
04201 if ( m_percent > ipercent )
04202 {
04203 emit percent( this, m_percent );
04204
04205 }
04206
04207 }
04208
04209 void DeleteJob::slotResult( Job *job )
04210 {
04211 switch ( state )
04212 {
04213 case STATE_STATING:
04214 {
04215
04216 if (job->error() )
04217 {
04218
04219 Job::slotResult( job );
04220 return;
04221 }
04222
04223
04224 UDSEntry entry = ((StatJob*)job)->statResult();
04225 bool bDir = false;
04226 bool bLink = false;
04227 KIO::filesize_t size = (KIO::filesize_t)-1;
04228 UDSEntry::ConstIterator it2 = entry.begin();
04229 int atomsFound(0);
04230 for( ; it2 != entry.end(); it2++ )
04231 {
04232 if ( ((*it2).m_uds) == UDS_FILE_TYPE )
04233 {
04234 bDir = S_ISDIR( (mode_t)(*it2).m_long );
04235 atomsFound++;
04236 }
04237 else if ( ((*it2).m_uds) == UDS_LINK_DEST )
04238 {
04239 bLink = !((*it2).m_str.isEmpty());
04240 atomsFound++;
04241 }
04242 else if ( ((*it2).m_uds) == UDS_SIZE )
04243 {
04244 size = (*it2).m_long;
04245 atomsFound++;
04246 }
04247 if (atomsFound==3) break;
04248 }
04249
04250 KURL url = ((SimpleJob*)job)->url();
04251
04252 subjobs.remove( job );
04253 assert( subjobs.isEmpty() );
04254
04255 if (bDir && !bLink)
04256 {
04257
04258 dirs.append( url );
04259 if ( url.isLocalFile() && !m_parentDirs.contains( url.path(-1) ) )
04260 m_parentDirs.append( url.path(-1) );
04261
04262 if ( !KProtocolInfo::canDeleteRecursive( url ) ) {
04263
04264
04265 state = STATE_LISTING;
04266 ListJob *newjob = listRecursive( url, false );
04267 newjob->setUnrestricted(true);
04268 Scheduler::scheduleJob(newjob);
04269 connect(newjob, SIGNAL(entries( KIO::Job *,
04270 const KIO::UDSEntryList& )),
04271 SLOT( slotEntries( KIO::Job*,
04272 const KIO::UDSEntryList& )));
04273 addSubjob(newjob);
04274 } else {
04275 ++m_currentStat;
04276 statNextSrc();
04277 }
04278 }
04279 else
04280 {
04281 if ( bLink ) {
04282
04283 symlinks.append( url );
04284 } else {
04285
04286 files.append( url );
04287 }
04288 if ( url.isLocalFile() && !m_parentDirs.contains( url.directory(false) ) )
04289 m_parentDirs.append( url.directory(false) );
04290 ++m_currentStat;
04291 statNextSrc();
04292 }
04293 }
04294 break;
04295 case STATE_LISTING:
04296 if ( job->error() )
04297 {
04298
04299 }
04300 subjobs.remove( job );
04301 assert( subjobs.isEmpty() );
04302 ++m_currentStat;
04303 statNextSrc();
04304 break;
04305 case STATE_DELETING_FILES:
04306 if ( job->error() )
04307 {
04308 Job::slotResult( job );
04309 return;
04310 }
04311 subjobs.remove( job );
04312 assert( subjobs.isEmpty() );
04313 m_processedFiles++;
04314
04315 deleteNextFile();
04316 break;
04317 case STATE_DELETING_DIRS:
04318 if ( job->error() )
04319 {
04320 Job::slotResult( job );
04321 return;
04322 }
04323 subjobs.remove( job );
04324 assert( subjobs.isEmpty() );
04325 m_processedDirs++;
04326
04327
04328
04329
04330 deleteNextDir();
04331 break;
04332 default:
04333 assert(0);
04334 }
04335 }
04336
04337 DeleteJob *KIO::del( const KURL& src, bool shred, bool showProgressInfo )
04338 {
04339 KURL::List srcList;
04340 srcList.append( src );
04341 DeleteJob *job = new DeleteJob( srcList, shred, showProgressInfo );
04342 return job;
04343 }
04344
04345 DeleteJob *KIO::del( const KURL::List& src, bool shred, bool showProgressInfo )
04346 {
04347 DeleteJob *job = new DeleteJob( src, shred, showProgressInfo );
04348 return job;
04349 }
04350
04351 MultiGetJob::MultiGetJob(const KURL& url,
04352 bool showProgressInfo)
04353 : TransferJob(url, 0, QByteArray(), QByteArray(), showProgressInfo)
04354 {
04355 m_waitQueue.setAutoDelete(true);
04356 m_activeQueue.setAutoDelete(true);
04357 m_currentEntry = 0;
04358 }
04359
04360 void MultiGetJob::get(long id, const KURL &url, const MetaData &metaData)
04361 {
04362 GetRequest *entry = new GetRequest(id, url, metaData);
04363 entry->metaData["request-id"] = QString("%1").arg(id);
04364 m_waitQueue.append(entry);
04365 }
04366
04367 void MultiGetJob::flushQueue(QPtrList<GetRequest> &queue)
04368 {
04369 GetRequest *entry;
04370
04371
04372 for(entry = m_waitQueue.first(); entry; )
04373 {
04374 if ((m_url.protocol() == entry->url.protocol()) &&
04375 (m_url.host() == entry->url.host()) &&
04376 (m_url.port() == entry->url.port()) &&
04377 (m_url.user() == entry->url.user()))
04378 {
04379 m_waitQueue.take();
04380 queue.append(entry);
04381 entry = m_waitQueue.current();
04382 }
04383 else
04384 {
04385 entry = m_waitQueue.next();
04386 }
04387 }
04388
04389 KIO_ARGS << (Q_INT32) queue.count();
04390 for(entry = queue.first(); entry; entry = queue.next())
04391 {
04392 stream << entry->url << entry->metaData;
04393 }
04394 m_packedArgs = packedArgs;
04395 m_command = CMD_MULTI_GET;
04396 m_outgoingMetaData.clear();
04397 }
04398
04399 void MultiGetJob::start(Slave *slave)
04400 {
04401
04402 GetRequest *entry = m_waitQueue.take(0);
04403 m_activeQueue.append(entry);
04404
04405 m_url = entry->url;
04406
04407 if (!entry->url.protocol().startsWith("http"))
04408 {
04409
04410 KIO_ARGS << entry->url;
04411 m_packedArgs = packedArgs;
04412 m_outgoingMetaData = entry->metaData;
04413 m_command = CMD_GET;
04414 b_multiGetActive = false;
04415 }
04416 else
04417 {
04418 flushQueue(m_activeQueue);
04419 b_multiGetActive = true;
04420 }
04421
04422 TransferJob::start(slave);
04423 }
04424
04425 bool MultiGetJob::findCurrentEntry()
04426 {
04427 if (b_multiGetActive)
04428 {
04429 long id = m_incomingMetaData["request-id"].toLong();
04430 for(GetRequest *entry = m_activeQueue.first(); entry; entry = m_activeQueue.next())
04431 {
04432 if (entry->id == id)
04433 {
04434 m_currentEntry = entry;
04435 return true;
04436 }
04437 }
04438 m_currentEntry = 0;
04439 return false;
04440 }
04441 else
04442 {
04443 m_currentEntry = m_activeQueue.first();
04444 return (m_currentEntry != 0);
04445 }
04446 }
04447
04448 void MultiGetJob::slotRedirection( const KURL &url)
04449 {
04450 if (!findCurrentEntry()) return;
04451 if (kapp && !kapp->authorizeURLAction("redirect", m_url, url))
04452 {
04453 kdWarning(7007) << "MultiGetJob: Redirection from " << m_currentEntry->url << " to " << url << " REJECTED!" << endl;
04454 return;
04455 }
04456 m_redirectionURL = url;
04457 if (m_currentEntry->url.hasUser() && !url.hasUser() && (m_currentEntry->url.host().lower() == url.host().lower()))
04458 m_redirectionURL.setUser(m_currentEntry->url.user());
04459 get(m_currentEntry->id, m_redirectionURL, m_currentEntry->metaData);
04460 }
04461
04462
04463 void MultiGetJob::slotFinished()
04464 {
04465 if (!findCurrentEntry()) return;
04466 if (m_redirectionURL.isEmpty())
04467 {
04468
04469 emit result(m_currentEntry->id);
04470 }
04471 m_redirectionURL = KURL();
04472 m_error = 0;
04473 m_incomingMetaData.clear();
04474 m_activeQueue.removeRef(m_currentEntry);
04475 if (m_activeQueue.count() == 0)
04476 {
04477 if (m_waitQueue.count() == 0)
04478 {
04479
04480 TransferJob::slotFinished();
04481 }
04482 else
04483 {
04484
04485
04486
04487 GetRequest *entry = m_waitQueue.at(0);
04488 m_url = entry->url;
04489 slaveDone();
04490 Scheduler::doJob(this);
04491 }
04492 }
04493 }
04494
04495 void MultiGetJob::slotData( const QByteArray &_data)
04496 {
04497 if(!m_currentEntry) return;
04498 if(m_redirectionURL.isEmpty() || !m_redirectionURL.isValid() || m_error)
04499 emit data(m_currentEntry->id, _data);
04500 }
04501
04502 void MultiGetJob::slotMimetype( const QString &_mimetype )
04503 {
04504 if (b_multiGetActive)
04505 {
04506 QPtrList<GetRequest> newQueue;
04507 flushQueue(newQueue);
04508 if (!newQueue.isEmpty())
04509 {
04510 while(!newQueue.isEmpty())
04511 m_activeQueue.append(newQueue.take(0));
04512 m_slave->send( m_command, m_packedArgs );
04513 }
04514 }
04515 if (!findCurrentEntry()) return;
04516 emit mimetype(m_currentEntry->id, _mimetype);
04517 }
04518
04519 MultiGetJob *KIO::multi_get(long id, const KURL &url, const MetaData &metaData)
04520 {
04521 MultiGetJob * job = new MultiGetJob( url, false );
04522 job->get(id, url, metaData);
04523 return job;
04524 }
04525
04526
04527 #ifdef CACHE_INFO
04528 CacheInfo::CacheInfo(const KURL &url)
04529 {
04530 m_url = url;
04531 }
04532
04533 QString CacheInfo::cachedFileName()
04534 {
04535 const QChar separator = '_';
04536
04537 QString CEF = m_url.path();
04538
04539 int p = CEF.find('/');
04540
04541 while(p != -1)
04542 {
04543 CEF[p] = separator;
04544 p = CEF.find('/', p);
04545 }
04546
04547 QString host = m_url.host().lower();
04548 CEF = host + CEF + '_';
04549
04550 QString dir = KProtocolManager::cacheDir();
04551 if (dir[dir.length()-1] != '/')
04552 dir += "/";
04553
04554 int l = m_url.host().length();
04555 for(int i = 0; i < l; i++)
04556 {
04557 if (host[i].isLetter() && (host[i] != 'w'))
04558 {
04559 dir += host[i];
04560 break;
04561 }
04562 }
04563 if (dir[dir.length()-1] == '/')
04564 dir += "0";
04565
04566 unsigned long hash = 0x00000000;
04567 QCString u = m_url.url().latin1();
04568 for(int i = u.length(); i--;)
04569 {
04570 hash = (hash * 12211 + u[i]) % 2147483563;
04571 }
04572
04573 QString hashString;
04574 hashString.sprintf("%08lx", hash);
04575
04576 CEF = CEF + hashString;
04577
04578 CEF = dir + "/" + CEF;
04579
04580 return CEF;
04581 }
04582
04583 QFile *CacheInfo::cachedFile()
04584 {
04585 #ifdef Q_WS_WIN
04586 const char *mode = (readWrite ? "rb+" : "rb");
04587 #else
04588 const char *mode = (readWrite ? "r+" : "r");
04589 #endif
04590
04591 FILE *fs = fopen(QFile::encodeName(CEF), mode);
04592 if (!fs)
04593 return 0;
04594
04595 char buffer[401];
04596 bool ok = true;
04597
04598
04599 if (ok && (!fgets(buffer, 400, fs)))
04600 ok = false;
04601 if (ok && (strcmp(buffer, CACHE_REVISION) != 0))
04602 ok = false;
04603
04604 time_t date;
04605 time_t currentDate = time(0);
04606
04607
04608 if (ok && (!fgets(buffer, 400, fs)))
04609 ok = false;
04610 if (ok)
04611 {
04612 int l = strlen(buffer);
04613 if (l>0)
04614 buffer[l-1] = 0;
04615 if (m_.url.url() != buffer)
04616 {
04617 ok = false;
04618 }
04619 }
04620
04621
04622 if (ok && (!fgets(buffer, 400, fs)))
04623 ok = false;
04624 if (ok)
04625 {
04626 date = (time_t) strtoul(buffer, 0, 10);
04627 if (m_maxCacheAge && (difftime(currentDate, date) > m_maxCacheAge))
04628 {
04629 m_bMustRevalidate = true;
04630 m_expireDate = currentDate;
04631 }
04632 }
04633
04634
04635 m_cacheExpireDateOffset = ftell(fs);
04636 if (ok && (!fgets(buffer, 400, fs)))
04637 ok = false;
04638 if (ok)
04639 {
04640 if (m_request.cache == CC_Verify)
04641 {
04642 date = (time_t) strtoul(buffer, 0, 10);
04643
04644 if (!date || difftime(currentDate, date) >= 0)
04645 m_bMustRevalidate = true;
04646 m_expireDate = date;
04647 }
04648 }
04649
04650
04651 if (ok && (!fgets(buffer, 400, fs)))
04652 ok = false;
04653 if (ok)
04654 {
04655 m_etag = QString(buffer).stripWhiteSpace();
04656 }
04657
04658
04659 if (ok && (!fgets(buffer, 400, fs)))
04660 ok = false;
04661 if (ok)
04662 {
04663 m_lastModified = QString(buffer).stripWhiteSpace();
04664 }
04665
04666 fclose(fs);
04667
04668 if (ok)
04669 return fs;
04670
04671 unlink( QFile::encodeName(CEF) );
04672 return 0;
04673
04674 }
04675
04676 void CacheInfo::flush()
04677 {
04678 cachedFile().remove();
04679 }
04680
04681 void CacheInfo::touch()
04682 {
04683
04684 }
04685 void CacheInfo::setExpireDate(int);
04686 void CacheInfo::setExpireTimeout(int);
04687
04688
04689 int CacheInfo::creationDate();
04690 int CacheInfo::expireDate();
04691 int CacheInfo::expireTimeout();
04692 #endif
04693
04694 void Job::virtual_hook( int, void* )
04695 { }
04696
04697 void SimpleJob::virtual_hook( int id, void* data )
04698 { KIO::Job::virtual_hook( id, data ); }
04699
04700 void MkdirJob::virtual_hook( int id, void* data )
04701 { SimpleJob::virtual_hook( id, data ); }
04702
04703 void StatJob::virtual_hook( int id, void* data )
04704 { SimpleJob::virtual_hook( id, data ); }
04705
04706 void TransferJob::virtual_hook( int id, void* data )
04707 { SimpleJob::virtual_hook( id, data ); }
04708
04709 void MultiGetJob::virtual_hook( int id, void* data )
04710 { TransferJob::virtual_hook( id, data ); }
04711
04712 void MimetypeJob::virtual_hook( int id, void* data )
04713 { TransferJob::virtual_hook( id, data ); }
04714
04715 void FileCopyJob::virtual_hook( int id, void* data )
04716 { Job::virtual_hook( id, data ); }
04717
04718 void ListJob::virtual_hook( int id, void* data )
04719 { SimpleJob::virtual_hook( id, data ); }
04720
04721 void CopyJob::virtual_hook( int id, void* data )
04722 { Job::virtual_hook( id, data ); }
04723
04724 void DeleteJob::virtual_hook( int id, void* data )
04725 { Job::virtual_hook( id, data ); }
04726
04727
04728 #include "jobclasses.moc"