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

KIO

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

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.7.5
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