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