• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • tdeio/tdeio
 

tdeio/tdeio

  • tdeio
  • tdeio
job.cpp
1 /* This file is part of the KDE libraries
2  Copyright (C) 2000 Stephan Kulow <coolo@kde.org>
3  David Faure <faure@kde.org>
4  Waldo Bastian <bastian@kde.org>
5 
6  This library is free software; you can redistribute it and/or
7  modify it under the terms of the GNU Library General Public
8  License as published by the Free Software Foundation; either
9  version 2 of the License, or (at your option) any later version.
10 
11  This library is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  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
18  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  Boston, MA 02110-1301, USA.
20 */
21 
22 #include "tdeio/job.h"
23 
24 #include <config.h>
25 
26 #include <sys/types.h>
27 #include <sys/wait.h>
28 #include <sys/stat.h>
29 
30 #include <assert.h>
31 
32 #include <signal.h>
33 #include <stdlib.h>
34 #include <stdio.h>
35 #include <time.h>
36 #include <unistd.h>
37 extern "C" {
38 #include <pwd.h>
39 #include <grp.h>
40 }
41 #include <tqtimer.h>
42 #include <tqfile.h>
43 
44 #include <tdeapplication.h>
45 #include <tdeglobal.h>
46 #include <tdelocale.h>
47 #include <ksimpleconfig.h>
48 #include <kdebug.h>
49 #include <kdialog.h>
50 #include <tdemessagebox.h>
51 #include <kdatastream.h>
52 #include <tdemainwindow.h>
53 #include <kde_file.h>
54 
55 #include <errno.h>
56 
57 #include "kmimetype.h"
58 #include "slave.h"
59 #include "scheduler.h"
60 #include "kdirwatch.h"
61 #include "kmimemagic.h"
62 #include "kprotocolinfo.h"
63 #include "tdeprotocolmanager.h"
64 
65 #include "tdeio/observer.h"
66 
67 #include "kssl/ksslcsessioncache.h"
68 
69 #include <kdirnotify_stub.h>
70 #include <tdetempfile.h>
71 #include <dcopclient.h>
72 
73 #ifdef Q_OS_UNIX
74 #include <utime.h>
75 #endif
76 #if defined TQ_WS_X11
77 #include <netwm.h>
78 #include <fixx11h.h>
79 #endif
80 
81 using namespace TDEIO;
82 template class TQPtrList<TDEIO::Job>;
83 
84 //this will update the report dialog with 5 Hz, I think this is fast enough, aleXXX
85 #define REPORT_TIMEOUT 200
86 
87 #define TDEIO_ARGS TQByteArray packedArgs; TQDataStream stream( packedArgs, IO_WriteOnly ); stream
88 
89 class Job::JobPrivate
90 {
91 public:
92  JobPrivate() : m_autoErrorHandling(false), m_autoWarningHandling(true),
93  m_interactive(true), m_errorParentWidgetGP(0), m_parentJob(0L),
94  m_extraFlags(0), m_processedSize(0), m_userTimestamp(0)
95  {}
96 
97  ~JobPrivate()
98  {
99  if (m_errorParentWidgetGP)
100  {
101  delete m_errorParentWidgetGP;
102  }
103  }
104 
105  bool m_autoErrorHandling;
106  bool m_autoWarningHandling;
107  bool m_interactive;
108  TQGuardedPtr<TQWidget> *m_errorParentWidgetGP;
109  // Maybe we could use the TQObject parent/child mechanism instead
110  // (requires a new ctor, and moving the ctor code to some init()).
111  Job* m_parentJob;
112  int m_extraFlags;
113  TDEIO::filesize_t m_processedSize;
114  unsigned long m_userTimestamp;
115 };
116 
117 static TQObject *__job_root_obj = nullptr;
118 
119 static TQObject* __getJobRoot()
120 {
121  if (!__job_root_obj)
122  {
123  __job_root_obj = new TQObject(0, "jobroot");
124  }
125  return __job_root_obj;
126 }
127 
128 Job::Job(bool showProgressInfo) : TQObject(__getJobRoot(), "job"), m_error(0), m_percent(0)
129  , m_progressId(0), m_speedTimer(0), d( new JobPrivate )
130 {
131  // All jobs delete themselves after emiting 'result'.
132 
133  // Notify the UI Server and get a progress id
134  if ( showProgressInfo )
135  {
136  m_progressId = Observer::self()->newJob( this, true );
137  addMetaData("progress-id", TQString::number(m_progressId));
138  //kdDebug(7007) << "Created job " << this << " with progress info -- m_progressId=" << m_progressId << endl;
139  // Connect global progress info signals
140  connect( this, TQ_SIGNAL( percent( TDEIO::Job*, unsigned long ) ),
141  Observer::self(), TQ_SLOT( slotPercent( TDEIO::Job*, unsigned long ) ) );
142  connect( this, TQ_SIGNAL( infoMessage( TDEIO::Job*, const TQString & ) ),
143  Observer::self(), TQ_SLOT( slotInfoMessage( TDEIO::Job*, const TQString & ) ) );
144  connect( this, TQ_SIGNAL( totalSize( TDEIO::Job*, TDEIO::filesize_t ) ),
145  Observer::self(), TQ_SLOT( slotTotalSize( TDEIO::Job*, TDEIO::filesize_t ) ) );
146  connect( this, TQ_SIGNAL( processedSize( TDEIO::Job*, TDEIO::filesize_t ) ),
147  Observer::self(), TQ_SLOT( slotProcessedSize( TDEIO::Job*, TDEIO::filesize_t ) ) );
148  connect( this, TQ_SIGNAL( speed( TDEIO::Job*, unsigned long ) ),
149  Observer::self(), TQ_SLOT( slotSpeed( TDEIO::Job*, unsigned long ) ) );
150  }
151  // Don't exit while this job is running
152  if (kapp)
153  kapp->ref();
154  if (kapp)
155  updateUserTimestamp( kapp->userTimestamp());
156 }
157 
158 Job::~Job()
159 {
160  delete m_speedTimer;
161  delete d;
162  if (kapp)
163  {
164  kapp->deref();
165  }
166 }
167 
168 int& Job::extraFlags()
169 {
170  return d->m_extraFlags;
171 }
172 
173 void Job::setProcessedSize(TDEIO::filesize_t size)
174 {
175  d->m_processedSize = size;
176 }
177 
178 TDEIO::filesize_t Job::getProcessedSize()
179 {
180  return d->m_processedSize;
181 }
182 
183 void Job::addSubjob(Job *job, bool inheritMetaData)
184 {
185  //kdDebug(7007) << "addSubjob(" << job << ") this = " << this << endl;
186  subjobs.append(job);
187 
188  connect( job, TQ_SIGNAL(result(TDEIO::Job*)),
189  TQ_SLOT(slotResult(TDEIO::Job*)) );
190 
191  // Forward information from that subjob.
192  connect( job, TQ_SIGNAL(speed( TDEIO::Job*, unsigned long )),
193  TQ_SLOT(slotSpeed(TDEIO::Job*, unsigned long)) );
194 
195  connect( job, TQ_SIGNAL(infoMessage( TDEIO::Job*, const TQString & )),
196  TQ_SLOT(slotInfoMessage(TDEIO::Job*, const TQString &)) );
197 
198  if (inheritMetaData)
199  job->mergeMetaData(m_outgoingMetaData);
200 
201  job->setWindow( m_window );
202  job->updateUserTimestamp( d->m_userTimestamp );
203 }
204 
205 void Job::removeSubjob( Job *job )
206 {
207  removeSubjob( job, false, true );
208 }
209 
210 void Job::removeSubjob( Job *job, bool mergeMetaData, bool emitResultIfLast )
211 {
212  //kdDebug(7007) << "removeSubjob(" << job << ") this = " << this << " subjobs = " << subjobs.count() << endl;
213  // Merge metadata from subjob
214  if ( mergeMetaData )
215  m_incomingMetaData += job->metaData();
216  subjobs.remove(job);
217  if ( subjobs.isEmpty() && emitResultIfLast )
218  emitResult();
219 }
220 
221 void Job::emitPercent( TDEIO::filesize_t processedSize, TDEIO::filesize_t totalSize )
222 {
223  // calculate percents
224  unsigned long ipercent = m_percent;
225 
226  if ( totalSize == 0 )
227  m_percent = 100;
228  else
229  m_percent = (unsigned long)(( (float)(processedSize) / (float)(totalSize) ) * 100.0);
230 
231  if ( m_percent != ipercent || m_percent == 100 /* for those buggy total sizes that grow */ ) {
232  emit percent( this, m_percent );
233  //kdDebug(7007) << "Job::emitPercent - percent = " << (unsigned int) m_percent << endl;
234  }
235 }
236 
237 void Job::emitSpeed( unsigned long bytes_per_second )
238 {
239  //kdDebug(7007) << "Job " << this << " emitSpeed " << bytes_per_second << endl;
240  if ( !m_speedTimer )
241  {
242  m_speedTimer = new TQTimer();
243  connect( m_speedTimer, TQ_SIGNAL( timeout() ), TQ_SLOT( slotSpeedTimeout() ) );
244  }
245  emit speed( this, bytes_per_second );
246  m_speedTimer->start( 5000 ); // 5 seconds interval should be enough
247 }
248 
249 void Job::emitResult()
250 {
251  // If we are displaying a progress dialog, remove it first.
252  if ( m_progressId ) // Did we get an ID from the observer ?
253  Observer::self()->jobFinished( m_progressId );
254  if ( m_error && d->m_interactive && d->m_autoErrorHandling )
255  showErrorDialog( d->m_errorParentWidgetGP ? *d->m_errorParentWidgetGP : nullptr);
256  emit result(this);
257  deleteLater();
258 }
259 
260 void Job::kill( bool quietly )
261 {
262  kdDebug(7007) << "Job::kill this=" << this << " " << className() << " m_progressId=" << m_progressId << " quietly=" << quietly << endl;
263  // kill all subjobs, without triggering their result slot
264  TQPtrListIterator<Job> it( subjobs );
265  for ( ; it.current() ; ++it )
266  (*it)->kill( true );
267  subjobs.clear();
268 
269  if ( ! quietly ) {
270  m_error = ERR_USER_CANCELED;
271  emit canceled( this ); // Not very useful (deprecated)
272  emitResult();
273  } else
274  {
275  if ( m_progressId ) // in both cases we want to hide the progress window
276  Observer::self()->jobFinished( m_progressId );
277  deleteLater();
278  }
279 }
280 
281 void Job::slotResult( Job *job )
282 {
283  // Did job have an error ?
284  if ( job->error() && !m_error )
285  {
286  // Store it in the parent only if first error
287  m_error = job->error();
288  m_errorText = job->errorText();
289  }
290  removeSubjob(job);
291 }
292 
293 void Job::slotSpeed( TDEIO::Job*, unsigned long speed )
294 {
295  //kdDebug(7007) << "Job::slotSpeed " << speed << endl;
296  emitSpeed( speed );
297 }
298 
299 void Job::slotInfoMessage( TDEIO::Job*, const TQString & msg )
300 {
301  emit infoMessage( this, msg );
302 }
303 
304 void Job::slotSpeedTimeout()
305 {
306  //kdDebug(7007) << "slotSpeedTimeout()" << endl;
307  // send 0 and stop the timer
308  // timer will be restarted only when we receive another speed event
309  emit speed( this, 0 );
310  m_speedTimer->stop();
311 }
312 
313 //Job::errorString is implemented in global.cpp
314 
315 void Job::showErrorDialog( TQWidget * parent )
316 {
317  //kdDebug(7007) << "Job::showErrorDialog parent=" << parent << endl;
318  kapp->enableStyles();
319  // Show a message box, except for "user canceled" or "no content"
320  if ( (m_error != ERR_USER_CANCELED) && (m_error != ERR_NO_CONTENT) ) {
321  //old plain error message
322  //kdDebug(7007) << "Default language: " << TDEGlobal::locale()->defaultLanguage() << endl;
323  if ( 1 )
324  KMessageBox::queuedMessageBox( parent, KMessageBox::Error, errorString() );
325 #if 0
326  } else {
327  TQStringList errors = detailedErrorStrings();
328  TQString caption, err, detail;
329  TQStringList::const_iterator it = errors.begin();
330  if ( it != errors.end() )
331  caption = *(it++);
332  if ( it != errors.end() )
333  err = *(it++);
334  if ( it != errors.end() )
335  detail = *it;
336  KMessageBox::queuedDetailedError( parent, err, detail, caption );
337  }
338 #endif
339  }
340 }
341 
342 void Job::setAutoErrorHandlingEnabled( bool enable, TQWidget *parentWidget )
343 {
344  if (d->m_errorParentWidgetGP && (TQWidget*)(*d->m_errorParentWidgetGP) != parentWidget)
345  {
346  delete d->m_errorParentWidgetGP;
347  d->m_errorParentWidgetGP = nullptr;
348  }
349  d->m_autoErrorHandling = enable;
350  if (enable && parentWidget && !d->m_errorParentWidgetGP)
351  {
352  d->m_errorParentWidgetGP = new TQGuardedPtr<TQWidget>(parentWidget);
353  }
354 }
355 
356 bool Job::isAutoErrorHandlingEnabled() const
357 {
358  return d->m_autoErrorHandling;
359 }
360 
361 void Job::setAutoWarningHandlingEnabled( bool enable )
362 {
363  d->m_autoWarningHandling = enable;
364 }
365 
366 bool Job::isAutoWarningHandlingEnabled() const
367 {
368  return d->m_autoWarningHandling;
369 }
370 
371 void Job::setInteractive(bool enable)
372 {
373  d->m_interactive = enable;
374 }
375 
376 bool Job::isInteractive() const
377 {
378  return d->m_interactive;
379 }
380 
381 void Job::setWindow(TQWidget *window)
382 {
383  m_window = window;
384  TDEIO::Scheduler::registerWindow(window);
385 }
386 
387 TQWidget *Job::window() const
388 {
389  return m_window;
390 }
391 
392 void Job::updateUserTimestamp( unsigned long time )
393 {
394 #if defined TQ_WS_X11
395  if( d->m_userTimestamp == 0 || NET::timestampCompare( time, d->m_userTimestamp ) > 0 )
396  d->m_userTimestamp = time;
397 #endif
398 }
399 
400 unsigned long Job::userTimestamp() const
401 {
402  return d->m_userTimestamp;
403 }
404 
405 void Job::setParentJob(Job* job)
406 {
407  Q_ASSERT(d->m_parentJob == 0L);
408  Q_ASSERT(job);
409  d->m_parentJob = job;
410 }
411 
412 Job* Job::parentJob() const
413 {
414  return d->m_parentJob;
415 }
416 
417 MetaData Job::metaData() const
418 {
419  return m_incomingMetaData;
420 }
421 
422 TQString Job::queryMetaData(const TQString &key)
423 {
424  if (!m_incomingMetaData.contains(key))
425  return TQString::null;
426  return m_incomingMetaData[key];
427 }
428 
429 void Job::setMetaData( const TDEIO::MetaData &_metaData)
430 {
431  m_outgoingMetaData = _metaData;
432 }
433 
434 void Job::addMetaData( const TQString &key, const TQString &value)
435 {
436  m_outgoingMetaData.insert(key, value);
437 }
438 
439 void Job::addMetaData( const TQMap<TQString,TQString> &values)
440 {
441  TQMapConstIterator<TQString,TQString> it = values.begin();
442  for(;it != values.end(); ++it)
443  m_outgoingMetaData.insert(it.key(), it.data());
444 }
445 
446 void Job::mergeMetaData( const TQMap<TQString,TQString> &values)
447 {
448  TQMapConstIterator<TQString,TQString> it = values.begin();
449  for(;it != values.end(); ++it)
450  m_outgoingMetaData.insert(it.key(), it.data(), false);
451 }
452 
453 MetaData Job::outgoingMetaData() const
454 {
455  return m_outgoingMetaData;
456 }
457 
458 
459 SimpleJob::SimpleJob(const KURL& url, int command, const TQByteArray &packedArgs,
460  bool showProgressInfo )
461  : Job(showProgressInfo), m_slave(0), m_packedArgs(packedArgs),
462  m_url(url), m_command(command), m_totalSize(0)
463 {
464  if (m_url.hasSubURL())
465  {
466  KURL::List list = KURL::split(m_url);
467  KURL::List::Iterator it = list.fromLast();
468  list.remove(it);
469  m_subUrl = KURL::join(list);
470  //kdDebug(7007) << "New URL = " << m_url.url() << endl;
471  //kdDebug(7007) << "Sub URL = " << m_subUrl.url() << endl;
472  }
473 
474  Scheduler::doJob(this);
475 
476  if (!m_url.isValid())
477  {
478  kdDebug() << "ERR_MALFORMED_URL" << endl;
479  m_error = ERR_MALFORMED_URL;
480  m_errorText = m_url.url();
481  TQTimer::singleShot(0, this, TQ_SLOT(slotFinished()) );
482  return;
483  }
484 }
485 
486 void SimpleJob::kill( bool quietly )
487 {
488  Scheduler::cancelJob( this ); // deletes the slave if not 0
489  m_slave = 0; // -> set to 0
490  Job::kill( quietly );
491 }
492 
493 void SimpleJob::putOnHold()
494 {
495  Q_ASSERT( m_slave );
496  if ( m_slave )
497  {
498  Scheduler::putSlaveOnHold(this, m_url);
499  m_slave = 0;
500  }
501  kill(true);
502 }
503 
504 void SimpleJob::removeOnHold()
505 {
506  Scheduler::removeSlaveOnHold();
507 }
508 
509 SimpleJob::~SimpleJob()
510 {
511  if (m_slave) // was running
512  {
513  kdDebug(7007) << "SimpleJob::~SimpleJob: Killing running job in destructor!" << endl;
514 #if 0
515  m_slave->kill();
516  Scheduler::jobFinished( this, m_slave ); // deletes the slave
517 #endif
518  Scheduler::cancelJob( this );
519  m_slave = 0; // -> set to 0
520  }
521 }
522 
523 void SimpleJob::start(Slave *slave)
524 {
525  m_slave = slave;
526 
527  connect( m_slave, TQ_SIGNAL( error( int , const TQString & ) ),
528  TQ_SLOT( slotError( int , const TQString & ) ) );
529 
530  connect( m_slave, TQ_SIGNAL( warning( const TQString & ) ),
531  TQ_SLOT( slotWarning( const TQString & ) ) );
532 
533  connect( m_slave, TQ_SIGNAL( infoMessage( const TQString & ) ),
534  TQ_SLOT( slotInfoMessage( const TQString & ) ) );
535 
536  connect( m_slave, TQ_SIGNAL( connected() ),
537  TQ_SLOT( slotConnected() ) );
538 
539  connect( m_slave, TQ_SIGNAL( finished() ),
540  TQ_SLOT( slotFinished() ) );
541 
542  if ((extraFlags() & EF_TransferJobDataSent) == 0)
543  {
544  connect( m_slave, TQ_SIGNAL( totalSize( TDEIO::filesize_t ) ),
545  TQ_SLOT( slotTotalSize( TDEIO::filesize_t ) ) );
546 
547  connect( m_slave, TQ_SIGNAL( processedSize( TDEIO::filesize_t ) ),
548  TQ_SLOT( slotProcessedSize( TDEIO::filesize_t ) ) );
549 
550  connect( m_slave, TQ_SIGNAL( speed( unsigned long ) ),
551  TQ_SLOT( slotSpeed( unsigned long ) ) );
552  }
553 
554  connect( slave, TQ_SIGNAL( needProgressId() ),
555  TQ_SLOT( slotNeedProgressId() ) );
556 
557  connect( slave, TQ_SIGNAL(metaData( const TDEIO::MetaData& ) ),
558  TQ_SLOT( slotMetaData( const TDEIO::MetaData& ) ) );
559 
560  if (m_window)
561  {
562  TQString id;
563  addMetaData("window-id", id.setNum((ulong)m_window->winId()));
564  }
565  if (userTimestamp())
566  {
567  TQString id;
568  addMetaData("user-timestamp", id.setNum(userTimestamp()));
569  }
570 
571  TQString sslSession = KSSLCSessionCache::getSessionForURL(m_url);
572  if ( !sslSession.isNull() )
573  {
574  addMetaData("ssl_session_id", sslSession);
575  }
576 
577  if (!isInteractive())
578  {
579  addMetaData("no-auth-prompt", "true");
580  }
581 
582  if (!m_outgoingMetaData.isEmpty())
583  {
584  TDEIO_ARGS << m_outgoingMetaData;
585  slave->send( CMD_META_DATA, packedArgs );
586  }
587 
588  if (!m_subUrl.isEmpty())
589  {
590  TDEIO_ARGS << m_subUrl;
591  m_slave->send( CMD_SUBURL, packedArgs );
592  }
593 
594  m_slave->send( m_command, m_packedArgs );
595 }
596 
597 void SimpleJob::slaveDone()
598 {
599  if (!m_slave) return;
600  disconnect(m_slave); // Remove all signals between slave and job
601  Scheduler::jobFinished( this, m_slave );
602  m_slave = 0;
603 }
604 
605 void SimpleJob::slotFinished( )
606 {
607  // Return slave to the scheduler
608  slaveDone();
609 
610  if (subjobs.isEmpty())
611  {
612  if ( !m_error && (m_command == CMD_MKDIR || m_command == CMD_RENAME ) )
613  {
614  KDirNotify_stub allDirNotify( "*", "KDirNotify*" );
615  if ( m_command == CMD_MKDIR )
616  {
617  KURL urlDir( url() );
618  urlDir.setPath( urlDir.directory() );
619  allDirNotify.FilesAdded( urlDir );
620  }
621  else /*if ( m_command == CMD_RENAME )*/
622  {
623  KURL src, dst;
624  TQDataStream str( m_packedArgs, IO_ReadOnly );
625  str >> src >> dst;
626  if ( src.directory() == dst.directory() ) // For the user, moving isn't renaming. Only renaming is.
627  allDirNotify.FileRenamed( src, dst );
628  }
629  }
630  emitResult();
631  }
632 }
633 
634 void SimpleJob::slotError( int error, const TQString & errorText )
635 {
636  m_error = error;
637  m_errorText = errorText;
638  if ((m_error == ERR_UNKNOWN_HOST) && m_url.host().isEmpty())
639  m_errorText = TQString::null;
640  // error terminates the job
641  slotFinished();
642 }
643 
644 void SimpleJob::slotWarning( const TQString & errorText )
645 {
646  TQGuardedPtr<SimpleJob> guard( this );
647  if (isInteractive() && isAutoWarningHandlingEnabled())
648  {
649  static uint msgBoxDisplayed = 0;
650  if ( msgBoxDisplayed == 0 ) // don't bomb the user with message boxes, only one at a time
651  {
652  msgBoxDisplayed++;
653  KMessageBox::information( 0L, errorText );
654  msgBoxDisplayed--;
655  }
656  // otherwise just discard it.
657  }
658 
659  if ( !guard.isNull() )
660  emit warning( this, errorText );
661 }
662 
663 void SimpleJob::slotInfoMessage( const TQString & msg )
664 {
665  emit infoMessage( this, msg );
666 }
667 
668 void SimpleJob::slotConnected()
669 {
670  emit connected( this );
671 }
672 
673 void SimpleJob::slotNeedProgressId()
674 {
675  if ( !m_progressId )
676  m_progressId = Observer::self()->newJob( this, false );
677  m_slave->setProgressId( m_progressId );
678 }
679 
680 void SimpleJob::slotTotalSize( TDEIO::filesize_t size )
681 {
682  if (size > m_totalSize)
683  {
684  m_totalSize = size;
685  emit totalSize( this, size );
686  }
687 }
688 
689 void SimpleJob::slotProcessedSize( TDEIO::filesize_t size )
690 {
691  //kdDebug(7007) << "SimpleJob::slotProcessedSize " << TDEIO::number(size) << endl;
692  setProcessedSize(size);
693  emit processedSize( this, size );
694  if ( size > m_totalSize ) {
695  slotTotalSize(size); // safety
696  }
697  emitPercent( size, m_totalSize );
698 }
699 
700 void SimpleJob::slotSpeed( unsigned long speed )
701 {
702  //kdDebug(7007) << "SimpleJob::slotSpeed( " << speed << " )" << endl;
703  emitSpeed( speed );
704 }
705 
706 void SimpleJob::slotMetaData( const TDEIO::MetaData &_metaData)
707 {
708  m_incomingMetaData += _metaData;
709 }
710 
711 void SimpleJob::storeSSLSessionFromJob(const KURL &m_redirectionURL) {
712  TQString sslSession = queryMetaData("ssl_session_id");
713 
714  if ( !sslSession.isNull() ) {
715  const KURL &queryURL = m_redirectionURL.isEmpty()?m_url:m_redirectionURL;
716  KSSLCSessionCache::putSessionForURL(queryURL, sslSession);
717  }
718 }
719 
721 MkdirJob::MkdirJob( const KURL& url, int command,
722  const TQByteArray &packedArgs, bool showProgressInfo )
723  : SimpleJob(url, command, packedArgs, showProgressInfo)
724 {
725 }
726 
727 void MkdirJob::start(Slave *slave)
728 {
729  connect( slave, TQ_SIGNAL( redirection(const KURL &) ),
730  TQ_SLOT( slotRedirection(const KURL &) ) );
731 
732  SimpleJob::start(slave);
733 }
734 
735 // Slave got a redirection request
736 void MkdirJob::slotRedirection( const KURL &url)
737 {
738  kdDebug(7007) << "MkdirJob::slotRedirection(" << url << ")" << endl;
739  if (!kapp->authorizeURLAction("redirect", m_url, url))
740  {
741  kdWarning(7007) << "MkdirJob: Redirection from " << m_url << " to " << url << " REJECTED!" << endl;
742  m_error = ERR_ACCESS_DENIED;
743  m_errorText = url.prettyURL();
744  return;
745  }
746  m_redirectionURL = url; // We'll remember that when the job finishes
747  if (m_url.hasUser() && !url.hasUser() && (m_url.host().lower() == url.host().lower()))
748  m_redirectionURL.setUser(m_url.user()); // Preserve user
749  // Tell the user that we haven't finished yet
750  emit redirection(this, m_redirectionURL);
751 }
752 
753 void MkdirJob::slotFinished()
754 {
755  if ( m_redirectionURL.isEmpty() || !m_redirectionURL.isValid())
756  {
757  // Return slave to the scheduler
758  SimpleJob::slotFinished();
759  } else {
760  //kdDebug(7007) << "MkdirJob: Redirection to " << m_redirectionURL << endl;
761  if (queryMetaData("permanent-redirect")=="true")
762  emit permanentRedirection(this, m_url, m_redirectionURL);
763  KURL dummyUrl;
764  int permissions;
765  TQDataStream istream( m_packedArgs, IO_ReadOnly );
766  istream >> dummyUrl >> permissions;
767 
768  m_url = m_redirectionURL;
769  m_redirectionURL = KURL();
770  m_packedArgs.truncate(0);
771  TQDataStream stream( m_packedArgs, IO_WriteOnly );
772  stream << m_url << permissions;
773 
774  // Return slave to the scheduler
775  slaveDone();
776  Scheduler::doJob(this);
777  }
778 }
779 
780 SimpleJob *TDEIO::mkdir( const KURL& url, int permissions )
781 {
782  //kdDebug(7007) << "mkdir " << url << endl;
783  TDEIO_ARGS << url << permissions;
784  return new MkdirJob(url, CMD_MKDIR, packedArgs, false);
785 }
786 
787 SimpleJob *TDEIO::rmdir( const KURL& url )
788 {
789  //kdDebug(7007) << "rmdir " << url << endl;
790  TDEIO_ARGS << url << TQ_INT8(false); // isFile is false
791  return new SimpleJob(url, CMD_DEL, packedArgs, false);
792 }
793 
794 SimpleJob *TDEIO::chmod( const KURL& url, int permissions )
795 {
796  //kdDebug(7007) << "chmod " << url << endl;
797  TDEIO_ARGS << url << permissions;
798  return new SimpleJob(url, CMD_CHMOD, packedArgs, false);
799 }
800 
801 SimpleJob *TDEIO::rename( const KURL& src, const KURL & dest, bool overwrite )
802 {
803  //kdDebug(7007) << "rename " << src << " " << dest << endl;
804  TDEIO_ARGS << src << dest << (TQ_INT8) overwrite;
805  return new SimpleJob(src, CMD_RENAME, packedArgs, false);
806 }
807 
808 SimpleJob *TDEIO::symlink( const TQString& target, const KURL & dest, bool overwrite, bool showProgressInfo )
809 {
810  //kdDebug(7007) << "symlink target=" << target << " " << dest << endl;
811  TDEIO_ARGS << target << dest << (TQ_INT8) overwrite;
812  return new SimpleJob(dest, CMD_SYMLINK, packedArgs, showProgressInfo);
813 }
814 
815 SimpleJob *TDEIO::special(const KURL& url, const TQByteArray & data, bool showProgressInfo)
816 {
817  //kdDebug(7007) << "special " << url << endl;
818  return new SimpleJob(url, CMD_SPECIAL, data, showProgressInfo);
819 }
820 
821 SimpleJob *TDEIO::mount( bool ro, const char *fstype, const TQString& dev, const TQString& point, bool showProgressInfo )
822 {
823  TDEIO_ARGS << int(1) << TQ_INT8( ro ? 1 : 0 )
824  << TQString::fromLatin1(fstype) << dev << point;
825  SimpleJob *job = special( KURL("file:/"), packedArgs, showProgressInfo );
826  if ( showProgressInfo )
827  Observer::self()->mounting( job, dev, point );
828  return job;
829 }
830 
831 SimpleJob *TDEIO::unmount( const TQString& point, bool showProgressInfo )
832 {
833  TDEIO_ARGS << int(2) << point;
834  SimpleJob *job = special( KURL("file:/"), packedArgs, showProgressInfo );
835  if ( showProgressInfo )
836  Observer::self()->unmounting( job, point );
837  return job;
838 }
839 
841 LocalURLJob::LocalURLJob( const KURL& url, int command,
842  const TQByteArray &packedArgs, bool showProgressInfo )
843  : SimpleJob(url, command, packedArgs, showProgressInfo)
844 {
845 
846 }
847 
848 void LocalURLJob::start(Slave *slave)
849 {
850  connect( slave, TQ_SIGNAL( localURL(const KURL &, bool) ),
851  TQ_SLOT( slotLocalURL(const KURL &, bool) ) );
852 
853  SimpleJob::start(slave);
854 }
855 
856 // Slave sent a response!
857 void LocalURLJob::slotLocalURL(const KURL &url, bool isLocal)
858 {
859  kdDebug(7007) << "LocalURLJob::slotLocalURL(" << url << ")" << endl;
860  emit localURL(this, url, isLocal);
861  deleteLater();
862 }
863 
864 void LocalURLJob::slotFinished()
865 {
866  // Return slave to the scheduler
867  SimpleJob::slotFinished();
868 }
869 
870 LocalURLJob *TDEIO::localURL( const KURL& remoteUrl )
871 {
872  TDEIO_ARGS << remoteUrl;
873  return new LocalURLJob(remoteUrl, CMD_LOCALURL, packedArgs, false);
874 }
875 
876 
878 
879 StatJob::StatJob( const KURL& url, int command,
880  const TQByteArray &packedArgs, bool showProgressInfo )
881  : SimpleJob(url, command, packedArgs, showProgressInfo),
882  m_bSource(true), m_details(2)
883 {
884 }
885 
886 void StatJob::start(Slave *slave)
887 {
888  m_outgoingMetaData.replace( "statSide", m_bSource ? "source" : "dest" );
889  m_outgoingMetaData.replace( "details", TQString::number(m_details) );
890 
891  connect( slave, TQ_SIGNAL( statEntry( const TDEIO::UDSEntry& ) ),
892  TQ_SLOT( slotStatEntry( const TDEIO::UDSEntry & ) ) );
893  connect( slave, TQ_SIGNAL( redirection(const KURL &) ),
894  TQ_SLOT( slotRedirection(const KURL &) ) );
895 
896  SimpleJob::start(slave);
897 }
898 
899 void StatJob::slotStatEntry( const TDEIO::UDSEntry & entry )
900 {
901  //kdDebug(7007) << "StatJob::slotStatEntry" << endl;
902  m_statResult = entry;
903 }
904 
905 // Slave got a redirection request
906 void StatJob::slotRedirection( const KURL &url)
907 {
908  kdDebug(7007) << "StatJob::slotRedirection(" << url << ")" << endl;
909  if (!kapp->authorizeURLAction("redirect", m_url, url))
910  {
911  kdWarning(7007) << "StatJob: Redirection from " << m_url << " to " << url << " REJECTED!" << endl;
912  m_error = ERR_ACCESS_DENIED;
913  m_errorText = url.prettyURL();
914  return;
915  }
916  m_redirectionURL = url; // We'll remember that when the job finishes
917  if (m_url.hasUser() && !url.hasUser() && (m_url.host().lower() == url.host().lower()))
918  m_redirectionURL.setUser(m_url.user()); // Preserve user
919  // Tell the user that we haven't finished yet
920  emit redirection(this, m_redirectionURL);
921 }
922 
923 void StatJob::slotFinished()
924 {
925  if ( m_redirectionURL.isEmpty() || !m_redirectionURL.isValid())
926  {
927  // Return slave to the scheduler
928  SimpleJob::slotFinished();
929  } else {
930  //kdDebug(7007) << "StatJob: Redirection to " << m_redirectionURL << endl;
931  if (queryMetaData("permanent-redirect")=="true")
932  emit permanentRedirection(this, m_url, m_redirectionURL);
933  m_url = m_redirectionURL;
934  m_redirectionURL = KURL();
935  m_packedArgs.truncate(0);
936  TQDataStream stream( m_packedArgs, IO_WriteOnly );
937  stream << m_url;
938 
939  // Return slave to the scheduler
940  slaveDone();
941  Scheduler::doJob(this);
942  }
943 }
944 
945 void StatJob::slotMetaData( const TDEIO::MetaData &_metaData) {
946  SimpleJob::slotMetaData(_metaData);
947  storeSSLSessionFromJob(m_redirectionURL);
948 }
949 
950 StatJob *TDEIO::stat(const KURL& url, bool showProgressInfo)
951 {
952  // Assume sideIsSource. Gets are more common than puts.
953  return stat( url, true, 2, showProgressInfo );
954 }
955 
956 StatJob *TDEIO::stat(const KURL& url, bool sideIsSource, short int details, bool showProgressInfo)
957 {
958  kdDebug(7007) << "stat " << url << endl;
959  TDEIO_ARGS << url;
960  StatJob * job = new StatJob(url, CMD_STAT, packedArgs, showProgressInfo );
961  job->setSide( sideIsSource );
962  job->setDetails( details );
963  if ( showProgressInfo )
964  Observer::self()->stating( job, url );
965  return job;
966 }
967 
968 SimpleJob *TDEIO::http_update_cache( const KURL& url, bool no_cache, time_t expireDate)
969 {
970  assert( (url.protocol() == "http") || (url.protocol() == "https") );
971  // Send http update_cache command (2)
972  TDEIO_ARGS << (int)2 << url << no_cache << expireDate;
973  SimpleJob * job = new SimpleJob( url, CMD_SPECIAL, packedArgs, false );
974  Scheduler::scheduleJob(job);
975  return job;
976 }
977 
979 
980 TransferJob::TransferJob( const KURL& url, int command,
981  const TQByteArray &packedArgs,
982  const TQByteArray &_staticData,
983  bool showProgressInfo)
984  : SimpleJob(url, command, packedArgs, showProgressInfo), staticData( _staticData)
985 {
986  m_suspended = false;
987  m_errorPage = false;
988  m_subJob = 0L;
989  if ( showProgressInfo )
990  Observer::self()->slotTransferring( this, url );
991 }
992 
993 // Slave sends data
994 void TransferJob::slotData( const TQByteArray &_data)
995 {
996  if(m_redirectionURL.isEmpty() || !m_redirectionURL.isValid() || m_error)
997  emit data( this, _data);
998 }
999 
1000 // Slave got a redirection request
1001 void TransferJob::slotRedirection( const KURL &url)
1002 {
1003  kdDebug(7007) << "TransferJob::slotRedirection(" << url << ")" << endl;
1004  if (!kapp->authorizeURLAction("redirect", m_url, url))
1005  {
1006  kdWarning(7007) << "TransferJob: Redirection from " << m_url << " to " << url << " REJECTED!" << endl;
1007  return;
1008  }
1009 
1010  // Some websites keep redirecting to themselves where each redirection
1011  // acts as the stage in a state-machine. We define "endless redirections"
1012  // as 5 redirections to the same URL.
1013  if (m_redirectionList.contains(url) > 5)
1014  {
1015  kdDebug(7007) << "TransferJob::slotRedirection: CYCLIC REDIRECTION!" << endl;
1016  m_error = ERR_CYCLIC_LINK;
1017  m_errorText = m_url.prettyURL();
1018  }
1019  else
1020  {
1021  m_redirectionURL = url; // We'll remember that when the job finishes
1022  if (m_url.hasUser() && !url.hasUser() && (m_url.host().lower() == url.host().lower()))
1023  m_redirectionURL.setUser(m_url.user()); // Preserve user
1024  m_redirectionList.append(url);
1025  m_outgoingMetaData["ssl_was_in_use"] = m_incomingMetaData["ssl_in_use"];
1026  // Tell the user that we haven't finished yet
1027  emit redirection(this, m_redirectionURL);
1028  }
1029 }
1030 
1031 void TransferJob::slotFinished()
1032 {
1033  //kdDebug(7007) << "TransferJob::slotFinished(" << this << ", " << m_url << ")" << endl;
1034  if (m_redirectionURL.isEmpty() || !m_redirectionURL.isValid())
1035  SimpleJob::slotFinished();
1036  else {
1037  //kdDebug(7007) << "TransferJob: Redirection to " << m_redirectionURL << endl;
1038  if (queryMetaData("permanent-redirect")=="true")
1039  emit permanentRedirection(this, m_url, m_redirectionURL);
1040  // Honour the redirection
1041  // We take the approach of "redirecting this same job"
1042  // Another solution would be to create a subjob, but the same problem
1043  // happens (unpacking+repacking)
1044  staticData.truncate(0);
1045  m_incomingMetaData.clear();
1046  if (queryMetaData("cache") != "reload")
1047  addMetaData("cache","refresh");
1048  m_suspended = false;
1049  m_url = m_redirectionURL;
1050  m_redirectionURL = KURL();
1051  // The very tricky part is the packed arguments business
1052  TQString dummyStr;
1053  KURL dummyUrl;
1054  TQDataStream istream( m_packedArgs, IO_ReadOnly );
1055  switch( m_command ) {
1056  case CMD_GET: {
1057  m_packedArgs.truncate(0);
1058  TQDataStream stream( m_packedArgs, IO_WriteOnly );
1059  stream << m_url;
1060  break;
1061  }
1062  case CMD_PUT: {
1063  int permissions;
1064  TQ_INT8 iOverwrite, iResume;
1065  istream >> dummyUrl >> iOverwrite >> iResume >> permissions;
1066  m_packedArgs.truncate(0);
1067  TQDataStream stream( m_packedArgs, IO_WriteOnly );
1068  stream << m_url << iOverwrite << iResume << permissions;
1069  break;
1070  }
1071  case CMD_SPECIAL: {
1072  int specialcmd;
1073  istream >> specialcmd;
1074  if (specialcmd == 1) // HTTP POST
1075  {
1076  addMetaData("cache","reload");
1077  m_packedArgs.truncate(0);
1078  TQDataStream stream( m_packedArgs, IO_WriteOnly );
1079  stream << m_url;
1080  m_command = CMD_GET;
1081  }
1082  break;
1083  }
1084  }
1085 
1086  // Return slave to the scheduler
1087  slaveDone();
1088  Scheduler::doJob(this);
1089  }
1090 }
1091 
1092 void TransferJob::setAsyncDataEnabled(bool enabled)
1093 {
1094  if (enabled)
1095  extraFlags() |= EF_TransferJobAsync;
1096  else
1097  extraFlags() &= ~EF_TransferJobAsync;
1098 }
1099 
1100 void TransferJob::sendAsyncData(const TQByteArray &dataForSlave)
1101 {
1102  if (extraFlags() & EF_TransferJobNeedData)
1103  {
1104  m_slave->send( MSG_DATA, dataForSlave );
1105  if (extraFlags() & EF_TransferJobDataSent)
1106  {
1107  TDEIO::filesize_t size = getProcessedSize()+dataForSlave.size();
1108  setProcessedSize(size);
1109  emit processedSize( this, size );
1110  if ( size > m_totalSize ) {
1111  slotTotalSize(size); // safety
1112  }
1113  emitPercent( size, m_totalSize );
1114  }
1115  }
1116 
1117  extraFlags() &= ~EF_TransferJobNeedData;
1118 }
1119 
1120 void TransferJob::setReportDataSent(bool enabled)
1121 {
1122  if (enabled)
1123  extraFlags() |= EF_TransferJobDataSent;
1124  else
1125  extraFlags() &= ~EF_TransferJobDataSent;
1126 }
1127 
1128 bool TransferJob::reportDataSent()
1129 {
1130  return (extraFlags() & EF_TransferJobDataSent);
1131 }
1132 
1133 
1134 // Slave requests data
1135 void TransferJob::slotDataReq()
1136 {
1137  TQByteArray dataForSlave;
1138 
1139  extraFlags() |= EF_TransferJobNeedData;
1140 
1141  if (!staticData.isEmpty())
1142  {
1143  dataForSlave = staticData;
1144  staticData = TQByteArray();
1145  }
1146  else
1147  {
1148  emit dataReq( this, dataForSlave);
1149 
1150  if (extraFlags() & EF_TransferJobAsync)
1151  return;
1152  }
1153 
1154  static const size_t max_size = 14 * 1024 * 1024;
1155  if (dataForSlave.size() > max_size)
1156  {
1157  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";
1158  staticData.duplicate(dataForSlave.data() + max_size , dataForSlave.size() - max_size);
1159  dataForSlave.truncate(max_size);
1160  }
1161 
1162  sendAsyncData(dataForSlave);
1163 
1164  if (m_subJob)
1165  {
1166  // Bitburger protocol in action
1167  suspend(); // Wait for more data from subJob.
1168  m_subJob->resume(); // Ask for more!
1169  }
1170 }
1171 
1172 void TransferJob::slotMimetype( const TQString& type )
1173 {
1174  m_mimetype = type;
1175  emit mimetype( this, m_mimetype);
1176 }
1177 
1178 
1179 void TransferJob::suspend()
1180 {
1181  m_suspended = true;
1182  if (m_slave)
1183  m_slave->suspend();
1184 }
1185 
1186 void TransferJob::resume()
1187 {
1188  m_suspended = false;
1189  if (m_slave)
1190  m_slave->resume();
1191 }
1192 
1193 void TransferJob::start(Slave *slave)
1194 {
1195  assert(slave);
1196  connect( slave, TQ_SIGNAL( data( const TQByteArray & ) ),
1197  TQ_SLOT( slotData( const TQByteArray & ) ) );
1198 
1199  connect( slave, TQ_SIGNAL( dataReq() ),
1200  TQ_SLOT( slotDataReq() ) );
1201 
1202  connect( slave, TQ_SIGNAL( redirection(const KURL &) ),
1203  TQ_SLOT( slotRedirection(const KURL &) ) );
1204 
1205  connect( slave, TQ_SIGNAL(mimeType( const TQString& ) ),
1206  TQ_SLOT( slotMimetype( const TQString& ) ) );
1207 
1208  connect( slave, TQ_SIGNAL(errorPage() ),
1209  TQ_SLOT( slotErrorPage() ) );
1210 
1211  connect( slave, TQ_SIGNAL( needSubURLData() ),
1212  TQ_SLOT( slotNeedSubURLData() ) );
1213 
1214  connect( slave, TQ_SIGNAL(canResume( TDEIO::filesize_t ) ),
1215  TQ_SLOT( slotCanResume( TDEIO::filesize_t ) ) );
1216 
1217  if (slave->suspended())
1218  {
1219  m_mimetype = "unknown";
1220  // WABA: The slave was put on hold. Resume operation.
1221  slave->resume();
1222  }
1223 
1224  SimpleJob::start(slave);
1225  if (m_suspended)
1226  slave->suspend();
1227 }
1228 
1229 void TransferJob::slotNeedSubURLData()
1230 {
1231  // Job needs data from subURL.
1232  m_subJob = TDEIO::get( m_subUrl, false, false);
1233  suspend(); // Put job on hold until we have some data.
1234  connect(m_subJob, TQ_SIGNAL( data(TDEIO::Job*,const TQByteArray &)),
1235  TQ_SLOT( slotSubURLData(TDEIO::Job*,const TQByteArray &)));
1236  addSubjob(m_subJob);
1237 }
1238 
1239 void TransferJob::slotSubURLData(TDEIO::Job*, const TQByteArray &data)
1240 {
1241  // The Alternating Bitburg protocol in action again.
1242  staticData = data;
1243  m_subJob->suspend(); // Put job on hold until we have delivered the data.
1244  resume(); // Activate ourselves again.
1245 }
1246 
1247 void TransferJob::slotMetaData( const TDEIO::MetaData &_metaData) {
1248  SimpleJob::slotMetaData(_metaData);
1249  storeSSLSessionFromJob(m_redirectionURL);
1250 }
1251 
1252 void TransferJob::slotErrorPage()
1253 {
1254  m_errorPage = true;
1255 }
1256 
1257 void TransferJob::slotCanResume( TDEIO::filesize_t offset )
1258 {
1259  emit canResume(this, offset);
1260 }
1261 
1262 void TransferJob::slotResult( TDEIO::Job *job)
1263 {
1264  // This can only be our suburl.
1265  assert(job == m_subJob);
1266  // Did job have an error ?
1267  if ( job->error() )
1268  {
1269  m_error = job->error();
1270  m_errorText = job->errorText();
1271 
1272  emitResult();
1273  return;
1274  }
1275 
1276  if (job == m_subJob)
1277  {
1278  m_subJob = 0; // No action required
1279  resume(); // Make sure we get the remaining data.
1280  }
1281  removeSubjob( job, false, false ); // Remove job, but don't kill this job.
1282 }
1283 
1284 TransferJob *TDEIO::get( const KURL& url, bool reload, bool showProgressInfo )
1285 {
1286  // Send decoded path and encoded query
1287  TDEIO_ARGS << url;
1288  TransferJob * job = new TransferJob( url, CMD_GET, packedArgs, TQByteArray(), showProgressInfo );
1289  if (reload)
1290  job->addMetaData("cache", "reload");
1291  return job;
1292 }
1293 
1294 class PostErrorJob : public TransferJob
1295 {
1296 public:
1297 
1298  PostErrorJob(int _error, const TQString& url, const TQByteArray &packedArgs, const TQByteArray &postData, bool showProgressInfo)
1299  : TransferJob(KURL(), CMD_SPECIAL, packedArgs, postData, showProgressInfo)
1300  {
1301  m_error = _error;
1302  m_errorText = url;
1303  }
1304 
1305 };
1306 
1307 TransferJob *TDEIO::http_post( const KURL& url, const TQByteArray &postData, bool showProgressInfo )
1308 {
1309  int _error = 0;
1310 
1311  // filter out some malicious ports
1312  static const int bad_ports[] = {
1313  1, // tcpmux
1314  7, // echo
1315  9, // discard
1316  11, // systat
1317  13, // daytime
1318  15, // netstat
1319  17, // qotd
1320  19, // chargen
1321  20, // ftp-data
1322  21, // ftp-cntl
1323  22, // ssh
1324  23, // telnet
1325  25, // smtp
1326  37, // time
1327  42, // name
1328  43, // nicname
1329  53, // domain
1330  77, // priv-rjs
1331  79, // finger
1332  87, // ttylink
1333  95, // supdup
1334  101, // hostriame
1335  102, // iso-tsap
1336  103, // gppitnp
1337  104, // acr-nema
1338  109, // pop2
1339  110, // pop3
1340  111, // sunrpc
1341  113, // auth
1342  115, // sftp
1343  117, // uucp-path
1344  119, // nntp
1345  123, // NTP
1346  135, // loc-srv / epmap
1347  139, // netbios
1348  143, // imap2
1349  179, // BGP
1350  389, // ldap
1351  512, // print / exec
1352  513, // login
1353  514, // shell
1354  515, // printer
1355  526, // tempo
1356  530, // courier
1357  531, // Chat
1358  532, // netnews
1359  540, // uucp
1360  556, // remotefs
1361  587, // sendmail
1362  601, //
1363  989, // ftps data
1364  990, // ftps
1365  992, // telnets
1366  993, // imap/SSL
1367  995, // pop3/SSL
1368  1080, // SOCKS
1369  2049, // nfs
1370  4045, // lockd
1371  6000, // x11
1372  6667, // irc
1373  0};
1374  for (int cnt=0; bad_ports[cnt]; ++cnt)
1375  if (url.port() == bad_ports[cnt])
1376  {
1377  _error = TDEIO::ERR_POST_DENIED;
1378  break;
1379  }
1380 
1381  if( _error )
1382  {
1383  static bool override_loaded = false;
1384  static TQValueList< int >* overriden_ports = NULL;
1385  if( !override_loaded )
1386  {
1387  TDEConfig cfg( "tdeio_httprc", true );
1388  overriden_ports = new TQValueList< int >;
1389  *overriden_ports = cfg.readIntListEntry( "OverriddenPorts" );
1390  override_loaded = true;
1391  }
1392  for( TQValueList< int >::ConstIterator it = overriden_ports->begin();
1393  it != overriden_ports->end();
1394  ++it )
1395  if( overriden_ports->contains( url.port()))
1396  _error = 0;
1397  }
1398 
1399  // filter out non https? protocols
1400  if ((url.protocol() != "http") && (url.protocol() != "https" ))
1401  _error = TDEIO::ERR_POST_DENIED;
1402 
1403  bool redirection = false;
1404  KURL _url(url);
1405  if (_url.path().isEmpty())
1406  {
1407  redirection = true;
1408  _url.setPath("/");
1409  }
1410 
1411  if (!_error && !kapp->authorizeURLAction("open", KURL(), _url))
1412  _error = TDEIO::ERR_ACCESS_DENIED;
1413 
1414  // if request is not valid, return an invalid transfer job
1415  if (_error)
1416  {
1417  TDEIO_ARGS << (int)1 << url;
1418  TransferJob * job = new PostErrorJob(_error, url.prettyURL(), packedArgs, postData, showProgressInfo);
1419  return job;
1420  }
1421 
1422  // Send http post command (1), decoded path and encoded query
1423  TDEIO_ARGS << (int)1 << _url;
1424  TransferJob * job = new TransferJob( _url, CMD_SPECIAL,
1425  packedArgs, postData, showProgressInfo );
1426 
1427  if (redirection)
1428  TQTimer::singleShot(0, job, TQ_SLOT(slotPostRedirection()) );
1429 
1430  return job;
1431 }
1432 
1433 // http post got redirected from http://host to http://host/ by TransferJob
1434 // We must do this redirection ourselves because redirections by the
1435 // slave change post jobs into get jobs.
1436 void TransferJob::slotPostRedirection()
1437 {
1438  kdDebug(7007) << "TransferJob::slotPostRedirection(" << m_url << ")" << endl;
1439  // Tell the user about the new url.
1440  emit redirection(this, m_url);
1441 }
1442 
1443 
1444 TransferJob *TDEIO::put( const KURL& url, int permissions,
1445  bool overwrite, bool resume, bool showProgressInfo )
1446 {
1447  TDEIO_ARGS << url << TQ_INT8( overwrite ? 1 : 0 ) << TQ_INT8( resume ? 1 : 0 ) << permissions;
1448  TransferJob * job = new TransferJob( url, CMD_PUT, packedArgs, TQByteArray(), showProgressInfo );
1449  return job;
1450 }
1451 
1453 
1454 StoredTransferJob::StoredTransferJob(const KURL& url, int command,
1455  const TQByteArray &packedArgs,
1456  const TQByteArray &_staticData,
1457  bool showProgressInfo)
1458  : TransferJob( url, command, packedArgs, _staticData, showProgressInfo ),
1459  m_uploadOffset( 0 )
1460 {
1461  connect( this, TQ_SIGNAL( data( TDEIO::Job *, const TQByteArray & ) ),
1462  TQ_SLOT( slotStoredData( TDEIO::Job *, const TQByteArray & ) ) );
1463  connect( this, TQ_SIGNAL( dataReq( TDEIO::Job *, TQByteArray & ) ),
1464  TQ_SLOT( slotStoredDataReq( TDEIO::Job *, TQByteArray & ) ) );
1465 }
1466 
1467 void StoredTransferJob::setData( const TQByteArray& arr )
1468 {
1469  Q_ASSERT( m_data.isNull() ); // check that we're only called once
1470  Q_ASSERT( m_uploadOffset == 0 ); // no upload started yet
1471  m_data = arr;
1472 }
1473 
1474 void StoredTransferJob::slotStoredData( TDEIO::Job *, const TQByteArray &data )
1475 {
1476  // check for end-of-data marker:
1477  if ( data.size() == 0 )
1478  return;
1479  unsigned int oldSize = m_data.size();
1480  m_data.resize( oldSize + data.size(), TQGArray::SpeedOptim );
1481  memcpy( m_data.data() + oldSize, data.data(), data.size() );
1482 }
1483 
1484 void StoredTransferJob::slotStoredDataReq( TDEIO::Job *, TQByteArray &data )
1485 {
1486  // Inspired from kmail's KMKernel::byteArrayToRemoteFile
1487  // send the data in 64 KB chunks
1488  const int MAX_CHUNK_SIZE = 64*1024;
1489  int remainingBytes = m_data.size() - m_uploadOffset;
1490  if( remainingBytes > MAX_CHUNK_SIZE ) {
1491  // send MAX_CHUNK_SIZE bytes to the receiver (deep copy)
1492  data.duplicate( m_data.data() + m_uploadOffset, MAX_CHUNK_SIZE );
1493  m_uploadOffset += MAX_CHUNK_SIZE;
1494  //kdDebug() << "Sending " << MAX_CHUNK_SIZE << " bytes ("
1495  // << remainingBytes - MAX_CHUNK_SIZE << " bytes remain)\n";
1496  } else {
1497  // send the remaining bytes to the receiver (deep copy)
1498  data.duplicate( m_data.data() + m_uploadOffset, remainingBytes );
1499  m_data = TQByteArray();
1500  m_uploadOffset = 0;
1501  //kdDebug() << "Sending " << remainingBytes << " bytes\n";
1502  }
1503 }
1504 
1505 StoredTransferJob *TDEIO::storedGet( const KURL& url, bool reload, bool showProgressInfo )
1506 {
1507  // Send decoded path and encoded query
1508  TDEIO_ARGS << url;
1509  StoredTransferJob * job = new StoredTransferJob( url, CMD_GET, packedArgs, TQByteArray(), showProgressInfo );
1510  if (reload)
1511  job->addMetaData("cache", "reload");
1512  return job;
1513 }
1514 
1515 StoredTransferJob *TDEIO::storedPut( const TQByteArray& arr, const KURL& url, int permissions,
1516  bool overwrite, bool resume, bool showProgressInfo )
1517 {
1518  TDEIO_ARGS << url << TQ_INT8( overwrite ? 1 : 0 ) << TQ_INT8( resume ? 1 : 0 ) << permissions;
1519  StoredTransferJob * job = new StoredTransferJob( url, CMD_PUT, packedArgs, TQByteArray(), showProgressInfo );
1520  job->setData( arr );
1521  return job;
1522 }
1523 
1525 
1526 MimetypeJob::MimetypeJob( const KURL& url, int command,
1527  const TQByteArray &packedArgs, bool showProgressInfo )
1528  : TransferJob(url, command, packedArgs, TQByteArray(), showProgressInfo)
1529 {
1530 }
1531 
1532 void MimetypeJob::start(Slave *slave)
1533 {
1534  TransferJob::start(slave);
1535 }
1536 
1537 
1538 void MimetypeJob::slotFinished( )
1539 {
1540  //kdDebug(7007) << "MimetypeJob::slotFinished()" << endl;
1541  if ( m_error == TDEIO::ERR_IS_DIRECTORY )
1542  {
1543  // It is in fact a directory. This happens when HTTP redirects to FTP.
1544  // Due to the "protocol doesn't support listing" code in KRun, we
1545  // assumed it was a file.
1546  kdDebug(7007) << "It is in fact a directory!" << endl;
1547  m_mimetype = TQString::fromLatin1("inode/directory");
1548  emit TransferJob::mimetype( this, m_mimetype );
1549  m_error = 0;
1550  }
1551  if ( m_redirectionURL.isEmpty() || !m_redirectionURL.isValid() || m_error )
1552  {
1553  // Return slave to the scheduler
1554  TransferJob::slotFinished();
1555  } else {
1556  //kdDebug(7007) << "MimetypeJob: Redirection to " << m_redirectionURL << endl;
1557  if (queryMetaData("permanent-redirect")=="true")
1558  emit permanentRedirection(this, m_url, m_redirectionURL);
1559  staticData.truncate(0);
1560  m_suspended = false;
1561  m_url = m_redirectionURL;
1562  m_redirectionURL = KURL();
1563  m_packedArgs.truncate(0);
1564  TQDataStream stream( m_packedArgs, IO_WriteOnly );
1565  stream << m_url;
1566 
1567  // Return slave to the scheduler
1568  slaveDone();
1569  Scheduler::doJob(this);
1570  }
1571 }
1572 
1573 MimetypeJob *TDEIO::mimetype(const KURL& url, bool showProgressInfo )
1574 {
1575  TDEIO_ARGS << url;
1576  MimetypeJob * job = new MimetypeJob(url, CMD_MIMETYPE, packedArgs, showProgressInfo);
1577  if ( showProgressInfo )
1578  Observer::self()->stating( job, url );
1579  return job;
1580 }
1581 
1583 
1584 DirectCopyJob::DirectCopyJob( const KURL& url, int command,
1585  const TQByteArray &packedArgs, bool showProgressInfo )
1586  : SimpleJob(url, command, packedArgs, showProgressInfo)
1587 {
1588 }
1589 
1590 void DirectCopyJob::start( Slave* slave )
1591 {
1592  connect( slave, TQ_SIGNAL(canResume( TDEIO::filesize_t ) ),
1593  TQ_SLOT( slotCanResume( TDEIO::filesize_t ) ) );
1594  SimpleJob::start(slave);
1595 }
1596 
1597 void DirectCopyJob::slotCanResume( TDEIO::filesize_t offset )
1598 {
1599  emit canResume(this, offset);
1600 }
1601 
1603 
1604 
1605 class FileCopyJob::FileCopyJobPrivate
1606 {
1607 public:
1608  TDEIO::filesize_t m_sourceSize;
1609  time_t m_modificationTime;
1610  SimpleJob *m_delJob;
1611 };
1612 
1613 /*
1614  * The FileCopyJob works according to the famous Bayern
1615  * 'Alternating Bitburger Protocol': we either drink a beer or we
1616  * we order a beer, but never both at the same time.
1617  * Tranlated to io-slaves: We alternate between receiving a block of data
1618  * and sending it away.
1619  */
1620 FileCopyJob::FileCopyJob( const KURL& src, const KURL& dest, int permissions,
1621  bool move, bool overwrite, bool resume, bool showProgressInfo)
1622  : Job(showProgressInfo), m_src(src), m_dest(dest),
1623  m_permissions(permissions), m_move(move), m_overwrite(overwrite), m_resume(resume),
1624  m_totalSize(0)
1625 {
1626  if (showProgressInfo && !move)
1627  Observer::self()->slotCopying( this, src, dest );
1628  else if (showProgressInfo && move)
1629  Observer::self()->slotMoving( this, src, dest );
1630 
1631  //kdDebug(7007) << "FileCopyJob::FileCopyJob()" << endl;
1632  m_moveJob = 0;
1633  m_copyJob = 0;
1634  m_getJob = 0;
1635  m_putJob = 0;
1636  d = new FileCopyJobPrivate;
1637  d->m_delJob = 0;
1638  d->m_sourceSize = (TDEIO::filesize_t) -1;
1639  d->m_modificationTime = static_cast<time_t>( -1 );
1640  TQTimer::singleShot(0, this, TQ_SLOT(slotStart()));
1641 }
1642 
1643 void FileCopyJob::slotStart()
1644 {
1645  if ( m_move )
1646  {
1647  // The if() below must be the same as the one in startBestCopyMethod
1648  if ((m_src.protocol() == m_dest.protocol()) &&
1649  (m_src.host() == m_dest.host()) &&
1650  (m_src.port() == m_dest.port()) &&
1651  (m_src.user() == m_dest.user()) &&
1652  (m_src.pass() == m_dest.pass()) &&
1653  !m_src.hasSubURL() && !m_dest.hasSubURL())
1654  {
1655  startRenameJob(m_src);
1656  return;
1657  }
1658  else if (m_src.isLocalFile() && KProtocolInfo::canRenameFromFile(m_dest))
1659  {
1660  startRenameJob(m_dest);
1661  return;
1662  }
1663  else if (m_dest.isLocalFile() && KProtocolInfo::canRenameToFile(m_src))
1664  {
1665  startRenameJob(m_src);
1666  return;
1667  }
1668  // No fast-move available, use copy + del.
1669  }
1670  startBestCopyMethod();
1671 }
1672 
1673 void FileCopyJob::startBestCopyMethod()
1674 {
1675  if ((m_src.protocol() == m_dest.protocol()) &&
1676  (m_src.host() == m_dest.host()) &&
1677  (m_src.port() == m_dest.port()) &&
1678  (m_src.user() == m_dest.user()) &&
1679  (m_src.pass() == m_dest.pass()) &&
1680  !m_src.hasSubURL() && !m_dest.hasSubURL())
1681  {
1682  startCopyJob();
1683  }
1684  else if (m_src.isLocalFile() && KProtocolInfo::canCopyFromFile(m_dest))
1685  {
1686  startCopyJob(m_dest);
1687  }
1688  else if (m_dest.isLocalFile() && KProtocolInfo::canCopyToFile(m_src))
1689  {
1690  startCopyJob(m_src);
1691  }
1692  else
1693  {
1694  startDataPump();
1695  }
1696 }
1697 
1698 FileCopyJob::~FileCopyJob()
1699 {
1700  delete d;
1701 }
1702 
1703 void FileCopyJob::setSourceSize( off_t size )
1704 {
1705  d->m_sourceSize = size;
1706  if (size != (off_t) -1)
1707  m_totalSize = size;
1708 }
1709 
1710 void FileCopyJob::setSourceSize64( TDEIO::filesize_t size )
1711 {
1712  d->m_sourceSize = size;
1713  if (size != (TDEIO::filesize_t) -1)
1714  m_totalSize = size;
1715 }
1716 
1717 void FileCopyJob::setModificationTime( time_t mtime )
1718 {
1719  d->m_modificationTime = mtime;
1720 }
1721 
1722 void FileCopyJob::startCopyJob()
1723 {
1724  startCopyJob(m_src);
1725 }
1726 
1727 void FileCopyJob::startCopyJob(const KURL &slave_url)
1728 {
1729  //kdDebug(7007) << "FileCopyJob::startCopyJob()" << endl;
1730  TDEIO_ARGS << m_src << m_dest << m_permissions << (TQ_INT8) m_overwrite;
1731  m_copyJob = new DirectCopyJob(slave_url, CMD_COPY, packedArgs, false);
1732  addSubjob( m_copyJob );
1733  connectSubjob( m_copyJob );
1734  connect( m_copyJob, TQ_SIGNAL(canResume(TDEIO::Job *, TDEIO::filesize_t)),
1735  TQ_SLOT( slotCanResume(TDEIO::Job *, TDEIO::filesize_t)));
1736 }
1737 
1738 void FileCopyJob::startRenameJob(const KURL &slave_url)
1739 {
1740  TDEIO_ARGS << m_src << m_dest << (TQ_INT8) m_overwrite;
1741  m_moveJob = new SimpleJob(slave_url, CMD_RENAME, packedArgs, false);
1742  addSubjob( m_moveJob );
1743  connectSubjob( m_moveJob );
1744 }
1745 
1746 void FileCopyJob::connectSubjob( SimpleJob * job )
1747 {
1748  connect( job, TQ_SIGNAL(totalSize( TDEIO::Job*, TDEIO::filesize_t )),
1749  this, TQ_SLOT( slotTotalSize(TDEIO::Job*, TDEIO::filesize_t)) );
1750 
1751  connect( job, TQ_SIGNAL(processedSize( TDEIO::Job*, TDEIO::filesize_t )),
1752  this, TQ_SLOT( slotProcessedSize(TDEIO::Job*, TDEIO::filesize_t)) );
1753 
1754  connect( job, TQ_SIGNAL(percent( TDEIO::Job*, unsigned long )),
1755  this, TQ_SLOT( slotPercent(TDEIO::Job*, unsigned long)) );
1756 
1757 }
1758 
1759 void FileCopyJob::slotProcessedSize( TDEIO::Job *, TDEIO::filesize_t size )
1760 {
1761  setProcessedSize(size);
1762  emit processedSize( this, size );
1763  if ( size > m_totalSize ) {
1764  slotTotalSize( this, size ); // safety
1765  }
1766  emitPercent( size, m_totalSize );
1767 }
1768 
1769 void FileCopyJob::slotTotalSize( TDEIO::Job*, TDEIO::filesize_t size )
1770 {
1771  if (size > m_totalSize)
1772  {
1773  m_totalSize = size;
1774  emit totalSize( this, m_totalSize );
1775  }
1776 }
1777 
1778 void FileCopyJob::slotPercent( TDEIO::Job*, unsigned long pct )
1779 {
1780  if ( pct > m_percent )
1781  {
1782  m_percent = pct;
1783  emit percent( this, m_percent );
1784  }
1785 }
1786 
1787 void FileCopyJob::startDataPump()
1788 {
1789  //kdDebug(7007) << "FileCopyJob::startDataPump()" << endl;
1790 
1791  m_canResume = false;
1792  m_resumeAnswerSent = false;
1793  m_getJob = 0L; // for now
1794  m_putJob = put( m_dest, m_permissions, m_overwrite, m_resume, false /* no GUI */);
1795  if ( d->m_modificationTime != static_cast<time_t>( -1 ) ) {
1796  TQDateTime dt; dt.setTime_t( d->m_modificationTime );
1797  m_putJob->addMetaData( "modified", dt.toString( TQt::ISODate ) );
1798  }
1799  //kdDebug(7007) << "FileCopyJob: m_putJob = " << m_putJob << " m_dest=" << m_dest << endl;
1800 
1801  // The first thing the put job will tell us is whether we can
1802  // resume or not (this is always emitted)
1803  connect( m_putJob, TQ_SIGNAL(canResume(TDEIO::Job *, TDEIO::filesize_t)),
1804  TQ_SLOT( slotCanResume(TDEIO::Job *, TDEIO::filesize_t)));
1805  connect( m_putJob, TQ_SIGNAL(dataReq(TDEIO::Job *, TQByteArray&)),
1806  TQ_SLOT( slotDataReq(TDEIO::Job *, TQByteArray&)));
1807  addSubjob( m_putJob );
1808 }
1809 
1810 void FileCopyJob::slotCanResume( TDEIO::Job* job, TDEIO::filesize_t offset )
1811 {
1812  if ( job == m_putJob || job == m_copyJob )
1813  {
1814  //kdDebug(7007) << "FileCopyJob::slotCanResume from PUT job. offset=" << TDEIO::number(offset) << endl;
1815  if (offset)
1816  {
1817  RenameDlg_Result res = R_RESUME;
1818 
1819  if (!KProtocolManager::autoResume() && !m_overwrite)
1820  {
1821  TQString newPath;
1822  TDEIO::Job* job = ( !m_progressId && parentJob() ) ? parentJob() : this;
1823  // Ask confirmation about resuming previous transfer
1824  res = Observer::self()->open_RenameDlg(
1825  job, i18n("File Already Exists"),
1826  m_src.url(),
1827  m_dest.url(),
1828  (RenameDlg_Mode) (M_OVERWRITE | M_RESUME | M_NORENAME), newPath,
1829  d->m_sourceSize, offset );
1830  }
1831 
1832  if ( res == R_OVERWRITE || m_overwrite )
1833  offset = 0;
1834  else if ( res == R_CANCEL )
1835  {
1836  if ( job == m_putJob )
1837  m_putJob->kill(true);
1838  else
1839  m_copyJob->kill(true);
1840  m_error = ERR_USER_CANCELED;
1841  emitResult();
1842  return;
1843  }
1844  }
1845  else
1846  m_resumeAnswerSent = true; // No need for an answer
1847 
1848  if ( job == m_putJob )
1849  {
1850  m_getJob = get( m_src, false, false /* no GUI */ );
1851  //kdDebug(7007) << "FileCopyJob: m_getJob = " << m_getJob << endl;
1852  m_getJob->addMetaData( "errorPage", "false" );
1853  m_getJob->addMetaData( "AllowCompressedPage", "false" );
1854  // Set size in subjob. This helps if the slave doesn't emit totalSize.
1855  if ( d->m_sourceSize != (TDEIO::filesize_t)-1 )
1856  m_getJob->slotTotalSize( d->m_sourceSize );
1857  if (offset)
1858  {
1859  //kdDebug(7007) << "Setting metadata for resume to " << (unsigned long) offset << endl;
1860  // TODO KDE4: rename to seek or offset and document it
1861  // This isn't used only for resuming, but potentially also for extracting (#72302).
1862  m_getJob->addMetaData( "resume", TDEIO::number(offset) );
1863 
1864  // Might or might not get emitted
1865  connect( m_getJob, TQ_SIGNAL(canResume(TDEIO::Job *, TDEIO::filesize_t)),
1866  TQ_SLOT( slotCanResume(TDEIO::Job *, TDEIO::filesize_t)));
1867  }
1868  m_putJob->slave()->setOffset( offset );
1869 
1870  m_putJob->suspend();
1871  addSubjob( m_getJob );
1872  connectSubjob( m_getJob ); // Progress info depends on get
1873  m_getJob->resume(); // Order a beer
1874 
1875  connect( m_getJob, TQ_SIGNAL(data(TDEIO::Job*,const TQByteArray&)),
1876  TQ_SLOT( slotData(TDEIO::Job*,const TQByteArray&)) );
1877  connect( m_getJob, TQ_SIGNAL(mimetype(TDEIO::Job*,const TQString&) ),
1878  TQ_SLOT(slotMimetype(TDEIO::Job*,const TQString&)) );
1879  }
1880  else // copyjob
1881  {
1882  m_copyJob->slave()->sendResumeAnswer( offset != 0 );
1883  }
1884  }
1885  else if ( job == m_getJob )
1886  {
1887  // Cool, the get job said ok, we can resume
1888  m_canResume = true;
1889  //kdDebug(7007) << "FileCopyJob::slotCanResume from the GET job -> we can resume" << endl;
1890 
1891  m_getJob->slave()->setOffset( m_putJob->slave()->offset() );
1892  }
1893  else
1894  kdWarning(7007) << "FileCopyJob::slotCanResume from unknown job=" << job
1895  << " m_getJob=" << m_getJob << " m_putJob=" << m_putJob << endl;
1896 }
1897 
1898 void FileCopyJob::slotData( TDEIO::Job * , const TQByteArray &data)
1899 {
1900  //kdDebug(7007) << "FileCopyJob::slotData" << endl;
1901  //kdDebug(7007) << " data size : " << data.size() << endl;
1902  assert(m_putJob);
1903  if (!m_putJob) return; // Don't crash
1904  m_getJob->suspend();
1905  m_putJob->resume(); // Drink the beer
1906  m_buffer = data;
1907 
1908  // On the first set of data incoming, we tell the "put" slave about our
1909  // decision about resuming
1910  if (!m_resumeAnswerSent)
1911  {
1912  m_resumeAnswerSent = true;
1913  //kdDebug(7007) << "FileCopyJob::slotData (first time) -> send resume answer " << m_canResume << endl;
1914  m_putJob->slave()->sendResumeAnswer( m_canResume );
1915  }
1916 }
1917 
1918 void FileCopyJob::slotDataReq( TDEIO::Job * , TQByteArray &data)
1919 {
1920  //kdDebug(7007) << "FileCopyJob::slotDataReq" << endl;
1921  if (!m_resumeAnswerSent && !m_getJob)
1922  {
1923  // This can't happen (except as a migration bug on 12/10/2000)
1924  m_error = ERR_INTERNAL;
1925  m_errorText = "'Put' job didn't send canResume or 'Get' job didn't send data!";
1926  m_putJob->kill(true);
1927  emitResult();
1928  return;
1929  }
1930  if (m_getJob)
1931  {
1932  m_getJob->resume(); // Order more beer
1933  m_putJob->suspend();
1934  }
1935  data = m_buffer;
1936  m_buffer = TQByteArray();
1937 }
1938 
1939 void FileCopyJob::slotMimetype( TDEIO::Job*, const TQString& type )
1940 {
1941  emit mimetype( this, type );
1942 }
1943 
1944 void FileCopyJob::slotResult( TDEIO::Job *job)
1945 {
1946  //kdDebug(7007) << "FileCopyJob this=" << this << " ::slotResult(" << job << ")" << endl;
1947  // Did job have an error ?
1948  if ( job->error() )
1949  {
1950  if ((job == m_moveJob) && (job->error() == ERR_UNSUPPORTED_ACTION))
1951  {
1952  m_moveJob = 0;
1953  startBestCopyMethod();
1954  removeSubjob(job);
1955  return;
1956  }
1957  else if ((job == m_copyJob) && (job->error() == ERR_UNSUPPORTED_ACTION))
1958  {
1959  m_copyJob = 0;
1960  startDataPump();
1961  removeSubjob(job);
1962  return;
1963  }
1964  else if (job == m_getJob)
1965  {
1966  m_getJob = 0L;
1967  if (m_putJob)
1968  m_putJob->kill(true);
1969  }
1970  else if (job == m_putJob)
1971  {
1972  m_putJob = 0L;
1973  if (m_getJob)
1974  m_getJob->kill(true);
1975  }
1976  m_error = job->error();
1977  m_errorText = job->errorText();
1978  emitResult();
1979  return;
1980  }
1981 
1982  if (job == m_moveJob)
1983  {
1984  m_moveJob = 0; // Finished
1985  }
1986 
1987  if (job == m_copyJob)
1988  {
1989  m_copyJob = 0;
1990  if (m_move)
1991  {
1992  d->m_delJob = file_delete( m_src, false/*no GUI*/ ); // Delete source
1993  addSubjob(d->m_delJob);
1994  }
1995  }
1996 
1997  if (job == m_getJob)
1998  {
1999  m_getJob = 0; // No action required
2000  if (m_putJob)
2001  m_putJob->resume();
2002  }
2003 
2004  if (job == m_putJob)
2005  {
2006  //kdDebug(7007) << "FileCopyJob: m_putJob finished " << endl;
2007  m_putJob = 0;
2008  if (m_getJob)
2009  {
2010  kdWarning(7007) << "WARNING ! Get still going on..." << endl;
2011  m_getJob->resume();
2012  }
2013  if (m_move)
2014  {
2015  d->m_delJob = file_delete( m_src, false/*no GUI*/ ); // Delete source
2016  addSubjob(d->m_delJob);
2017  }
2018  }
2019 
2020  if (job == d->m_delJob)
2021  {
2022  d->m_delJob = 0; // Finished
2023  }
2024  removeSubjob(job);
2025 }
2026 
2027 FileCopyJob *TDEIO::file_copy( const KURL& src, const KURL& dest, int permissions,
2028  bool overwrite, bool resume, bool showProgressInfo)
2029 {
2030  return new FileCopyJob( src, dest, permissions, false, overwrite, resume, showProgressInfo );
2031 }
2032 
2033 FileCopyJob *TDEIO::file_move( const KURL& src, const KURL& dest, int permissions,
2034  bool overwrite, bool resume, bool showProgressInfo)
2035 {
2036  return new FileCopyJob( src, dest, permissions, true, overwrite, resume, showProgressInfo );
2037 }
2038 
2039 SimpleJob *TDEIO::file_delete( const KURL& src, bool showProgressInfo)
2040 {
2041  TDEIO_ARGS << src << TQ_INT8(true); // isFile
2042  return new SimpleJob(src, CMD_DEL, packedArgs, showProgressInfo );
2043 }
2044 
2046 
2047 // KDE 4: Make it const TQString & _prefix
2048 ListJob::ListJob(const KURL& u, bool showProgressInfo, bool _recursive, TQString _prefix, bool _includeHidden) :
2049  SimpleJob(u, CMD_LISTDIR, TQByteArray(), showProgressInfo),
2050  recursive(_recursive), includeHidden(_includeHidden), prefix(_prefix), m_processedEntries(0)
2051 {
2052  // We couldn't set the args when calling the parent constructor,
2053  // so do it now.
2054  TQDataStream stream( m_packedArgs, IO_WriteOnly );
2055  stream << u;
2056 }
2057 
2058 void ListJob::slotListEntries( const TDEIO::UDSEntryList& list )
2059 {
2060  // Emit progress info (takes care of emit processedSize and percent)
2061  m_processedEntries += list.count();
2062  slotProcessedSize( m_processedEntries );
2063 
2064  if (recursive) {
2065  UDSEntryListConstIterator it = list.begin();
2066  UDSEntryListConstIterator end = list.end();
2067 
2068  for (; it != end; ++it) {
2069  bool isDir = false;
2070  bool isLink = false;
2071  KURL itemURL;
2072 
2073  UDSEntry::ConstIterator it2 = (*it).begin();
2074  UDSEntry::ConstIterator end2 = (*it).end();
2075  for( ; it2 != end2; it2++ ) {
2076  switch( (*it2).m_uds ) {
2077  case UDS_FILE_TYPE:
2078  isDir = S_ISDIR((*it2).m_long);
2079  break;
2080  case UDS_NAME:
2081  if( itemURL.isEmpty() ) {
2082  itemURL = url();
2083  itemURL.addPath( (*it2).m_str );
2084  }
2085  break;
2086  case UDS_URL:
2087  itemURL = (*it2).m_str;
2088  break;
2089  case UDS_LINK_DEST:
2090  // This is a link !!! Don't follow !
2091  isLink = !(*it2).m_str.isEmpty();
2092  break;
2093  default:
2094  break;
2095  }
2096  }
2097  if (isDir && !isLink) {
2098  const TQString filename = itemURL.fileName();
2099  // skip hidden dirs when listing if requested
2100  if (filename != ".." && filename != "." && (includeHidden || filename[0] != '.')) {
2101  ListJob *job = new ListJob(itemURL,
2102  false /*no progress info!*/,
2103  true /*recursive*/,
2104  prefix + filename + "/",
2105  includeHidden);
2106  Scheduler::scheduleJob(job);
2107  connect(job, TQ_SIGNAL(entries( TDEIO::Job *,
2108  const TDEIO::UDSEntryList& )),
2109  TQ_SLOT( gotEntries( TDEIO::Job*,
2110  const TDEIO::UDSEntryList& )));
2111  addSubjob(job);
2112  }
2113  }
2114  }
2115  }
2116 
2117  // Not recursive, or top-level of recursive listing : return now (send . and .. as well)
2118  // exclusion of hidden files also requires the full sweep, but the case for full-listing
2119  // a single dir is probably common enough to justify the shortcut
2120  if (prefix.isNull() && includeHidden) {
2121  emit entries(this, list);
2122  } else {
2123  // cull the unwanted hidden dirs and/or parent dir references from the listing, then emit that
2124  UDSEntryList newlist;
2125 
2126  UDSEntryListConstIterator it = list.begin();
2127  UDSEntryListConstIterator end = list.end();
2128  for (; it != end; ++it) {
2129 
2130  UDSEntry newone = *it;
2131  UDSEntry::Iterator it2 = newone.begin();
2132  TQString filename;
2133  for( ; it2 != newone.end(); it2++ ) {
2134  if ((*it2).m_uds == UDS_NAME) {
2135  filename = (*it2).m_str;
2136  (*it2).m_str = prefix + filename;
2137  }
2138  }
2139  // Avoid returning entries like subdir/. and subdir/.., but include . and .. for
2140  // the toplevel dir, and skip hidden files/dirs if that was requested
2141  if ( (prefix.isNull() || (filename != ".." && filename != ".") )
2142  && (includeHidden || (filename[0] != '.') ) )
2143  newlist.append(newone);
2144  }
2145 
2146  emit entries(this, newlist);
2147  }
2148 }
2149 
2150 void ListJob::gotEntries(TDEIO::Job *, const TDEIO::UDSEntryList& list )
2151 {
2152  // Forward entries received by subjob - faking we received them ourselves
2153  emit entries(this, list);
2154 }
2155 
2156 void ListJob::slotResult( TDEIO::Job * job )
2157 {
2158  // If we can't list a subdir, the result is still ok
2159  // This is why we override Job::slotResult() - to skip error checking
2160  removeSubjob( job );
2161 }
2162 
2163 void ListJob::slotRedirection( const KURL & url )
2164 {
2165  if (!kapp->authorizeURLAction("redirect", m_url, url))
2166  {
2167  kdWarning(7007) << "ListJob: Redirection from " << m_url << " to " << url << " REJECTED!" << endl;
2168  return;
2169  }
2170  m_redirectionURL = url; // We'll remember that when the job finishes
2171  if (m_url.hasUser() && !url.hasUser() && (m_url.host().lower() == url.host().lower()))
2172  m_redirectionURL.setUser(m_url.user()); // Preserve user
2173  emit redirection( this, m_redirectionURL );
2174 }
2175 
2176 void ListJob::slotFinished()
2177 {
2178  // Support for listing archives as directories
2179  if ( m_error == TDEIO::ERR_IS_FILE && m_url.isLocalFile() ) {
2180  KMimeType::Ptr ptr = KMimeType::findByURL( m_url, 0, true, true );
2181  if ( ptr ) {
2182  TQString proto = ptr->property("X-TDE-LocalProtocol").toString();
2183  if ( !proto.isEmpty() && KProtocolInfo::isKnownProtocol(proto) ) {
2184  m_redirectionURL = m_url;
2185  m_redirectionURL.setProtocol( proto );
2186  m_error = 0;
2187  emit redirection(this,m_redirectionURL);
2188  }
2189  }
2190  }
2191  if ( m_redirectionURL.isEmpty() || !m_redirectionURL.isValid() || m_error ) {
2192  // Return slave to the scheduler
2193  SimpleJob::slotFinished();
2194  } else {
2195 
2196  //kdDebug(7007) << "ListJob: Redirection to " << m_redirectionURL << endl;
2197  if (queryMetaData("permanent-redirect")=="true")
2198  emit permanentRedirection(this, m_url, m_redirectionURL);
2199  m_url = m_redirectionURL;
2200  m_redirectionURL = KURL();
2201  m_packedArgs.truncate(0);
2202  TQDataStream stream( m_packedArgs, IO_WriteOnly );
2203  stream << m_url;
2204 
2205  // Return slave to the scheduler
2206  slaveDone();
2207  Scheduler::doJob(this);
2208  }
2209 }
2210 
2211 void ListJob::slotMetaData( const TDEIO::MetaData &_metaData) {
2212  SimpleJob::slotMetaData(_metaData);
2213  storeSSLSessionFromJob(m_redirectionURL);
2214 }
2215 
2216 ListJob *TDEIO::listDir( const KURL& url, bool showProgressInfo, bool includeHidden )
2217 {
2218  ListJob * job = new ListJob(url, showProgressInfo,false,TQString::null,includeHidden);
2219  return job;
2220 }
2221 
2222 ListJob *TDEIO::listRecursive( const KURL& url, bool showProgressInfo, bool includeHidden )
2223 {
2224  ListJob * job = new ListJob(url, showProgressInfo, true,TQString::null,includeHidden);
2225  return job;
2226 }
2227 
2228 void ListJob::setUnrestricted(bool unrestricted)
2229 {
2230  if (unrestricted)
2231  extraFlags() |= EF_ListJobUnrestricted;
2232  else
2233  extraFlags() &= ~EF_ListJobUnrestricted;
2234 }
2235 
2236 void ListJob::start(Slave *slave)
2237 {
2238  if (kapp && !kapp->authorizeURLAction("list", m_url, m_url) && !(extraFlags() & EF_ListJobUnrestricted))
2239  {
2240  m_error = ERR_ACCESS_DENIED;
2241  m_errorText = m_url.url();
2242  TQTimer::singleShot(0, this, TQ_SLOT(slotFinished()) );
2243  return;
2244  }
2245  connect( slave, TQ_SIGNAL( listEntries( const TDEIO::UDSEntryList& )),
2246  TQ_SLOT( slotListEntries( const TDEIO::UDSEntryList& )));
2247  connect( slave, TQ_SIGNAL( totalSize( TDEIO::filesize_t ) ),
2248  TQ_SLOT( slotTotalSize( TDEIO::filesize_t ) ) );
2249  connect( slave, TQ_SIGNAL( redirection(const KURL &) ),
2250  TQ_SLOT( slotRedirection(const KURL &) ) );
2251 
2252  SimpleJob::start(slave);
2253 }
2254 
2255 class CopyJob::CopyJobPrivate
2256 {
2257 public:
2258  CopyJobPrivate() {
2259  m_defaultPermissions = false;
2260  m_bURLDirty = false;
2261  }
2262  // This is the dest URL that was initially given to CopyJob
2263  // It is copied into m_dest, which can be changed for a given src URL
2264  // (when using the RENAME dialog in slotResult),
2265  // and which will be reset for the next src URL.
2266  KURL m_globalDest;
2267  // The state info about that global dest
2268  CopyJob::DestinationState m_globalDestinationState;
2269  // See setDefaultPermissions
2270  bool m_defaultPermissions;
2271  // Whether URLs changed (and need to be emitted by the next slotReport call)
2272  bool m_bURLDirty;
2273  // Used after copying all the files into the dirs, to set mtime (TODO: and permissions?)
2274  // after the copy is done
2275  TQValueList<CopyInfo> m_directoriesCopied;
2276 };
2277 
2278 CopyJob::CopyJob( const KURL::List& src, const KURL& dest, CopyMode mode, bool asMethod, bool showProgressInfo )
2279  : Job(showProgressInfo), m_mode(mode), m_asMethod(asMethod),
2280  destinationState(DEST_NOT_STATED), state(STATE_STATING),
2281  m_totalSize(0), m_processedSize(0), m_fileProcessedSize(0),
2282  m_processedFiles(0), m_processedDirs(0),
2283  m_srcList(src), m_currentStatSrc(m_srcList.begin()),
2284  m_bCurrentOperationIsLink(false), m_bSingleFileCopy(false), m_bOnlyRenames(mode==Move),
2285  m_dest(dest), m_bAutoSkip( false ), m_bOverwriteAll( false ),
2286  m_conflictError(0), m_reportTimer(0)
2287 {
2288  d = new CopyJobPrivate;
2289  d->m_globalDest = dest;
2290  d->m_globalDestinationState = destinationState;
2291 
2292  if ( showProgressInfo ) {
2293  connect( this, TQ_SIGNAL( totalFiles( TDEIO::Job*, unsigned long ) ),
2294  Observer::self(), TQ_SLOT( slotTotalFiles( TDEIO::Job*, unsigned long ) ) );
2295 
2296  connect( this, TQ_SIGNAL( totalDirs( TDEIO::Job*, unsigned long ) ),
2297  Observer::self(), TQ_SLOT( slotTotalDirs( TDEIO::Job*, unsigned long ) ) );
2298  }
2299  TQTimer::singleShot(0, this, TQ_SLOT(slotStart()));
2314 }
2315 
2316 CopyJob::~CopyJob()
2317 {
2318  delete d;
2319 }
2320 
2321 void CopyJob::slotStart()
2322 {
2328  m_reportTimer = new TQTimer(this);
2329 
2330  connect(m_reportTimer,TQ_SIGNAL(timeout()),this,TQ_SLOT(slotReport()));
2331  m_reportTimer->start(REPORT_TIMEOUT,false);
2332 
2333  // Stat the dest
2334  TDEIO::Job * job = TDEIO::stat( m_dest, false, 2, false );
2335  //kdDebug(7007) << "CopyJob:stating the dest " << m_dest << endl;
2336  addSubjob(job);
2337 }
2338 
2339 // For unit test purposes
2340 TDEIO_EXPORT bool tdeio_resolve_local_urls = true;
2341 
2342 void CopyJob::slotResultStating( Job *job )
2343 {
2344  //kdDebug(7007) << "CopyJob::slotResultStating" << endl;
2345  // Was there an error while stating the src ?
2346  if (job->error() && destinationState != DEST_NOT_STATED )
2347  {
2348  KURL srcurl = ((SimpleJob*)job)->url();
2349  if ( !srcurl.isLocalFile() )
2350  {
2351  // Probably : src doesn't exist. Well, over some protocols (e.g. FTP)
2352  // this info isn't really reliable (thanks to MS FTP servers).
2353  // We'll assume a file, and try to download anyway.
2354  kdDebug(7007) << "Error while stating source. Activating hack" << endl;
2355  subjobs.remove( job );
2356  assert ( subjobs.isEmpty() ); // We should have only one job at a time ...
2357  struct CopyInfo info;
2358  info.permissions = (mode_t) -1;
2359  info.mtime = (time_t) -1;
2360  info.ctime = (time_t) -1;
2361  info.size = (TDEIO::filesize_t)-1;
2362  info.uSource = srcurl;
2363  info.uDest = m_dest;
2364  // Append filename or dirname to destination URL, if allowed
2365  if ( destinationState == DEST_IS_DIR && !m_asMethod )
2366  info.uDest.addPath( srcurl.fileName() );
2367 
2368  files.append( info );
2369  statNextSrc();
2370  return;
2371  }
2372  // Local file. If stat fails, the file definitely doesn't exist.
2373  Job::slotResult( job ); // will set the error and emit result(this)
2374  return;
2375  }
2376 
2377  // Is it a file or a dir ? Does it have a local path?
2378  UDSEntry entry = ((StatJob*)job)->statResult();
2379  bool bDir = false;
2380  bool bLink = false;
2381  TQString sName;
2382  TQString sLocalPath;
2383  UDSEntry::ConstIterator it2 = entry.begin();
2384  for( ; it2 != entry.end(); it2++ ) {
2385  if ( ((*it2).m_uds) == UDS_FILE_TYPE )
2386  bDir = S_ISDIR( (mode_t)(*it2).m_long );
2387  else if ( ((*it2).m_uds) == UDS_LINK_DEST )
2388  bLink = !((*it2).m_str.isEmpty());
2389  else if ( ((*it2).m_uds) == UDS_NAME )
2390  sName = (*it2).m_str;
2391  else if ( ((*it2).m_uds) == UDS_LOCAL_PATH )
2392  sLocalPath = (*it2).m_str;
2393  }
2394 
2395  if ( destinationState == DEST_NOT_STATED )
2396  // we were stating the dest
2397  {
2398  if (job->error())
2399  destinationState = DEST_DOESNT_EXIST;
2400  else {
2401  // Treat symlinks to dirs as dirs here, so no test on bLink
2402  destinationState = bDir ? DEST_IS_DIR : DEST_IS_FILE;
2403  //kdDebug(7007) << "CopyJob::slotResultStating dest is dir:" << bDir << endl;
2404  }
2405  const bool isGlobalDest = m_dest == d->m_globalDest;
2406  if ( isGlobalDest )
2407  d->m_globalDestinationState = destinationState;
2408 
2409  if ( !sLocalPath.isEmpty() && tdeio_resolve_local_urls ) {
2410  m_dest = KURL();
2411  m_dest.setPath(sLocalPath);
2412  if ( isGlobalDest )
2413  d->m_globalDest = m_dest;
2414  }
2415 
2416  subjobs.remove( job );
2417  assert ( subjobs.isEmpty() );
2418 
2419  // After knowing what the dest is, we can start stat'ing the first src.
2420  statCurrentSrc();
2421  return;
2422  }
2423  // We were stating the current source URL
2424  m_currentDest = m_dest; // used by slotEntries
2425  // Create a dummy list with it, for slotEntries
2426  UDSEntryList lst;
2427  lst.append(entry);
2428 
2429  // There 6 cases, and all end up calling slotEntries(job, lst) first :
2430  // 1 - src is a dir, destination is a directory,
2431  // slotEntries will append the source-dir-name to the destination
2432  // 2 - src is a dir, destination is a file, ERROR (done later on)
2433  // 3 - src is a dir, destination doesn't exist, then it's the destination dirname,
2434  // so slotEntries will use it as destination.
2435 
2436  // 4 - src is a file, destination is a directory,
2437  // slotEntries will append the filename to the destination.
2438  // 5 - src is a file, destination is a file, m_dest is the exact destination name
2439  // 6 - src is a file, destination doesn't exist, m_dest is the exact destination name
2440  // Tell slotEntries not to alter the src url
2441  m_bCurrentSrcIsDir = false;
2442  slotEntries(job, lst);
2443 
2444  KURL srcurl;
2445  if (!sLocalPath.isEmpty())
2446  srcurl.setPath(sLocalPath);
2447  else
2448  srcurl = ((SimpleJob*)job)->url();
2449 
2450  subjobs.remove( job );
2451  assert ( subjobs.isEmpty() ); // We should have only one job at a time ...
2452 
2453  if ( bDir
2454  && !bLink // treat symlinks as files (no recursion)
2455  && m_mode != Link ) // No recursion in Link mode either.
2456  {
2457  //kdDebug(7007) << " Source is a directory " << endl;
2458 
2459  m_bCurrentSrcIsDir = true; // used by slotEntries
2460  if ( destinationState == DEST_IS_DIR ) // (case 1)
2461  {
2462  if ( !m_asMethod )
2463  {
2464  // Use <desturl>/<directory_copied> as destination, from now on
2465  TQString directory = srcurl.fileName();
2466  if ( !sName.isEmpty() && KProtocolInfo::fileNameUsedForCopying( srcurl ) == KProtocolInfo::Name )
2467  {
2468  directory = sName;
2469  }
2470  m_currentDest.addPath( directory );
2471  }
2472  }
2473  else if ( destinationState == DEST_IS_FILE ) // (case 2)
2474  {
2475  m_error = ERR_IS_FILE;
2476  m_errorText = m_dest.prettyURL();
2477  emitResult();
2478  return;
2479  }
2480  else // (case 3)
2481  {
2482  // otherwise dest is new name for toplevel dir
2483  // so the destination exists, in fact, from now on.
2484  // (This even works with other src urls in the list, since the
2485  // dir has effectively been created)
2486  destinationState = DEST_IS_DIR;
2487  if ( m_dest == d->m_globalDest )
2488  d->m_globalDestinationState = destinationState;
2489  }
2490 
2491  startListing( srcurl );
2492  }
2493  else
2494  {
2495  //kdDebug(7007) << " Source is a file (or a symlink), or we are linking -> no recursive listing " << endl;
2496  statNextSrc();
2497  }
2498 }
2499 
2500 void CopyJob::slotReport()
2501 {
2502  // If showProgressInfo was set, m_progressId is > 0.
2503  Observer * observer = m_progressId ? Observer::self() : 0L;
2504  switch (state) {
2505  case STATE_COPYING_FILES:
2506  emit processedFiles( this, m_processedFiles );
2507  if (observer) observer->slotProcessedFiles(this, m_processedFiles);
2508  if (d->m_bURLDirty)
2509  {
2510  // Only emit urls when they changed. This saves time, and fixes #66281
2511  d->m_bURLDirty = false;
2512  if (m_mode==Move)
2513  {
2514  if (observer) observer->slotMoving( this, m_currentSrcURL, m_currentDestURL);
2515  emit moving( this, m_currentSrcURL, m_currentDestURL);
2516  }
2517  else if (m_mode==Link)
2518  {
2519  if (observer) observer->slotCopying( this, m_currentSrcURL, m_currentDestURL ); // we don't have a slotLinking
2520  emit linking( this, m_currentSrcURL.path(), m_currentDestURL );
2521  }
2522  else
2523  {
2524  if (observer) observer->slotCopying( this, m_currentSrcURL, m_currentDestURL );
2525  emit copying( this, m_currentSrcURL, m_currentDestURL );
2526  }
2527  }
2528  break;
2529 
2530  case STATE_CREATING_DIRS:
2531  if (observer) observer->slotProcessedDirs( this, m_processedDirs );
2532  emit processedDirs( this, m_processedDirs );
2533  if (d->m_bURLDirty)
2534  {
2535  d->m_bURLDirty = false;
2536  emit creatingDir( this, m_currentDestURL );
2537  if (observer) observer->slotCreatingDir( this, m_currentDestURL);
2538  }
2539  break;
2540 
2541  case STATE_STATING:
2542  case STATE_LISTING:
2543  if (d->m_bURLDirty)
2544  {
2545  d->m_bURLDirty = false;
2546  if (observer) observer->slotCopying( this, m_currentSrcURL, m_currentDestURL );
2547  }
2548  emit totalSize( this, m_totalSize );
2549  emit totalFiles( this, files.count() );
2550  emit totalDirs( this, dirs.count() );
2551  break;
2552 
2553  default:
2554  break;
2555  }
2556 }
2557 
2558 void CopyJob::slotEntries(TDEIO::Job* job, const UDSEntryList& list)
2559 {
2560  UDSEntryListConstIterator it = list.begin();
2561  UDSEntryListConstIterator end = list.end();
2562  for (; it != end; ++it) {
2563  UDSEntry::ConstIterator it2 = (*it).begin();
2564  struct CopyInfo info;
2565  info.permissions = -1;
2566  info.mtime = (time_t) -1;
2567  info.ctime = (time_t) -1;
2568  info.size = (TDEIO::filesize_t)-1;
2569  TQString displayName;
2570  KURL url;
2571  TQString localPath;
2572  bool isDir = false;
2573  for( ; it2 != (*it).end(); it2++ ) {
2574  switch ((*it2).m_uds) {
2575  case UDS_FILE_TYPE:
2576  //info.type = (mode_t)((*it2).m_long);
2577  isDir = S_ISDIR( (mode_t)((*it2).m_long) );
2578  break;
2579  case UDS_NAME: // recursive listing, displayName can be a/b/c/d
2580  displayName = (*it2).m_str;
2581  break;
2582  case UDS_URL: // optional
2583  url = KURL((*it2).m_str);
2584  break;
2585  case UDS_LOCAL_PATH:
2586  localPath = (*it2).m_str;
2587  break;
2588  case UDS_LINK_DEST:
2589  info.linkDest = (*it2).m_str;
2590  break;
2591  case UDS_ACCESS:
2592  info.permissions = ((*it2).m_long);
2593  break;
2594  case UDS_SIZE:
2595  info.size = (TDEIO::filesize_t)((*it2).m_long);
2596  m_totalSize += info.size;
2597  break;
2598  case UDS_MODIFICATION_TIME:
2599  info.mtime = (time_t)((*it2).m_long);
2600  break;
2601  case UDS_CREATION_TIME:
2602  info.ctime = (time_t)((*it2).m_long);
2603  default:
2604  break;
2605  }
2606  }
2607  if (displayName != ".." && displayName != ".")
2608  {
2609  bool hasCustomURL = !url.isEmpty() || !localPath.isEmpty();
2610  if( !hasCustomURL ) {
2611  // Make URL from displayName
2612  url = ((SimpleJob *)job)->url();
2613  if ( m_bCurrentSrcIsDir ) { // Only if src is a directory. Otherwise uSource is fine as is
2614  //kdDebug(7007) << "adding path " << displayName << endl;
2615  url.addPath( displayName );
2616  }
2617  }
2618  //kdDebug(7007) << "displayName=" << displayName << " url=" << url << endl;
2619  if (!localPath.isEmpty() && tdeio_resolve_local_urls) {
2620  url = KURL();
2621  url.setPath(localPath);
2622  }
2623 
2624  info.uSource = url;
2625  info.uDest = m_currentDest;
2626  //kdDebug(7007) << " uSource=" << info.uSource << " uDest(1)=" << info.uDest << endl;
2627  // Append filename or dirname to destination URL, if allowed
2628  if ( destinationState == DEST_IS_DIR &&
2629  // "copy/move as <foo>" means 'foo' is the dest for the base srcurl
2630  // (passed here during stating) but not its children (during listing)
2631  ( ! ( m_asMethod && state == STATE_STATING ) ) )
2632  {
2633  TQString destFileName;
2634  if ( hasCustomURL &&
2635  KProtocolInfo::fileNameUsedForCopying( url ) == KProtocolInfo::FromURL ) {
2636  //destFileName = url.fileName(); // Doesn't work for recursive listing
2637  // Count the number of prefixes used by the recursive listjob
2638  int numberOfSlashes = displayName.contains( '/' ); // don't make this a find()!
2639  TQString path = url.path();
2640  int pos = 0;
2641  for ( int n = 0; n < numberOfSlashes + 1; ++n ) {
2642  pos = path.findRev( '/', pos - 1 );
2643  if ( pos == -1 ) { // error
2644  kdWarning(7007) << "tdeioslave bug: not enough slashes in UDS_URL " << path << " - looking for " << numberOfSlashes << " slashes" << endl;
2645  break;
2646  }
2647  }
2648  if ( pos >= 0 ) {
2649  destFileName = path.mid( pos + 1 );
2650  }
2651 
2652  } else { // destination filename taken from UDS_NAME
2653  destFileName = displayName;
2654  }
2655 
2656  // Here we _really_ have to add some filename to the dest.
2657  // Otherwise, we end up with e.g. dest=..../Desktop/ itself.
2658  // (This can happen when dropping a link to a webpage with no path)
2659  if ( destFileName.isEmpty() )
2660  destFileName = TDEIO::encodeFileName( info.uSource.prettyURL() );
2661 
2662  //kdDebug(7007) << " adding destFileName=" << destFileName << endl;
2663  info.uDest.addPath( destFileName );
2664  }
2665  //kdDebug(7007) << " uDest(2)=" << info.uDest << endl;
2666  //kdDebug(7007) << " " << info.uSource << " -> " << info.uDest << endl;
2667  if ( info.linkDest.isEmpty() && isDir && m_mode != Link ) // Dir
2668  {
2669  dirs.append( info ); // Directories
2670  if (m_mode == Move)
2671  dirsToRemove.append( info.uSource );
2672  }
2673  else {
2674  files.append( info ); // Files and any symlinks
2675  }
2676  }
2677  }
2678 }
2679 
2680 void CopyJob::skipSrc()
2681 {
2682  m_dest = d->m_globalDest;
2683  destinationState = d->m_globalDestinationState;
2684  ++m_currentStatSrc;
2685  skip( m_currentSrcURL );
2686  statCurrentSrc();
2687 }
2688 
2689 void CopyJob::statNextSrc()
2690 {
2691  /* Revert to the global destination, the one that applies to all source urls.
2692  * Imagine you copy the items a b and c into /d, but /d/b exists so the user uses "Rename" to put it in /foo/b instead.
2693  * m_dest is /foo/b for b, but we have to revert to /d for item c and following.
2694  */
2695  m_dest = d->m_globalDest;
2696  destinationState = d->m_globalDestinationState;
2697  ++m_currentStatSrc;
2698  statCurrentSrc();
2699 }
2700 
2701 void CopyJob::statCurrentSrc()
2702 {
2703  if ( m_currentStatSrc != m_srcList.end() )
2704  {
2705  m_currentSrcURL = (*m_currentStatSrc);
2706  d->m_bURLDirty = true;
2707  if ( m_mode == Link )
2708  {
2709  // Skip the "stating the source" stage, we don't need it for linking
2710  m_currentDest = m_dest;
2711  struct CopyInfo info;
2712  info.permissions = -1;
2713  info.mtime = (time_t) -1;
2714  info.ctime = (time_t) -1;
2715  info.size = (TDEIO::filesize_t)-1;
2716  info.uSource = m_currentSrcURL;
2717  info.uDest = m_currentDest;
2718  // Append filename or dirname to destination URL, if allowed
2719  if ( destinationState == DEST_IS_DIR && !m_asMethod )
2720  {
2721  if (
2722  (m_currentSrcURL.protocol() == info.uDest.protocol()) &&
2723  (m_currentSrcURL.host() == info.uDest.host()) &&
2724  (m_currentSrcURL.port() == info.uDest.port()) &&
2725  (m_currentSrcURL.user() == info.uDest.user()) &&
2726  (m_currentSrcURL.pass() == info.uDest.pass()) )
2727  {
2728  // This is the case of creating a real symlink
2729  info.uDest.addPath( m_currentSrcURL.fileName() );
2730  }
2731  else
2732  {
2733  // Different protocols, we'll create a .desktop file
2734  // We have to change the extension anyway, so while we're at it,
2735  // name the file like the URL
2736  info.uDest.addPath( TDEIO::encodeFileName( m_currentSrcURL.prettyURL() )+".desktop" );
2737  }
2738  }
2739  files.append( info ); // Files and any symlinks
2740  statNextSrc(); // we could use a loop instead of a recursive call :)
2741  return;
2742  }
2743  else if ( m_mode == Move && (
2744  // Don't go renaming right away if we need a stat() to find out the destination filename
2745  KProtocolInfo::fileNameUsedForCopying( m_currentSrcURL ) == KProtocolInfo::FromURL ||
2746  destinationState != DEST_IS_DIR || m_asMethod )
2747  )
2748  {
2749  // If moving, before going for the full stat+[list+]copy+del thing, try to rename
2750  // The logic is pretty similar to FileCopyJob::slotStart()
2751  if ( (m_currentSrcURL.protocol() == m_dest.protocol()) &&
2752  (m_currentSrcURL.host() == m_dest.host()) &&
2753  (m_currentSrcURL.port() == m_dest.port()) &&
2754  (m_currentSrcURL.user() == m_dest.user()) &&
2755  (m_currentSrcURL.pass() == m_dest.pass()) )
2756  {
2757  startRenameJob( m_currentSrcURL );
2758  return;
2759  }
2760  else if ( m_currentSrcURL.isLocalFile() && KProtocolInfo::canRenameFromFile( m_dest ) )
2761  {
2762  startRenameJob( m_dest );
2763  return;
2764  }
2765  else if ( m_dest.isLocalFile() && KProtocolInfo::canRenameToFile( m_currentSrcURL ) )
2766  {
2767  startRenameJob( m_currentSrcURL );
2768  return;
2769  }
2770  }
2771 
2772  // if the file system doesn't support deleting, we do not even stat
2773  if (m_mode == Move && !KProtocolInfo::supportsDeleting(m_currentSrcURL)) {
2774  TQGuardedPtr<CopyJob> that = this;
2775  if (isInteractive())
2776  KMessageBox::information( 0, buildErrorString(ERR_CANNOT_DELETE, m_currentSrcURL.prettyURL()));
2777  if (that)
2778  statNextSrc(); // we could use a loop instead of a recursive call :)
2779  return;
2780  }
2781 
2782  // Stat the next src url
2783  Job * job = TDEIO::stat( m_currentSrcURL, true, 2, false );
2784  //kdDebug(7007) << "TDEIO::stat on " << m_currentSrcURL << endl;
2785  state = STATE_STATING;
2786  addSubjob(job);
2787  m_currentDestURL=m_dest;
2788  m_bOnlyRenames = false;
2789  d->m_bURLDirty = true;
2790  }
2791  else
2792  {
2793  // Finished the stat'ing phase
2794  // First make sure that the totals were correctly emitted
2795  state = STATE_STATING;
2796  d->m_bURLDirty = true;
2797  slotReport();
2798  if (!dirs.isEmpty())
2799  emit aboutToCreate( this, dirs );
2800  if (!files.isEmpty())
2801  emit aboutToCreate( this, files );
2802  // Check if we are copying a single file
2803  m_bSingleFileCopy = ( files.count() == 1 && dirs.isEmpty() );
2804  // Then start copying things
2805  state = STATE_CREATING_DIRS;
2806  createNextDir();
2807  }
2808 }
2809 
2810 void CopyJob::startRenameJob( const KURL& slave_url )
2811 {
2812  KURL dest = m_dest;
2813  // Append filename or dirname to destination URL, if allowed
2814  if ( destinationState == DEST_IS_DIR && !m_asMethod )
2815  dest.addPath( m_currentSrcURL.fileName() );
2816  kdDebug(7007) << "This seems to be a suitable case for trying to rename before stat+[list+]copy+del" << endl;
2817  state = STATE_RENAMING;
2818 
2819  struct CopyInfo info;
2820  info.permissions = -1;
2821  info.mtime = (time_t) -1;
2822  info.ctime = (time_t) -1;
2823  info.size = (TDEIO::filesize_t)-1;
2824  info.uSource = m_currentSrcURL;
2825  info.uDest = dest;
2826  TQValueList<CopyInfo> files;
2827  files.append(info);
2828  emit aboutToCreate( this, files );
2829 
2830  TDEIO_ARGS << m_currentSrcURL << dest << (TQ_INT8) false /*no overwrite*/;
2831  SimpleJob * newJob = new SimpleJob(slave_url, CMD_RENAME, packedArgs, false);
2832  Scheduler::scheduleJob(newJob);
2833  addSubjob( newJob );
2834  if ( m_currentSrcURL.directory() != dest.directory() ) // For the user, moving isn't renaming. Only renaming is.
2835  m_bOnlyRenames = false;
2836 }
2837 
2838 void CopyJob::startListing( const KURL & src )
2839 {
2840  state = STATE_LISTING;
2841  d->m_bURLDirty = true;
2842  ListJob * newjob = listRecursive( src, false );
2843  newjob->setUnrestricted(true);
2844  connect(newjob, TQ_SIGNAL(entries( TDEIO::Job *,
2845  const TDEIO::UDSEntryList& )),
2846  TQ_SLOT( slotEntries( TDEIO::Job*,
2847  const TDEIO::UDSEntryList& )));
2848  addSubjob( newjob );
2849 }
2850 
2851 void CopyJob::skip( const KURL & sourceUrl )
2852 {
2853  // Check if this is one if toplevel sources
2854  // If yes, remove it from m_srcList, for a correct FilesRemoved() signal
2855  //kdDebug(7007) << "CopyJob::skip: looking for " << sourceUrl << endl;
2856  KURL::List::Iterator sit = m_srcList.find( sourceUrl );
2857  if ( sit != m_srcList.end() )
2858  {
2859  //kdDebug(7007) << "CopyJob::skip: removing " << sourceUrl << " from list" << endl;
2860  m_srcList.remove( sit );
2861  }
2862  dirsToRemove.remove( sourceUrl );
2863 }
2864 
2865 bool CopyJob::shouldOverwrite( const TQString& path ) const
2866 {
2867  if ( m_bOverwriteAll )
2868  return true;
2869  TQStringList::ConstIterator sit = m_overwriteList.begin();
2870  for( ; sit != m_overwriteList.end(); ++sit )
2871  if ( path.startsWith( *sit ) )
2872  return true;
2873  return false;
2874 }
2875 
2876 bool CopyJob::shouldSkip( const TQString& path ) const
2877 {
2878  TQStringList::ConstIterator sit = m_skipList.begin();
2879  for( ; sit != m_skipList.end(); ++sit )
2880  if ( path.startsWith( *sit ) )
2881  return true;
2882  return false;
2883 }
2884 
2885 void CopyJob::slotResultCreatingDirs( Job * job )
2886 {
2887  // The dir we are trying to create:
2888  TQValueList<CopyInfo>::Iterator it = dirs.begin();
2889  // Was there an error creating a dir ?
2890  if ( job->error() )
2891  {
2892  m_conflictError = job->error();
2893  if ( (m_conflictError == ERR_DIR_ALREADY_EXIST)
2894  || (m_conflictError == ERR_FILE_ALREADY_EXIST) ) // can't happen?
2895  {
2896  KURL oldURL = ((SimpleJob*)job)->url();
2897  // Should we skip automatically ?
2898  if ( m_bAutoSkip ) {
2899  // We don't want to copy files in this directory, so we put it on the skip list
2900  m_skipList.append( oldURL.path( 1 ) );
2901  skip( oldURL );
2902  dirs.remove( it ); // Move on to next dir
2903  } else {
2904  // Did the user choose to overwrite already?
2905  const TQString destFile = (*it).uDest.path();
2906  if ( shouldOverwrite( destFile ) ) { // overwrite => just skip
2907  emit copyingDone( this, ( *it ).uSource, ( *it ).uDest, true /* directory */, false /* renamed */ );
2908  dirs.remove( it ); // Move on to next dir
2909  } else {
2910  if ( !isInteractive() ) {
2911  Job::slotResult( job ); // will set the error and emit result(this)
2912  return;
2913  }
2914 
2915  assert( ((SimpleJob*)job)->url().url() == (*it).uDest.url() );
2916  subjobs.remove( job );
2917  assert ( subjobs.isEmpty() ); // We should have only one job at a time ...
2918 
2919  // We need to stat the existing dir, to get its last-modification time
2920  KURL existingDest( (*it).uDest );
2921  SimpleJob * newJob = TDEIO::stat( existingDest, false, 2, false );
2922  Scheduler::scheduleJob(newJob);
2923  kdDebug(7007) << "TDEIO::stat for resolving conflict on " << existingDest << endl;
2924  state = STATE_CONFLICT_CREATING_DIRS;
2925  addSubjob(newJob);
2926  return; // Don't move to next dir yet !
2927  }
2928  }
2929  }
2930  else
2931  {
2932  // Severe error, abort
2933  Job::slotResult( job ); // will set the error and emit result(this)
2934  return;
2935  }
2936  }
2937  else // no error : remove from list, to move on to next dir
2938  {
2939  //this is required for the undo feature
2940  emit copyingDone( this, (*it).uSource, (*it).uDest, true, false );
2941  d->m_directoriesCopied.append( *it );
2942  dirs.remove( it );
2943  }
2944 
2945  m_processedDirs++;
2946  //emit processedDirs( this, m_processedDirs );
2947  subjobs.remove( job );
2948  assert( subjobs.isEmpty() ); // We should have only one job at a time ...
2949  createNextDir();
2950 }
2951 
2952 void CopyJob::slotResultConflictCreatingDirs( TDEIO::Job * job )
2953 {
2954  // We come here after a conflict has been detected and we've stated the existing dir
2955 
2956  // The dir we were trying to create:
2957  TQValueList<CopyInfo>::Iterator it = dirs.begin();
2958  // Its modification time:
2959  time_t destmtime = (time_t)-1;
2960  time_t destctime = (time_t)-1;
2961  TDEIO::filesize_t destsize = 0;
2962  TQString linkDest;
2963 
2964  UDSEntry entry = ((TDEIO::StatJob*)job)->statResult();
2965  TDEIO::UDSEntry::ConstIterator it2 = entry.begin();
2966  for( ; it2 != entry.end(); it2++ ) {
2967  switch ((*it2).m_uds) {
2968  case UDS_MODIFICATION_TIME:
2969  destmtime = (time_t)((*it2).m_long);
2970  break;
2971  case UDS_CREATION_TIME:
2972  destctime = (time_t)((*it2).m_long);
2973  break;
2974  case UDS_SIZE:
2975  destsize = (*it2).m_long;
2976  break;
2977  case UDS_LINK_DEST:
2978  linkDest = (*it2).m_str;
2979  break;
2980  }
2981  }
2982  subjobs.remove( job );
2983  assert ( subjobs.isEmpty() ); // We should have only one job at a time ...
2984 
2985  // Always multi and skip (since there are files after that)
2986  RenameDlg_Mode mode = (RenameDlg_Mode)( M_MULTI | M_SKIP );
2987  // Overwrite only if the existing thing is a dir (no chance with a file)
2988  if ( m_conflictError == ERR_DIR_ALREADY_EXIST )
2989  {
2990  if( (*it).uSource == (*it).uDest ||
2991  ((*it).uSource.protocol() == (*it).uDest.protocol() &&
2992  (*it).uSource.path(-1) == linkDest) )
2993  mode = (RenameDlg_Mode)( mode | M_OVERWRITE_ITSELF);
2994  else
2995  mode = (RenameDlg_Mode)( mode | M_OVERWRITE );
2996  }
2997 
2998  TQString existingDest = (*it).uDest.path();
2999  TQString newPath;
3000  if (m_reportTimer)
3001  m_reportTimer->stop();
3002  RenameDlg_Result r = Observer::self()->open_RenameDlg( this, i18n("Folder Already Exists"),
3003  (*it).uSource.url(),
3004  (*it).uDest.url(),
3005  mode, newPath,
3006  (*it).size, destsize,
3007  (*it).ctime, destctime,
3008  (*it).mtime, destmtime );
3009  if (m_reportTimer)
3010  m_reportTimer->start(REPORT_TIMEOUT,false);
3011  switch ( r ) {
3012  case R_CANCEL:
3013  m_error = ERR_USER_CANCELED;
3014  emitResult();
3015  return;
3016  case R_RENAME:
3017  {
3018  TQString oldPath = (*it).uDest.path( 1 );
3019  KURL newUrl( (*it).uDest );
3020  newUrl.setPath( newPath );
3021  emit renamed( this, (*it).uDest, newUrl ); // for e.g. kpropsdlg
3022 
3023  // Change the current one and strip the trailing '/'
3024  (*it).uDest.setPath( newUrl.path( -1 ) );
3025  newPath = newUrl.path( 1 ); // With trailing slash
3026  TQValueList<CopyInfo>::Iterator renamedirit = it;
3027  ++renamedirit;
3028  // Change the name of subdirectories inside the directory
3029  for( ; renamedirit != dirs.end() ; ++renamedirit )
3030  {
3031  TQString path = (*renamedirit).uDest.path();
3032  if ( path.left(oldPath.length()) == oldPath ) {
3033  TQString n = path;
3034  n.replace( 0, oldPath.length(), newPath );
3035  kdDebug(7007) << "dirs list: " << (*renamedirit).uSource.path()
3036  << " was going to be " << path
3037  << ", changed into " << n << endl;
3038  (*renamedirit).uDest.setPath( n );
3039  }
3040  }
3041  // Change filenames inside the directory
3042  TQValueList<CopyInfo>::Iterator renamefileit = files.begin();
3043  for( ; renamefileit != files.end() ; ++renamefileit )
3044  {
3045  TQString path = (*renamefileit).uDest.path();
3046  if ( path.left(oldPath.length()) == oldPath ) {
3047  TQString n = path;
3048  n.replace( 0, oldPath.length(), newPath );
3049  kdDebug(7007) << "files list: " << (*renamefileit).uSource.path()
3050  << " was going to be " << path
3051  << ", changed into " << n << endl;
3052  (*renamefileit).uDest.setPath( n );
3053  }
3054  }
3055  if (!dirs.isEmpty())
3056  emit aboutToCreate( this, dirs );
3057  if (!files.isEmpty())
3058  emit aboutToCreate( this, files );
3059  }
3060  break;
3061  case R_AUTO_SKIP:
3062  m_bAutoSkip = true;
3063  // fall through
3064  case R_SKIP:
3065  m_skipList.append( existingDest );
3066  skip( (*it).uSource );
3067  // Move on to next dir
3068  dirs.remove( it );
3069  m_processedDirs++;
3070  break;
3071  case R_OVERWRITE:
3072  m_overwriteList.append( existingDest );
3073  emit copyingDone( this, ( *it ).uSource, ( *it ).uDest, true /* directory */, false /* renamed */ );
3074  // Move on to next dir
3075  dirs.remove( it );
3076  m_processedDirs++;
3077  break;
3078  case R_OVERWRITE_ALL:
3079  m_bOverwriteAll = true;
3080  emit copyingDone( this, ( *it ).uSource, ( *it ).uDest, true /* directory */, false /* renamed */ );
3081  // Move on to next dir
3082  dirs.remove( it );
3083  m_processedDirs++;
3084  break;
3085  default:
3086  assert( 0 );
3087  }
3088  state = STATE_CREATING_DIRS;
3089  //emit processedDirs( this, m_processedDirs );
3090  createNextDir();
3091 }
3092 
3093 void CopyJob::createNextDir()
3094 {
3095  KURL udir;
3096  if ( !dirs.isEmpty() )
3097  {
3098  // Take first dir to create out of list
3099  TQValueList<CopyInfo>::Iterator it = dirs.begin();
3100  // Is this URL on the skip list or the overwrite list ?
3101  while( it != dirs.end() && udir.isEmpty() )
3102  {
3103  const TQString dir = (*it).uDest.path();
3104  if ( shouldSkip( dir ) ) {
3105  dirs.remove( it );
3106  it = dirs.begin();
3107  } else
3108  udir = (*it).uDest;
3109  }
3110  }
3111  if ( !udir.isEmpty() ) // any dir to create, finally ?
3112  {
3113  // Create the directory - with default permissions so that we can put files into it
3114  // TODO : change permissions once all is finished; but for stuff coming from CDROM it sucks...
3115  TDEIO::SimpleJob *newjob = TDEIO::mkdir( udir, -1 );
3116  Scheduler::scheduleJob(newjob);
3117 
3118  m_currentDestURL = udir;
3119  d->m_bURLDirty = true;
3120 
3121  addSubjob(newjob);
3122  return;
3123  }
3124  else // we have finished creating dirs
3125  {
3126  emit processedDirs( this, m_processedDirs ); // make sure final number appears
3127  if (m_progressId) Observer::self()->slotProcessedDirs( this, m_processedDirs );
3128 
3129  state = STATE_COPYING_FILES;
3130  m_processedFiles++; // Ralf wants it to start at 1, not 0
3131  copyNextFile();
3132  }
3133 }
3134 
3135 void CopyJob::slotResultCopyingFiles( Job * job )
3136 {
3137  // The file we were trying to copy:
3138  TQValueList<CopyInfo>::Iterator it = files.begin();
3139  if ( job->error() )
3140  {
3141  // Should we skip automatically ?
3142  if ( m_bAutoSkip )
3143  {
3144  skip( (*it).uSource );
3145  m_fileProcessedSize = (*it).size;
3146  files.remove( it ); // Move on to next file
3147  }
3148  else
3149  {
3150  if ( !isInteractive() ) {
3151  Job::slotResult( job ); // will set the error and emit result(this)
3152  return;
3153  }
3154 
3155  m_conflictError = job->error(); // save for later
3156  // Existing dest ?
3157  if ( ( m_conflictError == ERR_FILE_ALREADY_EXIST )
3158  || ( m_conflictError == ERR_DIR_ALREADY_EXIST )
3159  || ( m_conflictError == ERR_IDENTICAL_FILES ) )
3160  {
3161  subjobs.remove( job );
3162  assert ( subjobs.isEmpty() );
3163  // We need to stat the existing file, to get its last-modification time
3164  KURL existingFile( (*it).uDest );
3165  SimpleJob * newJob = TDEIO::stat( existingFile, false, 2, false );
3166  Scheduler::scheduleJob(newJob);
3167  kdDebug(7007) << "TDEIO::stat for resolving conflict on " << existingFile << endl;
3168  state = STATE_CONFLICT_COPYING_FILES;
3169  addSubjob(newJob);
3170  return; // Don't move to next file yet !
3171  }
3172  else
3173  {
3174  if ( m_bCurrentOperationIsLink && ::tqt_cast<TDEIO::DeleteJob*>( job ) )
3175  {
3176  // Very special case, see a few lines below
3177  // We are deleting the source of a symlink we successfully moved... ignore error
3178  m_fileProcessedSize = (*it).size;
3179  files.remove( it );
3180  } else {
3181  // Go directly to the conflict resolution, there is nothing to stat
3182  slotResultConflictCopyingFiles( job );
3183  return;
3184  }
3185  }
3186  }
3187  } else // no error
3188  {
3189  // Special case for moving links. That operation needs two jobs, unlike others.
3190  if ( m_bCurrentOperationIsLink && m_mode == Move
3191  && !::tqt_cast<TDEIO::DeleteJob *>( job ) // Deleting source not already done
3192  )
3193  {
3194  subjobs.remove( job );
3195  assert ( subjobs.isEmpty() );
3196  // The only problem with this trick is that the error handling for this del operation
3197  // is not going to be right... see 'Very special case' above.
3198  TDEIO::Job * newjob = TDEIO::del( (*it).uSource, false /*don't shred*/, false /*no GUI*/ );
3199  addSubjob( newjob );
3200  return; // Don't move to next file yet !
3201  }
3202 
3203  if ( m_bCurrentOperationIsLink )
3204  {
3205  TQString target = ( m_mode == Link ? (*it).uSource.path() : (*it).linkDest );
3206  //required for the undo feature
3207  emit copyingLinkDone( this, (*it).uSource, target, (*it).uDest );
3208  }
3209  else
3210  //required for the undo feature
3211  emit copyingDone( this, (*it).uSource, (*it).uDest, false, false );
3212  // remove from list, to move on to next file
3213  files.remove( it );
3214  }
3215  m_processedFiles++;
3216 
3217  // clear processed size for last file and add it to overall processed size
3218  m_processedSize += m_fileProcessedSize;
3219  m_fileProcessedSize = 0;
3220 
3221  //kdDebug(7007) << files.count() << " files remaining" << endl;
3222 
3223  removeSubjob( job, true, false ); // merge metadata
3224  assert ( subjobs.isEmpty() ); // We should have only one job at a time ...
3225  copyNextFile();
3226 }
3227 
3228 void CopyJob::slotResultConflictCopyingFiles( TDEIO::Job * job )
3229 {
3230  // We come here after a conflict has been detected and we've stated the existing file
3231  // The file we were trying to create:
3232  TQValueList<CopyInfo>::Iterator it = files.begin();
3233 
3234  RenameDlg_Result res;
3235  TQString newPath;
3236 
3237  if (m_reportTimer)
3238  m_reportTimer->stop();
3239 
3240  if ( ( m_conflictError == ERR_FILE_ALREADY_EXIST )
3241  || ( m_conflictError == ERR_DIR_ALREADY_EXIST )
3242  || ( m_conflictError == ERR_IDENTICAL_FILES ) )
3243  {
3244  // Its modification time:
3245  time_t destmtime = (time_t)-1;
3246  time_t destctime = (time_t)-1;
3247  TDEIO::filesize_t destsize = 0;
3248  TQString linkDest;
3249  UDSEntry entry = ((TDEIO::StatJob*)job)->statResult();
3250  TDEIO::UDSEntry::ConstIterator it2 = entry.begin();
3251  for( ; it2 != entry.end(); it2++ ) {
3252  switch ((*it2).m_uds) {
3253  case UDS_MODIFICATION_TIME:
3254  destmtime = (time_t)((*it2).m_long);
3255  break;
3256  case UDS_CREATION_TIME:
3257  destctime = (time_t)((*it2).m_long);
3258  break;
3259  case UDS_SIZE:
3260  destsize = (*it2).m_long;
3261  break;
3262  case UDS_LINK_DEST:
3263  linkDest = (*it2).m_str;
3264  break;
3265  }
3266  }
3267 
3268  // Offer overwrite only if the existing thing is a file
3269  // If src==dest, use "overwrite-itself"
3270  RenameDlg_Mode mode;
3271  bool isDir = true;
3272 
3273  if( m_conflictError == ERR_DIR_ALREADY_EXIST )
3274  mode = (RenameDlg_Mode) 0;
3275  else
3276  {
3277  if ( (*it).uSource == (*it).uDest ||
3278  ((*it).uSource.protocol() == (*it).uDest.protocol() &&
3279  (*it).uSource.path(-1) == linkDest) )
3280  mode = M_OVERWRITE_ITSELF;
3281  else
3282  mode = M_OVERWRITE;
3283  isDir = false;
3284  }
3285 
3286  if ( m_bSingleFileCopy )
3287  mode = (RenameDlg_Mode) ( mode | M_SINGLE );
3288  else
3289  mode = (RenameDlg_Mode) ( mode | M_MULTI | M_SKIP );
3290 
3291  res = Observer::self()->open_RenameDlg( this, !isDir ?
3292  i18n("File Already Exists") : i18n("Already Exists as Folder"),
3293  (*it).uSource.url(),
3294  (*it).uDest.url(),
3295  mode, newPath,
3296  (*it).size, destsize,
3297  (*it).ctime, destctime,
3298  (*it).mtime, destmtime );
3299 
3300  }
3301  else
3302  {
3303  if ( job->error() == ERR_USER_CANCELED )
3304  res = R_CANCEL;
3305  else if ( !isInteractive() ) {
3306  Job::slotResult( job ); // will set the error and emit result(this)
3307  return;
3308  }
3309  else
3310  {
3311  SkipDlg_Result skipResult = Observer::self()->open_SkipDlg( this, files.count() > 1,
3312  job->errorString() );
3313 
3314  // Convert the return code from SkipDlg into a RenameDlg code
3315  res = ( skipResult == S_SKIP ) ? R_SKIP :
3316  ( skipResult == S_AUTO_SKIP ) ? R_AUTO_SKIP :
3317  R_CANCEL;
3318  }
3319  }
3320 
3321  if (m_reportTimer)
3322  m_reportTimer->start(REPORT_TIMEOUT,false);
3323 
3324  subjobs.remove( job );
3325  assert ( subjobs.isEmpty() );
3326  switch ( res ) {
3327  case R_CANCEL:
3328  m_error = ERR_USER_CANCELED;
3329  emitResult();
3330  return;
3331  case R_RENAME:
3332  {
3333  KURL newUrl( (*it).uDest );
3334  newUrl.setPath( newPath );
3335  emit renamed( this, (*it).uDest, newUrl ); // for e.g. kpropsdlg
3336  (*it).uDest = newUrl;
3337 
3338  TQValueList<CopyInfo> files;
3339  files.append(*it);
3340  emit aboutToCreate( this, files );
3341  }
3342  break;
3343  case R_AUTO_SKIP:
3344  m_bAutoSkip = true;
3345  // fall through
3346  case R_SKIP:
3347  // Move on to next file
3348  skip( (*it).uSource );
3349  m_processedSize += (*it).size;
3350  files.remove( it );
3351  m_processedFiles++;
3352  break;
3353  case R_OVERWRITE_ALL:
3354  m_bOverwriteAll = true;
3355  break;
3356  case R_OVERWRITE:
3357  // Add to overwrite list, so that copyNextFile knows to overwrite
3358  m_overwriteList.append( (*it).uDest.path() );
3359  break;
3360  default:
3361  assert( 0 );
3362  }
3363  state = STATE_COPYING_FILES;
3364  //emit processedFiles( this, m_processedFiles );
3365  copyNextFile();
3366 }
3367 
3368 void CopyJob::copyNextFile()
3369 {
3370  bool bCopyFile = false;
3371  //kdDebug(7007) << "CopyJob::copyNextFile()" << endl;
3372  // Take the first file in the list
3373  TQValueList<CopyInfo>::Iterator it = files.begin();
3374  // Is this URL on the skip list ?
3375  while (it != files.end() && !bCopyFile)
3376  {
3377  const TQString destFile = (*it).uDest.path();
3378  bCopyFile = !shouldSkip( destFile );
3379  if ( !bCopyFile ) {
3380  files.remove( it );
3381  it = files.begin();
3382  }
3383  }
3384 
3385  if (bCopyFile) // any file to create, finally ?
3386  {
3387  // Do we set overwrite ?
3388  bool bOverwrite;
3389  const TQString destFile = (*it).uDest.path();
3390  kdDebug(7007) << "copying " << destFile << endl;
3391  if ( (*it).uDest == (*it).uSource )
3392  bOverwrite = false;
3393  else
3394  bOverwrite = shouldOverwrite( destFile );
3395 
3396  m_bCurrentOperationIsLink = false;
3397  TDEIO::Job * newjob = 0L;
3398  if ( m_mode == Link )
3399  {
3400  //kdDebug(7007) << "Linking" << endl;
3401  if (
3402  ((*it).uSource.protocol() == (*it).uDest.protocol()) &&
3403  ((*it).uSource.host() == (*it).uDest.host()) &&
3404  ((*it).uSource.port() == (*it).uDest.port()) &&
3405  ((*it).uSource.user() == (*it).uDest.user()) &&
3406  ((*it).uSource.pass() == (*it).uDest.pass()) )
3407  {
3408  // This is the case of creating a real symlink
3409  TDEIO::SimpleJob *newJob = TDEIO::symlink( (*it).uSource.path(), (*it).uDest, bOverwrite, false /*no GUI*/ );
3410  newjob = newJob;
3411  Scheduler::scheduleJob(newJob);
3412  //kdDebug(7007) << "CopyJob::copyNextFile : Linking target=" << (*it).uSource.path() << " link=" << (*it).uDest << endl;
3413  //emit linking( this, (*it).uSource.path(), (*it).uDest );
3414  m_bCurrentOperationIsLink = true;
3415  m_currentSrcURL=(*it).uSource;
3416  m_currentDestURL=(*it).uDest;
3417  d->m_bURLDirty = true;
3418  //Observer::self()->slotCopying( this, (*it).uSource, (*it).uDest ); // should be slotLinking perhaps
3419  } else {
3420  //kdDebug(7007) << "CopyJob::copyNextFile : Linking URL=" << (*it).uSource << " link=" << (*it).uDest << endl;
3421  if ( (*it).uDest.isLocalFile() )
3422  {
3423  bool devicesOk=false;
3424 
3425  // if the source is a devices url, handle it a littlebit special
3426  if ((*it).uSource.protocol()==TQString::fromLatin1("devices"))
3427  {
3428  TQByteArray data;
3429  TQByteArray param;
3430  TQCString retType;
3431  TQDataStream streamout(param,IO_WriteOnly);
3432  streamout<<(*it).uSource;
3433  streamout<<(*it).uDest;
3434  if ( kapp && kapp->dcopClient()->call( "kded",
3435  "mountwatcher", "createLink(KURL, KURL)", param,retType,data,false ) )
3436  {
3437  TQDataStream streamin(data,IO_ReadOnly);
3438  streamin>>devicesOk;
3439  }
3440  if (devicesOk)
3441  {
3442  files.remove( it );
3443  m_processedFiles++;
3444  //emit processedFiles( this, m_processedFiles );
3445  copyNextFile();
3446  return;
3447  }
3448  }
3449 
3450  if (!devicesOk)
3451  {
3452  TQString path = (*it).uDest.path();
3453  //kdDebug(7007) << "CopyJob::copyNextFile path=" << path << endl;
3454  TQFile f( path );
3455  if ( f.open( IO_ReadWrite ) )
3456  {
3457  f.close();
3458  KSimpleConfig config( path );
3459  config.setDesktopGroup();
3460  KURL url = (*it).uSource;
3461  url.setPass( "" );
3462  config.writePathEntry( TQString::fromLatin1("URL"), url.url() );
3463  config.writeEntry( TQString::fromLatin1("Name"), url.url() );
3464  config.writeEntry( TQString::fromLatin1("Type"), TQString::fromLatin1("Link") );
3465  TQString protocol = (*it).uSource.protocol();
3466  if ( protocol == TQString::fromLatin1("ftp") )
3467  config.writeEntry( TQString::fromLatin1("Icon"), TQString::fromLatin1("ftp") );
3468  else if ( protocol == TQString::fromLatin1("http") )
3469  config.writeEntry( TQString::fromLatin1("Icon"), TQString::fromLatin1("www") );
3470  else if ( protocol == TQString::fromLatin1("info") )
3471  config.writeEntry( TQString::fromLatin1("Icon"), TQString::fromLatin1("application-vnd.tde.info") );
3472  else if ( protocol == TQString::fromLatin1("mailto") ) // sven:
3473  config.writeEntry( TQString::fromLatin1("Icon"), TQString::fromLatin1("kmail") ); // added mailto: support
3474  else
3475  config.writeEntry( TQString::fromLatin1("Icon"), TQString::fromLatin1("unknown") );
3476  config.sync();
3477  files.remove( it );
3478  m_processedFiles++;
3479  //emit processedFiles( this, m_processedFiles );
3480  copyNextFile();
3481  return;
3482  }
3483  else
3484  {
3485  kdDebug(7007) << "CopyJob::copyNextFile ERR_CANNOT_OPEN_FOR_WRITING" << endl;
3486  m_error = ERR_CANNOT_OPEN_FOR_WRITING;
3487  m_errorText = (*it).uDest.path();
3488  emitResult();
3489  return;
3490  }
3491  }
3492  } else {
3493  // Todo: not show "link" on remote dirs if the src urls are not from the same protocol+host+...
3494  m_error = ERR_CANNOT_SYMLINK;
3495  m_errorText = (*it).uDest.prettyURL();
3496  emitResult();
3497  return;
3498  }
3499  }
3500  }
3501  else if ( !(*it).linkDest.isEmpty() &&
3502  ((*it).uSource.protocol() == (*it).uDest.protocol()) &&
3503  ((*it).uSource.host() == (*it).uDest.host()) &&
3504  ((*it).uSource.port() == (*it).uDest.port()) &&
3505  ((*it).uSource.user() == (*it).uDest.user()) &&
3506  ((*it).uSource.pass() == (*it).uDest.pass()))
3507  // Copying a symlink - only on the same protocol/host/etc. (#5601, downloading an FTP file through its link),
3508  {
3509  TDEIO::SimpleJob *newJob = TDEIO::symlink( (*it).linkDest, (*it).uDest, bOverwrite, false /*no GUI*/ );
3510  Scheduler::scheduleJob(newJob);
3511  newjob = newJob;
3512  //kdDebug(7007) << "CopyJob::copyNextFile : Linking target=" << (*it).linkDest << " link=" << (*it).uDest << endl;
3513  //emit linking( this, (*it).linkDest, (*it).uDest );
3514  m_currentSrcURL=(*it).linkDest;
3515  m_currentDestURL=(*it).uDest;
3516  d->m_bURLDirty = true;
3517  //Observer::self()->slotCopying( this, (*it).linkDest, (*it).uDest ); // should be slotLinking perhaps
3518  m_bCurrentOperationIsLink = true;
3519  // NOTE: if we are moving stuff, the deletion of the source will be done in slotResultCopyingFiles
3520  } else if (m_mode == Move) // Moving a file
3521  {
3522  TDEIO::FileCopyJob * moveJob = TDEIO::file_move( (*it).uSource, (*it).uDest, (*it).permissions, bOverwrite, false, false/*no GUI*/ );
3523  moveJob->setSourceSize64( (*it).size );
3524  newjob = moveJob;
3525  //kdDebug(7007) << "CopyJob::copyNextFile : Moving " << (*it).uSource << " to " << (*it).uDest << endl;
3526  //emit moving( this, (*it).uSource, (*it).uDest );
3527  m_currentSrcURL=(*it).uSource;
3528  m_currentDestURL=(*it).uDest;
3529  d->m_bURLDirty = true;
3530  //Observer::self()->slotMoving( this, (*it).uSource, (*it).uDest );
3531  }
3532  else // Copying a file
3533  {
3534  // If source isn't local and target is local, we ignore the original permissions
3535  // Otherwise, files downloaded from HTTP end up with -r--r--r--
3536  bool remoteSource = !KProtocolInfo::supportsListing((*it).uSource);
3537  int permissions = (*it).permissions;
3538  if ( d->m_defaultPermissions || ( remoteSource && (*it).uDest.isLocalFile() ) )
3539  permissions = -1;
3540  TDEIO::FileCopyJob * copyJob = TDEIO::file_copy( (*it).uSource, (*it).uDest, permissions, bOverwrite, false, false/*no GUI*/ );
3541  copyJob->setParentJob( this ); // in case of rename dialog
3542  copyJob->setSourceSize64( (*it).size );
3543  copyJob->setModificationTime( (*it).mtime );
3544  newjob = copyJob;
3545  //kdDebug(7007) << "CopyJob::copyNextFile : Copying " << (*it).uSource << " to " << (*it).uDest << endl;
3546  m_currentSrcURL=(*it).uSource;
3547  m_currentDestURL=(*it).uDest;
3548  d->m_bURLDirty = true;
3549  }
3550  addSubjob(newjob);
3551  connect( newjob, TQ_SIGNAL( processedSize( TDEIO::Job*, TDEIO::filesize_t ) ),
3552  this, TQ_SLOT( slotProcessedSize( TDEIO::Job*, TDEIO::filesize_t ) ) );
3553  connect( newjob, TQ_SIGNAL( totalSize( TDEIO::Job*, TDEIO::filesize_t ) ),
3554  this, TQ_SLOT( slotTotalSize( TDEIO::Job*, TDEIO::filesize_t ) ) );
3555  }
3556  else
3557  {
3558  // We're done
3559  //kdDebug(7007) << "copyNextFile finished" << endl;
3560  deleteNextDir();
3561  }
3562 }
3563 
3564 void CopyJob::deleteNextDir()
3565 {
3566  if ( m_mode == Move && !dirsToRemove.isEmpty() ) // some dirs to delete ?
3567  {
3568  state = STATE_DELETING_DIRS;
3569  d->m_bURLDirty = true;
3570  // Take first dir to delete out of list - last ones first !
3571  KURL::List::Iterator it = dirsToRemove.fromLast();
3572  SimpleJob *job = TDEIO::rmdir( *it );
3573  Scheduler::scheduleJob(job);
3574  dirsToRemove.remove(it);
3575  addSubjob( job );
3576  }
3577  else
3578  {
3579  // This step is done, move on
3580  setNextDirAttribute();
3581  }
3582 }
3583 
3584 void CopyJob::setNextDirAttribute()
3585 {
3586  if ( !d->m_directoriesCopied.isEmpty() )
3587  {
3588  state = STATE_SETTING_DIR_ATTRIBUTES;
3589 #ifdef Q_OS_UNIX
3590  // TODO KDE4: this should use a SlaveBase method, but we have none yet in KDE3.
3591  TQValueList<CopyInfo>::Iterator it = d->m_directoriesCopied.begin();
3592  for ( ; it != d->m_directoriesCopied.end() ; ++it ) {
3593  const KURL& url = (*it).uDest;
3594  if ( url.isLocalFile() && (*it).mtime != (time_t)-1 ) {
3595  const TQCString path = TQFile::encodeName( url.path() );
3596  KDE_struct_stat statbuf;
3597  if (KDE_lstat(path, &statbuf) == 0) {
3598  struct utimbuf utbuf;
3599  utbuf.actime = statbuf.st_atime; // access time, unchanged
3600  utbuf.modtime = (*it).mtime; // modification time
3601  utime( path, &utbuf );
3602  }
3603 
3604  }
3605  }
3606 #endif
3607  d->m_directoriesCopied.clear();
3608  }
3609 
3610  // No "else" here, since the above is a simple sync loop
3611 
3612  {
3613  // Finished - tell the world
3614  if ( !m_bOnlyRenames )
3615  {
3616  KDirNotify_stub allDirNotify("*", "KDirNotify*");
3617  KURL url( d->m_globalDest );
3618  if ( d->m_globalDestinationState != DEST_IS_DIR || m_asMethod )
3619  url.setPath( url.directory() );
3620  //kdDebug(7007) << "KDirNotify'ing FilesAdded " << url << endl;
3621  allDirNotify.FilesAdded( url );
3622 
3623  if ( m_mode == Move && !m_srcList.isEmpty() ) {
3624  //kdDebug(7007) << "KDirNotify'ing FilesRemoved " << m_srcList.toStringList() << endl;
3625  allDirNotify.FilesRemoved( m_srcList );
3626  }
3627  }
3628  if (m_reportTimer)
3629  m_reportTimer->stop();
3630  --m_processedFiles; // undo the "start at 1" hack
3631  slotReport(); // display final numbers, important if progress dialog stays up
3632 
3633  emitResult();
3634  }
3635 }
3636 
3637 void CopyJob::slotProcessedSize( TDEIO::Job*, TDEIO::filesize_t data_size )
3638 {
3639  //kdDebug(7007) << "CopyJob::slotProcessedSize " << data_size << endl;
3640  m_fileProcessedSize = data_size;
3641  setProcessedSize(m_processedSize + m_fileProcessedSize);
3642 
3643  if ( m_processedSize + m_fileProcessedSize > m_totalSize )
3644  {
3645  m_totalSize = m_processedSize + m_fileProcessedSize;
3646  //kdDebug(7007) << "Adjusting m_totalSize to " << m_totalSize << endl;
3647  emit totalSize( this, m_totalSize ); // safety
3648  }
3649  //kdDebug(7007) << "emit processedSize " << (unsigned long) (m_processedSize + m_fileProcessedSize) << endl;
3650  emit processedSize( this, m_processedSize + m_fileProcessedSize );
3651  emitPercent( m_processedSize + m_fileProcessedSize, m_totalSize );
3652 }
3653 
3654 void CopyJob::slotTotalSize( TDEIO::Job*, TDEIO::filesize_t size )
3655 {
3656  //kdDebug(7007) << "slotTotalSize: " << size << endl;
3657  // Special case for copying a single file
3658  // This is because some protocols don't implement stat properly
3659  // (e.g. HTTP), and don't give us a size in some cases (redirection)
3660  // so we'd rather rely on the size given for the transfer
3661  if ( m_bSingleFileCopy && size > m_totalSize)
3662  {
3663  //kdDebug(7007) << "slotTotalSize: updating totalsize to " << size << endl;
3664  m_totalSize = size;
3665  emit totalSize( this, size );
3666  }
3667 }
3668 
3669 void CopyJob::slotResultDeletingDirs( Job * job )
3670 {
3671  if (job->error())
3672  {
3673  // Couldn't remove directory. Well, perhaps it's not empty
3674  // because the user pressed Skip for a given file in it.
3675  // Let's not display "Could not remove dir ..." for each of those dir !
3676  }
3677  subjobs.remove( job );
3678  assert ( subjobs.isEmpty() );
3679  deleteNextDir();
3680 }
3681 
3682 #if 0 // TODO KDE4
3683 void CopyJob::slotResultSettingDirAttributes( Job * job )
3684 {
3685  if (job->error())
3686  {
3687  // Couldn't set directory attributes. Ignore the error, it can happen
3688  // with inferior file systems like VFAT.
3689  // Let's not display warnings for each dir like "cp -a" does.
3690  }
3691  subjobs.remove( job );
3692  assert ( subjobs.isEmpty() );
3693  setNextDirAttribute();
3694 }
3695 #endif
3696 
3697 void CopyJob::slotResultRenaming( Job* job )
3698 {
3699  int err = job->error();
3700  const TQString errText = job->errorText();
3701  removeSubjob( job, true, false ); // merge metadata
3702  assert ( subjobs.isEmpty() );
3703  // Determine dest again
3704  KURL dest = m_dest;
3705  if ( destinationState == DEST_IS_DIR && !m_asMethod )
3706  dest.addPath( m_currentSrcURL.fileName() );
3707  if ( err )
3708  {
3709  // Direct renaming didn't work. Try renaming to a temp name,
3710  // this can help e.g. when renaming 'a' to 'A' on a VFAT partition.
3711  // In that case it's the _same_ dir, we don't want to copy+del (data loss!)
3712  if ( m_currentSrcURL.isLocalFile() && m_currentSrcURL.url(-1) != dest.url(-1) &&
3713  m_currentSrcURL.url(-1).lower() == dest.url(-1).lower() &&
3714  ( err == ERR_FILE_ALREADY_EXIST ||
3715  err == ERR_DIR_ALREADY_EXIST ||
3716  err == ERR_IDENTICAL_FILES ) )
3717  {
3718  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;
3719  TQCString _src( TQFile::encodeName(m_currentSrcURL.path()) );
3720  TQCString _dest( TQFile::encodeName(dest.path()) );
3721  KTempFile tmpFile( m_currentSrcURL.directory(false) );
3722  TQCString _tmp( TQFile::encodeName(tmpFile.name()) );
3723  kdDebug(7007) << "CopyJob::slotResult KTempFile status:" << tmpFile.status() << " using " << _tmp << " as intermediary" << endl;
3724  tmpFile.unlink();
3725  if ( ::rename( _src, _tmp ) == 0 )
3726  {
3727  if ( !TQFile::exists( _dest ) && ::rename( _tmp, _dest ) == 0 )
3728  {
3729  kdDebug(7007) << "Success." << endl;
3730  err = 0;
3731  }
3732  else
3733  {
3734  // Revert back to original name!
3735  if ( ::rename( _tmp, _src ) != 0 ) {
3736  kdError(7007) << "Couldn't rename " << tmpFile.name() << " back to " << _src << " !" << endl;
3737  // Severe error, abort
3738  Job::slotResult( job ); // will set the error and emit result(this)
3739  return;
3740  }
3741  }
3742  }
3743  }
3744  }
3745  if ( err )
3746  {
3747  // This code is similar to CopyJob::slotResultConflictCopyingFiles
3748  // but here it's about the base src url being moved/renamed
3749  // (*m_currentStatSrc) and its dest (m_dest), not about a single file.
3750  // It also means we already stated the dest, here.
3751  // On the other hand we haven't stated the src yet (we skipped doing it
3752  // to save time, since it's not necessary to rename directly!)...
3753 
3754  Q_ASSERT( m_currentSrcURL == *m_currentStatSrc );
3755 
3756  // Existing dest?
3757  if ( ( err == ERR_DIR_ALREADY_EXIST ||
3758  err == ERR_FILE_ALREADY_EXIST ||
3759  err == ERR_IDENTICAL_FILES )
3760  && isInteractive() )
3761  {
3762  if (m_reportTimer)
3763  m_reportTimer->stop();
3764 
3765  // Should we skip automatically ?
3766  if ( m_bAutoSkip ) {
3767  // Move on to next file
3768  skipSrc();
3769  return;
3770  } else if ( m_bOverwriteAll ) {
3771  ; // nothing to do, stat+copy+del will overwrite
3772  } else {
3773  TQString newPath;
3774  // If src==dest, use "overwrite-itself"
3775  RenameDlg_Mode mode = (RenameDlg_Mode)
3776  ( ( m_currentSrcURL == dest ) ? M_OVERWRITE_ITSELF : M_OVERWRITE );
3777 
3778  if ( m_srcList.count() > 1 )
3779  mode = (RenameDlg_Mode) ( mode | M_MULTI | M_SKIP );
3780  else
3781  mode = (RenameDlg_Mode) ( mode | M_SINGLE );
3782 
3783  // we lack mtime info for both the src (not stated)
3784  // and the dest (stated but this info wasn't stored)
3785  // Let's do it for local files, at least
3786  TDEIO::filesize_t sizeSrc = (TDEIO::filesize_t) -1;
3787  TDEIO::filesize_t sizeDest = (TDEIO::filesize_t) -1;
3788  time_t ctimeSrc = (time_t) -1;
3789  time_t ctimeDest = (time_t) -1;
3790  time_t mtimeSrc = (time_t) -1;
3791  time_t mtimeDest = (time_t) -1;
3792 
3793  KDE_struct_stat stat_buf;
3794  if ( m_currentSrcURL.isLocalFile() &&
3795  KDE_stat(TQFile::encodeName(m_currentSrcURL.path()), &stat_buf) == 0 ) {
3796  sizeSrc = stat_buf.st_size;
3797  ctimeSrc = stat_buf.st_ctime;
3798  mtimeSrc = stat_buf.st_mtime;
3799  }
3800  if ( dest.isLocalFile() &&
3801  KDE_stat(TQFile::encodeName(dest.path()), &stat_buf) == 0 ) {
3802  sizeDest = stat_buf.st_size;
3803  ctimeDest = stat_buf.st_ctime;
3804  mtimeDest = stat_buf.st_mtime;
3805  }
3806 
3807  RenameDlg_Result r = Observer::self()->open_RenameDlg(
3808  this,
3809  err != ERR_DIR_ALREADY_EXIST ? i18n("File Already Exists") : i18n("Already Exists as Folder"),
3810  m_currentSrcURL.url(),
3811  dest.url(),
3812  mode, newPath,
3813  sizeSrc, sizeDest,
3814  ctimeSrc, ctimeDest,
3815  mtimeSrc, mtimeDest );
3816  if (m_reportTimer)
3817  m_reportTimer->start(REPORT_TIMEOUT,false);
3818 
3819  switch ( r )
3820  {
3821  case R_CANCEL:
3822  {
3823  m_error = ERR_USER_CANCELED;
3824  emitResult();
3825  return;
3826  }
3827  case R_RENAME:
3828  {
3829  // Set m_dest to the chosen destination
3830  // This is only for this src url; the next one will revert to d->m_globalDest
3831  m_dest.setPath( newPath );
3832  TDEIO::Job* job = TDEIO::stat( m_dest, false, 2, false );
3833  state = STATE_STATING;
3834  destinationState = DEST_NOT_STATED;
3835  addSubjob(job);
3836  return;
3837  }
3838  case R_AUTO_SKIP:
3839  m_bAutoSkip = true;
3840  // fall through
3841  case R_SKIP:
3842  // Move on to next file
3843  skipSrc();
3844  return;
3845  case R_OVERWRITE_ALL:
3846  m_bOverwriteAll = true;
3847  break;
3848  case R_OVERWRITE:
3849  // Add to overwrite list
3850  // Note that we add dest, not m_dest.
3851  // This ensures that when moving several urls into a dir (m_dest),
3852  // we only overwrite for the current one, not for all.
3853  // When renaming a single file (m_asMethod), it makes no difference.
3854  kdDebug(7007) << "adding to overwrite list: " << dest.path() << endl;
3855  m_overwriteList.append( dest.path() );
3856  break;
3857  default:
3858  //assert( 0 );
3859  break;
3860  }
3861  }
3862  } else if ( err != TDEIO::ERR_UNSUPPORTED_ACTION ) {
3863  kdDebug(7007) << "Couldn't rename " << m_currentSrcURL << " to " << dest << ", aborting" << endl;
3864  m_error = err;
3865  m_errorText = errText;
3866  emitResult();
3867  return;
3868  }
3869  kdDebug(7007) << "Couldn't rename " << m_currentSrcURL << " to " << dest << ", reverting to normal way, starting with stat" << endl;
3870  //kdDebug(7007) << "TDEIO::stat on " << m_currentSrcURL << endl;
3871  TDEIO::Job* job = TDEIO::stat( m_currentSrcURL, true, 2, false );
3872  state = STATE_STATING;
3873  addSubjob(job);
3874  m_bOnlyRenames = false;
3875  }
3876  else
3877  {
3878  //kdDebug(7007) << "Renaming succeeded, move on" << endl;
3879  emit copyingDone( this, *m_currentStatSrc, dest, true, true );
3880  statNextSrc();
3881  }
3882 }
3883 
3884 void CopyJob::slotResult( Job *job )
3885 {
3886  //kdDebug(7007) << "CopyJob::slotResult() state=" << (int) state << endl;
3887  // In each case, what we have to do is :
3888  // 1 - check for errors and treat them
3889  // 2 - subjobs.remove(job);
3890  // 3 - decide what to do next
3891 
3892  switch ( state ) {
3893  case STATE_STATING: // We were trying to stat a src url or the dest
3894  slotResultStating( job );
3895  break;
3896  case STATE_RENAMING: // We were trying to do a direct renaming, before even stat'ing
3897  {
3898  slotResultRenaming( job );
3899  break;
3900  }
3901  case STATE_LISTING: // recursive listing finished
3902  //kdDebug(7007) << "totalSize: " << (unsigned int) m_totalSize << " files: " << files.count() << " dirs: " << dirs.count() << endl;
3903  // Was there an error ?
3904  if (job->error())
3905  {
3906  Job::slotResult( job ); // will set the error and emit result(this)
3907  return;
3908  }
3909 
3910  subjobs.remove( job );
3911  assert ( subjobs.isEmpty() );
3912 
3913  statNextSrc();
3914  break;
3915  case STATE_CREATING_DIRS:
3916  slotResultCreatingDirs( job );
3917  break;
3918  case STATE_CONFLICT_CREATING_DIRS:
3919  slotResultConflictCreatingDirs( job );
3920  break;
3921  case STATE_COPYING_FILES:
3922  slotResultCopyingFiles( job );
3923  break;
3924  case STATE_CONFLICT_COPYING_FILES:
3925  slotResultConflictCopyingFiles( job );
3926  break;
3927  case STATE_DELETING_DIRS:
3928  slotResultDeletingDirs( job );
3929  break;
3930  case STATE_SETTING_DIR_ATTRIBUTES: // TODO KDE4
3931  assert( 0 );
3932  //slotResultSettingDirAttributes( job );
3933  break;
3934  default:
3935  assert( 0 );
3936  }
3937 }
3938 
3939 void TDEIO::CopyJob::setDefaultPermissions( bool b )
3940 {
3941  d->m_defaultPermissions = b;
3942 }
3943 
3944 // KDE4: remove
3945 void TDEIO::CopyJob::setInteractive( bool b )
3946 {
3947  Job::setInteractive( b );
3948 }
3949 
3950 CopyJob *TDEIO::copy(const KURL& src, const KURL& dest, bool showProgressInfo )
3951 {
3952  //kdDebug(7007) << "TDEIO::copy src=" << src << " dest=" << dest << endl;
3953  KURL::List srcList;
3954  srcList.append( src );
3955  return new CopyJob( srcList, dest, CopyJob::Copy, false, showProgressInfo );
3956 }
3957 
3958 CopyJob *TDEIO::copyAs(const KURL& src, const KURL& dest, bool showProgressInfo )
3959 {
3960  //kdDebug(7007) << "TDEIO::copyAs src=" << src << " dest=" << dest << endl;
3961  KURL::List srcList;
3962  srcList.append( src );
3963  return new CopyJob( srcList, dest, CopyJob::Copy, true, showProgressInfo );
3964 }
3965 
3966 CopyJob *TDEIO::copy( const KURL::List& src, const KURL& dest, bool showProgressInfo )
3967 {
3968  //kdDebug(7007) << src << " " << dest << endl;
3969  return new CopyJob( src, dest, CopyJob::Copy, false, showProgressInfo );
3970 }
3971 
3972 CopyJob *TDEIO::move(const KURL& src, const KURL& dest, bool showProgressInfo )
3973 {
3974  //kdDebug(7007) << src << " " << dest << endl;
3975  KURL::List srcList;
3976  srcList.append( src );
3977  return new CopyJob( srcList, dest, CopyJob::Move, false, showProgressInfo );
3978 }
3979 
3980 CopyJob *TDEIO::moveAs(const KURL& src, const KURL& dest, bool showProgressInfo )
3981 {
3982  //kdDebug(7007) << src << " " << dest << endl;
3983  KURL::List srcList;
3984  srcList.append( src );
3985  return new CopyJob( srcList, dest, CopyJob::Move, true, showProgressInfo );
3986 }
3987 
3988 CopyJob *TDEIO::move( const KURL::List& src, const KURL& dest, bool showProgressInfo )
3989 {
3990  //kdDebug(7007) << src << " " << dest << endl;
3991  return new CopyJob( src, dest, CopyJob::Move, false, showProgressInfo );
3992 }
3993 
3994 CopyJob *TDEIO::link(const KURL& src, const KURL& destDir, bool showProgressInfo )
3995 {
3996  KURL::List srcList;
3997  srcList.append( src );
3998  return new CopyJob( srcList, destDir, CopyJob::Link, false, showProgressInfo );
3999 }
4000 
4001 CopyJob *TDEIO::link(const KURL::List& srcList, const KURL& destDir, bool showProgressInfo )
4002 {
4003  return new CopyJob( srcList, destDir, CopyJob::Link, false, showProgressInfo );
4004 }
4005 
4006 CopyJob *TDEIO::linkAs(const KURL& src, const KURL& destDir, bool showProgressInfo )
4007 {
4008  KURL::List srcList;
4009  srcList.append( src );
4010  return new CopyJob( srcList, destDir, CopyJob::Link, false, showProgressInfo );
4011 }
4012 
4013 CopyJob *TDEIO::trash(const KURL& src, bool showProgressInfo )
4014 {
4015  KURL::List srcList;
4016  srcList.append( src );
4017  return new CopyJob( srcList, KURL( "trash:/" ), CopyJob::Move, false, showProgressInfo );
4018 }
4019 
4020 CopyJob *TDEIO::trash(const KURL::List& srcList, bool showProgressInfo )
4021 {
4022  return new CopyJob( srcList, KURL( "trash:/" ), CopyJob::Move, false, showProgressInfo );
4023 }
4024 
4026 
4027 DeleteJob::DeleteJob( const KURL::List& src, bool /*shred*/, bool showProgressInfo )
4028 : Job(showProgressInfo), m_totalSize( 0 ), m_processedSize( 0 ), m_fileProcessedSize( 0 ),
4029  m_processedFiles( 0 ), m_processedDirs( 0 ), m_totalFilesDirs( 0 ),
4030  m_srcList(src), m_currentStat(m_srcList.begin()), m_reportTimer(0)
4031 {
4032  if ( showProgressInfo ) {
4033 
4034  connect( this, TQ_SIGNAL( totalFiles( TDEIO::Job*, unsigned long ) ),
4035  Observer::self(), TQ_SLOT( slotTotalFiles( TDEIO::Job*, unsigned long ) ) );
4036 
4037  connect( this, TQ_SIGNAL( totalDirs( TDEIO::Job*, unsigned long ) ),
4038  Observer::self(), TQ_SLOT( slotTotalDirs( TDEIO::Job*, unsigned long ) ) );
4039 
4040  // See slotReport
4041  /*connect( this, TQ_SIGNAL( processedFiles( TDEIO::Job*, unsigned long ) ),
4042  m_observer, TQ_SLOT( slotProcessedFiles( TDEIO::Job*, unsigned long ) ) );
4043 
4044  connect( this, TQ_SIGNAL( processedDirs( TDEIO::Job*, unsigned long ) ),
4045  m_observer, TQ_SLOT( slotProcessedDirs( TDEIO::Job*, unsigned long ) ) );
4046 
4047  connect( this, TQ_SIGNAL( deleting( TDEIO::Job*, const KURL& ) ),
4048  m_observer, TQ_SLOT( slotDeleting( TDEIO::Job*, const KURL& ) ) );*/
4049 
4050  m_reportTimer=new TQTimer(this);
4051  connect(m_reportTimer,TQ_SIGNAL(timeout()),this,TQ_SLOT(slotReport()));
4052  //this will update the report dialog with 5 Hz, I think this is fast enough, aleXXX
4053  m_reportTimer->start(REPORT_TIMEOUT,false);
4054  }
4055 
4056  TQTimer::singleShot(0, this, TQ_SLOT(slotStart()));
4057 }
4058 
4059 void DeleteJob::slotStart()
4060 {
4061  statNextSrc();
4062 }
4063 
4064 //this is called often, so calling the functions
4065 //from Observer here directly might improve the performance a little bit
4066 //aleXXX
4067 void DeleteJob::slotReport()
4068 {
4069  if (m_progressId==0)
4070  return;
4071 
4072  Observer * observer = Observer::self();
4073 
4074  emit deleting( this, m_currentURL );
4075  observer->slotDeleting(this,m_currentURL);
4076 
4077  switch( state ) {
4078  case STATE_STATING:
4079  case STATE_LISTING:
4080  emit totalSize( this, m_totalSize );
4081  emit totalFiles( this, files.count() );
4082  emit totalDirs( this, dirs.count() );
4083  break;
4084  case STATE_DELETING_DIRS:
4085  emit processedDirs( this, m_processedDirs );
4086  observer->slotProcessedDirs(this,m_processedDirs);
4087  emitPercent( m_processedFiles + m_processedDirs, m_totalFilesDirs );
4088  break;
4089  case STATE_DELETING_FILES:
4090  observer->slotProcessedFiles(this,m_processedFiles);
4091  emit processedFiles( this, m_processedFiles );
4092  emitPercent( m_processedFiles, m_totalFilesDirs );
4093  break;
4094  }
4095 }
4096 
4097 
4098 void DeleteJob::slotEntries(TDEIO::Job* job, const UDSEntryList& list)
4099 {
4100  UDSEntryListConstIterator it = list.begin();
4101  UDSEntryListConstIterator end = list.end();
4102  for (; it != end; ++it)
4103  {
4104  UDSEntry::ConstIterator it2 = (*it).begin();
4105  bool bDir = false;
4106  bool bLink = false;
4107  TQString displayName;
4108  KURL url;
4109  int atomsFound(0);
4110  for( ; it2 != (*it).end(); it2++ )
4111  {
4112  switch ((*it2).m_uds)
4113  {
4114  case UDS_FILE_TYPE:
4115  bDir = S_ISDIR((*it2).m_long);
4116  atomsFound++;
4117  break;
4118  case UDS_NAME:
4119  displayName = (*it2).m_str;
4120  atomsFound++;
4121  break;
4122  case UDS_URL:
4123  url = KURL((*it2).m_str);
4124  atomsFound++;
4125  break;
4126  case UDS_LINK_DEST:
4127  bLink = !(*it2).m_str.isEmpty();
4128  atomsFound++;
4129  break;
4130  case UDS_SIZE:
4131  m_totalSize += (TDEIO::filesize_t)((*it2).m_long);
4132  atomsFound++;
4133  break;
4134  default:
4135  break;
4136  }
4137  if (atomsFound==5) break;
4138  }
4139  assert(!displayName.isEmpty());
4140  if (displayName != ".." && displayName != ".")
4141  {
4142  if( url.isEmpty() ) {
4143  url = ((SimpleJob *)job)->url(); // assumed to be a dir
4144  url.addPath( displayName );
4145  }
4146  //kdDebug(7007) << "DeleteJob::slotEntries " << displayName << " (" << url << ")" << endl;
4147  if ( bLink )
4148  symlinks.append( url );
4149  else if ( bDir )
4150  dirs.append( url );
4151  else
4152  files.append( url );
4153  }
4154  }
4155 }
4156 
4157 
4158 void DeleteJob::statNextSrc()
4159 {
4160  //kdDebug(7007) << "statNextSrc" << endl;
4161  if ( m_currentStat != m_srcList.end() )
4162  {
4163  m_currentURL = (*m_currentStat);
4164 
4165  // if the file system doesn't support deleting, we do not even stat
4166  if (!KProtocolInfo::supportsDeleting(m_currentURL)) {
4167  TQGuardedPtr<DeleteJob> that = this;
4168  ++m_currentStat;
4169  if (isInteractive())
4170  KMessageBox::information( 0, buildErrorString(ERR_CANNOT_DELETE, m_currentURL.prettyURL()));
4171  if (that)
4172  statNextSrc();
4173  return;
4174  }
4175  // Stat it
4176  state = STATE_STATING;
4177  TDEIO::SimpleJob * job = TDEIO::stat( m_currentURL, true, 1, false );
4178  Scheduler::scheduleJob(job);
4179  //kdDebug(7007) << "TDEIO::stat (DeleteJob) " << m_currentURL << endl;
4180  addSubjob(job);
4181  //if ( m_progressId ) // Did we get an ID from the observer ?
4182  // Observer::self()->slotDeleting( this, *it ); // show asap
4183  } else
4184  {
4185  m_totalFilesDirs = files.count()+symlinks.count() + dirs.count();
4186  slotReport();
4187  // Now we know which dirs hold the files we're going to delete.
4188  // To speed things up and prevent double-notification, we disable KDirWatch
4189  // on those dirs temporarily (using KDirWatch::self, that's the instanced
4190  // used by e.g. kdirlister).
4191  for ( TQStringList::Iterator it = m_parentDirs.begin() ; it != m_parentDirs.end() ; ++it )
4192  KDirWatch::self()->stopDirScan( *it );
4193  state = STATE_DELETING_FILES;
4194  deleteNextFile();
4195  }
4196 }
4197 
4198 void DeleteJob::deleteNextFile()
4199 {
4200  //kdDebug(7007) << "deleteNextFile" << endl;
4201  if ( !files.isEmpty() || !symlinks.isEmpty() )
4202  {
4203  SimpleJob *job;
4204  do {
4205  // Take first file to delete out of list
4206  KURL::List::Iterator it = files.begin();
4207  bool isLink = false;
4208  if ( it == files.end() ) // No more files
4209  {
4210  it = symlinks.begin(); // Pick up a symlink to delete
4211  isLink = true;
4212  }
4213  // Normal deletion
4214  // If local file, try do it directly
4215  if ( (*it).isLocalFile() && unlink( TQFile::encodeName((*it).path()) ) == 0 ) {
4216  //kdDebug(7007) << "DeleteJob deleted " << (*it).path() << endl;
4217  job = 0;
4218  m_processedFiles++;
4219  if ( m_processedFiles % 300 == 0 || m_totalFilesDirs < 300) { // update progress info every 300 files
4220  m_currentURL = *it;
4221  slotReport();
4222  }
4223  } else
4224  { // if remote - or if unlink() failed (we'll use the job's error handling in that case)
4225  job = TDEIO::file_delete( *it, false /*no GUI*/);
4226  Scheduler::scheduleJob(job);
4227  m_currentURL=(*it);
4228  }
4229  if ( isLink )
4230  symlinks.remove(it);
4231  else
4232  files.remove(it);
4233  if ( job ) {
4234  addSubjob(job);
4235  return;
4236  }
4237  // loop only if direct deletion worked (job=0) and there is something else to delete
4238  } while (!job && (!files.isEmpty() || !symlinks.isEmpty()));
4239  }
4240  state = STATE_DELETING_DIRS;
4241  deleteNextDir();
4242 }
4243 
4244 void DeleteJob::deleteNextDir()
4245 {
4246  if ( !dirs.isEmpty() ) // some dirs to delete ?
4247  {
4248  do {
4249  // Take first dir to delete out of list - last ones first !
4250  KURL::List::Iterator it = dirs.fromLast();
4251  // If local dir, try to rmdir it directly
4252  if ( (*it).isLocalFile() && ::rmdir( TQFile::encodeName((*it).path()) ) == 0 ) {
4253 
4254  m_processedDirs++;
4255  if ( m_processedDirs % 100 == 0 ) { // update progress info every 100 dirs
4256  m_currentURL = *it;
4257  slotReport();
4258  }
4259  } else {
4260  SimpleJob* job;
4261  if ( KProtocolInfo::canDeleteRecursive( *it ) ) {
4262  // If the ioslave supports recursive deletion of a directory, then
4263  // we only need to send a single CMD_DEL command, so we use file_delete :)
4264  job = TDEIO::file_delete( *it, false /*no gui*/ );
4265  } else {
4266  job = TDEIO::rmdir( *it );
4267  }
4268  Scheduler::scheduleJob(job);
4269  dirs.remove(it);
4270  addSubjob( job );
4271  return;
4272  }
4273  dirs.remove(it);
4274  } while ( !dirs.isEmpty() );
4275  }
4276 
4277  // Re-enable watching on the dirs that held the deleted files
4278  for ( TQStringList::Iterator it = m_parentDirs.begin() ; it != m_parentDirs.end() ; ++it )
4279  KDirWatch::self()->restartDirScan( *it );
4280 
4281  // Finished - tell the world
4282  if ( !m_srcList.isEmpty() )
4283  {
4284  KDirNotify_stub allDirNotify("*", "KDirNotify*");
4285  //kdDebug(7007) << "KDirNotify'ing FilesRemoved " << m_srcList.toStringList() << endl;
4286  allDirNotify.FilesRemoved( m_srcList );
4287  }
4288  if (m_reportTimer!=0)
4289  m_reportTimer->stop();
4290  emitResult();
4291 }
4292 
4293 void DeleteJob::slotProcessedSize( TDEIO::Job*, TDEIO::filesize_t data_size )
4294 {
4295  // Note: this is the same implementation as CopyJob::slotProcessedSize but
4296  // it's different from FileCopyJob::slotProcessedSize - which is why this
4297  // is not in Job.
4298 
4299  m_fileProcessedSize = data_size;
4300  setProcessedSize(m_processedSize + m_fileProcessedSize);
4301 
4302  //kdDebug(7007) << "DeleteJob::slotProcessedSize " << (unsigned int) (m_processedSize + m_fileProcessedSize) << endl;
4303 
4304  emit processedSize( this, m_processedSize + m_fileProcessedSize );
4305 
4306  // calculate percents
4307  unsigned long ipercent = m_percent;
4308 
4309  if ( m_totalSize == 0 )
4310  m_percent = 100;
4311  else
4312  m_percent = (unsigned long)(( (float)(m_processedSize + m_fileProcessedSize) / (float)m_totalSize ) * 100.0);
4313 
4314  if ( m_percent > ipercent )
4315  {
4316  emit percent( this, m_percent );
4317  //kdDebug(7007) << "DeleteJob::slotProcessedSize - percent = " << (unsigned int) m_percent << endl;
4318  }
4319 
4320 }
4321 
4322 void DeleteJob::slotResult( Job *job )
4323 {
4324  switch ( state )
4325  {
4326  case STATE_STATING:
4327  {
4328  // Was there an error while stating ?
4329  if (job->error() )
4330  {
4331  // Probably : doesn't exist
4332  Job::slotResult( job ); // will set the error and emit result(this)
4333  return;
4334  }
4335 
4336  // Is it a file or a dir ?
4337  UDSEntry entry = ((StatJob*)job)->statResult();
4338  bool bDir = false;
4339  bool bLink = false;
4340 // TDEIO::filesize_t size = (TDEIO::filesize_t)-1;
4341  UDSEntry::ConstIterator it2 = entry.begin();
4342  int atomsFound(0);
4343  for( ; it2 != entry.end(); it2++ )
4344  {
4345  if ( ((*it2).m_uds) == UDS_FILE_TYPE )
4346  {
4347  bDir = S_ISDIR( (mode_t)(*it2).m_long );
4348  atomsFound++;
4349  }
4350  else if ( ((*it2).m_uds) == UDS_LINK_DEST )
4351  {
4352  bLink = !((*it2).m_str.isEmpty());
4353  atomsFound++;
4354  }
4355  else if ( ((*it2).m_uds) == UDS_SIZE )
4356  {
4357 // size = (*it2).m_long;
4358  atomsFound++;
4359  }
4360  if (atomsFound==3) break;
4361  }
4362 
4363  KURL url = ((SimpleJob*)job)->url();
4364 
4365  subjobs.remove( job );
4366  assert( subjobs.isEmpty() );
4367 
4368  if (bDir && !bLink)
4369  {
4370  // Add toplevel dir in list of dirs
4371  dirs.append( url );
4372  if ( url.isLocalFile() && !m_parentDirs.contains( url.path(-1) ) )
4373  m_parentDirs.append( url.path(-1) );
4374 
4375  if ( !KProtocolInfo::canDeleteRecursive( url ) ) {
4376  //kdDebug(7007) << " Target is a directory " << endl;
4377  // List it
4378  state = STATE_LISTING;
4379  ListJob *newjob = listRecursive( url, false );
4380  newjob->setUnrestricted(true); // No KIOSK restrictions
4381  Scheduler::scheduleJob(newjob);
4382  connect(newjob, TQ_SIGNAL(entries( TDEIO::Job *,
4383  const TDEIO::UDSEntryList& )),
4384  TQ_SLOT( slotEntries( TDEIO::Job*,
4385  const TDEIO::UDSEntryList& )));
4386  addSubjob(newjob);
4387  } else {
4388  ++m_currentStat;
4389  statNextSrc();
4390  }
4391  }
4392  else
4393  {
4394  if ( bLink ) {
4395  //kdDebug(7007) << " Target is a symlink" << endl;
4396  symlinks.append( url );
4397  } else {
4398  //kdDebug(7007) << " Target is a file" << endl;
4399  files.append( url );
4400  }
4401  if ( url.isLocalFile() && !m_parentDirs.contains( url.directory(false) ) )
4402  m_parentDirs.append( url.directory(false) );
4403  ++m_currentStat;
4404  statNextSrc();
4405  }
4406  }
4407  break;
4408  case STATE_LISTING:
4409  if ( job->error() )
4410  {
4411  // Try deleting nonetheless, it may be empty (and non-listable)
4412  }
4413  subjobs.remove( job );
4414  assert( subjobs.isEmpty() );
4415  ++m_currentStat;
4416  statNextSrc();
4417  break;
4418  case STATE_DELETING_FILES:
4419  if ( job->error() )
4420  {
4421  Job::slotResult( job ); // will set the error and emit result(this)
4422  return;
4423  }
4424  subjobs.remove( job );
4425  assert( subjobs.isEmpty() );
4426  m_processedFiles++;
4427 
4428  deleteNextFile();
4429  break;
4430  case STATE_DELETING_DIRS:
4431  if ( job->error() )
4432  {
4433  Job::slotResult( job ); // will set the error and emit result(this)
4434  return;
4435  }
4436  subjobs.remove( job );
4437  assert( subjobs.isEmpty() );
4438  m_processedDirs++;
4439  //emit processedDirs( this, m_processedDirs );
4440  //if (!m_shred)
4441  //emitPercent( m_processedFiles + m_processedDirs, m_totalFilesDirs );
4442 
4443  deleteNextDir();
4444  break;
4445  default:
4446  assert(0);
4447  }
4448 }
4449 
4450 DeleteJob *TDEIO::del( const KURL& src, bool shred, bool showProgressInfo )
4451 {
4452  KURL::List srcList;
4453  srcList.append( src );
4454  DeleteJob *job = new DeleteJob( srcList, shred, showProgressInfo );
4455  return job;
4456 }
4457 
4458 DeleteJob *TDEIO::del( const KURL::List& src, bool shred, bool showProgressInfo )
4459 {
4460  DeleteJob *job = new DeleteJob( src, shred, showProgressInfo );
4461  return job;
4462 }
4463 
4464 MultiGetJob::MultiGetJob(const KURL& url,
4465  bool showProgressInfo)
4466  : TransferJob(url, 0, TQByteArray(), TQByteArray(), showProgressInfo)
4467 {
4468  m_waitQueue.setAutoDelete(true);
4469  m_activeQueue.setAutoDelete(true);
4470  m_currentEntry = 0;
4471 }
4472 
4473 void MultiGetJob::get(long id, const KURL &url, const MetaData &metaData)
4474 {
4475  GetRequest *entry = new GetRequest(id, url, metaData);
4476  entry->metaData["request-id"] = TQString("%1").arg(id);
4477  m_waitQueue.append(entry);
4478 }
4479 
4480 void MultiGetJob::flushQueue(TQPtrList<GetRequest> &queue)
4481 {
4482  GetRequest *entry;
4483  // Use multi-get
4484  // Scan all jobs in m_waitQueue
4485  for(entry = m_waitQueue.first(); entry; )
4486  {
4487  if ((m_url.protocol() == entry->url.protocol()) &&
4488  (m_url.host() == entry->url.host()) &&
4489  (m_url.port() == entry->url.port()) &&
4490  (m_url.user() == entry->url.user()))
4491  {
4492  m_waitQueue.take();
4493  queue.append(entry);
4494  entry = m_waitQueue.current();
4495  }
4496  else
4497  {
4498  entry = m_waitQueue.next();
4499  }
4500  }
4501  // Send number of URLs, (URL, metadata)*
4502  TDEIO_ARGS << (TQ_INT32) queue.count();
4503  for(entry = queue.first(); entry; entry = queue.next())
4504  {
4505  stream << entry->url << entry->metaData;
4506  }
4507  m_packedArgs = packedArgs;
4508  m_command = CMD_MULTI_GET;
4509  m_outgoingMetaData.clear();
4510 }
4511 
4512 void MultiGetJob::start(Slave *slave)
4513 {
4514  // Add first job from m_waitQueue and add it to m_activeQueue
4515  GetRequest *entry = m_waitQueue.take(0);
4516  m_activeQueue.append(entry);
4517 
4518  m_url = entry->url;
4519 
4520  if (!entry->url.protocol().startsWith("http"))
4521  {
4522  // Use normal get
4523  TDEIO_ARGS << entry->url;
4524  m_packedArgs = packedArgs;
4525  m_outgoingMetaData = entry->metaData;
4526  m_command = CMD_GET;
4527  b_multiGetActive = false;
4528  }
4529  else
4530  {
4531  flushQueue(m_activeQueue);
4532  b_multiGetActive = true;
4533  }
4534 
4535  TransferJob::start(slave); // Anything else to do??
4536 }
4537 
4538 bool MultiGetJob::findCurrentEntry()
4539 {
4540  if (b_multiGetActive)
4541  {
4542  long id = m_incomingMetaData["request-id"].toLong();
4543  for(GetRequest *entry = m_activeQueue.first(); entry; entry = m_activeQueue.next())
4544  {
4545  if (entry->id == id)
4546  {
4547  m_currentEntry = entry;
4548  return true;
4549  }
4550  }
4551  m_currentEntry = 0;
4552  return false;
4553  }
4554  else
4555  {
4556  m_currentEntry = m_activeQueue.first();
4557  return (m_currentEntry != 0);
4558  }
4559 }
4560 
4561 void MultiGetJob::slotRedirection( const KURL &url)
4562 {
4563  if (!findCurrentEntry()) return; // Error
4564  if (kapp && !kapp->authorizeURLAction("redirect", m_url, url))
4565  {
4566  kdWarning(7007) << "MultiGetJob: Redirection from " << m_currentEntry->url << " to " << url << " REJECTED!" << endl;
4567  return;
4568  }
4569  m_redirectionURL = url;
4570  if (m_currentEntry->url.hasUser() && !url.hasUser() && (m_currentEntry->url.host().lower() == url.host().lower()))
4571  m_redirectionURL.setUser(m_currentEntry->url.user()); // Preserve user
4572  get(m_currentEntry->id, m_redirectionURL, m_currentEntry->metaData); // Try again
4573 }
4574 
4575 
4576 void MultiGetJob::slotFinished()
4577 {
4578  if (!findCurrentEntry()) return;
4579  if (m_redirectionURL.isEmpty())
4580  {
4581  // No redirection, tell the world that we are finished.
4582  emit result(m_currentEntry->id);
4583  }
4584  m_redirectionURL = KURL();
4585  m_error = 0;
4586  m_incomingMetaData.clear();
4587  m_activeQueue.removeRef(m_currentEntry);
4588  if (m_activeQueue.count() == 0)
4589  {
4590  if (m_waitQueue.count() == 0)
4591  {
4592  // All done
4593  TransferJob::slotFinished();
4594  }
4595  else
4596  {
4597  // return slave to pool
4598  // fetch new slave for first entry in m_waitQueue and call start
4599  // again.
4600  GetRequest *entry = m_waitQueue.at(0);
4601  m_url = entry->url;
4602  slaveDone();
4603  Scheduler::doJob(this);
4604  }
4605  }
4606 }
4607 
4608 void MultiGetJob::slotData( const TQByteArray &_data)
4609 {
4610  if(!m_currentEntry) return;// Error, unknown request!
4611  if(m_redirectionURL.isEmpty() || !m_redirectionURL.isValid() || m_error)
4612  emit data(m_currentEntry->id, _data);
4613 }
4614 
4615 void MultiGetJob::slotMimetype( const TQString &_mimetype )
4616 {
4617  if (b_multiGetActive)
4618  {
4619  TQPtrList<GetRequest> newQueue;
4620  flushQueue(newQueue);
4621  if (!newQueue.isEmpty())
4622  {
4623  while(!newQueue.isEmpty())
4624  m_activeQueue.append(newQueue.take(0));
4625  m_slave->send( m_command, m_packedArgs );
4626  }
4627  }
4628  if (!findCurrentEntry()) return; // Error, unknown request!
4629  emit mimetype(m_currentEntry->id, _mimetype);
4630 }
4631 
4632 MultiGetJob *TDEIO::multi_get(long id, const KURL &url, const MetaData &metaData)
4633 {
4634  MultiGetJob * job = new MultiGetJob( url, false );
4635  job->get(id, url, metaData);
4636  return job;
4637 }
4638 
4639 
4640 #ifdef CACHE_INFO
4641 CacheInfo::CacheInfo(const KURL &url)
4642 {
4643  m_url = url;
4644 }
4645 
4646 TQString CacheInfo::cachedFileName()
4647 {
4648  const TQChar separator = '_';
4649 
4650  TQString CEF = m_url.path();
4651 
4652  int p = CEF.find('/');
4653 
4654  while(p != -1)
4655  {
4656  CEF[p] = separator;
4657  p = CEF.find('/', p);
4658  }
4659 
4660  TQString host = m_url.host().lower();
4661  CEF = host + CEF + '_';
4662 
4663  TQString dir = KProtocolManager::cacheDir();
4664  if (dir[dir.length()-1] != '/')
4665  dir += "/";
4666 
4667  int l = m_url.host().length();
4668  for(int i = 0; i < l; i++)
4669  {
4670  if (host[i].isLetter() && (host[i] != 'w'))
4671  {
4672  dir += host[i];
4673  break;
4674  }
4675  }
4676  if (dir[dir.length()-1] == '/')
4677  dir += "0";
4678 
4679  unsigned long hash = 0x00000000;
4680  TQCString u = m_url.url().latin1();
4681  for(int i = u.length(); i--;)
4682  {
4683  hash = (hash * 12211 + u[i]) % 2147483563;
4684  }
4685 
4686  TQString hashString;
4687  hashString.sprintf("%08lx", hash);
4688 
4689  CEF = CEF + hashString;
4690 
4691  CEF = dir + "/" + CEF;
4692 
4693  return CEF;
4694 }
4695 
4696 TQFile *CacheInfo::cachedFile()
4697 {
4698 #ifdef TQ_WS_WIN
4699  const char *mode = (readWrite ? "rb+" : "rb");
4700 #else
4701  const char *mode = (readWrite ? "r+" : "r");
4702 #endif
4703 
4704  FILE *fs = fopen(TQFile::encodeName(CEF), mode); // Open for reading and writing
4705  if (!fs)
4706  return 0;
4707 
4708  char buffer[401];
4709  bool ok = true;
4710 
4711  // CacheRevision
4712  if (ok && (!fgets(buffer, 400, fs)))
4713  ok = false;
4714  if (ok && (strcmp(buffer, CACHE_REVISION) != 0))
4715  ok = false;
4716 
4717  time_t date;
4718  time_t currentDate = time(0);
4719 
4720  // URL
4721  if (ok && (!fgets(buffer, 400, fs)))
4722  ok = false;
4723  if (ok)
4724  {
4725  int l = strlen(buffer);
4726  if (l>0)
4727  buffer[l-1] = 0; // Strip newline
4728  if (m_.url.url() != buffer)
4729  {
4730  ok = false; // Hash collision
4731  }
4732  }
4733 
4734  // Creation Date
4735  if (ok && (!fgets(buffer, 400, fs)))
4736  ok = false;
4737  if (ok)
4738  {
4739  date = (time_t) strtoul(buffer, 0, 10);
4740  if (m_maxCacheAge && (difftime(currentDate, date) > m_maxCacheAge))
4741  {
4742  m_bMustRevalidate = true;
4743  m_expireDate = currentDate;
4744  }
4745  }
4746 
4747  // Expiration Date
4748  m_cacheExpireDateOffset = ftell(fs);
4749  if (ok && (!fgets(buffer, 400, fs)))
4750  ok = false;
4751  if (ok)
4752  {
4753  if (m_request.cache == CC_Verify)
4754  {
4755  date = (time_t) strtoul(buffer, 0, 10);
4756  // After the expire date we need to revalidate.
4757  if (!date || difftime(currentDate, date) >= 0)
4758  m_bMustRevalidate = true;
4759  m_expireDate = date;
4760  }
4761  }
4762 
4763  // ETag
4764  if (ok && (!fgets(buffer, 400, fs)))
4765  ok = false;
4766  if (ok)
4767  {
4768  m_etag = TQString(buffer).stripWhiteSpace();
4769  }
4770 
4771  // Last-Modified
4772  if (ok && (!fgets(buffer, 400, fs)))
4773  ok = false;
4774  if (ok)
4775  {
4776  m_lastModified = TQString(buffer).stripWhiteSpace();
4777  }
4778 
4779  fclose(fs);
4780 
4781  if (ok)
4782  return fs;
4783 
4784  unlink( TQFile::encodeName(CEF) );
4785  return 0;
4786 
4787 }
4788 
4789 void CacheInfo::flush()
4790 {
4791  cachedFile().remove();
4792 }
4793 
4794 void CacheInfo::touch()
4795 {
4796 
4797 }
4798 void CacheInfo::setExpireDate(int);
4799 void CacheInfo::setExpireTimeout(int);
4800 
4801 
4802 int CacheInfo::creationDate();
4803 int CacheInfo::expireDate();
4804 int CacheInfo::expireTimeout();
4805 #endif
4806 
4807 void Job::virtual_hook( int, void* )
4808 { /*BASE::virtual_hook( id, data );*/ }
4809 
4810 void SimpleJob::virtual_hook( int id, void* data )
4811 { TDEIO::Job::virtual_hook( id, data ); }
4812 
4813 void MkdirJob::virtual_hook( int id, void* data )
4814 { SimpleJob::virtual_hook( id, data ); }
4815 
4816 void StatJob::virtual_hook( int id, void* data )
4817 { SimpleJob::virtual_hook( id, data ); }
4818 
4819 void TransferJob::virtual_hook( int id, void* data )
4820 { SimpleJob::virtual_hook( id, data ); }
4821 
4822 void MultiGetJob::virtual_hook( int id, void* data )
4823 { TransferJob::virtual_hook( id, data ); }
4824 
4825 void MimetypeJob::virtual_hook( int id, void* data )
4826 { TransferJob::virtual_hook( id, data ); }
4827 
4828 void FileCopyJob::virtual_hook( int id, void* data )
4829 { Job::virtual_hook( id, data ); }
4830 
4831 void ListJob::virtual_hook( int id, void* data )
4832 { SimpleJob::virtual_hook( id, data ); }
4833 
4834 void CopyJob::virtual_hook( int id, void* data )
4835 { Job::virtual_hook( id, data ); }
4836 
4837 void DeleteJob::virtual_hook( int id, void* data )
4838 { Job::virtual_hook( id, data ); }
4839 
4840 void LocalURLJob::virtual_hook( int id, void* data )
4841 { Job::virtual_hook( id, data ); }
4842 
4843 
4844 #include "jobclasses.moc"
KDirWatch::restartDirScan
bool restartDirScan(const TQString &path)
Restarts scanning for specified path.
Definition: kdirwatch.cpp:1737
KDirWatch::self
static KDirWatch * self()
The KDirWatch instance usually globally used in an application.
Definition: kdirwatch.cpp:1634
KDirWatch::stopDirScan
bool stopDirScan(const TQString &path)
Stops scanning the specified path.
Definition: kdirwatch.cpp:1728
KMimeType::findByURL
static Ptr findByURL(const KURL &_url, mode_t _mode=0, bool _is_local_file=false, bool _fast_mode=false)
Finds a KMimeType with the given _url.
Definition: kmimetype.cpp:165
KProtocolInfo::isKnownProtocol
static bool isKnownProtocol(const KURL &url)
Returns whether a protocol is installed that is able to handle url.
Definition: kprotocolinfo.cpp:109
KProtocolInfo::supportsDeleting
static bool supportsDeleting(const KURL &url)
Returns whether the protocol can delete files/objects.
Definition: kprotocolinfo.cpp:166
KProtocolInfo::canCopyFromFile
static bool canCopyFromFile(const KURL &url)
Returns whether the protocol can copy files/objects directly from the filesystem itself.
Definition: kprotocolinfo.cpp:193
KProtocolInfo::canCopyToFile
static bool canCopyToFile(const KURL &url)
Returns whether the protocol can copy files/objects directly to the filesystem itself.
Definition: kprotocolinfo.cpp:203
KProtocolInfo::supportsListing
static bool supportsListing(const KURL &url)
Returns whether the protocol can list files/objects.
Definition: kprotocolinfo.cpp:121
KProtocolManager::cacheDir
static TQString cacheDir()
The directory which contains the cache files.
Definition: tdeprotocolmanager.cpp:189
KProtocolManager::autoResume
static bool autoResume()
Returns true if partial downloads should be automatically resumed.
Definition: tdeprotocolmanager.cpp:523
Observer
Observer for TDEIO::Job progress information.
Definition: observer.h:55
Observer::newJob
int newJob(TDEIO::Job *job, bool showProgress)
Called by the job constructor, to signal its presence to the UI Server.
Definition: observer.cpp:81
Observer::slotTransferring
void slotTransferring(TDEIO::Job *, const KURL &url)
Definition: observer.cpp:188
Observer::self
static Observer * self()
Returns the unique observer object.
Definition: observer.h:66
Observer::jobFinished
void jobFinished(int progressId)
Called by the job destructor, to tell the UI Server that the job ended.
Definition: observer.cpp:93
TDEIO::CopyJob
CopyJob is used to move, copy or symlink files and directories.
Definition: jobclasses.h:1507
TDEIO::CopyJob::renamed
void renamed(TDEIO::Job *job, const KURL &from, const KURL &to)
TDEIO::CopyJob::copyingLinkDone
void copyingLinkDone(TDEIO::Job *job, const KURL &from, const TQString &target, const KURL &to)
TDEIO::CopyJob::CopyMode
CopyMode
Defines the mode of the operation.
Definition: jobclasses.h:1514
TDEIO::CopyJob::aboutToCreate
void aboutToCreate(TDEIO::Job *job, const TQValueList< TDEIO::CopyInfo > &files)
Emitted when it is known which files / directories are going to be created.
TDEIO::CopyJob::processedFiles
void processedFiles(TDEIO::Job *job, unsigned long files)
Sends the number of processed files.
TDEIO::CopyJob::moving
void moving(TDEIO::Job *job, const KURL &from, const KURL &to)
TDEIO::CopyJob::linking
void linking(TDEIO::Job *job, const TQString &target, const KURL &to)
TDEIO::CopyJob::copyingDone
void copyingDone(TDEIO::Job *job, const KURL &from, const KURL &to, bool directory, bool renamed)
TDEIO::CopyJob::CopyJob
CopyJob(const KURL::List &src, const KURL &dest, CopyMode mode, bool asMethod, bool showProgressInfo)
Do not create a CopyJob directly.
Definition: job.cpp:2278
TDEIO::CopyJob::totalDirs
void totalDirs(TDEIO::Job *job, unsigned long dirs)
Emitted when the toal number of direcotries is known.
TDEIO::CopyJob::creatingDir
void creatingDir(TDEIO::Job *job, const KURL &dir)
TDEIO::CopyJob::slotStart
void slotStart()
Definition: job.cpp:2321
TDEIO::CopyJob::slotTotalSize
void slotTotalSize(TDEIO::Job *, TDEIO::filesize_t size)
Definition: job.cpp:3654
TDEIO::CopyJob::setDefaultPermissions
void setDefaultPermissions(bool b)
By default the permissions of the copied files will be those of the source files.
Definition: job.cpp:3939
TDEIO::CopyJob::slotProcessedSize
void slotProcessedSize(TDEIO::Job *, TDEIO::filesize_t data_size)
Forward signal from subjob.
Definition: job.cpp:3637
TDEIO::CopyJob::totalFiles
void totalFiles(TDEIO::Job *job, unsigned long files)
Emitted when the total number of files is known.
TDEIO::CopyJob::setInteractive
void setInteractive(bool b)
When an error happens while copying/moving a file, the user will be presented with a dialog for skipp...
Definition: job.cpp:3945
TDEIO::CopyJob::processedDirs
void processedDirs(TDEIO::Job *job, unsigned long dirs)
Sends the number of processed directories.
TDEIO::CopyJob::copying
void copying(TDEIO::Job *job, const KURL &from, const KURL &to)
TDEIO::DeleteJob
A more complex Job to delete files and directories.
Definition: jobclasses.h:1762
TDEIO::DeleteJob::totalDirs
void totalDirs(TDEIO::Job *job, unsigned long dirs)
Emitted when the toal number of direcotries is known.
TDEIO::DeleteJob::processedDirs
void processedDirs(TDEIO::Job *job, unsigned long dirs)
Sends the number of processed directories.
TDEIO::DeleteJob::DeleteJob
DeleteJob(const KURL::List &src, bool shred, bool showProgressInfo)
Do not create a DeleteJob directly.
Definition: job.cpp:4027
TDEIO::DeleteJob::processedFiles
void processedFiles(TDEIO::Job *job, unsigned long files)
Sends the number of processed files.
TDEIO::DeleteJob::deleting
void deleting(TDEIO::Job *job, const KURL &file)
Sends the URL of the file that is currently being deleted.
TDEIO::DeleteJob::slotProcessedSize
void slotProcessedSize(TDEIO::Job *, TDEIO::filesize_t data_size)
Forward signal from subjob.
Definition: job.cpp:4293
TDEIO::DeleteJob::totalFiles
void totalFiles(TDEIO::Job *job, unsigned long files)
Emitted when the total number of files is known.
TDEIO::FileCopyJob
The FileCopyJob copies data from one place to another.
Definition: jobclasses.h:1249
TDEIO::FileCopyJob::slotCanResume
void slotCanResume(TDEIO::Job *job, TDEIO::filesize_t offset)
Definition: job.cpp:1810
TDEIO::FileCopyJob::slotPercent
void slotPercent(TDEIO::Job *job, unsigned long pct)
Definition: job.cpp:1778
TDEIO::FileCopyJob::slotResult
virtual void slotResult(TDEIO::Job *job)
Definition: job.cpp:1944
TDEIO::FileCopyJob::slotProcessedSize
void slotProcessedSize(TDEIO::Job *job, TDEIO::filesize_t size)
Definition: job.cpp:1759
TDEIO::FileCopyJob::setSourceSize64
void setSourceSize64(TDEIO::filesize_t size)
Definition: job.cpp:1710
TDEIO::FileCopyJob::slotTotalSize
void slotTotalSize(TDEIO::Job *job, TDEIO::filesize_t size)
Definition: job.cpp:1769
TDEIO::FileCopyJob::setSourceSize
void setSourceSize(off_t size) TDE_DEPRECATED
Definition: job.cpp:1703
TDEIO::FileCopyJob::setModificationTime
void setModificationTime(time_t mtime)
Sets the modification time of the file.
Definition: job.cpp:1717
TDEIO::FileCopyJob::mimetype
void mimetype(TDEIO::Job *job, const TQString &type)
Mimetype determined during a file copy.
TDEIO::Job
The base class for all jobs.
Definition: jobclasses.h:67
TDEIO::Job::isAutoWarningHandlingEnabled
bool isAutoWarningHandlingEnabled() const
Returns whether automatic warning handling is enabled or disabled.
Definition: job.cpp:366
TDEIO::Job::removeSubjob
virtual void removeSubjob(Job *job)
Definition: job.cpp:205
TDEIO::Job::errorText
const TQString & errorText() const
Returns the error text if there has been an error.
Definition: jobclasses.h:110
TDEIO::Job::updateUserTimestamp
void updateUserTimestamp(unsigned long time)
Updates the last user action timestamp to the given time.
Definition: job.cpp:392
TDEIO::Job::slotResult
virtual void slotResult(TDEIO::Job *job)
Definition: job.cpp:281
TDEIO::Job::mergeMetaData
void mergeMetaData(const TQMap< TQString, TQString > &values)
Definition: job.cpp:446
TDEIO::Job::setProcessedSize
void setProcessedSize(TDEIO::filesize_t size)
Set the processed size, does not emit processedSize.
Definition: job.cpp:173
TDEIO::Job::setParentJob
void setParentJob(Job *parentJob)
Definition: job.cpp:405
TDEIO::Job::emitResult
void emitResult()
Utility function to emit the result signal, and suicide this job.
Definition: job.cpp:249
TDEIO::Job::setAutoWarningHandlingEnabled
void setAutoWarningHandlingEnabled(bool enable)
Enable or disable the automatic warning handling.
Definition: job.cpp:361
TDEIO::Job::addSubjob
virtual void addSubjob(Job *job, bool inheritMetaData=true)
Definition: job.cpp:183
TDEIO::Job::getProcessedSize
TDEIO::filesize_t getProcessedSize()
Returns the processed size for this job.
Definition: job.cpp:178
TDEIO::Job::emitSpeed
void emitSpeed(unsigned long speed)
Definition: job.cpp:237
TDEIO::Job::slotSpeed
void slotSpeed(TDEIO::Job *job, unsigned long speed)
Definition: job.cpp:293
TDEIO::Job::detailedErrorStrings
TQStringList detailedErrorStrings(const KURL *reqUrl=0L, int method=-1) const
Converts an error code and a non-i18n error message into i18n strings suitable for presentation in a ...
Definition: global.cpp:478
TDEIO::Job::parentJob
Job * parentJob() const
Returns the parent job, if there is one.
Definition: job.cpp:412
TDEIO::Job::showErrorDialog
void showErrorDialog(TQWidget *parent=0L)
Display a dialog box to inform the user of the error given by this job.
Definition: job.cpp:315
TDEIO::Job::result
void result(TDEIO::Job *job)
TDEIO::Job::infoMessage
void infoMessage(TDEIO::Job *job, const TQString &msg)
TDEIO::Job::connected
void connected(TDEIO::Job *job)
TDEIO::Job::kill
virtual void kill(bool quietly=true)
Abort this job.
Definition: job.cpp:260
TDEIO::Job::addMetaData
void addMetaData(const TQString &key, const TQString &value)
Definition: job.cpp:434
TDEIO::Job::totalSize
void totalSize(TDEIO::Job *job, TDEIO::filesize_t size)
TDEIO::Job::slotSpeedTimeout
void slotSpeedTimeout()
Remove speed information.
Definition: job.cpp:304
TDEIO::Job::speed
void speed(TDEIO::Job *job, unsigned long speed)
TDEIO::Job::emitPercent
void emitPercent(TDEIO::filesize_t processedSize, TDEIO::filesize_t totalSize)
Definition: job.cpp:221
TDEIO::Job::isInteractive
bool isInteractive() const
Returns whether message display is enabled or disabled.
Definition: job.cpp:376
TDEIO::Job::error
int error() const
Returns the error code, if there has been an error.
Definition: jobclasses.h:94
TDEIO::Job::canceled
void canceled(TDEIO::Job *job)
TDEIO::Job::setWindow
void setWindow(TQWidget *window)
Definition: job.cpp:381
TDEIO::Job::queryMetaData
TQString queryMetaData(const TQString &key)
Definition: job.cpp:422
TDEIO::Job::setInteractive
void setInteractive(bool enable)
Enable or disable the message display from the job.
Definition: job.cpp:371
TDEIO::Job::percent
void percent(TDEIO::Job *job, unsigned long percent)
TDEIO::Job::window
TQWidget * window() const
Definition: job.cpp:387
TDEIO::Job::slotInfoMessage
void slotInfoMessage(TDEIO::Job *job, const TQString &msg)
Definition: job.cpp:299
TDEIO::Job::isAutoErrorHandlingEnabled
bool isAutoErrorHandlingEnabled() const
Definition: job.cpp:356
TDEIO::Job::errorString
TQString errorString() const
Definition: global.cpp:225
TDEIO::Job::metaData
MetaData metaData() const
Definition: job.cpp:417
TDEIO::Job::warning
void warning(TDEIO::Job *job, const TQString &msg)
Emitted to display a warning about this job, as sent by the slave.
TDEIO::Job::setMetaData
void setMetaData(const TDEIO::MetaData &metaData)
Definition: job.cpp:429
TDEIO::Job::processedSize
void processedSize(TDEIO::Job *job, TDEIO::filesize_t size)
TDEIO::ListJob
A ListJob is allows you to get the get the content of a directory.
Definition: jobclasses.h:1391
TDEIO::ListJob::redirection
void redirection(TDEIO::Job *job, const KURL &url)
TDEIO::ListJob::entries
void entries(TDEIO::Job *job, const TDEIO::UDSEntryList &list)
TDEIO::ListJob::setUnrestricted
void setUnrestricted(bool unrestricted)
Do not apply any KIOSK restrictions to this job.
Definition: job.cpp:2228
TDEIO::ListJob::permanentRedirection
void permanentRedirection(TDEIO::Job *job, const KURL &fromUrl, const KURL &toUrl)
TDEIO::ListJob::ListJob
ListJob(const KURL &url, bool showProgressInfo, bool recursive=false, TQString prefix=TQString::null, bool includeHidden=true)
Do not create a ListJob directly.
Definition: job.cpp:2048
TDEIO::LocalURLJob
A TDEIO job that finds a local URL.
Definition: jobclasses.h:1865
TDEIO::LocalURLJob::localURL
void localURL(TDEIO::LocalURLJob *job, const KURL &url, bool isLocal)
TDEIO::LocalURLJob::LocalURLJob
LocalURLJob(const KURL &url, int command, const TQByteArray &packedArgs, bool showProgressInfo)
Do not use this constructor to create a LocalURLJob, use TDEIO::localURL() instead.
Definition: job.cpp:841
TDEIO::MetaData
MetaData is a simple map of key/value strings.
Definition: global.h:516
TDEIO::MimetypeJob
A MimetypeJob is a TransferJob that allows you to get the mime type of an URL.
Definition: jobclasses.h:1207
TDEIO::MimetypeJob::MimetypeJob
MimetypeJob(const KURL &url, int command, const TQByteArray &packedArgs, bool showProgressInfo)
Do not create a MimetypeJob directly.
Definition: job.cpp:1526
TDEIO::MkdirJob
A TDEIO job that creates a directory.
Definition: jobclasses.h:779
TDEIO::MkdirJob::redirection
void redirection(TDEIO::Job *job, const KURL &url)
TDEIO::MkdirJob::permanentRedirection
void permanentRedirection(TDEIO::Job *job, const KURL &fromUrl, const KURL &toUrl)
TDEIO::MkdirJob::MkdirJob
MkdirJob(const KURL &url, int command, const TQByteArray &packedArgs, bool showProgressInfo)
Do not use this constructor to create a MkdirJob, use TDEIO::mkdir() instead.
Definition: job.cpp:721
TDEIO::MultiGetJob
The MultiGetJob is a TransferJob that allows you to get several files from a single server.
Definition: jobclasses.h:1119
TDEIO::MultiGetJob::mimetype
void mimetype(long id, const TQString &type)
TDEIO::MultiGetJob::get
void get(long id, const KURL &url, const MetaData &metaData)
Get an additional file.
Definition: job.cpp:4473
TDEIO::MultiGetJob::data
void data(long id, const TQByteArray &data)
TDEIO::MultiGetJob::MultiGetJob
MultiGetJob(const KURL &url, bool showProgressInfo)
Do not create a MultiGetJob directly, use TDEIO::multi_get() instead.
Definition: job.cpp:4464
TDEIO::MultiGetJob::result
void result(long id)
TDEIO::Scheduler::scheduleJob
static void scheduleJob(SimpleJob *job)
Definition: scheduler.h:137
TDEIO::Scheduler::registerWindow
static void registerWindow(TQWidget *wid)
Definition: scheduler.h:242
TDEIO::Scheduler::putSlaveOnHold
static void putSlaveOnHold(TDEIO::SimpleJob *job, const KURL &url)
Definition: scheduler.h:166
TDEIO::Scheduler::removeSlaveOnHold
static void removeSlaveOnHold()
Removes any slave that might have been put on hold.
Definition: scheduler.h:173
TDEIO::Scheduler::cancelJob
static void cancelJob(SimpleJob *job)
Definition: scheduler.h:144
TDEIO::Scheduler::jobFinished
static void jobFinished(TDEIO::SimpleJob *job, TDEIO::Slave *slave)
Definition: scheduler.h:152
TDEIO::Scheduler::doJob
static void doJob(SimpleJob *job)
Definition: scheduler.h:128
TDEIO::SimpleJob
A simple job (one url and one command).
Definition: jobclasses.h:527
TDEIO::SimpleJob::slotSpeed
void slotSpeed(unsigned long speed)
Definition: job.cpp:700
TDEIO::SimpleJob::removeOnHold
static void removeOnHold()
Discard suspended slave.
Definition: job.cpp:504
TDEIO::SimpleJob::putOnHold
virtual void putOnHold()
Abort job.
Definition: job.cpp:493
TDEIO::SimpleJob::slotMetaData
virtual void slotMetaData(const TDEIO::MetaData &_metaData)
Definition: job.cpp:706
TDEIO::SimpleJob::slotProcessedSize
void slotProcessedSize(TDEIO::filesize_t data_size)
Definition: job.cpp:689
TDEIO::SimpleJob::slotConnected
void slotConnected()
Definition: job.cpp:668
TDEIO::SimpleJob::url
const KURL & url() const
Returns the SimpleJob's URL.
Definition: jobclasses.h:548
TDEIO::SimpleJob::slotFinished
virtual void slotFinished()
Called when the slave marks the job as finished.
Definition: job.cpp:605
TDEIO::SimpleJob::SimpleJob
SimpleJob(const KURL &url, int command, const TQByteArray &packedArgs, bool showProgressInfo)
Creates a new simple job.
Definition: job.cpp:459
TDEIO::SimpleJob::slotInfoMessage
void slotInfoMessage(const TQString &s)
Definition: job.cpp:663
TDEIO::SimpleJob::slotTotalSize
void slotTotalSize(TDEIO::filesize_t data_size)
Definition: job.cpp:680
TDEIO::SimpleJob::kill
virtual void kill(bool quietly=true)
Abort job.
Definition: job.cpp:486
TDEIO::SlaveInterface::sendResumeAnswer
void sendResumeAnswer(bool resume)
Send our answer to the MSG_RESUME (canResume) request (to tell the "put" job whether to resume or not...
Definition: slaveinterface.cpp:447
TDEIO::Slave
Attention developers: If you change the implementation of TDEIO::Slave, do not use connection() or sl...
Definition: slave.h:44
TDEIO::Slave::suspended
bool suspended()
Tells wether the tdeioslave is suspended.
Definition: slave.cpp:274
TDEIO::Slave::suspend
void suspend()
Suspends the operation of the attached tdeioslave.
Definition: slave.cpp:254
TDEIO::Slave::kill
void kill()
Force termination.
Definition: slave.cpp:317
TDEIO::Slave::send
void send(int cmd, const TQByteArray &data=TQByteArray())
Sends the given command to the tdeioslave.
Definition: slave.cpp:285
TDEIO::Slave::resume
void resume()
Resumes the operation of the attached tdeioslave.
Definition: slave.cpp:264
TDEIO::StatJob
A TDEIO job that retrieves information about a file or directory.
Definition: jobclasses.h:687
TDEIO::StatJob::redirection
void redirection(TDEIO::Job *job, const KURL &url)
TDEIO::StatJob::setSide
void setSide(bool source)
A stat() can have two meanings.
Definition: jobclasses.h:708
TDEIO::StatJob::StatJob
StatJob(const KURL &url, int command, const TQByteArray &packedArgs, bool showProgressInfo)
Do not use this constructor to create a StatJob, use TDEIO::stat() instead.
Definition: job.cpp:879
TDEIO::StatJob::permanentRedirection
void permanentRedirection(TDEIO::Job *job, const KURL &fromUrl, const KURL &toUrl)
TDEIO::StatJob::setDetails
void setDetails(short int details)
Definition: jobclasses.h:719
TDEIO::StoredTransferJob
StoredTransferJob is a TransferJob (for downloading or uploading data) that also stores a TQByteArray...
Definition: jobclasses.h:1074
TDEIO::StoredTransferJob::data
TQByteArray data() const
Get hold of the downloaded data.
Definition: jobclasses.h:1103
TDEIO::StoredTransferJob::StoredTransferJob
StoredTransferJob(const KURL &url, int command, const TQByteArray &packedArgs, const TQByteArray &_staticData, bool showProgressInfo)
Do not create a StoredTransferJob.
Definition: job.cpp:1454
TDEIO::StoredTransferJob::setData
void setData(const TQByteArray &arr)
Set data to be uploaded.
Definition: job.cpp:1467
TDEIO::TransferJob
The transfer job pumps data into and/or out of a Slave.
Definition: jobclasses.h:874
TDEIO::TransferJob::data
void data(TDEIO::Job *job, const TQByteArray &data)
Data from the slave has arrived.
TDEIO::TransferJob::mimetype
void mimetype(TDEIO::Job *job, const TQString &type)
TDEIO::TransferJob::resume
void resume()
Flow control.
Definition: job.cpp:1186
TDEIO::TransferJob::slotResult
virtual void slotResult(TDEIO::Job *job)
Definition: job.cpp:1262
TDEIO::TransferJob::redirection
void redirection(TDEIO::Job *job, const KURL &url)
TDEIO::TransferJob::TransferJob
TransferJob(const KURL &url, int command, const TQByteArray &packedArgs, const TQByteArray &_staticData, bool showProgressInfo)
Do not create a TransferJob.
Definition: job.cpp:980
TDEIO::TransferJob::permanentRedirection
void permanentRedirection(TDEIO::Job *job, const KURL &fromUrl, const KURL &toUrl)
TDEIO::TransferJob::reportDataSent
bool reportDataSent()
Returns whether the job reports the amount of data that has been sent (true), or whether the job repo...
Definition: job.cpp:1128
TDEIO::TransferJob::dataReq
void dataReq(TDEIO::Job *job, TQByteArray &data)
TDEIO::TransferJob::suspend
void suspend()
Flow control.
Definition: job.cpp:1179
TDEIO::TransferJob::sendAsyncData
void sendAsyncData(const TQByteArray &data)
Provide data to the job when async data is enabled.
Definition: job.cpp:1100
TDEIO::TransferJob::setReportDataSent
void setReportDataSent(bool enabled)
When enabled, the job reports the amount of data that has been sent, instead of the amount of data th...
Definition: job.cpp:1120
TDEIO::TransferJob::setAsyncDataEnabled
void setAsyncDataEnabled(bool enabled)
Enable the async data mode.
Definition: job.cpp:1092
TDEIO
A namespace for TDEIO globals.
Definition: authinfo.h:29
TDEIO::chmod
TDEIO_EXPORT ChmodJob * chmod(const KFileItemList &lstItems, int permissions, int mask, TQString newOwner, TQString newGroup, bool recursive, bool showProgressInfo=true)
Creates a job that changes permissions/ownership on several files or directories, optionally recursiv...
Definition: chmodjob.cpp:230
TDEIO::file_move
TDEIO_EXPORT FileCopyJob * file_move(const KURL &src, const KURL &dest, int permissions=-1, bool overwrite=false, bool resume=false, bool showProgressInfo=true)
Move a single file.
Definition: job.cpp:2033
TDEIO::link
TDEIO_EXPORT CopyJob * link(const KURL &src, const KURL &destDir, bool showProgressInfo=true)
Create a link.
Definition: job.cpp:3994
TDEIO::multi_get
TDEIO_EXPORT MultiGetJob * multi_get(long id, const KURL &url, const MetaData &metaData)
Creates a new multiple get job.
Definition: job.cpp:4632
TDEIO::symlink
TDEIO_EXPORT SimpleJob * symlink(const TQString &target, const KURL &dest, bool overwrite, bool showProgressInfo=true)
Create or move a symlink.
Definition: job.cpp:808
TDEIO::move
TDEIO_EXPORT CopyJob * move(const KURL &src, const KURL &dest, bool showProgressInfo=true)
Moves a file or directory src to the given destination dest.
Definition: job.cpp:3972
TDEIO::number
TDEIO_EXPORT TQString number(TDEIO::filesize_t size)
Converts a size to a string representation Not unlike TQString::number(...)
Definition: global.cpp:96
TDEIO::file_copy
TDEIO_EXPORT FileCopyJob * file_copy(const KURL &src, const KURL &dest, int permissions=-1, bool overwrite=false, bool resume=false, bool showProgressInfo=true)
Copy a single file.
Definition: job.cpp:2027
TDEIO::del
TDEIO_EXPORT DeleteJob * del(const KURL &src, bool shred=false, bool showProgressInfo=true)
Delete a file or directory.
Definition: job.cpp:4450
TDEIO::special
TDEIO_EXPORT SimpleJob * special(const KURL &url, const TQByteArray &data, bool showProgressInfo=true)
Execute any command that is specific to one slave (protocol).
Definition: job.cpp:815
TDEIO::localURL
TDEIO_EXPORT LocalURLJob * localURL(const KURL &remoteUrl)
Retrieve local URL if available.
Definition: job.cpp:870
TDEIO::mimetype
TDEIO_EXPORT MimetypeJob * mimetype(const KURL &url, bool showProgressInfo=true)
Find mimetype for one file or directory.
Definition: job.cpp:1573
TDEIO::copyAs
TDEIO_EXPORT CopyJob * copyAs(const KURL &src, const KURL &dest, bool showProgressInfo=true)
Copy a file or directory src into the destination dest, which is the destination name in any case,...
Definition: job.cpp:3958
TDEIO::linkAs
TDEIO_EXPORT CopyJob * linkAs(const KURL &src, const KURL &dest, bool showProgressInfo=true)
Create a link.
Definition: job.cpp:4006
TDEIO::file_delete
TDEIO_EXPORT SimpleJob * file_delete(const KURL &src, bool showProgressInfo=true)
Delete a single file.
Definition: job.cpp:2039
TDEIO::http_update_cache
TDEIO_EXPORT SimpleJob * http_update_cache(const KURL &url, bool no_cache, time_t expireDate)
HTTP cache update.
Definition: job.cpp:968
TDEIO::mkdir
TDEIO_EXPORT SimpleJob * mkdir(const KURL &url, int permissions=-1)
Creates a single directory.
Definition: job.cpp:780
TDEIO::UDS_LINK_DEST
@ UDS_LINK_DEST
Name of the file where the link points to Allows to check for a symlink (don't use S_ISLNK !...
Definition: global.h:369
TDEIO::UDS_URL
@ UDS_URL
An alternative URL (If different from the caption)
Definition: global.h:371
TDEIO::UDS_SIZE
@ UDS_SIZE
Size of the file.
Definition: global.h:319
TDEIO::UDS_CREATION_TIME
@ UDS_CREATION_TIME
The time the file was created.
Definition: global.h:362
TDEIO::UDS_MODIFICATION_TIME
@ UDS_MODIFICATION_TIME
The last time the file was modified.
Definition: global.h:358
TDEIO::UDS_FILE_TYPE
@ UDS_FILE_TYPE
File type, part of the mode returned by stat (for a link, this returns the file type of the pointed i...
Definition: global.h:366
TDEIO::UDS_ACCESS
@ UDS_ACCESS
Access permissions (part of the mode returned by stat)
Definition: global.h:356
TDEIO::UDS_NAME
@ UDS_NAME
Filename - as displayed in directory listings etc.
Definition: global.h:335
TDEIO::UDS_LOCAL_PATH
@ UDS_LOCAL_PATH
A local file path if the ioslave display files sitting on the local filesystem (but in another hierar...
Definition: global.h:338
TDEIO::UDSEntry
TQValueList< UDSAtom > UDSEntry
An entry is the list of atoms containing all the information for a file or URL.
Definition: global.h:507
TDEIO::moveAs
TDEIO_EXPORT CopyJob * moveAs(const KURL &src, const KURL &dest, bool showProgressInfo=true)
Moves a file or directory src to the given destination dest.
Definition: job.cpp:3980
TDEIO::buildErrorString
TDEIO_EXPORT TQString buildErrorString(int errorCode, const TQString &errorText)
Returns a translated error message for errorCode using the additional error information provided by e...
Definition: global.cpp:230
TDEIO::put
TDEIO_EXPORT TransferJob * put(const KURL &url, int permissions, bool overwrite, bool resume, bool showProgressInfo=true)
Put (a.k.a.
Definition: job.cpp:1444
TDEIO::trash
TDEIO_EXPORT CopyJob * trash(const KURL &src, bool showProgressInfo=true)
Trash a file or directory.
Definition: job.cpp:4013
TDEIO::rename
TDEIO_EXPORT SimpleJob * rename(const KURL &src, const KURL &dest, bool overwrite)
Rename a file or directory.
Definition: job.cpp:801
TDEIO::storedGet
TDEIO_EXPORT StoredTransferJob * storedGet(const KURL &url, bool reload=false, bool showProgressInfo=true)
Get (a.k.a.
Definition: job.cpp:1505
TDEIO::listDir
TDEIO_EXPORT ListJob * listDir(const KURL &url, bool showProgressInfo=true, bool includeHidden=true)
List the contents of url, which is assumed to be a directory.
Definition: job.cpp:2216
TDEIO::storedPut
TDEIO_EXPORT StoredTransferJob * storedPut(const TQByteArray &arr, const KURL &url, int permissions, bool overwrite, bool resume, bool showProgressInfo=true)
Put (a.k.a.
Definition: job.cpp:1515
TDEIO::encodeFileName
TDEIO_EXPORT TQString encodeFileName(const TQString &str)
Encodes (from the text displayed to the real filename) This translates % into %% and / into ∕ (U+2215...
Definition: global.cpp:165
TDEIO::CC_Verify
@ CC_Verify
Validate cached entry with remote site if expired.
Definition: global.h:391
TDEIO::copy
TDEIO_EXPORT CopyJob * copy(const KURL &src, const KURL &dest, bool showProgressInfo=true)
Copy a file or directory src into the destination dest, which can be a file (including the final file...
Definition: job.cpp:3950
TDEIO::get
TDEIO_EXPORT TransferJob * get(const KURL &url, bool reload=false, bool showProgressInfo=true)
Get (a.k.a.
Definition: job.cpp:1284
TDEIO::RenameDlg_Result
RenameDlg_Result
The result of open_RenameDlg().
Definition: renamedlg.h:40
TDEIO::filesize_t
TQ_ULLONG filesize_t
64-bit file size
Definition: global.h:39
TDEIO::http_post
TDEIO_EXPORT TransferJob * http_post(const KURL &url, const TQByteArray &postData, bool showProgressInfo=true)
HTTP POST (for form data).
Definition: job.cpp:1307
TDEIO::stat
TDEIO_EXPORT StatJob * stat(const KURL &url, bool showProgressInfo=true)
Find all details for one file or directory.
Definition: job.cpp:950
TDEIO::listRecursive
TDEIO_EXPORT ListJob * listRecursive(const KURL &url, bool showProgressInfo=true, bool includeHidden=true)
The same as the previous method, but recurses subdirectories.
Definition: job.cpp:2222
TDEIO::rmdir
TDEIO_EXPORT SimpleJob * rmdir(const KURL &url)
Removes a single directory.
Definition: job.cpp:787
TDEIO::unmount
TDEIO_EXPORT SimpleJob * unmount(const TQString &point, bool showProgressInfo=true)
Unmount filesystem.
Definition: job.cpp:831
TDEIO::mount
TDEIO_EXPORT SimpleJob * mount(bool ro, const char *fstype, const TQString &dev, const TQString &point, bool showProgressInfo=true)
Mount filesystem.
Definition: job.cpp:821

tdeio/tdeio

Skip menu "tdeio/tdeio"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

tdeio/tdeio

Skip menu "tdeio/tdeio"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdeio/tdeio by doxygen 1.9.1
This website is maintained by Timothy Pearson.