job.cpp 84.6 KB
Newer Older
1
2
/* This file is part of the KDE libraries
    Copyright (C) 2000 Stephan Kulow <coolo@kde.org>
3
                  2000-2009 David Faure <faure@kde.org>
4
5
6
                       Waldo Bastian <bastian@kde.org>

    This library is free software; you can redistribute it and/or
7
    modify it under the terms of the GNU Library General Public
8
9
10
11
12
13
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
    Library General Public License for more details.
15

16
    You should have received a copy of the GNU Library General Public License
17
    along with this library; see the file COPYING.LIB.  If not, write to
Dirk Mueller's avatar
Dirk Mueller committed
18
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Dirk Mueller's avatar
Dirk Mueller committed
19
    Boston, MA 02110-1301, USA.
20
21
*/

Alex Merry's avatar
Alex Merry committed
22
#include "job.h"
23
#include "job_p.h"
Christian Ehrlicher's avatar
Christian Ehrlicher committed
24

Alex Merry's avatar
Alex Merry committed
25
#include <config.h>
26
27
28
29
30
31
32
33
34
35
36
37
38
39

#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>

#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>
extern "C" {
#include <pwd.h>
#include <grp.h>
}
Dirk Mueller's avatar
Dirk Mueller committed
40
41
#include <QtCore/QTimer>
#include <QtCore/QFile>
42
43

#include <kapplication.h>
44
#include <kauthorized.h>
45
46
#include <kglobal.h>
#include <klocale.h>
47
#include <kconfig.h>
48
#include <kdebug.h>
49
#include <kde_file.h>
50
51
52

#include <errno.h>

53
#include "jobuidelegate.h"
54
#include "kmimetype.h"
55
56
#include "slave.h"
#include "scheduler.h"
57
#include "kdirwatch.h"
58
#include "kprotocolinfo.h"
59
#include "kprotocolmanager.h"
60
#include "filejob.h"
61

62
#include <kdirnotify.h>
Jaison Lee's avatar
Jaison Lee committed
63
#include <ktemporaryfile.h>
64
65
66

using namespace KIO;

67
68
69
70
71
static inline Slave *jobSlave(SimpleJob *job)
{
    return SimpleJobPrivate::get(job)->m_slave;
}

72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
// Returns true if the scheme and domain of the two urls match...
static bool domainSchemeMatch(const KUrl& u1, const KUrl& u2)
{
    if (u1.scheme() != u2.scheme())
        return false;

    QStringList u1List = u1.host().split(QLatin1Char('.'), QString::SkipEmptyParts);
    QStringList u2List = u2.host().split(QLatin1Char('.'), QString::SkipEmptyParts);

    if (qMin(u1List.count(), u2List.count()) < 2)
        return false;  // better safe than sorry...

    while (u1List.count() > 2)
        u1List.removeFirst();

    while (u2List.count() > 2)
        u2List.removeFirst();

    return (u1List == u2List);
}

93
static void clearNonSSLMetaData(KIO::MetaData *metaData)
94
{
95
    QMutableMapIterator<QString, QString> it(*metaData);
96
97
98
99
100
101
102
    while (it.hasNext()) {
        it.next();
        if (!it.key().startsWith(QLatin1String("ssl_"), Qt::CaseInsensitive))
            it.remove();
    }
}

103
104
105
//this will update the report dialog with 5 Hz, I think this is fast enough, aleXXX
#define REPORT_TIMEOUT 200

106
Job::Job() : KCompositeJob(*new JobPrivate, 0)
107
{
108
109
    setCapabilities( KJob::Killable | KJob::Suspendable );
}
110

111
Job::Job(JobPrivate &dd) : KCompositeJob(dd, 0)
112
{
113
    setCapabilities( KJob::Killable | KJob::Suspendable );
114
115
116
117
118
119
}

Job::~Job()
{
}

120
121
122
123
124
JobUiDelegate *Job::ui() const
{
    return static_cast<JobUiDelegate*>( uiDelegate() );
}

