KIO
netaccess.cpp
Go to the documentation of this file.
00001 /* 00002 This file is part of the KDE libraries 00003 Copyright (C) 1997 Torben Weis (weis@kde.org) 00004 Copyright (C) 1998 Matthias Ettrich (ettrich@kde.org) 00005 Copyright (C) 1999 David Faure (faure@kde.org) 00006 00007 This library is free software; you can redistribute it and/or 00008 modify it under the terms of the GNU Library General Public 00009 License as published by the Free Software Foundation; either 00010 version 2 of the License, or (at your option) any later version. 00011 00012 This library is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 Library General Public License for more details. 00016 00017 You should have received a copy of the GNU Library General Public License 00018 along with this library; see the file COPYING.LIB. If not, write to 00019 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00020 Boston, MA 02110-1301, USA. 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 <klocale.h> 00039 #include <ktemporaryfile.h> 00040 #include <kdebug.h> 00041 #include <kurl.h> 00042 #include <kstandarddirs.h> 00043 00044 #include "job.h" 00045 #include "copyjob.h" 00046 #include "deletejob.h" 00047 #include "jobuidelegate.h" 00048 #include "scheduler.h" 00049 00050 namespace KIO 00051 { 00052 class NetAccessPrivate 00053 { 00054 public: 00055 NetAccessPrivate() 00056 : m_metaData(0) 00057 , bJobOK(true) 00058 {} 00059 UDSEntry m_entry; 00060 QString m_mimetype; 00061 QByteArray m_data; 00062 KUrl m_url; 00063 QMap<QString, QString> *m_metaData; 00064 00068 bool bJobOK; 00069 }; 00070 00071 } // namespace KIO 00072 00073 using namespace KIO; 00074 00075 00079 static QStringList* tmpfiles; 00080 00081 static QString* lastErrorMsg = 0; 00082 static int lastErrorCode = 0; 00083 00084 NetAccess::NetAccess() : 00085 d( new NetAccessPrivate ) 00086 { 00087 } 00088 00089 NetAccess::~NetAccess() 00090 { 00091 delete d; 00092 } 00093 00094 bool NetAccess::download(const KUrl& u, QString & target, QWidget* window) 00095 { 00096 if (u.isLocalFile()) { 00097 // file protocol. We do not need the network 00098 target = u.toLocalFile(); 00099 bool accessible = KStandardDirs::checkAccess(target, R_OK); 00100 if(!accessible) 00101 { 00102 if(!lastErrorMsg) 00103 lastErrorMsg = new QString; 00104 *lastErrorMsg = i18n("File '%1' is not readable", target); 00105 lastErrorCode = ERR_COULD_NOT_READ; 00106 } 00107 return accessible; 00108 } 00109 00110 if (target.isEmpty()) 00111 { 00112 KTemporaryFile tmpFile; 00113 tmpFile.setAutoRemove(false); 00114 tmpFile.open(); 00115 target = tmpFile.fileName(); 00116 if (!tmpfiles) 00117 tmpfiles = new QStringList; 00118 tmpfiles->append(target); 00119 } 00120 00121 NetAccess kioNet; 00122 KUrl dest; 00123 dest.setPath( target ); 00124 return kioNet.filecopyInternal( u, dest, -1, KIO::Overwrite, window, false /*copy*/); 00125 } 00126 00127 bool NetAccess::upload(const QString& src, const KUrl& target, QWidget* window) 00128 { 00129 if (target.isEmpty()) 00130 return false; 00131 00132 // If target is local... well, just copy. This can be useful 00133 // when the client code uses a temp file no matter what. 00134 // Let's make sure it's not the exact same file though 00135 if (target.isLocalFile() && target.toLocalFile() == src) 00136 return true; 00137 00138 NetAccess kioNet; 00139 KUrl s; 00140 s.setPath(src); 00141 return kioNet.filecopyInternal( s, target, -1, KIO::Overwrite, window, false /*copy*/ ); 00142 } 00143 00144 bool NetAccess::file_copy( const KUrl & src, const KUrl & target, QWidget* window ) 00145 { 00146 NetAccess kioNet; 00147 return kioNet.filecopyInternal( src, target, -1, KIO::DefaultFlags, 00148 window, false /*copy*/ ); 00149 } 00150 00151 #ifndef KDE_NO_DEPRECATED 00152 bool NetAccess::copy( const KUrl& src, const KUrl& target, QWidget* window ) 00153 { 00154 return file_copy( src, target, window ); 00155 } 00156 #endif 00157 00158 // bool NetAccess::file_copy( const KUrl& src, const KUrl& target, int permissions, 00159 // bool overwrite, bool resume, QWidget* window ) 00160 // { 00161 // NetAccess kioNet; 00162 // return kioNet.filecopyInternal( src, target, permissions, overwrite, resume, 00163 // window, false /*copy*/ ); 00164 // } 00165 00166 00167 // bool NetAccess::file_move( const KUrl& src, const KUrl& target, int permissions, 00168 // bool overwrite, bool resume, QWidget* window ) 00169 // { 00170 // NetAccess kioNet; 00171 // return kioNet.filecopyInternal( src, target, permissions, overwrite, resume, 00172 // window, true /*move*/ ); 00173 // } 00174 00175 bool NetAccess::dircopy( const KUrl & src, const KUrl & target, QWidget* window ) 00176 { 00177 KUrl::List srcList; 00178 srcList.append( src ); 00179 return NetAccess::dircopy( srcList, target, window ); 00180 } 00181 00182 bool NetAccess::dircopy( const KUrl::List & srcList, const KUrl & target, QWidget* window ) 00183 { 00184 NetAccess kioNet; 00185 return kioNet.dircopyInternal( srcList, target, window, false /*copy*/ ); 00186 } 00187 00188 #ifndef KDE_NO_DEPRECATED 00189 bool NetAccess::move( const KUrl& src, const KUrl& target, QWidget* window ) 00190 { 00191 KUrl::List srcList; 00192 srcList.append( src ); 00193 NetAccess kioNet; 00194 return kioNet.dircopyInternal( srcList, target, window, true /*move*/ ); 00195 } 00196 #endif 00197 00198 #ifndef KDE_NO_DEPRECATED 00199 bool NetAccess::move( const KUrl::List& srcList, const KUrl& target, QWidget* window ) 00200 { 00201 NetAccess kioNet; 00202 return kioNet.dircopyInternal( srcList, target, window, true /*move*/ ); 00203 } 00204 #endif 00205 00206 #ifndef KDE_NO_DEPRECATED 00207 bool NetAccess::exists( const KUrl & url, bool source, QWidget* window ) 00208 { 00209 if ( url.isLocalFile() ) 00210 return QFile::exists( url.toLocalFile() ); 00211 NetAccess kioNet; 00212 return kioNet.statInternal( url, 0 /*no details*/, 00213 source ? SourceSide : DestinationSide, window ); 00214 } 00215 #endif 00216 00217 bool NetAccess::exists( const KUrl & url, StatSide side, QWidget* window ) 00218 { 00219 if ( url.isLocalFile() ) 00220 return QFile::exists( url.toLocalFile() ); 00221 NetAccess kioNet; 00222 return kioNet.statInternal( url, 0 /*no details*/, side, window ); 00223 } 00224 00225 bool NetAccess::stat( const KUrl & url, KIO::UDSEntry & entry, QWidget* window ) 00226 { 00227 NetAccess kioNet; 00228 bool ret = kioNet.statInternal( url, 2 /*all details*/, SourceSide, window ); 00229 if (ret) 00230 entry = kioNet.d->m_entry; 00231 return ret; 00232 } 00233 00234 KUrl NetAccess::mostLocalUrl(const KUrl & url, QWidget* window) 00235 { 00236 if ( url.isLocalFile() ) 00237 { 00238 return url; 00239 } 00240 00241 KIO::UDSEntry entry; 00242 if (!stat(url, entry, window)) 00243 { 00244 return url; 00245 } 00246 00247 const QString path = entry.stringValue( KIO::UDSEntry::UDS_LOCAL_PATH ); 00248 if ( !path.isEmpty() ) 00249 { 00250 KUrl new_url; 00251 new_url.setPath(path); 00252 return new_url; 00253 } 00254 00255 return url; 00256 } 00257 00258 bool NetAccess::del( const KUrl & url, QWidget* window ) 00259 { 00260 NetAccess kioNet; 00261 return kioNet.delInternal( url, window ); 00262 } 00263 00264 bool NetAccess::mkdir( const KUrl & url, QWidget* window, int permissions ) 00265 { 00266 NetAccess kioNet; 00267 return kioNet.mkdirInternal( url, permissions, window ); 00268 } 00269 00270 QString NetAccess::fish_execute( const KUrl & url, const QString &command, QWidget* window ) 00271 { 00272 NetAccess kioNet; 00273 return kioNet.fish_executeInternal( url, command, window ); 00274 } 00275 00276 bool NetAccess::synchronousRun( Job* job, QWidget* window, QByteArray* data, 00277 KUrl* finalURL, QMap<QString, QString>* metaData ) 00278 { 00279 NetAccess kioNet; 00280 // Disable autodeletion until we are back from this event loop (#170963) 00281 // We just have to hope people don't mess with setAutoDelete in slots connected to the job, though. 00282 const bool wasAutoDelete = job->isAutoDelete(); 00283 job->setAutoDelete(false); 00284 const bool ok = kioNet.synchronousRunInternal(job, window, data, finalURL, metaData); 00285 if (wasAutoDelete) { 00286 job->deleteLater(); 00287 } 00288 return ok; 00289 } 00290 00291 QString NetAccess::mimetype( const KUrl& url, QWidget* window ) 00292 { 00293 NetAccess kioNet; 00294 return kioNet.mimetypeInternal( url, window ); 00295 } 00296 00297 QString NetAccess::lastErrorString() 00298 { 00299 return lastErrorMsg ? *lastErrorMsg : QString(); 00300 } 00301 00302 int NetAccess::lastError() 00303 { 00304 return lastErrorCode; 00305 } 00306 00307 void NetAccess::removeTempFile(const QString& name) 00308 { 00309 if (!tmpfiles) 00310 return; 00311 if (tmpfiles->contains(name)) 00312 { 00313 unlink(QFile::encodeName(name)); 00314 tmpfiles->removeAll(name); 00315 } 00316 } 00317 00318 bool NetAccess::filecopyInternal(const KUrl& src, const KUrl& target, int permissions, 00319 KIO::JobFlags flags, QWidget* window, bool move) 00320 { 00321 d->bJobOK = true; // success unless further error occurs 00322 00323 KIO::Scheduler::checkSlaveOnHold(true); 00324 KIO::Job * job = move 00325 ? KIO::file_move( src, target, permissions, flags ) 00326 : KIO::file_copy( src, target, permissions, flags ); 00327 job->ui()->setWindow (window); 00328 connect( job, SIGNAL( result (KJob *) ), 00329 this, SLOT( slotResult (KJob *) ) ); 00330 00331 enter_loop(); 00332 return d->bJobOK; 00333 } 00334 00335 bool NetAccess::dircopyInternal(const KUrl::List& src, const KUrl& target, 00336 QWidget* window, bool move) 00337 { 00338 d->bJobOK = true; // success unless further error occurs 00339 00340 KIO::Job * job = move 00341 ? KIO::move( src, target ) 00342 : KIO::copy( src, target ); 00343 job->ui()->setWindow (window); 00344 connect( job, SIGNAL( result (KJob *) ), 00345 this, SLOT( slotResult (KJob *) ) ); 00346 00347 enter_loop(); 00348 return d->bJobOK; 00349 } 00350 00351 bool NetAccess::statInternal( const KUrl & url, int details, StatSide side, 00352 QWidget* window ) 00353 { 00354 d->bJobOK = true; // success unless further error occurs 00355 KIO::JobFlags flags = url.isLocalFile() ? KIO::HideProgressInfo : KIO::DefaultFlags; 00356 KIO::StatJob * job = KIO::stat( url, flags ); 00357 job->ui()->setWindow (window); 00358 job->setDetails( details ); 00359 job->setSide( side == SourceSide ? StatJob::SourceSide : StatJob::DestinationSide ); 00360 connect( job, SIGNAL( result (KJob *) ), 00361 this, SLOT( slotResult (KJob *) ) ); 00362 enter_loop(); 00363 return d->bJobOK; 00364 } 00365 00366 bool NetAccess::delInternal( const KUrl & url, QWidget* window ) 00367 { 00368 d->bJobOK = true; // success unless further error occurs 00369 KIO::Job * job = KIO::del( url ); 00370 job->ui()->setWindow (window); 00371 connect( job, SIGNAL( result (KJob *) ), 00372 this, SLOT( slotResult (KJob *) ) ); 00373 enter_loop(); 00374 return d->bJobOK; 00375 } 00376 00377 bool NetAccess::mkdirInternal( const KUrl & url, int permissions, 00378 QWidget* window ) 00379 { 00380 d->bJobOK = true; // success unless further error occurs 00381 KIO::Job * job = KIO::mkdir( url, permissions ); 00382 job->ui()->setWindow (window); 00383 connect( job, SIGNAL( result (KJob *) ), 00384 this, SLOT( slotResult (KJob *) ) ); 00385 enter_loop(); 00386 return d->bJobOK; 00387 } 00388 00389 QString NetAccess::mimetypeInternal( const KUrl & url, QWidget* window ) 00390 { 00391 d->bJobOK = true; // success unless further error occurs 00392 d->m_mimetype = QLatin1String("unknown"); 00393 KIO::Job * job = KIO::mimetype( url ); 00394 job->ui()->setWindow (window); 00395 connect( job, SIGNAL( result (KJob *) ), 00396 this, SLOT( slotResult (KJob *) ) ); 00397 connect( job, SIGNAL( mimetype (KIO::Job *, const QString &) ), 00398 this, SLOT( slotMimetype (KIO::Job *, const QString &) ) ); 00399 enter_loop(); 00400 return d->m_mimetype; 00401 } 00402 00403 void NetAccess::slotMimetype( KIO::Job *, const QString & type ) 00404 { 00405 d->m_mimetype = type; 00406 } 00407 00408 QString NetAccess::fish_executeInternal(const KUrl & url, const QString &command, QWidget* window) 00409 { 00410 QString target, remoteTempFileName, resultData; 00411 KUrl tempPathUrl; 00412 KTemporaryFile tmpFile; 00413 tmpFile.open(); 00414 00415 if( url.protocol() == "fish" ) 00416 { 00417 // construct remote temp filename 00418 tempPathUrl = url; 00419 remoteTempFileName = tmpFile.fileName(); 00420 // only need the filename KTempFile adds some KDE specific dirs 00421 // that probably does not exist on the remote side 00422 int pos = remoteTempFileName.lastIndexOf('/'); 00423 remoteTempFileName = "/tmp/fishexec_" + remoteTempFileName.mid(pos + 1); 00424 tempPathUrl.setPath( remoteTempFileName ); 00425 d->bJobOK = true; // success unless further error occurs 00426 QByteArray packedArgs; 00427 QDataStream stream( &packedArgs, QIODevice::WriteOnly ); 00428 00429 stream << int('X') << tempPathUrl << command; 00430 00431 KIO::Job * job = KIO::special( tempPathUrl, packedArgs ); 00432 job->ui()->setWindow( window ); 00433 connect( job, SIGNAL( result (KJob *) ), 00434 this, SLOT( slotResult (KJob *) ) ); 00435 enter_loop(); 00436 00437 // since the KIO::special does not provide feedback we need to download the result 00438 if( NetAccess::download( tempPathUrl, target, window ) ) 00439 { 00440 QFile resultFile( target ); 00441 00442 if (resultFile.open( QIODevice::ReadOnly )) 00443 { 00444 QTextStream ts( &resultFile ); // default encoding is Locale 00445 resultData = ts.readAll(); 00446 resultFile.close(); 00447 NetAccess::del( tempPathUrl, window ); 00448 } 00449 } 00450 } 00451 else 00452 { 00453 resultData = i18n( "ERROR: Unknown protocol '%1'", url.protocol() ); 00454 } 00455 return resultData; 00456 } 00457 00458 bool NetAccess::synchronousRunInternal( Job* job, QWidget* window, QByteArray* data, 00459 KUrl* finalURL, QMap<QString,QString>* metaData ) 00460 { 00461 if ( job->ui() ) job->ui()->setWindow( window ); 00462 00463 d->m_metaData = metaData; 00464 if ( d->m_metaData ) { 00465 for ( QMap<QString, QString>::iterator it = d->m_metaData->begin(); it != d->m_metaData->end(); ++it ) { 00466 job->addMetaData( it.key(), it.value() ); 00467 } 00468 } 00469 00470 if ( finalURL ) { 00471 SimpleJob *sj = qobject_cast<SimpleJob*>( job ); 00472 if ( sj ) { 00473 d->m_url = sj->url(); 00474 } 00475 } 00476 00477 connect( job, SIGNAL( result (KJob *) ), 00478 this, SLOT( slotResult (KJob *) ) ); 00479 00480 const QMetaObject* meta = job->metaObject(); 00481 00482 static const char dataSignal[] = "data(KIO::Job*,QByteArray)"; 00483 if ( meta->indexOfSignal( dataSignal ) != -1 ) { 00484 connect( job, SIGNAL(data(KIO::Job*,const QByteArray&)), 00485 this, SLOT(slotData(KIO::Job*,const QByteArray&)) ); 00486 } 00487 00488 static const char redirSignal[] = "redirection(KIO::Job*,KUrl)"; 00489 if ( meta->indexOfSignal( redirSignal ) != -1 ) { 00490 connect( job, SIGNAL(redirection(KIO::Job*,const KUrl&)), 00491 this, SLOT(slotRedirection(KIO::Job*, const KUrl&)) ); 00492 } 00493 00494 enter_loop(); 00495 00496 if ( finalURL ) 00497 *finalURL = d->m_url; 00498 if ( data ) 00499 *data = d->m_data; 00500 00501 return d->bJobOK; 00502 } 00503 00504 void NetAccess::enter_loop() 00505 { 00506 QEventLoop eventLoop; 00507 connect(this, SIGNAL(leaveModality()), 00508 &eventLoop, SLOT(quit())); 00509 eventLoop.exec(QEventLoop::ExcludeUserInputEvents); 00510 } 00511 00512 void NetAccess::slotResult( KJob * job ) 00513 { 00514 lastErrorCode = job->error(); 00515 d->bJobOK = !job->error(); 00516 if ( !d->bJobOK ) 00517 { 00518 if ( !lastErrorMsg ) 00519 lastErrorMsg = new QString; 00520 *lastErrorMsg = job->errorString(); 00521 } 00522 KIO::StatJob* statJob = qobject_cast<KIO::StatJob *>( job ); 00523 if ( statJob ) 00524 d->m_entry = statJob->statResult(); 00525 00526 KIO::Job* kioJob = qobject_cast<KIO::Job *>( job ); 00527 if ( kioJob && d->m_metaData ) 00528 *d->m_metaData = kioJob->metaData(); 00529 00530 emit leaveModality(); 00531 } 00532 00533 void NetAccess::slotData( KIO::Job*, const QByteArray& data ) 00534 { 00535 if ( data.isEmpty() ) 00536 return; 00537 00538 unsigned offset = d->m_data.size(); 00539 d->m_data.resize( offset + data.size() ); 00540 std::memcpy( d->m_data.data() + offset, data.data(), data.size() ); 00541 } 00542 00543 void NetAccess::slotRedirection( KIO::Job*, const KUrl& url ) 00544 { 00545 d->m_url = url; 00546 } 00547 00548 #include "netaccess.moc"
KDE 4.7 API Reference