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 <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 } // namespace KIO 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 // file protocol. We do not need the network 00099 target = u.toLocalFile(); 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 /*copy*/); 00126 } 00127 00128 bool NetAccess::upload(const QString& src, const KUrl& target, QWidget* window) 00129 { 00130 if (target.isEmpty()) 00131 return false; 00132 00133 // If target is local... well, just copy. This can be useful 00134 // when the client code uses a temp file no matter what. 00135 // Let's make sure it's not the exact same file though 00136 if (target.isLocalFile() && target.toLocalFile() == 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 /*copy*/ ); 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 /*copy*/ ); 00150 } 00151 00152 #ifndef KDE_NO_DEPRECATED 00153 bool NetAccess::copy( const KUrl& src, const KUrl& target, QWidget* window ) 00154 { 00155 return file_copy( src, target, window ); 00156 } 00157 #endif 00158 00159 // bool NetAccess::file_copy( const KUrl& src, const KUrl& target, int permissions, 00160 // bool overwrite, bool resume, QWidget* window ) 00161 // { 00162 // NetAccess kioNet; 00163 // return kioNet.filecopyInternal( src, target, permissions, overwrite, resume, 00164 // window, false /*copy*/ ); 00165 // } 00166 00167 00168 // bool NetAccess::file_move( const KUrl& src, const KUrl& target, int permissions, 00169 // bool overwrite, bool resume, QWidget* window ) 00170 // { 00171 // NetAccess kioNet; 00172 // return kioNet.filecopyInternal( src, target, permissions, overwrite, resume, 00173 // window, true /*move*/ ); 00174 // } 00175 00176 bool NetAccess::dircopy( const KUrl & src, const KUrl & target, QWidget* window ) 00177 { 00178 KUrl::List srcList; 00179 srcList.append( src ); 00180 return NetAccess::dircopy( srcList, target, window ); 00181 } 00182 00183 bool NetAccess::dircopy( const KUrl::List & srcList, const KUrl & target, QWidget* window ) 00184 { 00185 NetAccess kioNet; 00186 return kioNet.dircopyInternal( srcList, target, window, false /*copy*/ ); 00187 } 00188 00189 #ifndef KDE_NO_DEPRECATED 00190 bool NetAccess::move( const KUrl& src, const KUrl& target, QWidget* window ) 00191 { 00192 KUrl::List srcList; 00193 srcList.append( src ); 00194 NetAccess kioNet; 00195 return kioNet.dircopyInternal( srcList, target, window, true /*move*/ ); 00196 } 00197 #endif 00198 00199 #ifndef KDE_NO_DEPRECATED 00200 bool NetAccess::move( const KUrl::List& srcList, const KUrl& target, QWidget* window ) 00201 { 00202 NetAccess kioNet; 00203 return kioNet.dircopyInternal( srcList, target, window, true /*move*/ ); 00204 } 00205 #endif 00206 00207 #ifndef KDE_NO_DEPRECATED 00208 bool NetAccess::exists( const KUrl & url, bool source, QWidget* window ) 00209 { 00210 if ( url.isLocalFile() ) 00211 return QFile::exists( url.toLocalFile() ); 00212 NetAccess kioNet; 00213 return kioNet.statInternal( url, 0 /*no details*/, 00214 source ? SourceSide : DestinationSide, window ); 00215 } 00216 #endif 00217 00218 bool NetAccess::exists( const KUrl & url, StatSide side, QWidget* window ) 00219 { 00220 if ( url.isLocalFile() ) 00221 return QFile::exists( url.toLocalFile() ); 00222 NetAccess kioNet; 00223 return kioNet.statInternal( url, 0 /*no details*/, side, window ); 00224 } 00225 00226 bool NetAccess::stat( const KUrl & url, KIO::UDSEntry & entry, QWidget* window ) 00227 { 00228 NetAccess kioNet; 00229 bool ret = kioNet.statInternal( url, 2 /*all details*/, SourceSide, window ); 00230 if (ret) 00231 entry = kioNet.d->m_entry; 00232 return ret; 00233 } 00234 00235 KUrl NetAccess::mostLocalUrl(const KUrl & url, QWidget* window) 00236 { 00237 if ( url.isLocalFile() ) 00238 { 00239 return url; 00240 } 00241 00242 KIO::UDSEntry entry; 00243 if (!stat(url, entry, window)) 00244 { 00245 return url; 00246 } 00247 00248 const QString path = entry.stringValue( KIO::UDSEntry::UDS_LOCAL_PATH ); 00249 if ( !path.isEmpty() ) 00250 { 00251 KUrl new_url; 00252 new_url.setPath(path); 00253 return new_url; 00254 } 00255 00256 return url; 00257 } 00258 00259 bool NetAccess::del( const KUrl & url, QWidget* window ) 00260 { 00261 NetAccess kioNet; 00262 return kioNet.delInternal( url, window ); 00263 } 00264 00265 bool NetAccess::mkdir( const KUrl & url, QWidget* window, int permissions ) 00266 { 00267 NetAccess kioNet; 00268 return kioNet.mkdirInternal( url, permissions, window ); 00269 } 00270 00271 QString NetAccess::fish_execute( const KUrl & url, const QString &command, QWidget* window ) 00272 { 00273 NetAccess kioNet; 00274 return kioNet.fish_executeInternal( url, command, window ); 00275 } 00276 00277 bool NetAccess::synchronousRun( Job* job, QWidget* window, QByteArray* data, 00278 KUrl* finalURL, QMap<QString, QString>* metaData ) 00279 { 00280 NetAccess kioNet; 00281 // Disable autodeletion until we are back from this event loop (#170963) 00282 // We just have to hope people don't mess with setAutoDelete in slots connected to the job, though. 00283 const bool wasAutoDelete = job->isAutoDelete(); 00284 job->setAutoDelete(false); 00285 const bool ok = kioNet.synchronousRunInternal(job, window, data, finalURL, metaData); 00286 if (wasAutoDelete) { 00287 job->deleteLater(); 00288 } 00289 return ok; 00290 } 00291 00292 QString NetAccess::mimetype( const KUrl& url, QWidget* window ) 00293 { 00294 NetAccess kioNet; 00295 return kioNet.mimetypeInternal( url, window ); 00296 } 00297 00298 QString NetAccess::lastErrorString() 00299 { 00300 return lastErrorMsg ? *lastErrorMsg : QString(); 00301 } 00302 00303 int NetAccess::lastError() 00304 { 00305 return lastErrorCode; 00306 } 00307 00308 void NetAccess::removeTempFile(const QString& name) 00309 { 00310 if (!tmpfiles) 00311 return; 00312 if (tmpfiles->contains(name)) 00313 { 00314 unlink(QFile::encodeName(name)); 00315 tmpfiles->removeAll(name); 00316 } 00317 } 00318 00319 bool NetAccess::filecopyInternal(const KUrl& src, const KUrl& target, int permissions, 00320 KIO::JobFlags flags, QWidget* window, bool move) 00321 { 00322 d->bJobOK = true; // success unless further error occurs 00323 00324 KIO::Scheduler::checkSlaveOnHold(true); 00325 KIO::Job * job = move 00326 ? KIO::file_move( src, target, permissions, flags ) 00327 : KIO::file_copy( src, target, permissions, flags ); 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::dircopyInternal(const KUrl::List& src, const KUrl& target, 00337 QWidget* window, bool move) 00338 { 00339 d->bJobOK = true; // success unless further error occurs 00340 00341 KIO::Job * job = move 00342 ? KIO::move( src, target ) 00343 : KIO::copy( src, target ); 00344 job->ui()->setWindow (window); 00345 connect( job, SIGNAL( result (KJob *) ), 00346 this, SLOT( slotResult (KJob *) ) ); 00347 00348 enter_loop(); 00349 return d->bJobOK; 00350 } 00351 00352 bool NetAccess::statInternal( const KUrl & url, int details, StatSide side, 00353 QWidget* window ) 00354 { 00355 d->bJobOK = true; // success unless further error occurs 00356 KIO::JobFlags flags = url.isLocalFile() ? KIO::HideProgressInfo : KIO::DefaultFlags; 00357 KIO::StatJob * job = KIO::stat( url, flags ); 00358 job->ui()->setWindow (window); 00359 job->setDetails( details ); 00360 job->setSide( side == SourceSide ? StatJob::SourceSide : StatJob::DestinationSide ); 00361 connect( job, SIGNAL( result (KJob *) ), 00362 this, SLOT( slotResult (KJob *) ) ); 00363 enter_loop(); 00364 return d->bJobOK; 00365 } 00366 00367 bool NetAccess::delInternal( const KUrl & url, QWidget* window ) 00368 { 00369 d->bJobOK = true; // success unless further error occurs 00370 KIO::Job * job = KIO::del( url ); 00371 job->ui()->setWindow (window); 00372 connect( job, SIGNAL( result (KJob *) ), 00373 this, SLOT( slotResult (KJob *) ) ); 00374 enter_loop(); 00375 return d->bJobOK; 00376 } 00377 00378 bool NetAccess::mkdirInternal( const KUrl & url, int permissions, 00379 QWidget* window ) 00380 { 00381 d->bJobOK = true; // success unless further error occurs 00382 KIO::Job * job = KIO::mkdir( url, permissions ); 00383 job->ui()->setWindow (window); 00384 connect( job, SIGNAL( result (KJob *) ), 00385 this, SLOT( slotResult (KJob *) ) ); 00386 enter_loop(); 00387 return d->bJobOK; 00388 } 00389 00390 QString NetAccess::mimetypeInternal( const KUrl & url, QWidget* window ) 00391 { 00392 d->bJobOK = true; // success unless further error occurs 00393 d->m_mimetype = QLatin1String("unknown"); 00394 KIO::Job * job = KIO::mimetype( url ); 00395 job->ui()->setWindow (window); 00396 connect( job, SIGNAL( result (KJob *) ), 00397 this, SLOT( slotResult (KJob *) ) ); 00398 connect( job, SIGNAL( mimetype (KIO::Job *, const QString &) ), 00399 this, SLOT( slotMimetype (KIO::Job *, const QString &) ) ); 00400 enter_loop(); 00401 return d->m_mimetype; 00402 } 00403 00404 void NetAccess::slotMimetype( KIO::Job *, const QString & type ) 00405 { 00406 d->m_mimetype = type; 00407 } 00408 00409 QString NetAccess::fish_executeInternal(const KUrl & url, const QString &command, QWidget* window) 00410 { 00411 QString target, remoteTempFileName, resultData; 00412 KUrl tempPathUrl; 00413 KTemporaryFile tmpFile; 00414 tmpFile.open(); 00415 00416 if( url.protocol() == "fish" ) 00417 { 00418 // construct remote temp filename 00419 tempPathUrl = url; 00420 remoteTempFileName = tmpFile.fileName(); 00421 // only need the filename KTempFile adds some KDE specific dirs 00422 // that probably does not exist on the remote side 00423 int pos = remoteTempFileName.lastIndexOf('/'); 00424 remoteTempFileName = "/tmp/fishexec_" + remoteTempFileName.mid(pos + 1); 00425 tempPathUrl.setPath( remoteTempFileName ); 00426 d->bJobOK = true; // success unless further error occurs 00427 QByteArray packedArgs; 00428 QDataStream stream( &packedArgs, QIODevice::WriteOnly ); 00429 00430 stream << int('X') << tempPathUrl << command; 00431 00432 KIO::Job * job = KIO::special( tempPathUrl, packedArgs ); 00433 job->ui()->setWindow( window ); 00434 connect( job, SIGNAL( result (KJob *) ), 00435 this, SLOT( slotResult (KJob *) ) ); 00436 enter_loop(); 00437 00438 // since the KIO::special does not provide feedback we need to download the result 00439 if( NetAccess::download( tempPathUrl, target, window ) ) 00440 { 00441 QFile resultFile( target ); 00442 00443 if (resultFile.open( QIODevice::ReadOnly )) 00444 { 00445 QTextStream ts( &resultFile ); // default encoding is Locale 00446 resultData = ts.readAll(); 00447 resultFile.close(); 00448 NetAccess::del( tempPathUrl, window ); 00449 } 00450 } 00451 } 00452 else 00453 { 00454 resultData = i18n( "ERROR: Unknown protocol '%1'", url.protocol() ); 00455 } 00456 return resultData; 00457 } 00458 00459 bool NetAccess::synchronousRunInternal( Job* job, QWidget* window, QByteArray* data, 00460 KUrl* finalURL, QMap<QString,QString>* metaData ) 00461 { 00462 if ( job->ui() ) job->ui()->setWindow( window ); 00463 00464 d->m_metaData = metaData; 00465 if ( d->m_metaData ) { 00466 for ( QMap<QString, QString>::iterator it = d->m_metaData->begin(); it != d->m_metaData->end(); ++it ) { 00467 job->addMetaData( it.key(), it.value() ); 00468 } 00469 } 00470 00471 if ( finalURL ) { 00472 SimpleJob *sj = qobject_cast<SimpleJob*>( job ); 00473 if ( sj ) { 00474 d->m_url = sj->url(); 00475 } 00476 } 00477 00478 connect( job, SIGNAL( result (KJob *) ), 00479 this, SLOT( slotResult (KJob *) ) ); 00480 00481 const QMetaObject* meta = job->metaObject(); 00482 00483 static const char dataSignal[] = "data(KIO::Job*,QByteArray)"; 00484 if ( meta->indexOfSignal( dataSignal ) != -1 ) { 00485 connect( job, SIGNAL(data(KIO::Job*,const QByteArray&)), 00486 this, SLOT(slotData(KIO::Job*,const QByteArray&)) ); 00487 } 00488 00489 static const char redirSignal[] = "redirection(KIO::Job*,KUrl)"; 00490 if ( meta->indexOfSignal( redirSignal ) != -1 ) { 00491 connect( job, SIGNAL(redirection(KIO::Job*,const KUrl&)), 00492 this, SLOT(slotRedirection(KIO::Job*, const KUrl&)) ); 00493 } 00494 00495 enter_loop(); 00496 00497 if ( finalURL ) 00498 *finalURL = d->m_url; 00499 if ( data ) 00500 *data = d->m_data; 00501 00502 return d->bJobOK; 00503 } 00504 00505 void NetAccess::enter_loop() 00506 { 00507 QEventLoop eventLoop; 00508 connect(this, SIGNAL(leaveModality()), 00509 &eventLoop, SLOT(quit())); 00510 eventLoop.exec(QEventLoop::ExcludeUserInputEvents); 00511 } 00512 00513 void NetAccess::slotResult( KJob * job ) 00514 { 00515 lastErrorCode = job->error(); 00516 d->bJobOK = !job->error(); 00517 if ( !d->bJobOK ) 00518 { 00519 if ( !lastErrorMsg ) 00520 lastErrorMsg = new QString; 00521 *lastErrorMsg = job->errorString(); 00522 } 00523 KIO::StatJob* statJob = qobject_cast<KIO::StatJob *>( job ); 00524 if ( statJob ) 00525 d->m_entry = statJob->statResult(); 00526 00527 KIO::Job* kioJob = qobject_cast<KIO::Job *>( job ); 00528 if ( kioJob && d->m_metaData ) 00529 *d->m_metaData = kioJob->metaData(); 00530 00531 emit leaveModality(); 00532 } 00533 00534 void NetAccess::slotData( KIO::Job*, const QByteArray& data ) 00535 { 00536 if ( data.isEmpty() ) 00537 return; 00538 00539 unsigned offset = d->m_data.size(); 00540 d->m_data.resize( offset + data.size() ); 00541 std::memcpy( d->m_data.data() + offset, data.data(), data.size() ); 00542 } 00543 00544 void NetAccess::slotRedirection( KIO::Job*, const KUrl& url ) 00545 { 00546 d->m_url = url; 00547 } 00548 00549 #include "netaccess.moc"
KDE 4.6 API Reference