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