125
bool Job::addSubjob(KJob *jobBase)
126
{
127
    //kDebug(7007) << "addSubjob(" << jobBase << ") this=" << this;
128

129
130
131
    bool ok = KCompositeJob::addSubjob( jobBase );
    KIO::Job *job = dynamic_cast<KIO::Job*>( jobBase );
    if (ok && job) {
132
133
134
135
        // Copy metadata into subjob (e.g. window-id, user-timestamp etc.)
        Q_D(Job);
        job->mergeMetaData(d->m_outgoingMetaData);

136
        // Forward information from that subjob.
137
138
        connect(job, SIGNAL(speed(KJob*,ulong)),
                SLOT(slotSpeed(KJob*,ulong)));
139
140
141
142
143

        if (ui() && job->ui()) {
            job->ui()->setWindow( ui()->window() );
            job->ui()->updateUserTimestamp( ui()->userTimestamp() );
        }
144
    }
145
    return ok;
146
147
}

148
bool Job::removeSubjob( KJob *jobBase )
149
{
150
151
    //kDebug(7007) << "removeSubjob(" << jobBase << ") this=" << this << "subjobs=" << subjobs().count();
    return KCompositeJob::removeSubjob( jobBase );
152
153
}

154
void JobPrivate::emitMoving(KIO::Job * job, const KUrl &src, const KUrl &dest)
155
{
Nick Shaforostoff's avatar
Nick Shaforostoff committed
156
    emit job->description(job, i18nc("@title job","Moving"),
157
158
                          qMakePair(i18nc("The source of a file operation", "Source"), src.pathOrUrl()),
                          qMakePair(i18nc("The destination of a file operation", "Destination"), dest.pathOrUrl()));
159
160
}

161
void JobPrivate::emitCopying(KIO::Job * job, const KUrl &src, const KUrl &dest)
162
{
Nick Shaforostoff's avatar
Nick Shaforostoff committed
163
    emit job->description(job, i18nc("@title job","Copying"),
164
165
                          qMakePair(i18nc("The source of a file operation", "Source"), src.pathOrUrl()),
                          qMakePair(i18nc("The destination of a file operation", "Destination"), dest.pathOrUrl()));
166
167
}

168
void JobPrivate::emitCreatingDir(KIO::Job * job, const KUrl &dir)
169
{
Nick Shaforostoff's avatar
Nick Shaforostoff committed
170
    emit job->description(job, i18nc("@title job","Creating directory"),
171
                          qMakePair(i18n("Directory"), dir.pathOrUrl()));
172
173
}

174
void JobPrivate::emitDeleting(KIO::Job *job, const KUrl &url)
175
{
Nick Shaforostoff's avatar
Nick Shaforostoff committed
176
    emit job->description(job, i18nc("@title job","Deleting"),
177
                          qMakePair(i18n("File"), url.pathOrUrl()));
178
179
}

180
void JobPrivate::emitStating(KIO::Job *job, const KUrl &url)
181
{
182
    emit job->description(job, i18nc("@title job","Examining"),
183
                          qMakePair(i18n("File"), url.pathOrUrl()));
184
185
}

186
void JobPrivate::emitTransferring(KIO::Job *job, const KUrl &url)
187
{
Nick Shaforostoff's avatar
Nick Shaforostoff committed
188
    emit job->description(job, i18nc("@title job","Transferring"),
189
                          qMakePair(i18nc("The source of a file operation", "Source"), url.pathOrUrl()));
190
191
}

192
void JobPrivate::emitMounting(KIO::Job * job, const QString &dev, const QString &point)
193
{
Nick Shaforostoff's avatar
Nick Shaforostoff committed
194
    emit job->description(job, i18nc("@title job","Mounting"),
195
196
                          qMakePair(i18n("Device"), dev),
                          qMakePair(i18n("Mountpoint"), point));
197
198
}

199
void JobPrivate::emitUnmounting(KIO::Job * job, const QString &point)
200
{
Nick Shaforostoff's avatar
Nick Shaforostoff committed
201
    emit job->description(job, i18nc("@title job","Unmounting"),
202
                          qMakePair(i18n("Mountpoint"), point));
203
204
}

205
bool Job::doKill()
206
207
{
  // kill all subjobs, without triggering their result slot
208
209
210
  Q_FOREACH( KJob* it, subjobs()) {
      it->kill( KJob::Quietly );
  }
211
  clearSubjobs();
212

213
  return true;
214
215
}

