00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "netaccess.h"
00024
00025 #include <stdlib.h>
00026 #include <stdio.h>
00027 #include <signal.h>
00028 #include <unistd.h>
00029
00030 #include <cstring>
00031
00032 #include <QtCore/QCharRef>
00033 #include <QtGui/QApplication>
00034 #include <QtCore/QFile>
00035 #include <QtCore/QMetaClassInfo>
00036 #include <QtCore/QTextIStream>
00037
00038 #include <kapplication.h>
00039 #include <klocale.h>
00040 #include <ktemporaryfile.h>
00041 #include <kdebug.h>
00042 #include <kurl.h>
00043 #include <kstandarddirs.h>
00044
00045 #include "job.h"
00046 #include "copyjob.h"
00047 #include "deletejob.h"
00048 #include "jobuidelegate.h"
00049 #include "scheduler.h"
00050
00051 namespace KIO
00052 {
00053 class NetAccessPrivate
00054 {
00055 public:
00056 NetAccessPrivate()
00057 : m_metaData(0)
00058 , bJobOK(true)
00059 {}
00060 UDSEntry m_entry;
00061 QString m_mimetype;
00062 QByteArray m_data;
00063 KUrl m_url;
00064 QMap<QString, QString> *m_metaData;
00065
00069 bool bJobOK;
00070 };
00071
00072 }
00073
00074 using namespace KIO;
00075
00076
00080 static QStringList* tmpfiles;
00081
00082 static QString* lastErrorMsg = 0;
00083 static int lastErrorCode = 0;
00084
00085 NetAccess::NetAccess() :
00086 d( new NetAccessPrivate )
00087 {
00088 }
00089
00090 NetAccess::~NetAccess()
00091 {
00092 delete d;
00093 }
00094
00095 bool NetAccess::download(const KUrl& u, QString & target, QWidget* window)
00096 {
00097 if (u.isLocalFile()) {
00098
00099 target = u.path();
00100 bool accessible = KStandardDirs::checkAccess(target, R_OK);
00101 if(!accessible)
00102 {
00103 if(!lastErrorMsg)
00104 lastErrorMsg = new QString;
00105 *lastErrorMsg = i18n("File '%1' is not readable", target);
00106 lastErrorCode = ERR_COULD_NOT_READ;
00107 }
00108 return accessible;
00109 }
00110
00111 if (target.isEmpty())
00112 {
00113 KTemporaryFile tmpFile;
00114 tmpFile.setAutoRemove(false);
00115 tmpFile.open();
00116 target = tmpFile.fileName();
00117 if (!tmpfiles)
00118 tmpfiles = new QStringList;
00119 tmpfiles->append(target);
00120 }
00121
00122 NetAccess kioNet;
00123 KUrl dest;
00124 dest.setPath( target );
00125 return kioNet.filecopyInternal( u, dest, -1, KIO::Overwrite, window, false );
00126 }
00127
00128 bool NetAccess::upload(const QString& src, const KUrl& target, QWidget* window)
00129 {
00130 if (target.isEmpty())
00131 return false;
00132
00133
00134
00135
00136 if (target.isLocalFile() && target.path() == src)
00137 return true;
00138
00139 NetAccess kioNet;
00140 KUrl s;
00141 s.setPath(src);
00142 return kioNet.filecopyInternal( s, target, -1, KIO::Overwrite, window, false );
00143 }
00144
00145 bool NetAccess::file_copy( const KUrl & src, const KUrl & target, QWidget* window )
00146 {
00147 NetAccess kioNet;
00148 return kioNet.filecopyInternal( src, target, -1, KIO::DefaultFlags,
00149 window, false );
00150 }
00151
00152 bool NetAccess::copy( const KUrl& src, const KUrl& target, QWidget* window )
00153 {
00154 return file_copy( src, target, window );
00155 }
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174 bool NetAccess::dircopy( const KUrl & src, const KUrl & target, QWidget* window )
00175 {
00176 KUrl::List srcList;
00177 srcList.append( src );
00178 return NetAccess::dircopy( srcList, target, window );
00179 }
00180
00181 bool NetAccess::dircopy( const KUrl::List & srcList, const KUrl & target, QWidget* window )
00182 {
00183 NetAccess kioNet;
00184 return kioNet.dircopyInternal( srcList, target, window, false );
00185 }
00186
00187 bool NetAccess::move( const KUrl& src, const KUrl& target, QWidget* window )
00188 {
00189 KUrl::List srcList;
00190 srcList.append( src );
00191 NetAccess kioNet;
00192 return kioNet.dircopyInternal( srcList, target, window, true );
00193 }
00194
00195 bool NetAccess::move( const KUrl::List& srcList, const KUrl& target, QWidget* window )
00196 {
00197 NetAccess kioNet;
00198 return kioNet.dircopyInternal( srcList, target, window, true );
00199 }
00200
00201 bool NetAccess::exists( const KUrl & url, bool source, QWidget* window )
00202 {
00203 if ( url.isLocalFile() )
00204 return QFile::exists( url.path() );
00205 NetAccess kioNet;
00206 return kioNet.statInternal( url, 0 ,
00207 source ? SourceSide : DestinationSide, window );
00208 }
00209
00210 bool NetAccess::exists( const KUrl & url, StatSide side, QWidget* window )
00211 {
00212 if ( url.isLocalFile() )
00213 return QFile::exists( url.path() );
00214 NetAccess kioNet;
00215 return kioNet.statInternal( url, 0 , side, window );
00216 }
00217
00218 bool NetAccess::stat( const KUrl & url, KIO::UDSEntry & entry, QWidget* window )
00219 {
00220 NetAccess kioNet;
00221 bool ret = kioNet.statInternal( url, 2 , SourceSide, window );
00222 if (ret)
00223 entry = kioNet.d->m_entry;
00224 return ret;
00225 }
00226
00227 KUrl NetAccess::mostLocalUrl(const KUrl & url, QWidget* window)
00228 {
00229 if ( url.isLocalFile() )
00230 {
00231 return url;
00232 }
00233
00234 KIO::UDSEntry entry;
00235 if (!stat(url, entry, window))
00236 {
00237 return url;
00238 }
00239
00240 const QString path = entry.stringValue( KIO::UDSEntry::UDS_LOCAL_PATH );
00241 if ( !path.isEmpty() )
00242 {
00243 KUrl new_url;
00244 new_url.setPath(path);
00245 return new_url;
00246 }
00247
00248 return url;
00249 }
00250
00251 bool NetAccess::del( const KUrl & url, QWidget* window )
00252 {
00253 NetAccess kioNet;
00254 return kioNet.delInternal( url, window );
00255 }
00256
00257 bool NetAccess::mkdir( const KUrl & url, QWidget* window, int permissions )
00258 {
00259 NetAccess kioNet;
00260 return kioNet.mkdirInternal( url, permissions, window );
00261 }
00262
00263 QString NetAccess::fish_execute( const KUrl & url, const QString &command, QWidget* window )
00264 {
00265 NetAccess kioNet;
00266 return kioNet.fish_executeInternal( url, command, window );
00267 }
00268
00269 bool NetAccess::synchronousRun( Job* job, QWidget* window, QByteArray* data,
00270 KUrl* finalURL, QMap<QString, QString>* metaData )
00271 {
00272 NetAccess kioNet;
00273
00274
00275 const bool wasAutoDelete = job->isAutoDelete();
00276 job->setAutoDelete(false);
00277 const bool ok = kioNet.synchronousRunInternal(job, window, data, finalURL, metaData);
00278 if (wasAutoDelete) {
00279 job->deleteLater();
00280 }
00281 return ok;
00282 }
00283
00284 QString NetAccess::mimetype( const KUrl& url, QWidget* window )
00285 {
00286 NetAccess kioNet;
00287 return kioNet.mimetypeInternal( url, window );
00288 }
00289
00290 QString NetAccess::lastErrorString()
00291 {
00292 return lastErrorMsg ? *lastErrorMsg : QString();
00293 }
00294
00295 int NetAccess::lastError()
00296 {
00297 return lastErrorCode;
00298 }
00299
00300 void NetAccess::removeTempFile(const QString& name)
00301 {
00302 if (!tmpfiles)
00303 return;
00304 if (tmpfiles->contains(name))
00305 {
00306 unlink(QFile::encodeName(name));
00307 tmpfiles->removeAll(name);
00308 }
00309 }
00310
00311 bool NetAccess::filecopyInternal(const KUrl& src, const KUrl& target, int permissions,
00312 KIO::JobFlags flags, QWidget* window, bool move)
00313 {
00314 d->bJobOK = true;
00315
00316 KIO::Scheduler::checkSlaveOnHold(true);
00317 KIO::Job * job = move
00318 ? KIO::file_move( src, target, permissions, flags )
00319 : KIO::file_copy( src, target, permissions, flags );
00320 job->ui()->setWindow (window);
00321 connect( job, SIGNAL( result (KJob *) ),
00322 this, SLOT( slotResult (KJob *) ) );
00323
00324 enter_loop();
00325 return d->bJobOK;
00326 }
00327
00328 bool NetAccess::dircopyInternal(const KUrl::List& src, const KUrl& target,
00329 QWidget* window, bool move)
00330 {
00331 d->bJobOK = true;
00332
00333 KIO::Job * job = move
00334 ? KIO::move( src, target )
00335 : KIO::copy( src, target );
00336 job->ui()->setWindow (window);
00337 connect( job, SIGNAL( result (KJob *) ),
00338 this, SLOT( slotResult (KJob *) ) );
00339
00340 enter_loop();
00341 return d->bJobOK;
00342 }
00343
00344 bool NetAccess::statInternal( const KUrl & url, int details, StatSide side,
00345 QWidget* window )
00346 {
00347 d->bJobOK = true;
00348 KIO::JobFlags flags = url.isLocalFile() ? KIO::HideProgressInfo : KIO::DefaultFlags;
00349 KIO::StatJob * job = KIO::stat( url, flags );
00350 job->ui()->setWindow (window);
00351 job->setDetails( details );
00352 job->setSide( side == SourceSide ? StatJob::SourceSide : StatJob::DestinationSide );
00353 connect( job, SIGNAL( result (KJob *) ),
00354 this, SLOT( slotResult (KJob *) ) );
00355 enter_loop();
00356 return d->bJobOK;
00357 }
00358
00359 bool NetAccess::delInternal( const KUrl & url, QWidget* window )
00360 {
00361 d->bJobOK = true;
00362 KIO::Job * job = KIO::del( url );
00363 job->ui()->setWindow (window);
00364 connect( job, SIGNAL( result (KJob *) ),
00365 this, SLOT( slotResult (KJob *) ) );
00366 enter_loop();
00367 return d->bJobOK;
00368 }
00369
00370 bool NetAccess::mkdirInternal( const KUrl & url, int permissions,
00371 QWidget* window )
00372 {
00373 d->bJobOK = true;
00374 KIO::Job * job = KIO::mkdir( url, permissions );
00375 job->ui()->setWindow (window);
00376 connect( job, SIGNAL( result (KJob *) ),
00377 this, SLOT( slotResult (KJob *) ) );
00378 enter_loop();
00379 return d->bJobOK;
00380 }
00381
00382 QString NetAccess::mimetypeInternal( const KUrl & url, QWidget* window )
00383 {
00384 d->bJobOK = true;
00385 d->m_mimetype = QLatin1String("unknown");
00386 KIO::Job * job = KIO::mimetype( url );
00387 job->ui()->setWindow (window);
00388 connect( job, SIGNAL( result (KJob *) ),
00389 this, SLOT( slotResult (KJob *) ) );
00390 connect( job, SIGNAL( mimetype (KIO::Job *, const QString &) ),
00391 this, SLOT( slotMimetype (KIO::Job *, const QString &) ) );
00392 enter_loop();
00393 return d->m_mimetype;
00394 }
00395
00396 void NetAccess::slotMimetype( KIO::Job *, const QString & type )
00397 {
00398 d->m_mimetype = type;
00399 }
00400
00401 QString NetAccess::fish_executeInternal(const KUrl & url, const QString &command, QWidget* window)
00402 {
00403 QString target, remoteTempFileName, resultData;
00404 KUrl tempPathUrl;
00405 KTemporaryFile tmpFile;
00406 tmpFile.open();
00407
00408 if( url.protocol() == "fish" )
00409 {
00410
00411 tempPathUrl = url;
00412 remoteTempFileName = tmpFile.fileName();
00413
00414
00415 int pos = remoteTempFileName.lastIndexOf('/');
00416 remoteTempFileName = "/tmp/fishexec_" + remoteTempFileName.mid(pos + 1);
00417 tempPathUrl.setPath( remoteTempFileName );
00418 d->bJobOK = true;
00419 QByteArray packedArgs;
00420 QDataStream stream( &packedArgs, QIODevice::WriteOnly );
00421
00422 stream << int('X') << tempPathUrl << command;
00423
00424 KIO::Job * job = KIO::special( tempPathUrl, packedArgs );
00425 job->ui()->setWindow( window );
00426 connect( job, SIGNAL( result (KJob *) ),
00427 this, SLOT( slotResult (KJob *) ) );
00428 enter_loop();
00429
00430
00431 if( NetAccess::download( tempPathUrl, target, window ) )
00432 {
00433 QFile resultFile( target );
00434
00435 if (resultFile.open( QIODevice::ReadOnly ))
00436 {
00437 QTextStream ts( &resultFile );
00438 resultData = ts.readAll();
00439 resultFile.close();
00440 NetAccess::del( tempPathUrl, window );
00441 }
00442 }
00443 }
00444 else
00445 {
00446 resultData = i18n( "ERROR: Unknown protocol '%1'", url.protocol() );
00447 }
00448 return resultData;
00449 }
00450
00451 bool NetAccess::synchronousRunInternal( Job* job, QWidget* window, QByteArray* data,
00452 KUrl* finalURL, QMap<QString,QString>* metaData )
00453 {
00454 if ( job->ui() ) job->ui()->setWindow( window );
00455
00456 d->m_metaData = metaData;
00457 if ( d->m_metaData ) {
00458 for ( QMap<QString, QString>::iterator it = d->m_metaData->begin(); it != d->m_metaData->end(); ++it ) {
00459 job->addMetaData( it.key(), it.value() );
00460 }
00461 }
00462
00463 if ( finalURL ) {
00464 SimpleJob *sj = qobject_cast<SimpleJob*>( job );
00465 if ( sj ) {
00466 d->m_url = sj->url();
00467 }
00468 }
00469
00470 connect( job, SIGNAL( result (KJob *) ),
00471 this, SLOT( slotResult (KJob *) ) );
00472
00473 const QMetaObject* meta = job->metaObject();
00474
00475 static const char dataSignal[] = "data(KIO::Job*,QByteArray)";
00476 if ( meta->indexOfSignal( dataSignal ) != -1 ) {
00477 connect( job, SIGNAL(data(KIO::Job*,const QByteArray&)),
00478 this, SLOT(slotData(KIO::Job*,const QByteArray&)) );
00479 }
00480
00481 static const char redirSignal[] = "redirection(KIO::Job*,KUrl)";
00482 if ( meta->indexOfSignal( redirSignal ) != -1 ) {
00483 connect( job, SIGNAL(redirection(KIO::Job*,const KUrl&)),
00484 this, SLOT(slotRedirection(KIO::Job*, const KUrl&)) );
00485 }
00486
00487 enter_loop();
00488
00489 if ( finalURL )
00490 *finalURL = d->m_url;
00491 if ( data )
00492 *data = d->m_data;
00493
00494 return d->bJobOK;
00495 }
00496
00497 void NetAccess::enter_loop()
00498 {
00499 QEventLoop eventLoop;
00500 connect(this, SIGNAL(leaveModality()),
00501 &eventLoop, SLOT(quit()));
00502 eventLoop.exec(QEventLoop::ExcludeUserInputEvents);
00503 }
00504
00505 void NetAccess::slotResult( KJob * job )
00506 {
00507 lastErrorCode = job->error();
00508 d->bJobOK = !job->error();
00509 if ( !d->bJobOK )
00510 {
00511 if ( !lastErrorMsg )
00512 lastErrorMsg = new QString;
00513 *lastErrorMsg = job->errorString();
00514 }
00515 KIO::StatJob* statJob = qobject_cast<KIO::StatJob *>( job );
00516 if ( statJob )
00517 d->m_entry = statJob->statResult();
00518
00519 KIO::Job* kioJob = qobject_cast<KIO::Job *>( job );
00520 if ( kioJob && d->m_metaData )
00521 *d->m_metaData = kioJob->metaData();
00522
00523 emit leaveModality();
00524 }
00525
00526 void NetAccess::slotData( KIO::Job*, const QByteArray& data )
00527 {
00528 if ( data.isEmpty() )
00529 return;
00530
00531 unsigned offset = d->m_data.size();
00532 d->m_data.resize( offset + data.size() );
00533 std::memcpy( d->m_data.data() + offset, data.data(), data.size() );
00534 }
00535
00536 void NetAccess::slotRedirection( KIO::Job*, const KUrl& url )
00537 {
00538 d->m_url = url;
00539 }
00540
00541 #include "netaccess.moc"