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 return kioNet.synchronousRunInternal( job, window, data, finalURL, metaData );
00274 }
00275
00276 QString NetAccess::mimetype( const KUrl& url, QWidget* window )
00277 {
00278 NetAccess kioNet;
00279 return kioNet.mimetypeInternal( url, window );
00280 }
00281
00282 QString NetAccess::lastErrorString()
00283 {
00284 return lastErrorMsg ? *lastErrorMsg : QString();
00285 }
00286
00287 int NetAccess::lastError()
00288 {
00289 return lastErrorCode;
00290 }
00291
00292 void NetAccess::removeTempFile(const QString& name)
00293 {
00294 if (!tmpfiles)
00295 return;
00296 if (tmpfiles->contains(name))
00297 {
00298 unlink(QFile::encodeName(name));
00299 tmpfiles->removeAll(name);
00300 }
00301 }
00302
00303 bool NetAccess::filecopyInternal(const KUrl& src, const KUrl& target, int permissions,
00304 KIO::JobFlags flags, QWidget* window, bool move)
00305 {
00306 d->bJobOK = true;
00307
00308 KIO::Scheduler::checkSlaveOnHold(true);
00309 KIO::Job * job = move
00310 ? KIO::file_move( src, target, permissions, flags )
00311 : KIO::file_copy( src, target, permissions, flags );
00312 job->ui()->setWindow (window);
00313 connect( job, SIGNAL( result (KJob *) ),
00314 this, SLOT( slotResult (KJob *) ) );
00315
00316 enter_loop();
00317 return d->bJobOK;
00318 }
00319
00320 bool NetAccess::dircopyInternal(const KUrl::List& src, const KUrl& target,
00321 QWidget* window, bool move)
00322 {
00323 d->bJobOK = true;
00324
00325 KIO::Job * job = move
00326 ? KIO::move( src, target )
00327 : KIO::copy( src, target );
00328 job->ui()->setWindow (window);
00329 connect( job, SIGNAL( result (KJob *) ),
00330 this, SLOT( slotResult (KJob *) ) );
00331
00332 enter_loop();
00333 return d->bJobOK;
00334 }
00335
00336 bool NetAccess::statInternal( const KUrl & url, int details, StatSide side,
00337 QWidget* window )
00338 {
00339 d->bJobOK = true;
00340 KIO::JobFlags flags = url.isLocalFile() ? KIO::HideProgressInfo : KIO::DefaultFlags;
00341 KIO::StatJob * job = KIO::stat( url, flags );
00342 job->ui()->setWindow (window);
00343 job->setDetails( details );
00344 job->setSide( side == SourceSide ? StatJob::SourceSide : StatJob::DestinationSide );
00345 connect( job, SIGNAL( result (KJob *) ),
00346 this, SLOT( slotResult (KJob *) ) );
00347 enter_loop();
00348 return d->bJobOK;
00349 }
00350
00351 bool NetAccess::delInternal( const KUrl & url, QWidget* window )
00352 {
00353 d->bJobOK = true;
00354 KIO::Job * job = KIO::del( url );
00355 job->ui()->setWindow (window);
00356 connect( job, SIGNAL( result (KJob *) ),
00357 this, SLOT( slotResult (KJob *) ) );
00358 enter_loop();
00359 return d->bJobOK;
00360 }
00361
00362 bool NetAccess::mkdirInternal( const KUrl & url, int permissions,
00363 QWidget* window )
00364 {
00365 d->bJobOK = true;
00366 KIO::Job * job = KIO::mkdir( url, permissions );
00367 job->ui()->setWindow (window);
00368 connect( job, SIGNAL( result (KJob *) ),
00369 this, SLOT( slotResult (KJob *) ) );
00370 enter_loop();
00371 return d->bJobOK;
00372 }
00373
00374 QString NetAccess::mimetypeInternal( const KUrl & url, QWidget* window )
00375 {
00376 d->bJobOK = true;
00377 d->m_mimetype = QLatin1String("unknown");
00378 KIO::Job * job = KIO::mimetype( url );
00379 job->ui()->setWindow (window);
00380 connect( job, SIGNAL( result (KJob *) ),
00381 this, SLOT( slotResult (KJob *) ) );
00382 connect( job, SIGNAL( mimetype (KIO::Job *, const QString &) ),
00383 this, SLOT( slotMimetype (KIO::Job *, const QString &) ) );
00384 enter_loop();
00385 return d->m_mimetype;
00386 }
00387
00388 void NetAccess::slotMimetype( KIO::Job *, const QString & type )
00389 {
00390 d->m_mimetype = type;
00391 }
00392
00393 QString NetAccess::fish_executeInternal(const KUrl & url, const QString &command, QWidget* window)
00394 {
00395 QString target, remoteTempFileName, resultData;
00396 KUrl tempPathUrl;
00397 KTemporaryFile tmpFile;
00398 tmpFile.open();
00399
00400 if( url.protocol() == "fish" )
00401 {
00402
00403 tempPathUrl = url;
00404 remoteTempFileName = tmpFile.fileName();
00405
00406
00407 int pos = remoteTempFileName.lastIndexOf('/');
00408 remoteTempFileName = "/tmp/fishexec_" + remoteTempFileName.mid(pos + 1);
00409 tempPathUrl.setPath( remoteTempFileName );
00410 d->bJobOK = true;
00411 QByteArray packedArgs;
00412 QDataStream stream( &packedArgs, QIODevice::WriteOnly );
00413
00414 stream << int('X') << tempPathUrl << command;
00415
00416 KIO::Job * job = KIO::special( tempPathUrl, packedArgs );
00417 job->ui()->setWindow( window );
00418 connect( job, SIGNAL( result (KJob *) ),
00419 this, SLOT( slotResult (KJob *) ) );
00420 enter_loop();
00421
00422
00423 if( NetAccess::download( tempPathUrl, target, window ) )
00424 {
00425 QFile resultFile( target );
00426
00427 if (resultFile.open( QIODevice::ReadOnly ))
00428 {
00429 QTextStream ts( &resultFile );
00430 resultData = ts.readAll();
00431 resultFile.close();
00432 NetAccess::del( tempPathUrl, window );
00433 }
00434 }
00435 }
00436 else
00437 {
00438 resultData = i18n( "ERROR: Unknown protocol '%1'", url.protocol() );
00439 }
00440 return resultData;
00441 }
00442
00443 bool NetAccess::synchronousRunInternal( Job* job, QWidget* window, QByteArray* data,
00444 KUrl* finalURL, QMap<QString,QString>* metaData )
00445 {
00446 if ( job->ui() ) job->ui()->setWindow( window );
00447
00448 d->m_metaData = metaData;
00449 if ( d->m_metaData ) {
00450 for ( QMap<QString, QString>::iterator it = d->m_metaData->begin(); it != d->m_metaData->end(); ++it ) {
00451 job->addMetaData( it.key(), it.value() );
00452 }
00453 }
00454
00455 if ( finalURL ) {
00456 SimpleJob *sj = qobject_cast<SimpleJob*>( job );
00457 if ( sj ) {
00458 d->m_url = sj->url();
00459 }
00460 }
00461
00462 connect( job, SIGNAL( result (KJob *) ),
00463 this, SLOT( slotResult (KJob *) ) );
00464
00465 const QMetaObject* meta = job->metaObject();
00466
00467 static const char dataSignal[] = "data(KIO::Job*,QByteArray)";
00468 if ( meta->indexOfSignal( dataSignal ) != -1 ) {
00469 connect( job, SIGNAL(data(KIO::Job*,const QByteArray&)),
00470 this, SLOT(slotData(KIO::Job*,const QByteArray&)) );
00471 }
00472
00473 static const char redirSignal[] = "redirection(KIO::Job*,KUrl)";
00474 if ( meta->indexOfSignal( redirSignal ) != -1 ) {
00475 connect( job, SIGNAL(redirection(KIO::Job*,const KUrl&)),
00476 this, SLOT(slotRedirection(KIO::Job*, const KUrl&)) );
00477 }
00478
00479 enter_loop();
00480
00481 if ( finalURL )
00482 *finalURL = d->m_url;
00483 if ( data )
00484 *data = d->m_data;
00485
00486 return d->bJobOK;
00487 }
00488
00489 void NetAccess::enter_loop()
00490 {
00491 QEventLoop eventLoop;
00492 connect(this, SIGNAL(leaveModality()),
00493 &eventLoop, SLOT(quit()));
00494 eventLoop.exec(QEventLoop::ExcludeUserInputEvents);
00495 }
00496
00497 void NetAccess::slotResult( KJob * job )
00498 {
00499 lastErrorCode = job->error();
00500 d->bJobOK = !job->error();
00501 if ( !d->bJobOK )
00502 {
00503 if ( !lastErrorMsg )
00504 lastErrorMsg = new QString;
00505 *lastErrorMsg = job->errorString();
00506 }
00507 KIO::StatJob* statJob = qobject_cast<KIO::StatJob *>( job );
00508 if ( statJob )
00509 d->m_entry = statJob->statResult();
00510
00511 KIO::Job* kioJob = qobject_cast<KIO::Job *>( job );
00512 if ( kioJob && d->m_metaData )
00513 *d->m_metaData = kioJob->metaData();
00514
00515 emit leaveModality();
00516 }
00517
00518 void NetAccess::slotData( KIO::Job*, const QByteArray& data )
00519 {
00520 if ( data.isEmpty() )
00521 return;
00522
00523 unsigned offset = d->m_data.size();
00524 d->m_data.resize( offset + data.size() );
00525 std::memcpy( d->m_data.data() + offset, data.data(), data.size() );
00526 }
00527
00528 void NetAccess::slotRedirection( KIO::Job*, const KUrl& url )
00529 {
00530 d->m_url = url;
00531 }
00532
00533 #include "netaccess.moc"