216
bool Job::doSuspend()
217
{
218
219
    Q_FOREACH(KJob* it, subjobs()) {
        if (!it->suspend())
220
            return false;
221
    }
222
223

    return true;
224
225
}

226
bool Job::doResume()
227
{
228
    Q_FOREACH ( KJob* it, subjobs() )
229
    {
230
        if (!it->resume())
231
            return false;
232
233
    }

234
    return true;
235
236
}

237
void JobPrivate::slotSpeed( KJob*, unsigned long speed )
238
{
239
    //kDebug(7007) << speed;
240
    q_func()->emitSpeed( speed );
241
242
243
244
}

//Job::errorString is implemented in global.cpp

245
#ifndef KDE_NO_DEPRECATED
246
247
248
249
250
251
252
253
254
void Job::showErrorDialog( QWidget *parent )
{
    if ( ui() )
    {
        ui()->setWindow( parent );
        ui()->showErrorMessage();
    }
    else
    {
255
        kError() << errorString();
256
257
    }
}
258
#endif
259

260
261
bool Job::isInteractive() const
{
262
  return uiDelegate() != 0;
263
264
}

265
266
void Job::setParentJob(Job* job)
{
267
  Q_D(Job);
268
269
270
271
272
273
274
  Q_ASSERT(d->m_parentJob == 0L);
  Q_ASSERT(job);
  d->m_parentJob = job;
}

Job* Job::parentJob() const
{
275
  return d_func()->m_parentJob;
276
277
}

278
279
MetaData Job::metaData() const
{
280
    return d_func()->m_incomingMetaData;
281
282
283
284
}

QString Job::queryMetaData(const QString &key)
{
285
    return d_func()->m_incomingMetaData.value(key, QString());
286
287
288
289
}

void Job::setMetaData( const KIO::MetaData &_metaData)
{
290
291
    Q_D(Job);
    d->m_outgoingMetaData = _metaData;
292
293
294
295
}

void Job::addMetaData( const QString &key, const QString &value)
{
296
    d_func()->m_outgoingMetaData.insert(key, value);
297
298
299
300
}

void Job::addMetaData( const QMap<QString,QString> &values)
{
301
    Q_D(Job);
Albert Astals Cid's avatar
Albert Astals Cid committed
302
    QMap<QString,QString>::const_iterator it = values.begin();
303
    for(;it != values.end(); ++it)
304
        d->m_outgoingMetaData.insert(it.key(), it.value());
305
306
307
308
}

void Job::mergeMetaData( const QMap<QString,QString> &values)
{
309
    Q_D(Job);
Albert Astals Cid's avatar
Albert Astals Cid committed
310
    QMap<QString,QString>::const_iterator it = values.begin();
311
    for(;it != values.end(); ++it)
David Faure's avatar
David Faure committed
312
        // there's probably a faster way
313
314
        if ( !d->m_outgoingMetaData.contains( it.key() ) )
            d->m_outgoingMetaData.insert( it.key(), it.value() );
315
316
317
318
}

MetaData Job::outgoingMetaData() const
{
319
    return d_func()->m_outgoingMetaData;
320
321
}

322
323
SimpleJob::SimpleJob(SimpleJobPrivate &dd)
  : Job(dd)
324
325
326
327
328
{
    d_func()->simpleJobInit();
}

void SimpleJobPrivate::simpleJobInit()
329
{
330
    Q_Q(SimpleJob);
331
    if (!m_url.isValid())
332
    {
333
        q->setError( ERR_MALFORMED_URL );
334
        q->setErrorText( m_url.url() );
335
        QTimer::singleShot(0, q, SLOT(slotFinished()) );
336
337
338
        return;
    }

339
    Scheduler::doJob(q);
340
341
}

342

343
bool SimpleJob::doKill()
344
{
345
346
347
348
349
    Q_D(SimpleJob);
    if ((d->m_extraFlags & JobPrivate::EF_KillCalled) == 0) {
        d->m_extraFlags |= JobPrivate::EF_KillCalled;
        Scheduler::cancelJob(this); // deletes the slave if not 0
    } else {
350
        kWarning(7007) << this << "This is overkill.";
351
    }
352
    return Job::doKill();
353
354
}

