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