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