355
bool SimpleJob::doSuspend()
356
{
357
358
359
    Q_D(SimpleJob);
    if ( d->m_slave )
        d->m_slave->suspend();
360
    return Job::doSuspend();
361
362
}

363
bool SimpleJob::doResume()
364
{
365
366
367
    Q_D(SimpleJob);
    if ( d->m_slave )
        d->m_slave->resume();
368
    return Job::doResume();
369
370
}

371
372
const KUrl& SimpleJob::url() const
{
373
    return d_func()->m_url;
374
375
}

376
377
void SimpleJob::putOnHold()
{
378
379
380
    Q_D(SimpleJob);
    Q_ASSERT( d->m_slave );
    if ( d->m_slave )
381
    {
382
        Scheduler::putSlaveOnHold(this, d->m_url);
383
    }
384
385
    // we should now be disassociated from the slave
    Q_ASSERT(!d->m_slave);
386
    kill( Quietly );
387
388
389
390
391
392
393
}

void SimpleJob::removeOnHold()
{
    Scheduler::removeSlaveOnHold();
}

394
bool SimpleJob::isRedirectionHandlingEnabled() const
395
396
397
398
{
    return d_func()->m_redirectionHandlingEnabled;
}

399
void SimpleJob::setRedirectionHandlingEnabled(bool handle)
400
401
402
403
404
{
    Q_D(SimpleJob);
    d->m_redirectionHandlingEnabled = handle;
}

405
406
SimpleJob::~SimpleJob()
{
407
    Q_D(SimpleJob);
408
409
    // last chance to remove this job from the scheduler!
    if (d->m_schedSerial) {
410
        kDebug(7007) << "Killing job" << this << "in destructor!"  << kBacktrace();
411
        Scheduler::cancelJob(this);
412
413
414
    }
}

415
void SimpleJobPrivate::start(Slave *slave)
416
{
417
    Q_Q(SimpleJob);
418
    m_slave = slave;
419
420
421
422
423

    // Slave::setJob can send us SSL metadata if there is a persistent connection
    q->connect( slave, SIGNAL(metaData(KIO::MetaData)),
                SLOT(slotMetaData(KIO::MetaData)) );

424
    slave->setJob(q);
425

426
427
    q->connect( slave, SIGNAL(error(int,QString)),
                SLOT(slotError(int,QString)) );
428

429
430
    q->connect( slave, SIGNAL(warning(QString)),
                SLOT(slotWarning(QString)) );
431

432
433
    q->connect( slave, SIGNAL(infoMessage(QString)),
                SLOT(_k_slotSlaveInfoMessage(QString)) );
434

435
436
    q->connect( slave, SIGNAL(connected()),
                SLOT(slotConnected()));
437

438
439
    q->connect( slave, SIGNAL(finished()),
                SLOT(slotFinished()) );
440

441
    if ((m_extraFlags & EF_TransferJobDataSent) == 0) // this is a "get" job
442
    {
443
444
        q->connect( slave, SIGNAL(totalSize(KIO::filesize_t)),
                    SLOT(slotTotalSize(KIO::filesize_t)) );
445

446
447
        q->connect( slave, SIGNAL(processedSize(KIO::filesize_t)),
                    SLOT(slotProcessedSize(KIO::filesize_t)) );
448

449
450
        q->connect( slave, SIGNAL(speed(ulong)),
                    SLOT(slotSpeed(ulong)) );
451
    }
452

453
    if (ui() && ui()->window())
454
    {
455
        m_outgoingMetaData.insert("window-id", QString::number((qptrdiff)ui()->window()->winId()));
456
457
    }

458
459
    if (ui() && ui()->userTimestamp())
    {
460
        m_outgoingMetaData.insert("user-timestamp", QString::number(ui()->userTimestamp()));
461
462
    }

463
    if (ui() == 0)              // not interactive
464
    {
465
        m_outgoingMetaData.insert("no-auth-prompt", "true");
466
    }
467

468
    if (!m_outgoingMetaData.isEmpty())
469
    {
470
471
        KIO_ARGS << m_outgoingMetaData;
        slave->send( CMD_META_DATA, packedArgs );
472
473
474
475
476
    }

    if (!m_subUrl.isEmpty())
    {
       KIO_ARGS << m_subUrl;
477
       slave->send( CMD_SUBURL, packedArgs );
478
479
    }

480
    slave->send( m_command, m_packedArgs );
481
482
}

