netaccess.cpp
00001 /* $Id: netaccess.cpp 580558 2006-09-03 21:46:23Z osterfeld $ 00002 00003 This file is part of the KDE libraries 00004 Copyright (C) 1997 Torben Weis (weis@kde.org) 00005 Copyright (C) 1998 Matthias Ettrich (ettrich@kde.org) 00006 Copyright (C) 1999 David Faure (faure@kde.org) 00007 00008 This library is free software; you can redistribute it and/or 00009 modify it under the terms of the GNU Library General Public 00010 License as published by the Free Software Foundation; either 00011 version 2 of the License, or (at your option) any later version. 00012 00013 This library is distributed in the hope that it will be useful, 00014 but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 Library General Public License for more details. 00017 00018 You should have received a copy of the GNU Library General Public License 00019 along with this library; see the file COPYING.LIB. If not, write to 00020 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00021 Boston, MA 02110-1301, USA. 00022 */ 00023 00024 #include <stdlib.h> 00025 #include <stdio.h> 00026 #include <signal.h> 00027 #include <unistd.h> 00028 00029 #include <cstring> 00030 00031 #include <qstring.h> 00032 #include <qapplication.h> 00033 #include <qfile.h> 00034 #include <qmetaobject.h> 00035 00036 #include <kapplication.h> 00037 #include <klocale.h> 00038 #include <ktempfile.h> 00039 #include <kdebug.h> 00040 #include <kurl.h> 00041 #include <kio/job.h> 00042 #include <kio/scheduler.h> 00043 00044 #include "kio/netaccess.h" 00045 00046 using namespace KIO; 00047 00048 QString * NetAccess::lastErrorMsg; 00049 int NetAccess::lastErrorCode = 0; 00050 QStringList* NetAccess::tmpfiles; 00051 00052 bool NetAccess::download(const KURL& u, QString & target) 00053 { 00054 return NetAccess::download (u, target, 0); 00055 } 00056 00057 bool NetAccess::download(const KURL& u, QString & target, QWidget* window) 00058 { 00059 if (u.isLocalFile()) { 00060 // file protocol. We do not need the network 00061 target = u.path(); 00062 bool accessible = checkAccess(target, R_OK); 00063 if(!accessible) 00064 { 00065 if(!lastErrorMsg) 00066 lastErrorMsg = new QString; 00067 *lastErrorMsg = i18n("File '%1' is not readable").arg(target); 00068 lastErrorCode = ERR_COULD_NOT_READ; 00069 } 00070 return accessible; 00071 } 00072 00073 if (target.isEmpty()) 00074 { 00075 KTempFile tmpFile; 00076 target = tmpFile.name(); 00077 if (!tmpfiles) 00078 tmpfiles = new QStringList; 00079 tmpfiles->append(target); 00080 } 00081 00082 NetAccess kioNet; 00083 KURL dest; 00084 dest.setPath( target ); 00085 return kioNet.filecopyInternal( u, dest, -1, true /*overwrite*/, 00086 false, window, false /*copy*/); 00087 } 00088 00089 bool NetAccess::upload(const QString& src, const KURL& target) 00090 { 00091 return NetAccess::upload(src, target, 0); 00092 } 00093 00094 bool NetAccess::upload(const QString& src, const KURL& target, QWidget* window) 00095 { 00096 if (target.isEmpty()) 00097 return false; 00098 00099 // If target is local... well, just copy. This can be useful 00100 // when the client code uses a temp file no matter what. 00101 // Let's make sure it's not the exact same file though 00102 if (target.isLocalFile() && target.path() == src) 00103 return true; 00104 00105 NetAccess kioNet; 00106 KURL s; 00107 s.setPath(src); 00108 return kioNet.filecopyInternal( s, target, -1, true /*overwrite*/, 00109 false, window, false /*copy*/ ); 00110 } 00111 00112 bool NetAccess::copy( const KURL & src, const KURL & target ) 00113 { 00114 return NetAccess::file_copy( src, target, -1, false /*not overwrite*/, false, 0L ); 00115 } 00116 00117 bool NetAccess::copy( const KURL & src, const KURL & target, QWidget* window ) 00118 { 00119 return NetAccess::file_copy( src, target, -1, false /*not overwrite*/, false, window ); 00120 } 00121 00122 bool NetAccess::file_copy( const KURL& src, const KURL& target, int permissions, 00123 bool overwrite, bool resume, QWidget* window ) 00124 { 00125 NetAccess kioNet; 00126 return kioNet.filecopyInternal( src, target, permissions, overwrite, resume, 00127 window, false /*copy*/ ); 00128 } 00129 00130 00131 bool NetAccess::file_move( const KURL& src, const KURL& target, int permissions, 00132 bool overwrite, bool resume, QWidget* window ) 00133 { 00134 NetAccess kioNet; 00135 return kioNet.filecopyInternal( src, target, permissions, overwrite, resume, 00136 window, true /*move*/ ); 00137 } 00138 00139 bool NetAccess::dircopy( const KURL & src, const KURL & target ) 00140 { 00141 return NetAccess::dircopy( src, target, 0 ); 00142 } 00143 00144 bool NetAccess::dircopy( const KURL & src, const KURL & target, QWidget* window ) 00145 { 00146 KURL::List srcList; 00147 srcList.append( src ); 00148 return NetAccess::dircopy( srcList, target, window ); 00149 } 00150 00151 bool NetAccess::dircopy( const KURL::List & srcList, const KURL & target, QWidget* window ) 00152 { 00153 NetAccess kioNet; 00154 return kioNet.dircopyInternal( srcList, target, window, false /*copy*/ ); 00155 } 00156 00157 bool NetAccess::move( const KURL& src, const KURL& target, QWidget* window ) 00158 { 00159 KURL::List srcList; 00160 srcList.append( src ); 00161 return NetAccess::move( srcList, target, window ); 00162 } 00163 00164 bool NetAccess::move( const KURL::List& srcList, const KURL& target, QWidget* window ) 00165 { 00166 NetAccess kioNet; 00167 return kioNet.dircopyInternal( srcList, target, window, true /*move*/ ); 00168 } 00169 00170 bool NetAccess::exists( const KURL & url ) 00171 { 00172 return NetAccess::exists( url, false, 0 ); 00173 } 00174 00175 bool NetAccess::exists( const KURL & url, QWidget* window ) 00176 { 00177 return NetAccess::exists( url, false, window ); 00178 } 00179 00180 bool NetAccess::exists( const KURL & url, bool source ) 00181 { 00182 return NetAccess::exists( url, source, 0 ); 00183 } 00184 00185 bool NetAccess::exists( const KURL & url, bool source, QWidget* window ) 00186 { 00187 if ( url.isLocalFile() ) 00188 return QFile::exists( url.path() ); 00189 NetAccess kioNet; 00190 return kioNet.statInternal( url, 0 /*no details*/, source, window ); 00191 } 00192 00193 bool NetAccess::stat( const KURL & url, KIO::UDSEntry & entry ) 00194 { 00195 return NetAccess::stat( url, entry, 0 ); 00196 } 00197 00198 bool NetAccess::stat( const KURL & url, KIO::UDSEntry & entry, QWidget* window ) 00199 { 00200 NetAccess kioNet; 00201 bool ret = kioNet.statInternal( url, 2 /*all details*/, true /*source*/, window ); 00202 if (ret) 00203 entry = kioNet.m_entry; 00204 return ret; 00205 } 00206 00207 KURL NetAccess::mostLocalURL(const KURL & url, QWidget* window) 00208 { 00209 if ( url.isLocalFile() ) 00210 { 00211 return url; 00212 } 00213 00214 KIO::UDSEntry entry; 00215 if (!stat(url, entry, window)) 00216 { 00217 return url; 00218 } 00219 00220 QString path; 00221 00222 // Extract the local path from the KIO::UDSEntry 00223 KIO::UDSEntry::ConstIterator it = entry.begin(); 00224 const KIO::UDSEntry::ConstIterator end = entry.end(); 00225 for ( ; it != end; ++it ) 00226 { 00227 if ( (*it).m_uds == KIO::UDS_LOCAL_PATH ) 00228 { 00229 path = (*it).m_str; 00230 break; 00231 } 00232 } 00233 00234 if ( !path.isEmpty() ) 00235 { 00236 KURL new_url; 00237 new_url.setPath(path); 00238 return new_url; 00239 } 00240 00241 return url; 00242 } 00243 00244 00245 bool NetAccess::del( const KURL & url ) 00246 { 00247 return NetAccess::del( url, 0 ); 00248 } 00249 00250 bool NetAccess::del( const KURL & url, QWidget* window ) 00251 { 00252 NetAccess kioNet; 00253 return kioNet.delInternal( url, window ); 00254 } 00255 00256 bool NetAccess::mkdir( const KURL & url, int permissions ) 00257 { 00258 return NetAccess::mkdir( url, 0, permissions ); 00259 } 00260 00261 bool NetAccess::mkdir( const KURL & url, QWidget* window, int permissions ) 00262 { 00263 NetAccess kioNet; 00264 return kioNet.mkdirInternal( url, permissions, window ); 00265 } 00266 00267 QString NetAccess::fish_execute( const KURL & url, const QString command, QWidget* window ) 00268 { 00269 NetAccess kioNet; 00270 return kioNet.fish_executeInternal( url, command, window ); 00271 } 00272 00273 bool NetAccess::synchronousRun( Job* job, QWidget* window, QByteArray* data, 00274 KURL* finalURL, QMap<QString, QString>* metaData ) 00275 { 00276 NetAccess kioNet; 00277 return kioNet.synchronousRunInternal( job, window, data, finalURL, metaData ); 00278 } 00279 00280 QString NetAccess::mimetype( const KURL& url ) 00281 { 00282 NetAccess kioNet; 00283 return kioNet.mimetypeInternal( url, 0 ); 00284 } 00285 00286 QString NetAccess::mimetype( const KURL& url, QWidget* window ) 00287 { 00288 NetAccess kioNet; 00289 return kioNet.mimetypeInternal( url, window ); 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->remove(name); 00300 } 00301 } 00302 00303 bool NetAccess::filecopyInternal(const KURL& src, const KURL& target, int permissions, 00304 bool overwrite, bool resume, QWidget* window, bool move) 00305 { 00306 bJobOK = true; // success unless further error occurs 00307 00308 KIO::Scheduler::checkSlaveOnHold(true); 00309 KIO::Job * job = move 00310 ? KIO::file_move( src, target, permissions, overwrite, resume ) 00311 : KIO::file_copy( src, target, permissions, overwrite, resume ); 00312 job->setWindow (window); 00313 connect( job, SIGNAL( result (KIO::Job *) ), 00314 this, SLOT( slotResult (KIO::Job *) ) ); 00315 00316 enter_loop(); 00317 return bJobOK; 00318 } 00319 00320 bool NetAccess::dircopyInternal(const KURL::List& src, const KURL& target, 00321 QWidget* window, bool move) 00322 { 00323 bJobOK = true; // success unless further error occurs 00324 00325 KIO::Job * job = move 00326 ? KIO::move( src, target ) 00327 : KIO::copy( src, target ); 00328 job->setWindow (window); 00329 connect( job, SIGNAL( result (KIO::Job *) ), 00330 this, SLOT( slotResult (KIO::Job *) ) ); 00331 00332 enter_loop(); 00333 return bJobOK; 00334 } 00335 00336 bool NetAccess::statInternal( const KURL & url, int details, bool source, 00337 QWidget* window ) 00338 { 00339 bJobOK = true; // success unless further error occurs 00340 KIO::StatJob * job = KIO::stat( url, !url.isLocalFile() ); 00341 job->setWindow (window); 00342 job->setDetails( details ); 00343 job->setSide( source ); 00344 connect( job, SIGNAL( result (KIO::Job *) ), 00345 this, SLOT( slotResult (KIO::Job *) ) ); 00346 enter_loop(); 00347 return bJobOK; 00348 } 00349 00350 bool NetAccess::delInternal( const KURL & url, QWidget* window ) 00351 { 00352 bJobOK = true; // success unless further error occurs 00353 KIO::Job * job = KIO::del( url ); 00354 job->setWindow (window); 00355 connect( job, SIGNAL( result (KIO::Job *) ), 00356 this, SLOT( slotResult (KIO::Job *) ) ); 00357 enter_loop(); 00358 return bJobOK; 00359 } 00360 00361 bool NetAccess::mkdirInternal( const KURL & url, int permissions, 00362 QWidget* window ) 00363 { 00364 bJobOK = true; // success unless further error occurs 00365 KIO::Job * job = KIO::mkdir( url, permissions ); 00366 job->setWindow (window); 00367 connect( job, SIGNAL( result (KIO::Job *) ), 00368 this, SLOT( slotResult (KIO::Job *) ) ); 00369 enter_loop(); 00370 return bJobOK; 00371 } 00372 00373 QString NetAccess::mimetypeInternal( const KURL & url, QWidget* window ) 00374 { 00375 bJobOK = true; // success unless further error occurs 00376 m_mimetype = QString::fromLatin1("unknown"); 00377 KIO::Job * job = KIO::mimetype( url ); 00378 job->setWindow (window); 00379 connect( job, SIGNAL( result (KIO::Job *) ), 00380 this, SLOT( slotResult (KIO::Job *) ) ); 00381 connect( job, SIGNAL( mimetype (KIO::Job *, const QString &) ), 00382 this, SLOT( slotMimetype (KIO::Job *, const QString &) ) ); 00383 enter_loop(); 00384 return m_mimetype; 00385 } 00386 00387 void NetAccess::slotMimetype( KIO::Job *, const QString & type ) 00388 { 00389 m_mimetype = type; 00390 } 00391 00392 QString NetAccess::fish_executeInternal(const KURL & url, const QString command, QWidget* window) 00393 { 00394 QString target, remoteTempFileName, resultData; 00395 KURL tempPathUrl; 00396 KTempFile tmpFile; 00397 tmpFile.setAutoDelete( true ); 00398 00399 if( url.protocol() == "fish" ) 00400 { 00401 // construct remote temp filename 00402 tempPathUrl = url; 00403 remoteTempFileName = tmpFile.name(); 00404 // only need the filename KTempFile adds some KDE specific dirs 00405 // that probably does not exist on the remote side 00406 int pos = remoteTempFileName.findRev('/'); 00407 remoteTempFileName = "/tmp/fishexec_" + remoteTempFileName.mid(pos + 1); 00408 tempPathUrl.setPath( remoteTempFileName ); 00409 bJobOK = true; // success unless further error occurs 00410 QByteArray packedArgs; 00411 QDataStream stream( packedArgs, IO_WriteOnly ); 00412 00413 stream << int('X') << tempPathUrl << command; 00414 00415 KIO::Job * job = KIO::special( tempPathUrl, packedArgs, true ); 00416 job->setWindow( window ); 00417 connect( job, SIGNAL( result (KIO::Job *) ), 00418 this, SLOT( slotResult (KIO::Job *) ) ); 00419 enter_loop(); 00420 00421 // since the KIO::special does not provide feedback we need to download the result 00422 if( NetAccess::download( tempPathUrl, target, window ) ) 00423 { 00424 QFile resultFile( target ); 00425 00426 if (resultFile.open( IO_ReadOnly )) 00427 { 00428 QTextStream ts( &resultFile ); 00429 ts.setEncoding( QTextStream::Locale ); // Locale?? 00430 resultData = ts.read(); 00431 resultFile.close(); 00432 NetAccess::del( tempPathUrl, window ); 00433 } 00434 } 00435 } 00436 else 00437 { 00438 resultData = i18n( "ERROR: Unknown protocol '%1'" ).arg( 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 job->setWindow( window ); 00447 00448 m_metaData = metaData; 00449 if ( m_metaData ) { 00450 for ( QMap<QString, QString>::iterator it = m_metaData->begin(); it != m_metaData->end(); ++it ) { 00451 job->addMetaData( it.key(), it.data() ); 00452 } 00453 } 00454 00455 if ( finalURL ) { 00456 SimpleJob *sj = dynamic_cast<SimpleJob*>( job ); 00457 if ( sj ) { 00458 m_url = sj->url(); 00459 } 00460 } 00461 00462 connect( job, SIGNAL( result (KIO::Job *) ), 00463 this, SLOT( slotResult (KIO::Job *) ) ); 00464 00465 QMetaObject *meta = job->metaObject(); 00466 00467 static const char dataSignal[] = "data(KIO::Job*,const QByteArray&)"; 00468 if ( meta->findSignal( 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*,const KURL&)"; 00474 if ( meta->findSignal( 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 = m_url; 00483 if ( data ) 00484 *data = m_data; 00485 00486 return bJobOK; 00487 } 00488 00489 // If a troll sees this, he kills me 00490 void qt_enter_modal( QWidget *widget ); 00491 void qt_leave_modal( QWidget *widget ); 00492 00493 void NetAccess::enter_loop() 00494 { 00495 QWidget dummy(0,0,WType_Dialog | WShowModal); 00496 dummy.setFocusPolicy( QWidget::NoFocus ); 00497 qt_enter_modal(&dummy); 00498 qApp->enter_loop(); 00499 qt_leave_modal(&dummy); 00500 } 00501 00502 void NetAccess::slotResult( KIO::Job * job ) 00503 { 00504 lastErrorCode = job->error(); 00505 bJobOK = !job->error(); 00506 if ( !bJobOK ) 00507 { 00508 if ( !lastErrorMsg ) 00509 lastErrorMsg = new QString; 00510 *lastErrorMsg = job->errorString(); 00511 } 00512 if ( job->isA("KIO::StatJob") ) 00513 m_entry = static_cast<KIO::StatJob *>(job)->statResult(); 00514 00515 if ( m_metaData ) 00516 *m_metaData = job->metaData(); 00517 00518 qApp->exit_loop(); 00519 } 00520 00521 void NetAccess::slotData( KIO::Job*, const QByteArray& data ) 00522 { 00523 if ( data.isEmpty() ) 00524 return; 00525 00526 unsigned offset = m_data.size(); 00527 m_data.resize( offset + data.size() ); 00528 std::memcpy( m_data.data() + offset, data.data(), data.size() ); 00529 } 00530 00531 void NetAccess::slotRedirection( KIO::Job*, const KURL& url ) 00532 { 00533 m_url = url; 00534 } 00535 00536 #include "netaccess.moc"