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