483
void SimpleJobPrivate::slaveDone()
484
{
485
    Q_Q(SimpleJob);
486
487
488
489
490
491
    if (m_slave) {
        if (m_command == CMD_OPEN) {
            m_slave->send(CMD_CLOSE);
        }
        q->disconnect(m_slave); // Remove all signals between slave and job
    }
492
493
494
495
    // only finish a job once; Scheduler::jobFinished() resets schedSerial to zero.
    if (m_schedSerial) {
        Scheduler::jobFinished(q, m_slave);
    }
496
497
}

498
499
void SimpleJob::slotFinished( )
{
500
    Q_D(SimpleJob);
501
    // Return slave to the scheduler
502
    d->slaveDone();
503

504
    if (!hasSubjobs())
505
    {
506
        if ( !error() && (d->m_command == CMD_MKDIR || d->m_command == CMD_RENAME ) )
507
        {
508
            if ( d->m_command == CMD_MKDIR )
509
            {
510
                KUrl urlDir( url() );
511
                urlDir.setPath( urlDir.directory() );
512
                org::kde::KDirNotify::emitFilesAdded( urlDir.url() );
513
            }
514
            else /*if ( m_command == CMD_RENAME )*/
515
            {
516
                KUrl src, dst;
517
                QDataStream str( d->m_packedArgs );
518
                str >> src >> dst;
Arto Hytönen's avatar
hotfix4    
Arto Hytönen committed
519
                if( src.directory() == dst.directory() ) // For the user, moving isn't renaming. Only renaming is.
520
                    org::kde::KDirNotify::emitFileRenamed( src.url(), dst.url() );
521
522

                org::kde::KDirNotify::emitFileMoved( src.url(), dst.url() );
523
524
525
526
527
528
            }
        }
        emitResult();
    }
}

529
void SimpleJob::slotError( int err, const QString & errorText )
530
{
531
    Q_D(SimpleJob);
532
533
    setError( err );
    setErrorText( errorText );
534
    if ((error() == ERR_UNKNOWN_HOST) && d->m_url.host().isEmpty())
535
       setErrorText( QString() );
536
537
538
539
540
541
    // error terminates the job
    slotFinished();
}

void SimpleJob::slotWarning( const QString & errorText )
{
542
    emit warning( this, errorText );
543
544
}

545
void SimpleJobPrivate::_k_slotSlaveInfoMessage( const QString & msg )
546
{
547
    emit q_func()->infoMessage( q_func(), msg );
548
549
}

550
void SimpleJobPrivate::slotConnected()
551
{
552
    emit q_func()->connected( q_func() );
553
554
}

555
void SimpleJobPrivate::slotTotalSize( KIO::filesize_t size )
556
{
557
    Q_Q(SimpleJob);
558
    if (size != q->totalAmount(KJob::Bytes))
559
    {
560
        q->setTotalAmount(KJob::Bytes, size);
561
    }
562
563
}

564
void SimpleJobPrivate::slotProcessedSize( KIO::filesize_t size )
565
{
566
    Q_Q(SimpleJob);
567
    //kDebug(7007) << KIO::number(size);
568
    q->setProcessedAmount(KJob::Bytes, size);
569
570
}

571
void SimpleJobPrivate::slotSpeed( unsigned long speed )
572
{
573
    //kDebug(7007) << speed;
574
    q_func()->emitSpeed( speed );
575
576
}

577
578
579
580
581
582
583
584
585
586
587
588
589
590
void SimpleJobPrivate::restartAfterRedirection(KUrl *redirectionUrl)
{
    Q_Q(SimpleJob);
    // Return slave to the scheduler while we still have the old URL in place; the scheduler
    // requires a job URL to stay invariant while the job is running.
    slaveDone();

    m_url = *redirectionUrl;
    redirectionUrl->clear();
    if ((m_extraFlags & EF_KillCalled) == 0) {
        Scheduler::doJob(q);
    }
}

591
void SimpleJob::slotMetaData( const KIO::MetaData &_metaData )
592
{
593
    Q_D(SimpleJob);
594
595
596
597
598
599
600
601
    QMapIterator<QString,QString> it (_metaData);
    while (it.hasNext()) {
        it.next();
        if (it.key().startsWith(QLatin1String("{internal~"), Qt::CaseInsensitive))
            d->m_internalMetaData.insert(it.key(), it.value());
        else
            d->m_incomingMetaData.insert(it.key(), it.value());
    }
602
603
}

604
605
void SimpleJob::storeSSLSessionFromJob(const KUrl &redirectionURL)
{
606
    Q_UNUSED(redirectionURL);
607
608
}

609

Waldo Bastian's avatar
Waldo Bastian committed
610
//////////
611
612
613
class KIO::MkdirJobPrivate: public SimpleJobPrivate
{
public:
614
615
616
617
618
619
620
621
622
623
624
625
626
627
    MkdirJobPrivate(const KUrl& url, int command, const QByteArray &packedArgs)
        : SimpleJobPrivate(url, command, packedArgs)
        { }
    KUrl m_redirectionURL;
    void slotRedirection(const KUrl &url);

    /**
     * @internal
     * Called by the scheduler when a @p slave gets to
     * work on this job.
     * @param slave the slave that starts working on this job
     */
    virtual void start( Slave *slave );

628
    Q_DECLARE_PUBLIC(MkdirJob)
629
630
631
632
633
634
635

    static inline MkdirJob *newJob(const KUrl& url, int command, const QByteArray &packedArgs)
    {
        MkdirJob *job = new MkdirJob(*new MkdirJobPrivate(url, command, packedArgs));
        job->setUiDelegate(new JobUiDelegate);
        return job;
    }
636
637
};

638
639
MkdirJob::MkdirJob(MkdirJobPrivate &dd)
    : SimpleJob(dd)
640
641
642
643
{
}

MkdirJob::~MkdirJob()
Waldo Bastian's avatar
Waldo Bastian committed
644
645
646
{
}

647
void MkdirJobPrivate::start(Slave *slave)
Waldo Bastian's avatar
Waldo Bastian committed
648
{
649
650
651
    Q_Q(MkdirJob);
    q->connect( slave, SIGNAL( redirection(const KUrl &) ),
                SLOT( slotRedirection(const KUrl &) ) );
652

653
    SimpleJobPrivate::start(slave);
Waldo Bastian's avatar
Waldo Bastian committed
654
655
656
}

// Slave got a redirection request
657
void MkdirJobPrivate::slotRedirection( const KUrl &url)
Waldo Bastian's avatar
Waldo Bastian committed
658
{
659
     Q_Q(MkdirJob);
660
     kDebug(7007) << url;
661
     if (!KAuthorized::authorizeUrlAction("redirect", m_url, url))
Waldo Bastian's avatar
Waldo Bastian committed
662
     {
663
         kWarning(7007) << "Redirection from" << m_url << "to" << url << "REJECTED!";
664
         q->setError( ERR_ACCESS_DENIED );
665
         q->setErrorText( url.pathOrUrl() );
666
         return;
Waldo Bastian's avatar
Waldo Bastian committed
667
668
669
     }
     m_redirectionURL = url; // We'll remember that when the job finishes
     // Tell the user that we haven't finished yet
670
     emit q->redirection(q, m_redirectionURL);
Waldo Bastian's avatar
Waldo Bastian committed
671
672
673
674
}

void MkdirJob::slotFinished()
{
675
    Q_D(MkdirJob);
676
677

    if ( !d->m_redirectionURL.isEmpty() && d->m_redirectionURL.isValid() )
Waldo Bastian's avatar
Waldo Bastian committed
678
    {
Laurent Montel's avatar
Laurent Montel committed
679
        //kDebug(7007) << "MkdirJob: Redirection to " << m_redirectionURL;
Waldo Bastian's avatar
Waldo Bastian committed
680
        if (queryMetaData("permanent-redirect")=="true")
681
            emit permanentRedirection(this, d->m_url, d->m_redirectionURL);
682

683
684
685
686
687
688
        if ( d->m_redirectionHandlingEnabled )
        {
            KUrl dummyUrl;
            int permissions;
            QDataStream istream( d->m_packedArgs );
            istream >> dummyUrl >> permissions;
Waldo Bastian's avatar
Waldo Bastian committed
689

690
691
692
693
694
695
696
            d->m_packedArgs.truncate(0);
            QDataStream stream( &d->m_packedArgs, QIODevice::WriteOnly );
            stream << d->m_redirectionURL << permissions;

            d->restartAfterRedirection(&d->m_redirectionURL);
            return;
        }
Waldo Bastian's avatar
Waldo Bastian committed
697
    }
698
699
700

    // Return slave to the scheduler
    SimpleJob::slotFinished();
Waldo Bastian's avatar
Waldo Bastian committed
701
702
}

703
SimpleJob *KIO::mkdir( const KUrl& url, int permissions )
704
{
Laurent Montel's avatar
Laurent Montel committed
705
    //kDebug(7007) << "mkdir " << url;
706
    KIO_ARGS << url << permissions;
707
    return MkdirJobPrivate::newJob(url, CMD_MKDIR, packedArgs);
708
709
}

710
SimpleJob *KIO::rmdir( const KUrl& url )
711
{
Laurent Montel's avatar
Laurent Montel committed
712
    //kDebug(7007) << "rmdir " << url;
713
    KIO_ARGS << url << qint8(false); // isFile is false
714
    return SimpleJobPrivate::newJob(url, CMD_DEL, packedArgs);
715
716
}

717
SimpleJob *KIO::chmod( const KUrl& url, int permissions )
718
{
Laurent Montel's avatar
Laurent Montel committed
719
    //kDebug(7007) << "chmod " << url;
720
    KIO_ARGS << url << permissions;
721
    return SimpleJobPrivate::newJob(url, CMD_CHMOD, packedArgs);
722
723
}

724
725
726
SimpleJob *KIO::chown( const KUrl& url, const QString& owner, const QString& group )
{
    KIO_ARGS << url << owner << group;
727
    return SimpleJobPrivate::newJob(url, CMD_CHOWN, packedArgs);
728
729
}

730
731
SimpleJob *KIO::setModificationTime( const KUrl& url, const QDateTime& mtime )
{
Laurent Montel's avatar
Laurent Montel committed
732
    //kDebug(7007) << "setModificationTime " << url << " " << mtime;
733
    KIO_ARGS << url << mtime;
734
    return SimpleJobPrivate::newJobNoUi(url, CMD_SETMODIFICATIONTIME, packedArgs);
735
736
}

David Faure's avatar
David Faure committed
737
SimpleJob *KIO::rename( const KUrl& src, const KUrl & dest, JobFlags flags )
738
{
Laurent Montel's avatar
Laurent Montel committed
739
    //kDebug(7007) << "rename " << src << " " << dest;
David Faure's avatar
David Faure committed
740
    KIO_ARGS << src << dest << (qint8) (flags & Overwrite);
741
    return SimpleJobPrivate::newJob(src, CMD_RENAME, packedArgs);
742
743
}

David Faure's avatar
David Faure committed
744
SimpleJob *KIO::symlink( const QString& target, const KUrl & dest, JobFlags flags )
745
{
Laurent Montel's avatar
Laurent Montel committed
746
    //kDebug(7007) << "symlink target=" << target << " " << dest;
David Faure's avatar
David Faure committed
747
748
    KIO_ARGS << target << dest << (qint8) (flags & Overwrite);
    return SimpleJobPrivate::newJob(dest, CMD_SYMLINK, packedArgs, flags);
749
750
}

David Faure's avatar
David Faure committed
751
SimpleJob *KIO::special(const KUrl& url, const QByteArray & data, JobFlags flags)
752
{
Laurent Montel's avatar
Laurent Montel committed
753
    //kDebug(7007) << "special " << url;
David Faure's avatar
David Faure committed
754
    return SimpleJobPrivate::newJob(url, CMD_SPECIAL, data, flags);
755
756
}

