• Skip to content
  • Skip to link menu
KDE 4.3 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

KIO

slavebase.cpp

Go to the documentation of this file.
00001 /*
00002  *  This file is part of the KDE libraries
00003  *  Copyright (c) 2000 Waldo Bastian <bastian@kde.org>
00004  *  Copyright (c) 2000 David Faure <faure@kde.org>
00005  *  Copyright (c) 2000 Stephan Kulow <coolo@kde.org>
00006  *  Copyright (c) 2007 Thiago Macieira <thiago@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 version 2 as published by the Free Software Foundation.
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 
00024 #include "slavebase.h"
00025 
00026 #include <config.h>
00027 
00028 #include <sys/time.h>
00029 
00030 #include <kdebug.h>
00031 #include <stdlib.h>
00032 #include <errno.h>
00033 #include <unistd.h>
00034 #include <signal.h>
00035 #include <time.h>
00036 
00037 #include <QtCore/QFile>
00038 #include <QtCore/QList>
00039 #include <QtCore/QDateTime>
00040 
00041 #include <kapplication.h>
00042 #include <kcrash.h>
00043 #include <kconfig.h>
00044 #include <kconfiggroup.h>
00045 #include <kde_file.h>
00046 #include <kdesu/client.h>
00047 #include <klocale.h>
00048 
00049 #include "kremoteencoding.h"
00050 
00051 #include "connection.h"
00052 #include "ioslave_defaults.h"
00053 #include "slaveinterface.h"
00054 #include "kpasswdserver_p.h"
00055 
00056 #ifndef NDEBUG
00057 #ifdef HAVE_BACKTRACE
00058 #include <execinfo.h>
00059 #endif
00060 #endif
00061 
00062 extern "C" {
00063     static void sigsegv_handler(int sig);
00064     static void sigpipe_handler(int sig);
00065 }
00066 
00067 using namespace KIO;
00068 
00069 typedef QList<QByteArray> AuthKeysList;
00070 typedef QMap<QString,QByteArray> AuthKeysMap;
00071 #define KIO_DATA QByteArray data; QDataStream stream( &data, QIODevice::WriteOnly ); stream
00072 #define KIO_FILESIZE_T(x) quint64(x)
00073 
00074 namespace KIO {
00075 
00076 class SlaveBasePrivate {
00077 public:
00078     SlaveBase* q;
00079     SlaveBasePrivate(SlaveBase* owner): q(owner) {}
00080 
00081     UDSEntryList pendingListEntries;
00082     int listEntryCurrentSize;
00083     long listEntry_sec, listEntry_usec;
00084     Connection appConnection;
00085     QString poolSocket;
00086     bool isConnectedToApp;
00087     static qlonglong s_seqNr;
00088 
00089     QString slaveid;
00090     bool resume:1;
00091     bool needSendCanResume:1;
00092     bool onHold:1;
00093     bool wasKilled:1;
00094     bool inOpenLoop:1;
00095     bool exit_loop:1;
00096     MetaData configData;
00097     KConfig *config;
00098     KConfigGroup *configGroup;
00099     KUrl onHoldUrl;
00100 
00101     struct timeval last_tv;
00102     KIO::filesize_t totalSize;
00103     KIO::filesize_t sentListEntries;
00104     KRemoteEncoding *remotefile;
00105     time_t timeout;
00106     enum { Idle, InsideMethod, FinishedCalled, ErrorCalled } m_state;
00107     QByteArray timeoutData;
00108 
00109     // Reconstructs configGroup from configData and mIncomingMetaData
00110     void rebuildConfig()
00111     {
00112         configGroup->deleteGroup(KConfigGroup::WriteConfigFlags());
00113 
00114         // mIncomingMetaData cascades over config, so we write config first,
00115         // to let it be overwritten
00116         MetaData::ConstIterator end = configData.constEnd();
00117         for (MetaData::ConstIterator it = configData.constBegin(); it != end; ++it)
00118             configGroup->writeEntry(it.key(), it->toUtf8(), KConfigGroup::WriteConfigFlags());
00119 
00120         end = q->mIncomingMetaData.constEnd();
00121         for (MetaData::ConstIterator it = q->mIncomingMetaData.constBegin(); it != end; ++it)
00122             configGroup->writeEntry(it.key(), it->toUtf8(), KConfigGroup::WriteConfigFlags());
00123     }
00124 
00125     void verifyState(const char* cmdName)
00126     {
00127         if ((m_state != FinishedCalled) && (m_state != ErrorCalled)){
00128             kWarning(7019) << cmdName << "did not call finished() or error()! Please fix the KIO slave.";
00129         }
00130     }
00131     void verifyErrorFinishedNotCalled(const char* cmdName)
00132     {
00133         if (m_state == FinishedCalled || m_state == ErrorCalled) {
00134             kWarning(7019) << cmdName << "called finished() or error(), but it's not supposed to! Please fix the KIO slave.";
00135         }
00136     }
00137 };
00138 
00139 }
00140 
00141 static SlaveBase *globalSlave;
00142 qlonglong SlaveBasePrivate::s_seqNr;
00143 
00144 static volatile bool slaveWriteError = false;
00145 
00146 static const char *s_protocol;
00147 
00148 #ifdef Q_OS_UNIX
00149 extern "C" {
00150 static void genericsig_handler(int sigNumber)
00151 {
00152    KDE_signal(sigNumber,SIG_IGN);
00153    //WABA: Don't do anything that requires malloc, we can deadlock on it since
00154    //a SIGTERM signal can come in while we are in malloc/free.
00155    //kDebug()<<"kioslave : exiting due to signal "<<sigNumber;
00156    //set the flag which will be checked in dispatchLoop() and which *should* be checked
00157    //in lengthy operations in the various slaves
00158    if (globalSlave!=0)
00159       globalSlave->setKillFlag();
00160    KDE_signal(SIGALRM,SIG_DFL);
00161    alarm(5);  //generate an alarm signal in 5 seconds, in this time the slave has to exit
00162 }
00163 }
00164 #endif
00165 
00167 
00168 SlaveBase::SlaveBase( const QByteArray &protocol,
00169                       const QByteArray &pool_socket,
00170                       const QByteArray &app_socket )
00171     : mProtocol(protocol),
00172       d(new SlaveBasePrivate(this))
00173 
00174 {
00175     d->poolSocket = QFile::decodeName(pool_socket);
00176     s_protocol = protocol.data();
00177 #ifdef Q_OS_UNIX
00178     if (qgetenv("KDE_DEBUG").isEmpty())
00179     {
00180         KCrash::setCrashHandler( sigsegv_handler );
00181         KDE_signal(SIGILL,&sigsegv_handler);
00182         KDE_signal(SIGTRAP,&sigsegv_handler);
00183         KDE_signal(SIGABRT,&sigsegv_handler);
00184         KDE_signal(SIGBUS,&sigsegv_handler);
00185         KDE_signal(SIGALRM,&sigsegv_handler);
00186         KDE_signal(SIGFPE,&sigsegv_handler);
00187 #ifdef SIGPOLL
00188         KDE_signal(SIGPOLL, &sigsegv_handler);
00189 #endif
00190 #ifdef SIGSYS
00191         KDE_signal(SIGSYS, &sigsegv_handler);
00192 #endif
00193 #ifdef SIGVTALRM
00194         KDE_signal(SIGVTALRM, &sigsegv_handler);
00195 #endif
00196 #ifdef SIGXCPU
00197         KDE_signal(SIGXCPU, &sigsegv_handler);
00198 #endif
00199 #ifdef SIGXFSZ
00200         KDE_signal(SIGXFSZ, &sigsegv_handler);
00201 #endif
00202     }
00203 
00204     struct sigaction act;
00205     act.sa_handler = sigpipe_handler;
00206     sigemptyset( &act.sa_mask );
00207     act.sa_flags = 0;
00208     sigaction( SIGPIPE, &act, 0 );
00209 
00210     KDE_signal(SIGINT,&genericsig_handler);
00211     KDE_signal(SIGQUIT,&genericsig_handler);
00212     KDE_signal(SIGTERM,&genericsig_handler);
00213 #endif
00214 
00215     globalSlave=this;
00216 
00217     d->listEntryCurrentSize = 100;
00218     struct timeval tp;
00219     gettimeofday(&tp, 0);
00220     d->listEntry_sec = tp.tv_sec;
00221     d->listEntry_usec = tp.tv_usec;
00222     d->isConnectedToApp = true;
00223 
00224     // by kahl for netmgr (need a way to identify slaves)
00225     d->slaveid = protocol;
00226     d->slaveid += QString::number(getpid());
00227     d->resume = false;
00228     d->needSendCanResume = false;
00229     d->config = new KConfig(QString(), KConfig::SimpleConfig);
00230     // The KConfigGroup needs the KConfig to exist during its whole lifetime.
00231     d->configGroup = new KConfigGroup(d->config, QString());
00232     d->onHold = false;
00233     d->wasKilled=false;
00234     d->last_tv.tv_sec = 0;
00235     d->last_tv.tv_usec = 0;
00236 //    d->processed_size = 0;
00237     d->totalSize=0;
00238     d->sentListEntries=0;
00239     d->timeout = 0;
00240     connectSlave(QFile::decodeName(app_socket));
00241 
00242     d->remotefile = 0;
00243     d->inOpenLoop = false;
00244     d->exit_loop = false;
00245 }
00246 
00247 SlaveBase::~SlaveBase()
00248 {
00249     delete d->configGroup;
00250     delete d->config;
00251     delete d;
00252     s_protocol = "";
00253 }
00254 
00255 void SlaveBase::dispatchLoop()
00256 {
00257     while (!d->exit_loop) {
00258         if (d->timeout && (d->timeout < time(0))) {
00259             QByteArray data = d->timeoutData;
00260             d->timeout = 0;
00261             d->timeoutData = QByteArray();
00262             special(data);
00263         }
00264 
00265         Q_ASSERT(d->appConnection.inited());
00266 
00267         int ms = -1;
00268         if (d->timeout)
00269             ms = 1000 * qMax<time_t>(d->timeout - time(0), 1);
00270 
00271         int ret = -1;
00272         if (d->appConnection.hasTaskAvailable() || d->appConnection.waitForIncomingTask(ms)) {
00273             // dispatch application messages
00274             int cmd;
00275             QByteArray data;
00276             ret = d->appConnection.read(&cmd, data);
00277 
00278             if (ret != -1) {
00279                 if (d->inOpenLoop)
00280                     dispatchOpenCommand(cmd, data);
00281                 else
00282                     dispatch(cmd, data);
00283             }
00284         } else {
00285             ret = d->appConnection.isConnected() ? 0 : -1;
00286         }
00287 
00288         if (ret == -1) { // some error occurred, perhaps no more application
00289             // When the app exits, should the slave be put back in the pool ?
00290             if (!d->exit_loop && d->isConnectedToApp && !d->poolSocket.isEmpty()) {
00291                 disconnectSlave();
00292                 d->isConnectedToApp = false;
00293                 closeConnection();
00294                 connectSlave(d->poolSocket);
00295             } else {
00296                 return;
00297             }
00298         }
00299 
00300         //I think we get here when we were killed in dispatch() and not in select()
00301         if (wasKilled()) {
00302             kDebug(7019)<<" dispatchLoop() slave was killed, returning";
00303             return;
00304         }
00305     }
00306 }
00307 
00308 void SlaveBase::connectSlave(const QString &address)
00309 {
00310     d->appConnection.connectToRemote(address);
00311 
00312     if (!d->appConnection.inited())
00313     {
00314         kDebug(7019) << "SlaveBase: failed to connect to" << address << endl
00315               << "Reason:" << d->appConnection.errorString();
00316         exit();
00317         return;
00318     }
00319 
00320     d->inOpenLoop = false;
00321 }
00322 
00323 void SlaveBase::disconnectSlave()
00324 {
00325     d->appConnection.close();
00326 }
00327 
00328 void SlaveBase::setMetaData(const QString &key, const QString &value)
00329 {
00330     mOutgoingMetaData.insert(key, value); // replaces existing key if already there
00331 }
00332 
00333 QString SlaveBase::metaData(const QString &key) const
00334 {
00335    if (mIncomingMetaData.contains(key))
00336       return mIncomingMetaData[key];
00337    if (d->configData.contains(key))
00338       return d->configData[key];
00339    return QString();
00340 }
00341 
00342 MetaData SlaveBase::allMetaData() const
00343 {
00344     return mIncomingMetaData;
00345 }
00346 
00347 bool SlaveBase::hasMetaData(const QString &key) const
00348 {
00349    if (mIncomingMetaData.contains(key))
00350       return true;
00351    if (d->configData.contains(key))
00352       return true;
00353    return false;
00354 }
00355 
00356 KConfigGroup *SlaveBase::config()
00357 {
00358    return d->configGroup;
00359 }
00360 
00361 void SlaveBase::sendMetaData()
00362 {
00363     sendAndKeepMetaData();
00364     mOutgoingMetaData.clear();
00365 }
00366 
00367 void SlaveBase::sendAndKeepMetaData()
00368 {
00369     if (!mOutgoingMetaData.isEmpty()) {
00370         KIO_DATA << mOutgoingMetaData;
00371 
00372         send(INF_META_DATA, data);
00373     }
00374 }
00375 
00376 KRemoteEncoding *SlaveBase::remoteEncoding()
00377 {
00378    if (d->remotefile != 0)
00379       return d->remotefile;
00380 
00381    QByteArray charset = metaData("Charset").toLatin1();
00382    return d->remotefile = new KRemoteEncoding( charset );
00383 }
00384 
00385 void SlaveBase::data( const QByteArray &data )
00386 {
00387    sendMetaData();
00388    send( MSG_DATA, data );
00389 }
00390 
00391 void SlaveBase::dataReq( )
00392 {
00393    //sendMetaData();
00394    if (d->needSendCanResume)
00395       canResume(0);
00396    send( MSG_DATA_REQ );
00397 }
00398 
00399 void SlaveBase::opened()
00400 {
00401    sendMetaData();
00402    send( MSG_OPENED );
00403    d->inOpenLoop = true;
00404 }
00405 
00406 void SlaveBase::error( int _errid, const QString &_text )
00407 {
00408     if (d->m_state == d->ErrorCalled) {
00409         kWarning(7019) << "error() called twice! Please fix the KIO slave.";
00410         return;
00411     } else if (d->m_state == d->FinishedCalled) {
00412         kWarning(7019) << "error() called after finished()! Please fix the KIO slave.";
00413         return;
00414     }
00415 
00416     d->m_state = d->ErrorCalled;
00417     mIncomingMetaData.clear(); // Clear meta data
00418     d->rebuildConfig();
00419     mOutgoingMetaData.clear();
00420     KIO_DATA << (qint32) _errid << _text;
00421 
00422     send( MSG_ERROR, data );
00423     //reset
00424     d->listEntryCurrentSize = 100;
00425     d->sentListEntries=0;
00426     d->totalSize=0;
00427     d->inOpenLoop=false;
00428 }
00429 
00430 void SlaveBase::connected()
00431 {
00432     send( MSG_CONNECTED );
00433 }
00434 
00435 void SlaveBase::finished()
00436 {
00437     if (d->m_state == d->FinishedCalled) {
00438         kWarning(7019) << "finished() called twice! Please fix the KIO slave.";
00439         return;
00440     } else if (d->m_state == d->ErrorCalled) {
00441         kWarning(7019) << "finished() called after error()! Please fix the KIO slave.";
00442         return;
00443     }
00444 
00445     d->m_state = d->FinishedCalled;
00446     mIncomingMetaData.clear(); // Clear meta data
00447     d->rebuildConfig();
00448     sendMetaData();
00449     send( MSG_FINISHED );
00450 
00451     // reset
00452     d->listEntryCurrentSize = 100;
00453     d->sentListEntries=0;
00454     d->totalSize=0;
00455     d->inOpenLoop=false;
00456 }
00457 
00458 void SlaveBase::needSubUrlData()
00459 {
00460     send( MSG_NEED_SUBURL_DATA );
00461 }
00462 
00463 /*
00464  * Map pid_t to a signed integer type that makes sense for QByteArray;
00465  * only the most common sizes 16 bit and 32 bit are special-cased.
00466  */
00467 template<int T> struct PIDType { typedef pid_t PID_t; } ;
00468 template<> struct PIDType<2> { typedef qint16 PID_t; } ;
00469 template<> struct PIDType<4> { typedef qint32 PID_t; } ;
00470 
00471 void SlaveBase::slaveStatus( const QString &host, bool connected )
00472 {
00473     pid_t pid = getpid();
00474     qint8 b = connected ? 1 : 0;
00475     KIO_DATA << (PIDType<sizeof(pid_t)>::PID_t)pid << mProtocol << host << b;
00476     if (d->onHold)
00477        stream << d->onHoldUrl;
00478     send( MSG_SLAVE_STATUS, data );
00479 }
00480 
00481 void SlaveBase::canResume()
00482 {
00483     send( MSG_CANRESUME );
00484 }
00485 
00486 void SlaveBase::totalSize( KIO::filesize_t _bytes )
00487 {
00488     KIO_DATA << KIO_FILESIZE_T(_bytes);
00489     send( INF_TOTAL_SIZE, data );
00490 
00491     //this one is usually called before the first item is listed in listDir()
00492     struct timeval tp;
00493     gettimeofday(&tp, 0);
00494     d->listEntry_sec = tp.tv_sec;
00495     d->listEntry_usec = tp.tv_usec;
00496     d->totalSize=_bytes;
00497     d->sentListEntries=0;
00498 }
00499 
00500 void SlaveBase::processedSize( KIO::filesize_t _bytes )
00501 {
00502     bool           emitSignal=false;
00503     struct timeval tv;
00504     int            gettimeofday_res=gettimeofday( &tv, 0L );
00505 
00506     if( _bytes == d->totalSize )
00507         emitSignal=true;
00508     else if ( gettimeofday_res == 0 ) {
00509         time_t msecdiff = 2000;
00510         if (d->last_tv.tv_sec) {
00511             // Compute difference, in ms
00512             msecdiff = 1000 * ( tv.tv_sec - d->last_tv.tv_sec );
00513             time_t usecdiff = tv.tv_usec - d->last_tv.tv_usec;
00514             if ( usecdiff < 0 ) {
00515                 msecdiff--;
00516                 msecdiff += 1000;
00517             }
00518             msecdiff += usecdiff / 1000;
00519         }
00520         emitSignal=msecdiff >= 100; // emit size 10 times a second
00521     }
00522 
00523     if( emitSignal ) {
00524         KIO_DATA << KIO_FILESIZE_T(_bytes);
00525         send( INF_PROCESSED_SIZE, data );
00526         if ( gettimeofday_res == 0 ) {
00527             d->last_tv.tv_sec = tv.tv_sec;
00528             d->last_tv.tv_usec = tv.tv_usec;
00529         }
00530     }
00531 //    d->processed_size = _bytes;
00532 }
00533 
00534 void SlaveBase::written( KIO::filesize_t _bytes )
00535 {
00536     KIO_DATA << KIO_FILESIZE_T(_bytes);
00537     send( MSG_WRITTEN, data );
00538 }
00539 
00540 void SlaveBase::position( KIO::filesize_t _pos )
00541 {
00542     KIO_DATA << KIO_FILESIZE_T(_pos);
00543     send( INF_POSITION, data );
00544 }
00545 
00546 void SlaveBase::processedPercent( float /* percent */ )
00547 {
00548   kDebug(7019) << "STUB";
00549 }
00550 
00551 
00552 void SlaveBase::speed( unsigned long _bytes_per_second )
00553 {
00554     KIO_DATA << (quint32) _bytes_per_second;
00555     send( INF_SPEED, data );
00556 }
00557 
00558 void SlaveBase::redirection( const KUrl& _url )
00559 {
00560     KIO_DATA << _url;
00561     send( INF_REDIRECTION, data );
00562 }
00563 
00564 void SlaveBase::errorPage()
00565 {
00566     send( INF_ERROR_PAGE );
00567 }
00568 
00569 static bool isSubCommand(int cmd)
00570 {
00571    return ( (cmd == CMD_REPARSECONFIGURATION) ||
00572             (cmd == CMD_META_DATA) ||
00573             (cmd == CMD_CONFIG) ||
00574             (cmd == CMD_SUBURL) ||
00575             (cmd == CMD_SLAVE_STATUS) ||
00576             (cmd == CMD_SLAVE_CONNECT) ||
00577             (cmd == CMD_SLAVE_HOLD) ||
00578             (cmd == CMD_MULTI_GET));
00579 }
00580 
00581 void SlaveBase::mimeType( const QString &_type)
00582 {
00583   // kDebug(7019) << "(" << getpid() << ")" << _type;
00584   int cmd;
00585   do
00586   {
00587     // Send the meta-data each time we send the mime-type.
00588     if (!mOutgoingMetaData.isEmpty())
00589     {
00590       // kDebug(7019) << "(" << getpid() << ") mimeType: emitting meta data";
00591       KIO_DATA << mOutgoingMetaData;
00592       send( INF_META_DATA, data );
00593     }
00594     KIO_DATA << _type;
00595     send( INF_MIME_TYPE, data );
00596     while(true)
00597     {
00598        cmd = 0;
00599        int ret = -1;
00600        if (d->appConnection.hasTaskAvailable() || d->appConnection.waitForIncomingTask(-1)) {
00601            ret = d->appConnection.read( &cmd, data );
00602        }
00603        if (ret == -1) {
00604            kDebug(7019) << "SlaveBase: mimetype: read error";
00605            exit();
00606            return;
00607        }
00608        // kDebug(7019) << "(" << getpid() << ") Slavebase: mimetype got " << cmd;
00609        if ( cmd == CMD_HOST) // Ignore.
00610           continue;
00611        if (!isSubCommand(cmd))
00612           break;
00613 
00614        dispatch( cmd, data );
00615     }
00616   }
00617   while (cmd != CMD_NONE);
00618   mOutgoingMetaData.clear();
00619 }
00620 
00621 void SlaveBase::exit()
00622 {
00623     d->exit_loop = true;
00624     // Using ::exit() here is too much (crashes in qdbus's qglobalstatic object),
00625     // so let's cleanly exit dispatchLoop() instead.
00626     // Update: we do need to call exit(), otherwise a long download (get()) would
00627     // keep going until it ends, even though the application exited.
00628     ::exit(255);
00629 }
00630 
00631 void SlaveBase::warning( const QString &_msg)
00632 {
00633     KIO_DATA << _msg;
00634     send( INF_WARNING, data );
00635 }
00636 
00637 void SlaveBase::infoMessage( const QString &_msg)
00638 {
00639     KIO_DATA << _msg;
00640     send( INF_INFOMESSAGE, data );
00641 }
00642 
00643 bool SlaveBase::requestNetwork(const QString& host)
00644 {
00645     KIO_DATA << host << d->slaveid;
00646     send( MSG_NET_REQUEST, data );
00647 
00648     if ( waitForAnswer( INF_NETWORK_STATUS, 0, data ) != -1 )
00649     {
00650         bool status;
00651         QDataStream stream( data );
00652         stream >> status;
00653         return status;
00654     } else
00655         return false;
00656 }
00657 
00658 void SlaveBase::dropNetwork(const QString& host)
00659 {
00660     KIO_DATA << host << d->slaveid;
00661     send( MSG_NET_DROP, data );
00662 }
00663 
00664 void SlaveBase::statEntry( const UDSEntry& entry )
00665 {
00666     KIO_DATA << entry;
00667     send( MSG_STAT_ENTRY, data );
00668 }
00669 
00670 void SlaveBase::listEntry( const UDSEntry& entry, bool _ready )
00671 {
00672    static struct timeval tp;
00673    static const int maximum_updatetime = 300;
00674    static const int minimum_updatetime = 100;
00675 
00676    if (!_ready) {
00677       d->pendingListEntries.append(entry);
00678 
00679       if (d->pendingListEntries.count() > d->listEntryCurrentSize) {
00680          gettimeofday(&tp, 0);
00681 
00682          long diff = ((tp.tv_sec - d->listEntry_sec) * 1000000 +
00683                       tp.tv_usec - d->listEntry_usec) / 1000;
00684          if (diff==0) diff=1;
00685 
00686          if (diff > maximum_updatetime) {
00687             d->listEntryCurrentSize = d->listEntryCurrentSize * 3 / 4;
00688             _ready = true;
00689          }
00690 //if we can send all list entries of this dir which have not yet been sent
00691 //within maximum_updatetime, then make d->listEntryCurrentSize big enough for all of them
00692          else if (((d->pendingListEntries.count()*maximum_updatetime)/diff) > static_cast<long>(d->totalSize-d->sentListEntries))
00693             d->listEntryCurrentSize=d->totalSize-d->sentListEntries+1;
00694 //if we are below minimum_updatetime, estimate how much we will get within
00695 //maximum_updatetime
00696          else if (diff < minimum_updatetime)
00697             d->listEntryCurrentSize = (d->pendingListEntries.count() * maximum_updatetime) / diff;
00698          else
00699             _ready=true;
00700       }
00701    }
00702    if (_ready) { // may happen when we started with !ready
00703       listEntries( d->pendingListEntries );
00704       d->pendingListEntries.clear();
00705 
00706       gettimeofday(&tp, 0);
00707       d->listEntry_sec = tp.tv_sec;
00708       d->listEntry_usec = tp.tv_usec;
00709    }
00710 }
00711 
00712 void SlaveBase::listEntries( const UDSEntryList& list )
00713 {
00714     KIO_DATA << (quint32)list.count();
00715     UDSEntryList::ConstIterator it = list.begin();
00716     const UDSEntryList::ConstIterator end = list.end();
00717     for (; it != end; ++it)
00718       stream << *it;
00719     send( MSG_LIST_ENTRIES, data);
00720     d->sentListEntries+=(uint)list.count();
00721 }
00722 
00723 static void sigsegv_handler(int sig)
00724 {
00725 #ifdef Q_OS_UNIX
00726     KDE_signal(sig,SIG_DFL); // Next one kills
00727 
00728     //Kill us if we deadlock
00729     KDE_signal(SIGALRM,SIG_DFL);
00730     alarm(5);  //generate an alarm signal in 5 seconds, in this time the slave has to exit
00731 
00732     // Debug and printf should be avoided because they might
00733     // call malloc.. and get in a nice recursive malloc loop
00734     char buffer[120];
00735     qsnprintf(buffer, sizeof(buffer), "kioslave: ####### CRASH ###### protocol = %s pid = %d signal = %d\n", s_protocol, getpid(), sig);
00736     write(2, buffer, strlen(buffer));
00737 #ifndef NDEBUG
00738 #ifdef HAVE_BACKTRACE
00739     void* trace[256];
00740     int n = backtrace(trace, 256);
00741     if (n)
00742       backtrace_symbols_fd(trace, n, 2);
00743 #endif
00744 #endif
00745     ::exit(1);
00746 #endif
00747 }
00748 
00749 static void sigpipe_handler (int)
00750 {
00751     // We ignore a SIGPIPE in slaves.
00752     // A SIGPIPE can happen in two cases:
00753     // 1) Communication error with application.
00754     // 2) Communication error with network.
00755     slaveWriteError = true;
00756 
00757     // Don't add anything else here, especially no debug output
00758 }
00759 
00760 void SlaveBase::setHost(QString const &, quint16, QString const &, QString const &)
00761 {
00762 }
00763 
00764 void SlaveBase::openConnection(void)
00765 { error(  ERR_UNSUPPORTED_ACTION, unsupportedActionErrorString(mProtocol, CMD_CONNECT)); }
00766 void SlaveBase::closeConnection(void)
00767 { } // No response!
00768 void SlaveBase::stat(KUrl const &)
00769 { error(  ERR_UNSUPPORTED_ACTION, unsupportedActionErrorString(mProtocol, CMD_STAT)); }
00770 void SlaveBase::put(KUrl const &, int, JobFlags )
00771 { error(  ERR_UNSUPPORTED_ACTION, unsupportedActionErrorString(mProtocol, CMD_PUT)); }
00772 void SlaveBase::special(const QByteArray &)
00773 { error(  ERR_UNSUPPORTED_ACTION, unsupportedActionErrorString(mProtocol, CMD_SPECIAL)); }
00774 void SlaveBase::listDir(KUrl const &)
00775 { error(  ERR_UNSUPPORTED_ACTION, unsupportedActionErrorString(mProtocol, CMD_LISTDIR)); }
00776 void SlaveBase::get(KUrl const & )
00777 { error(  ERR_UNSUPPORTED_ACTION, unsupportedActionErrorString(mProtocol, CMD_GET)); }
00778 void SlaveBase::open(KUrl const &, QIODevice::OpenMode)
00779 { error(  ERR_UNSUPPORTED_ACTION, unsupportedActionErrorString(mProtocol, CMD_OPEN)); }
00780 void SlaveBase::read(KIO::filesize_t)
00781 { error(  ERR_UNSUPPORTED_ACTION, unsupportedActionErrorString(mProtocol, CMD_READ)); }
00782 void SlaveBase::write(const QByteArray &)
00783 { error(  ERR_UNSUPPORTED_ACTION, unsupportedActionErrorString(mProtocol, CMD_WRITE)); }
00784 void SlaveBase::seek(KIO::filesize_t)
00785 { error(  ERR_UNSUPPORTED_ACTION, unsupportedActionErrorString(mProtocol, CMD_SEEK)); }
00786 void SlaveBase::close()
00787 { error(  ERR_UNSUPPORTED_ACTION, unsupportedActionErrorString(mProtocol, CMD_CLOSE)); }
00788 void SlaveBase::mimetype(KUrl const &url)
00789 { get(url); }
00790 void SlaveBase::rename(KUrl const &, KUrl const &, JobFlags)
00791 { error(  ERR_UNSUPPORTED_ACTION, unsupportedActionErrorString(mProtocol, CMD_RENAME)); }
00792 void SlaveBase::symlink(QString const &, KUrl const &, JobFlags)
00793 { error(  ERR_UNSUPPORTED_ACTION, unsupportedActionErrorString(mProtocol, CMD_SYMLINK)); }
00794 void SlaveBase::copy(KUrl const &, KUrl const &, int, JobFlags)
00795 { error(  ERR_UNSUPPORTED_ACTION, unsupportedActionErrorString(mProtocol, CMD_COPY)); }
00796 void SlaveBase::del(KUrl const &, bool)
00797 { error(  ERR_UNSUPPORTED_ACTION, unsupportedActionErrorString(mProtocol, CMD_DEL)); }
00798 void SlaveBase::setLinkDest(const KUrl &, const QString&)
00799 { error(  ERR_UNSUPPORTED_ACTION, unsupportedActionErrorString(mProtocol, CMD_SETLINKDEST)); }
00800 void SlaveBase::mkdir(KUrl const &, int)
00801 { error(  ERR_UNSUPPORTED_ACTION, unsupportedActionErrorString(mProtocol, CMD_MKDIR)); }
00802 void SlaveBase::chmod(KUrl const &, int)
00803 { error(  ERR_UNSUPPORTED_ACTION, unsupportedActionErrorString(mProtocol, CMD_CHMOD)); }
00804 void SlaveBase::setModificationTime(KUrl const &, const QDateTime&)
00805 { error(  ERR_UNSUPPORTED_ACTION, unsupportedActionErrorString(mProtocol, CMD_SETMODIFICATIONTIME)); }
00806 void SlaveBase::chown(KUrl const &, const QString &, const QString &)
00807 { error(  ERR_UNSUPPORTED_ACTION, unsupportedActionErrorString(mProtocol, CMD_CHOWN)); }
00808 void SlaveBase::setSubUrl(KUrl const &)
00809 { error(  ERR_UNSUPPORTED_ACTION, unsupportedActionErrorString(mProtocol, CMD_SUBURL)); }
00810 void SlaveBase::multiGet(const QByteArray &)
00811 { error(  ERR_UNSUPPORTED_ACTION, unsupportedActionErrorString(mProtocol, CMD_MULTI_GET)); }
00812 
00813 
00814 void SlaveBase::slave_status()
00815 { slaveStatus( QString(), false ); }
00816 
00817 void SlaveBase::reparseConfiguration()
00818 {
00819 }
00820 
00821 bool SlaveBase::openPasswordDialog( AuthInfo& info, const QString &errorMsg )
00822 {
00823     const long windowId = metaData("window-id").toLong();
00824     const unsigned long userTimestamp = metaData("user-timestamp").toULong();
00825     QString errorMessage;
00826     if (metaData("no-auth-prompt").toLower() == "true") {
00827         errorMessage = QLatin1String("<NoAuthPrompt>");
00828     } else {
00829         errorMessage = errorMsg;
00830     }
00831 
00832     KPasswdServer srv;
00833     qlonglong seqNr = srv.queryAuthInfo(info, errorMessage, windowId,
00834                                         SlaveBasePrivate::s_seqNr, userTimestamp);
00835     if (seqNr > 0) {
00836         SlaveBasePrivate::s_seqNr = seqNr;
00837         if (info.isModified()) {
00838             return true;
00839         }
00840     }
00841 
00842     return false;
00843 }
00844 
00845 int SlaveBase::messageBox( MessageBoxType type, const QString &text, const QString &caption,
00846                            const QString &buttonYes, const QString &buttonNo )
00847 {
00848     return messageBox( text, type, caption, buttonYes, buttonNo, QString() );
00849 }
00850 
00851 int SlaveBase::messageBox( const QString &text, MessageBoxType type, const QString &caption,
00852                            const QString &buttonYes, const QString &buttonNo,
00853                            const QString &dontAskAgainName )
00854 {
00855     kDebug(7019) << "messageBox " << type << " " << text << " - " << caption << buttonYes << buttonNo;
00856     KIO_DATA << (qint32)type << text << caption << buttonYes << buttonNo << dontAskAgainName;
00857     send( INF_MESSAGEBOX, data );
00858     if ( waitForAnswer( CMD_MESSAGEBOXANSWER, 0, data ) != -1 )
00859     {
00860         QDataStream stream( data );
00861         int answer;
00862         stream >> answer;
00863         kDebug(7019) << "got messagebox answer" << answer;
00864         return answer;
00865     } else
00866         return 0; // communication failure
00867 }
00868 
00869 bool SlaveBase::canResume( KIO::filesize_t offset )
00870 {
00871     kDebug(7019) << "offset=" << KIO::number(offset);
00872     d->needSendCanResume = false;
00873     KIO_DATA << KIO_FILESIZE_T(offset);
00874     send( MSG_RESUME, data );
00875     if ( offset )
00876     {
00877         int cmd;
00878         if ( waitForAnswer( CMD_RESUMEANSWER, CMD_NONE, data, &cmd ) != -1 )
00879         {
00880             kDebug(7019) << "returning" << (cmd == CMD_RESUMEANSWER);
00881             return cmd == CMD_RESUMEANSWER;
00882         } else
00883             return false;
00884     }
00885     else // No resuming possible -> no answer to wait for
00886         return true;
00887 }
00888 
00889 
00890 
00891 int SlaveBase::waitForAnswer( int expected1, int expected2, QByteArray & data, int *pCmd )
00892 {
00893     int cmd, result = -1;
00894     for (;;)
00895     {
00896         if (d->appConnection.hasTaskAvailable() || d->appConnection.waitForIncomingTask(-1)) {
00897             result = d->appConnection.read( &cmd, data );
00898         }
00899         if (result == -1) {
00900             kDebug(7019) << "read error.";
00901             return -1;
00902         }
00903 
00904         if ( cmd == expected1 || cmd == expected2 )
00905         {
00906             if ( pCmd ) *pCmd = cmd;
00907             return result;
00908         }
00909         if ( isSubCommand(cmd) )
00910         {
00911             dispatch( cmd, data );
00912         }
00913         else
00914         {
00915             kWarning(7019) << "Got cmd " << cmd << " while waiting for an answer!";
00916         }
00917     }
00918 }
00919 
00920 
00921 int SlaveBase::readData( QByteArray &buffer)
00922 {
00923    int result = waitForAnswer( MSG_DATA, 0, buffer );
00924    //kDebug(7019) << "readData: length = " << result << " ";
00925    return result;
00926 }
00927 
00928 void SlaveBase::setTimeoutSpecialCommand(int timeout, const QByteArray &data)
00929 {
00930    if (timeout > 0)
00931       d->timeout = time(0)+(time_t)timeout;
00932    else if (timeout == 0)
00933       d->timeout = 1; // Immediate timeout
00934    else
00935       d->timeout = 0; // Canceled
00936 
00937    d->timeoutData = data;
00938 }
00939 
00940 void SlaveBase::dispatch( int command, const QByteArray &data )
00941 {
00942     QDataStream stream( data );
00943 
00944     KUrl url;
00945     int i;
00946 
00947     switch( command ) {
00948     case CMD_HOST: {
00949         // Reset s_seqNr, see kpasswdserver/DESIGN
00950         SlaveBasePrivate::s_seqNr = 0;
00951         QString passwd;
00952         QString host, user;
00953         quint16 port;
00954         stream >> host >> port >> user >> passwd;
00955         d->m_state = d->InsideMethod;
00956         setHost( host, port, user, passwd );
00957         d->verifyErrorFinishedNotCalled("setHost()");
00958         d->m_state = d->Idle;
00959     } break;
00960     case CMD_CONNECT: {
00961         openConnection( );
00962     } break;
00963     case CMD_DISCONNECT: {
00964         closeConnection( );
00965     } break;
00966     case CMD_SLAVE_STATUS: {
00967         d->m_state = d->InsideMethod;
00968         slave_status();
00969         // TODO verify that the slave has called slaveStatus()?
00970         d->verifyErrorFinishedNotCalled("slave_status()");
00971         d->m_state = d->Idle;
00972     } break;
00973     case CMD_SLAVE_CONNECT: {
00974         d->onHold = false;
00975         QString app_socket;
00976         QDataStream stream( data );
00977         stream >> app_socket;
00978         d->appConnection.send( MSG_SLAVE_ACK );
00979         disconnectSlave();
00980         d->isConnectedToApp = true;
00981         connectSlave(app_socket);
00982     } break;
00983     case CMD_SLAVE_HOLD: {
00984         KUrl url;
00985         QDataStream stream( data );
00986         stream >> url;
00987         d->onHoldUrl = url;
00988         d->onHold = true;
00989         disconnectSlave();
00990         d->isConnectedToApp = false;
00991         // Do not close connection!
00992         connectSlave(d->poolSocket);
00993     } break;
00994     case CMD_REPARSECONFIGURATION: {
00995         d->m_state = d->InsideMethod;
00996         reparseConfiguration();
00997         d->verifyErrorFinishedNotCalled("reparseConfiguration()");
00998         d->m_state = d->Idle;
00999     } break;
01000     case CMD_CONFIG: {
01001         stream >> d->configData;
01002         d->rebuildConfig();
01003 #if 0 //TODO: decide what to do in KDE 4.1
01004         KSocks::setConfig(d->configGroup);
01005 #endif
01006         delete d->remotefile;
01007         d->remotefile = 0;
01008     } break;
01009     case CMD_GET: {
01010         stream >> url;
01011         d->m_state = d->InsideMethod;
01012         get( url );
01013         d->verifyState("get()");
01014         d->m_state = d->Idle;
01015     } break;
01016     case CMD_OPEN: {
01017         stream >> url >> i;
01018         QIODevice::OpenMode mode = QFlag(i);
01019         d->m_state = d->InsideMethod;
01020         open(url, mode); //krazy:exclude=syscalls
01021         d->m_state = d->Idle;
01022     } break;
01023     case CMD_PUT: {
01024         int permissions;
01025         qint8 iOverwrite, iResume;
01026         stream >> url >> iOverwrite >> iResume >> permissions;
01027         JobFlags flags;
01028         if ( iOverwrite != 0 ) flags |= Overwrite;
01029         if ( iResume != 0 ) flags |= Resume;
01030 
01031         // Remember that we need to send canResume(), TransferJob is expecting
01032         // it. Well, in theory this shouldn't be done if resume is true.
01033         //   (the resume bool is currently unused)
01034         d->needSendCanResume = true   /* !resume */;
01035 
01036         d->m_state = d->InsideMethod;
01037         put( url, permissions, flags);
01038         d->verifyState("put()");
01039         d->m_state = d->Idle;
01040     } break;
01041     case CMD_STAT: {
01042         stream >> url;
01043         d->m_state = d->InsideMethod;
01044         stat( url ); //krazy:exclude=syscalls
01045         d->verifyState("stat()");
01046         d->m_state = d->Idle;
01047     } break;
01048     case CMD_MIMETYPE: {
01049         stream >> url;
01050         d->m_state = d->InsideMethod;
01051         mimetype( url );
01052         d->verifyState("mimetype()");
01053         d->m_state = d->Idle;
01054     } break;
01055     case CMD_LISTDIR: {
01056         stream >> url;
01057         d->m_state = d->InsideMethod;
01058         listDir( url );
01059         d->verifyState("listDir()");
01060         d->m_state = d->Idle;
01061     } break;
01062     case CMD_MKDIR: {
01063         stream >> url >> i;
01064         d->m_state = d->InsideMethod;
01065         mkdir( url, i ); //krazy:exclude=syscalls
01066         d->verifyState("mkdir()");
01067         d->m_state = d->Idle;
01068     } break;
01069     case CMD_RENAME: {
01070         qint8 iOverwrite;
01071         KUrl url2;
01072         stream >> url >> url2 >> iOverwrite;
01073         JobFlags flags;
01074         if ( iOverwrite != 0 ) flags |= Overwrite;
01075         d->m_state = d->InsideMethod;
01076         rename( url, url2, flags ); //krazy:exclude=syscalls
01077         d->verifyState("rename()");
01078         d->m_state = d->Idle;
01079     } break;
01080     case CMD_SYMLINK: {
01081         qint8 iOverwrite;
01082         QString target;
01083         stream >> target >> url >> iOverwrite;
01084         JobFlags flags;
01085         if ( iOverwrite != 0 ) flags |= Overwrite;
01086         d->m_state = d->InsideMethod;
01087         symlink( target, url, flags );
01088         d->verifyState("symlink()");
01089         d->m_state = d->Idle;
01090     } break;
01091     case CMD_COPY: {
01092         int permissions;
01093         qint8 iOverwrite;
01094         KUrl url2;
01095         stream >> url >> url2 >> permissions >> iOverwrite;
01096         JobFlags flags;
01097         if ( iOverwrite != 0 ) flags |= Overwrite;
01098         d->m_state = d->InsideMethod;
01099         copy( url, url2, permissions, flags );
01100         d->verifyState("copy()");
01101         d->m_state = d->Idle;
01102     } break;
01103     case CMD_DEL: {
01104         qint8 isFile;
01105         stream >> url >> isFile;
01106         d->m_state = d->InsideMethod;
01107         del( url, isFile != 0);
01108         d->verifyState("del()");
01109         d->m_state = d->Idle;
01110     } break;
01111     case CMD_CHMOD: {
01112         stream >> url >> i;
01113         d->m_state = d->InsideMethod;
01114         chmod( url, i);
01115         d->verifyState("chmod()");
01116         d->m_state = d->Idle;
01117     } break;
01118     case CMD_CHOWN: {
01119         QString owner, group;
01120         stream >> url >> owner >> group;
01121         d->m_state = d->InsideMethod;
01122         chown(url, owner, group);
01123         d->verifyState("chown()");
01124         d->m_state = d->Idle;
01125     } break;
01126     case CMD_SETMODIFICATIONTIME: {
01127         QDateTime dt;
01128         stream >> url >> dt;
01129         d->m_state = d->InsideMethod;
01130         setModificationTime(url, dt);
01131         d->verifyState("setModificationTime()");
01132         d->m_state = d->Idle;
01133     } break;
01134     case CMD_SPECIAL: {
01135         d->m_state = d->InsideMethod;
01136         special( data );
01137         d->verifyState("special()");
01138         d->m_state = d->Idle;
01139     } break;
01140     case CMD_META_DATA: {
01141         //kDebug(7019) << "(" << getpid() << ") Incoming meta-data...";
01142         stream >> mIncomingMetaData;
01143         d->rebuildConfig();
01144     } break;
01145     case CMD_SUBURL: {
01146         stream >> url;
01147         d->m_state = d->InsideMethod;
01148         setSubUrl(url);
01149         d->verifyErrorFinishedNotCalled("setSubUrl()");
01150         d->m_state = d->Idle;
01151     } break;
01152     case CMD_NONE: {
01153         kWarning(7019) << "Got unexpected CMD_NONE!";
01154     } break;
01155     case CMD_MULTI_GET: {
01156         d->m_state = d->InsideMethod;
01157         multiGet( data );
01158         d->verifyState("multiGet()");
01159         d->m_state = d->Idle;
01160     } break;
01161     default: {
01162         // Some command we don't understand.
01163         // Just ignore it, it may come from some future version of KDE.
01164     } break;
01165     }
01166 }
01167 
01168 bool SlaveBase::checkCachedAuthentication( AuthInfo& info )
01169 {
01170     return KPasswdServer().checkAuthInfo(info, metaData("window-id").toLong(),
01171                                          metaData("user-timestamp").toULong());
01172 }
01173 
01174 void SlaveBase::dispatchOpenCommand( int command, const QByteArray &data )
01175 {
01176     QDataStream stream( data );
01177 
01178     switch( command ) {
01179     case CMD_READ: {
01180         KIO::filesize_t bytes;
01181         stream >> bytes;
01182         read(bytes);
01183         break;
01184     }
01185     case CMD_WRITE: {
01186         write(data);
01187         break;
01188     }
01189     case CMD_SEEK: {
01190         KIO::filesize_t offset;
01191         stream >> offset;
01192         seek(offset);
01193     }
01194     case CMD_NONE:
01195         break;
01196     case CMD_CLOSE:
01197         close();                // must call finish(), which will set d->inOpenLoop=false
01198         break;
01199     default:
01200         // Some command we don't understand.
01201         // Just ignore it, it may come from some future version of KDE.
01202         break;
01203     }
01204 }
01205 
01206 bool SlaveBase::cacheAuthentication( const AuthInfo& info )
01207 {
01208     KPasswdServer().addAuthInfo(info, metaData("window-id").toLongLong());
01209     return true;
01210 }
01211 
01212 int SlaveBase::connectTimeout()
01213 {
01214     bool ok;
01215     QString tmp = metaData("ConnectTimeout");
01216     int result = tmp.toInt(&ok);
01217     if (ok)
01218        return result;
01219     return DEFAULT_CONNECT_TIMEOUT;
01220 }
01221 
01222 int SlaveBase::proxyConnectTimeout()
01223 {
01224     bool ok;
01225     QString tmp = metaData("ProxyConnectTimeout");
01226     int result = tmp.toInt(&ok);
01227     if (ok)
01228        return result;
01229     return DEFAULT_PROXY_CONNECT_TIMEOUT;
01230 }
01231 
01232 
01233 int SlaveBase::responseTimeout()
01234 {
01235     bool ok;
01236     QString tmp = metaData("ResponseTimeout");
01237     int result = tmp.toInt(&ok);
01238     if (ok)
01239        return result;
01240     return DEFAULT_RESPONSE_TIMEOUT;
01241 }
01242 
01243 
01244 int SlaveBase::readTimeout()
01245 {
01246     bool ok;
01247     QString tmp = metaData("ReadTimeout");
01248     int result = tmp.toInt(&ok);
01249     if (ok)
01250        return result;
01251     return DEFAULT_READ_TIMEOUT;
01252 }
01253 
01254 bool SlaveBase::wasKilled() const
01255 {
01256    return d->wasKilled;
01257 }
01258 
01259 void SlaveBase::setKillFlag()
01260 {
01261    d->wasKilled=true;
01262 }
01263 
01264 void SlaveBase::send(int cmd, const QByteArray& arr )
01265 {
01266    slaveWriteError = false;
01267    if (!d->appConnection.send(cmd, arr))
01268        // Note that slaveWriteError can also be set by sigpipe_handler
01269        slaveWriteError = true;
01270    if (slaveWriteError) exit();
01271 }
01272 
01273 void SlaveBase::virtual_hook( int, void* )
01274 { /*BASE::virtual_hook( id, data );*/ }
01275 
01276 void SlaveBase::lookupHost(const QString& host)
01277 {
01278     KIO_DATA << host;
01279     send(MSG_HOST_INFO_REQ, data);
01280 }
01281 
01282 int SlaveBase::waitForHostInfo(QHostInfo& info)
01283 {
01284     QByteArray data;
01285     int result = waitForAnswer(CMD_HOST_INFO, 0, data);
01286 
01287     if (result  == -1) {
01288         info.setError(QHostInfo::UnknownError);
01289         info.setErrorString(i18n("Unknown Error"));
01290         return result;
01291     }
01292 
01293     QDataStream stream(data);
01294     QString hostName;
01295     QList<QHostAddress> addresses;
01296     int error;
01297     QString errorString;
01298 
01299     stream >> hostName >> addresses >> error >> errorString;
01300 
01301     info.setHostName(hostName);
01302     info.setAddresses(addresses);
01303     info.setError(QHostInfo::HostInfoError(error));
01304     info.setErrorString(errorString);
01305 
01306     return result;
01307 }

KIO

Skip menu "KIO"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.6.1
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal