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