David Faure's avatar
David Faure committed
757
SimpleJob *KIO::mount( bool ro, const QByteArray& fstype, const QString& dev, const QString& point, JobFlags flags )
758
{
759
    KIO_ARGS << int(1) << qint8( ro ? 1 : 0 )
760
             << QString::fromLatin1(fstype) << dev << point;
David Faure's avatar
David Faure committed
761
762
    SimpleJob *job = special( KUrl("file:/"), packedArgs, flags );
    if (!(flags & HideProgressInfo)) {
763
        KIO::JobPrivate::emitMounting(job, dev, point);
764
    }
765
766
767
    return job;
}

David Faure's avatar
David Faure committed
768
SimpleJob *KIO::unmount( const QString& point, JobFlags flags )
769
770
{
    KIO_ARGS << int(2) << point;
David Faure's avatar
David Faure committed
771
772
    SimpleJob *job = special( KUrl("file:/"), packedArgs, flags );
    if (!(flags & HideProgressInfo)) {
773
        KIO::JobPrivate::emitUnmounting(job, point);
774
    }
775
776
777
    return job;
}

Waldo Bastian's avatar
Waldo Bastian committed
778
779


780
781
//////////

782
783
784
class KIO::StatJobPrivate: public SimpleJobPrivate
{
public:
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
    inline StatJobPrivate(const KUrl& url, int command, const QByteArray &packedArgs)
        : SimpleJobPrivate(url, command, packedArgs), m_bSource(true), m_details(2)
        {}

    UDSEntry m_statResult;
    KUrl m_redirectionURL;
    bool m_bSource;
    short int m_details;
    void slotStatEntry( const KIO::UDSEntry & entry );
    void slotRedirection( const KUrl &url);

    /**
     * @internal
     * Called by the scheduler when a @p slave gets to
     * work on this job.
     * @param slave the slave that starts working on this job
     */
    virtual void start( Slave *slave );

804
    Q_DECLARE_PUBLIC(StatJob)
805
806

    static inline StatJob *newJob(const KUrl& url, int command, const QByteArray &packedArgs,
David Faure's avatar
David Faure committed
807
        JobFlags flags )
808
809
810
    {
        StatJob *job = new StatJob(*new StatJobPrivate(url, command, packedArgs));
        job->setUiDelegate(new JobUiDelegate);
David Faure's avatar
David Faure committed
811
        if (!(flags & HideProgressInfo)) {
812
813
814
815
816
            KIO::getJobTracker()->registerJob(job);
            emitStating(job, url);
        }
        return job;
    }
817
818
};

819
820
StatJob::StatJob(StatJobPrivate &dd)
    : SimpleJob(dd)
821
822
823
824
825
826
827
{
}

StatJob::~StatJob()
{
}

828
#ifndef KDE_NO_DEPRECATED
829
830
void StatJob::setSide( bool source )
{
831
832
    d_func()->m_bSource = source;
}
833
#endif
834
835
836
837

void StatJob::setSide( StatSide side )
{
    d_func()->m_bSource = side == SourceSide;
838
839
840
841
}

void StatJob::setDetails( short int details )
{
842
    d_func()->m_details = details;
843
844
845
}

const UDSEntry & StatJob::statResult() const
846
{
847
    return d_func()->m_statResult;
848
849
}

850
851
852
853
854
855
856
857
858
859
860
KUrl StatJob::mostLocalUrl() const
{
    if (!url().isLocalFile()) {
        const UDSEntry& udsEntry = d_func()->m_statResult;
        const QString path = udsEntry.stringValue( KIO::UDSEntry::UDS_LOCAL_PATH );
        if (!path.isEmpty())
            return KUrl(path);
    }
    return url();
}

861
void StatJobPrivate::start(Slave *slave)
862
{
863
    Q_Q(StatJob);
David Faure's avatar
David Faure committed
864
865
    m_outgoingMetaData.insert( "statSide", m_bSource ? "source" : "dest" );
    m_outgoingMetaData.insert( "details", QString::number(m_details) );
866

867
    q->connect( slave, SIGNAL( statEntry( const KIO::UDSEntry& ) ),
868
             SLOT( slotStatEntry( const KIO::UDSEntry & ) ) );
869
    q->connect( slave, SIGNAL( redirection(const KUrl &) ),