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

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
  •     tdecore
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  • tdeioslave
  •   http
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdeio/tdeio by doxygen 1.8.8
This website is maintained by Timothy Pearson.