00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include <config.h>
00027
00028 #include <sys/time.h>
00029 #ifdef HAVE_SYS_SELECT_H
00030 #include <sys/select.h>
00031 #endif
00032
00033 #include <assert.h>
00034 #include <kdebug.h>
00035 #include <stdlib.h>
00036 #include <errno.h>
00037 #include <unistd.h>
00038 #include <signal.h>
00039 #include <time.h>
00040
00041 #include <qfile.h>
00042
00043 #include <dcopclient.h>
00044
00045 #include <kapplication.h>
00046 #include <ksock.h>
00047 #include <kcrash.h>
00048 #include <kdesu/client.h>
00049 #include <klocale.h>
00050
00051 #include <ksocks.h>
00052
00053 #include "slavebase.h"
00054
00055 #include "kio/slavebase.h"
00056 #include "kio/connection.h"
00057 #include "kio/ioslave_defaults.h"
00058 #include "kio/slaveinterface.h"
00059
00060 using namespace KIO;
00061
00062 template class QPtrList<QValueList<UDSAtom> >;
00063 typedef QValueList<QCString> AuthKeysList;
00064 typedef QMap<QString,QCString> AuthKeysMap;
00065 #define KIO_DATA QByteArray data; QDataStream stream( data, IO_WriteOnly ); stream
00066 #define KIO_FILESIZE_T(x) (unsigned long)(x & 0xffffffff) << (unsigned long)(x >> 32)
00067
00068 namespace KIO {
00069
00070 class SlaveBaseConfig : public KConfigBase
00071 {
00072 public:
00073 SlaveBaseConfig(SlaveBase *_slave)
00074 : slave(_slave) { }
00075
00076 bool internalHasGroup(const QCString &) const { qWarning("hasGroup(const QCString &)");
00077 return false; }
00078
00079 QStringList groupList() const { return QStringList(); }
00080
00081 QMap<QString,QString> entryMap(const QString &) const
00082 { return QMap<QString,QString>(); }
00083
00084 void reparseConfiguration() { }
00085
00086 KEntryMap internalEntryMap( const QString &) const { return KEntryMap(); }
00087
00088 KEntryMap internalEntryMap() const { return KEntryMap(); }
00089
00090 void putData(const KEntryKey &, const KEntry&, bool) { }
00091
00092 KEntry lookupData(const KEntryKey &key) const
00093 {
00094 KEntry entry;
00095 QString value = slave->metaData(key.c_key);
00096 if (!value.isNull())
00097 entry.mValue = value.utf8();
00098 return entry;
00099 }
00100 protected:
00101 SlaveBase *slave;
00102 };
00103
00104
00105 class SlaveBasePrivate {
00106 public:
00107 QString slaveid;
00108 bool resume:1;
00109 bool needSendCanResume:1;
00110 bool multipleAuthCaching:1;
00111 bool onHold:1;
00112 bool wasKilled:1;
00113 MetaData configData;
00114 SlaveBaseConfig *config;
00115 KURL onHoldUrl;
00116
00117 struct timeval last_tv;
00118 KIO::filesize_t totalSize;
00119 KIO::filesize_t sentListEntries;
00120 DCOPClient *dcopClient;
00121 time_t timeout;
00122 QByteArray timeoutData;
00123 };
00124
00125 };
00126
00127 SlaveBase *globalSlave=0;
00128 long SlaveBase::s_seqNr = 0;
00129
00130 static volatile bool slaveWriteError = false;
00131
00132 void sigalarm_handler(int sigNumber)
00133 {
00134 signal(sigNumber,SIG_IGN);
00135
00136 kdDebug()<<"kioslave : exiting due to alarm signal "<<endl;
00137 exit(2);
00138 };
00139
00140 void genericsig_handler(int sigNumber)
00141 {
00142 signal(sigNumber,SIG_IGN);
00143
00144 kdDebug()<<"kioslave : exiting due to signal "<<sigNumber<<endl;
00145
00146
00147 if (globalSlave!=0)
00148 globalSlave->setKillFlag();
00149 signal(SIGALRM,&sigalarm_handler);
00150 alarm(5);
00151 };
00152
00154
00155 SlaveBase::SlaveBase( const QCString &protocol,
00156 const QCString &pool_socket,
00157 const QCString &app_socket )
00158 : mProtocol(protocol), m_pConnection(0),
00159 mPoolSocket( QFile::decodeName(pool_socket)),
00160 mAppSocket( QFile::decodeName(app_socket))
00161 {
00162 if (!getenv("KDE_DEBUG"))
00163 KCrash::setCrashHandler( sigsegv_handler );
00164 signal( SIGPIPE, sigpipe_handler );
00165
00166 signal(SIGINT,&genericsig_handler);
00167 signal(SIGQUIT,&genericsig_handler);
00168 signal(SIGILL,&genericsig_handler);
00169 signal(SIGTRAP,&genericsig_handler);
00170 signal(SIGABRT,&genericsig_handler);
00171 signal(SIGBUS,&genericsig_handler);
00172 signal(SIGALRM,&genericsig_handler);
00173 signal(SIGTERM,&genericsig_handler);
00174 signal(SIGFPE,&genericsig_handler);
00175 #ifdef SIGPOLL
00176 signal(SIGPOLL, &genericsig_handler);
00177 #endif
00178 #ifdef SIGSYS
00179 signal(SIGSYS, &genericsig_handler);
00180 #endif
00181 #ifdef SIGVTALRM
00182 signal(SIGVTALRM, &genericsig_handler);
00183 #endif
00184 #ifdef SIGXCPU
00185 signal(SIGXCPU, &genericsig_handler);
00186 #endif
00187 #ifdef SIGXFSZ
00188 signal(SIGXFSZ, &genericsig_handler);
00189 #endif
00190 globalSlave=this;
00191
00192 appconn = new Connection();
00193 listEntryCurrentSize = 100;
00194 struct timeval tp;
00195 gettimeofday(&tp, 0);
00196 listEntry_sec = tp.tv_sec;
00197 listEntry_usec = tp.tv_usec;
00198 mConnectedToApp = true;
00199
00200 d = new SlaveBasePrivate;
00201
00202 d->slaveid = protocol;
00203 d->slaveid += QString::number(getpid());
00204 d->resume = false;
00205 d->needSendCanResume = false;
00206 d->multipleAuthCaching = false;
00207 d->config = new SlaveBaseConfig(this);
00208 d->onHold = false;
00209 d->wasKilled=false;
00210 d->last_tv.tv_sec = 0;
00211 d->last_tv.tv_usec = 0;
00212
00213 d->totalSize=0;
00214 d->sentListEntries=0;
00215 d->timeout = 0;
00216 connectSlave(mAppSocket);
00217
00218 d->dcopClient = 0;
00219 }
00220
00221 SlaveBase::~SlaveBase()
00222 {
00223 delete d;
00224 }
00225
00226 DCOPClient *SlaveBase::dcopClient()
00227 {
00228 if (!d->dcopClient)
00229 {
00230 d->dcopClient = new DCOPClient();
00231 d->dcopClient->attach();
00232 }
00233 return d->dcopClient;
00234 }
00235
00236 void SlaveBase::dispatchLoop()
00237 {
00238 fd_set rfds;
00239 int retval;
00240
00241 while (true) {
00242 if (d->timeout && (d->timeout < time(0)))
00243 {
00244 QByteArray data = d->timeoutData;
00245 d->timeout = 0;
00246 d->timeoutData = QByteArray();
00247 special(data);
00248 }
00249 FD_ZERO(&rfds);
00250
00251 assert(appconn->inited());
00252 FD_SET(appconn->fd_from(), &rfds);
00253
00254 struct timeval tv;
00255 tv.tv_sec = 1;
00256 tv.tv_usec = 0;
00257 retval = select(appconn->fd_from()+ 1, &rfds, NULL, NULL, &tv);
00258 if ((retval>0) && FD_ISSET(appconn->fd_from(), &rfds))
00259 {
00260 int cmd;
00261 QByteArray data;
00262 if ( appconn->read(&cmd, data) != -1 )
00263 {
00264 dispatch(cmd, data);
00265 }
00266 else
00267 {
00268
00269 if (mConnectedToApp && !mPoolSocket.isEmpty())
00270 {
00271 disconnectSlave();
00272 mConnectedToApp = false;
00273 closeConnection();
00274 connectSlave(mPoolSocket);
00275 }
00276 else
00277 {
00278 return;
00279 }
00280 }
00281 }
00282 else if (retval<0)
00283 {
00284 kdDebug(7019) << "dispatchLoop(): select returned " << retval << " "
00285 << (errno==EBADF?"EBADF":errno==EINTR?"EINTR":errno==EINVAL?"EINVAL":errno==ENOMEM?"ENOMEM":"unknown")
00286 << " (" << errno << ")" << endl;
00287 return;
00288 };
00289
00290 if (wasKilled())
00291 {
00292 kdDebug(7019)<<" dispatchLoop() slave was killed, returning"<<endl;
00293 return;
00294 }
00295 }
00296 }
00297
00298 void SlaveBase::connectSlave(const QString& path)
00299 {
00300 appconn->init(new KSocket(QFile::encodeName(path)));
00301 if (!appconn->inited())
00302 {
00303 kdDebug(7019) << "SlaveBase: failed to connect to " << path << endl;
00304 exit();
00305 }
00306
00307 setConnection(appconn);
00308 }
00309
00310 void SlaveBase::disconnectSlave()
00311 {
00312 appconn->close();
00313 }
00314
00315 void SlaveBase::setMetaData(const QString &key, const QString &value)
00316 {
00317 mOutgoingMetaData.replace(key, value);
00318 }
00319
00320 QString SlaveBase::metaData(const QString &key)
00321 {
00322 if (mIncomingMetaData.contains(key))
00323 return mIncomingMetaData[key];
00324 if (d->configData.contains(key))
00325 return d->configData[key];
00326 return QString::null;
00327 }
00328
00329 bool SlaveBase::hasMetaData(const QString &key)
00330 {
00331 if (mIncomingMetaData.contains(key))
00332 return true;
00333 if (d->configData.contains(key))
00334 return true;
00335 return false;
00336 }
00337
00338 KConfigBase *SlaveBase::config()
00339 {
00340 return d->config;
00341 }
00342
00343 void SlaveBase::sendMetaData()
00344 {
00345 KIO_DATA << mOutgoingMetaData;
00346
00347 slaveWriteError = false;
00348 m_pConnection->send( INF_META_DATA, data );
00349 if (slaveWriteError) exit();
00350 mOutgoingMetaData.clear();
00351 }
00352
00353
00354 void SlaveBase::data( const QByteArray &data )
00355 {
00356 if (!mOutgoingMetaData.isEmpty())
00357 sendMetaData();
00358 slaveWriteError = false;
00359 m_pConnection->send( MSG_DATA, data );
00360 if (slaveWriteError) exit();
00361 }
00362
00363 void SlaveBase::dataReq( )
00364 {
00365
00366
00367
00368
00369 if (d->needSendCanResume)
00370 canResume(0);
00371 m_pConnection->send( MSG_DATA_REQ );
00372 }
00373
00374 void SlaveBase::error( int _errid, const QString &_text )
00375 {
00376 mIncomingMetaData.clear();
00377 mOutgoingMetaData.clear();
00378 KIO_DATA << _errid << _text;
00379
00380 m_pConnection->send( MSG_ERROR, data );
00381
00382 listEntryCurrentSize = 100;
00383 d->sentListEntries=0;
00384 d->totalSize=0;
00385 }
00386
00387 void SlaveBase::connected()
00388 {
00389 slaveWriteError = false;
00390 m_pConnection->send( MSG_CONNECTED );
00391 if (slaveWriteError) exit();
00392 }
00393
00394 void SlaveBase::finished()
00395 {
00396 mIncomingMetaData.clear();
00397 if (!mOutgoingMetaData.isEmpty())
00398 sendMetaData();
00399 m_pConnection->send( MSG_FINISHED );
00400
00401
00402 listEntryCurrentSize = 100;
00403 d->sentListEntries=0;
00404 d->totalSize=0;
00405 }
00406
00407 void SlaveBase::needSubURLData()
00408 {
00409 m_pConnection->send( MSG_NEED_SUBURL_DATA );
00410 }
00411
00412 void SlaveBase::slaveStatus( const QString &host, bool connected )
00413 {
00414 pid_t pid = getpid();
00415 Q_INT8 b = connected ? 1 : 0;
00416 KIO_DATA << pid << mProtocol << host << b;
00417 if (d->onHold)
00418 stream << d->onHoldUrl;
00419 m_pConnection->send( MSG_SLAVE_STATUS, data );
00420 }
00421
00422 void SlaveBase::canResume()
00423 {
00424 m_pConnection->send( MSG_CANRESUME );
00425 }
00426
00427 void SlaveBase::totalSize( KIO::filesize_t _bytes )
00428 {
00429 KIO_DATA << KIO_FILESIZE_T(_bytes);
00430 slaveWriteError = false;
00431 m_pConnection->send( INF_TOTAL_SIZE, data );
00432 if (slaveWriteError) exit();
00433
00434
00435 struct timeval tp;
00436 gettimeofday(&tp, 0);
00437 listEntry_sec = tp.tv_sec;
00438 listEntry_usec = tp.tv_usec;
00439 d->totalSize=_bytes;
00440 d->sentListEntries=0;
00441 }
00442
00443 void SlaveBase::processedSize( KIO::filesize_t _bytes )
00444 {
00445 struct timeval tv;
00446 if ( gettimeofday( &tv, 0L ) == 0 ) {
00447 time_t msecdiff = 2000;
00448 if (d->last_tv.tv_sec) {
00449
00450 msecdiff = 1000 * ( tv.tv_sec - d->last_tv.tv_sec );
00451 time_t usecdiff = tv.tv_usec - d->last_tv.tv_usec;
00452 if ( usecdiff < 0 ) {
00453 msecdiff--;
00454 msecdiff += 1000;
00455 }
00456 msecdiff += usecdiff / 1000;
00457 }
00458 if ( msecdiff >= 100 ) {
00459 KIO_DATA << KIO_FILESIZE_T(_bytes);
00460 slaveWriteError = false;
00461 m_pConnection->send( INF_PROCESSED_SIZE, data );
00462 if (slaveWriteError) exit();
00463 d->last_tv.tv_sec = tv.tv_sec;
00464 d->last_tv.tv_usec = tv.tv_usec;
00465 }
00466 }
00467
00468 }
00469
00470 void SlaveBase::processedPercent( float )
00471 {
00472 kdDebug(7019) << "SlaveBase::processedPercent: STUB" << endl;
00473 }
00474
00475
00476 void SlaveBase::speed( unsigned long _bytes_per_second )
00477 {
00478 KIO_DATA << _bytes_per_second;
00479 slaveWriteError = false;
00480 m_pConnection->send( INF_SPEED, data );
00481 if (slaveWriteError) exit();
00482 }
00483
00484 void SlaveBase::redirection( const KURL& _url )
00485 {
00486 KIO_DATA << _url;
00487 m_pConnection->send( INF_REDIRECTION, data );
00488 }
00489
00490 void SlaveBase::errorPage()
00491 {
00492 m_pConnection->send( INF_ERROR_PAGE );
00493 }
00494
00495 static bool isSubCommand(int cmd)
00496 {
00497 return ( (cmd == CMD_REPARSECONFIGURATION) ||
00498 (cmd == CMD_META_DATA) ||
00499 (cmd == CMD_CONFIG) ||
00500 (cmd == CMD_SUBURL) ||
00501 (cmd == CMD_SLAVE_STATUS) ||
00502 (cmd == CMD_SLAVE_CONNECT) ||
00503 (cmd == CMD_SLAVE_HOLD) ||
00504 (cmd == CMD_MULTI_GET));
00505 }
00506
00507 void SlaveBase::mimeType( const QString &_type)
00508 {
00509
00510 int cmd;
00511 do
00512 {
00513
00514 if (!mOutgoingMetaData.isEmpty())
00515 {
00516
00517 KIO_DATA << mOutgoingMetaData;
00518 m_pConnection->send( INF_META_DATA, data );
00519 }
00520 KIO_DATA << _type;
00521 m_pConnection->send( INF_MIME_TYPE, data );
00522 while(true)
00523 {
00524 cmd = 0;
00525 if ( m_pConnection->read( &cmd, data ) == -1 ) {
00526 kdDebug(7019) << "SlaveBase: mimetype: read error" << endl;
00527 exit();
00528 }
00529
00530 if ( cmd == CMD_HOST)
00531 continue;
00532 if ( isSubCommand(cmd) )
00533 {
00534 dispatch( cmd, data );
00535 continue;
00536 };
00537 break;
00538 }
00539 }
00540 while (cmd != CMD_NONE);
00541 mOutgoingMetaData.clear();
00542 }
00543
00544 void SlaveBase::exit()
00545 {
00546 this->~SlaveBase();
00547 ::exit(255);
00548 }
00549
00550 void SlaveBase::warning( const QString &_msg)
00551 {
00552 KIO_DATA << _msg;
00553 m_pConnection->send( INF_WARNING, data );
00554 }
00555
00556 void SlaveBase::infoMessage( const QString &_msg)
00557 {
00558 KIO_DATA << _msg;
00559 m_pConnection->send( INF_INFOMESSAGE, data );
00560 }
00561
00562 bool SlaveBase::requestNetwork(const QString& host)
00563 {
00564 KIO_DATA << host << d->slaveid;
00565 m_pConnection->send( MSG_NET_REQUEST, data );
00566
00567 if ( waitForAnswer( INF_NETWORK_STATUS, 0, data ) != -1 )
00568 {
00569 bool status;
00570 QDataStream stream( data, IO_ReadOnly );
00571 stream >> status;
00572 return status;
00573 } else
00574 return false;
00575 }
00576
00577 void SlaveBase::dropNetwork(const QString& host)
00578 {
00579 KIO_DATA << host << d->slaveid;
00580 m_pConnection->send( MSG_NET_DROP, data );
00581 }
00582
00583 void SlaveBase::statEntry( const UDSEntry& entry )
00584 {
00585 KIO_DATA << entry;
00586 slaveWriteError = false;
00587 m_pConnection->send( MSG_STAT_ENTRY, data );
00588 if (slaveWriteError) exit();
00589 }
00590
00591 void SlaveBase::listEntry( const UDSEntry& entry, bool _ready )
00592 {
00593 static struct timeval tp;
00594 static const int maximum_updatetime = 300;
00595 static const int minimum_updatetime = 100;
00596
00597 if (!_ready) {
00598 pendingListEntries.append(entry);
00599
00600 if (pendingListEntries.count() > listEntryCurrentSize) {
00601 gettimeofday(&tp, 0);
00602
00603 long diff = ((tp.tv_sec - listEntry_sec) * 1000000 +
00604 tp.tv_usec - listEntry_usec) / 1000;
00605 if (diff==0) diff=1;
00606
00607 if (diff > maximum_updatetime) {
00608 listEntryCurrentSize = listEntryCurrentSize * 3 / 4;
00609 _ready = true;
00610 }
00611
00612
00613 else if (((pendingListEntries.count()*maximum_updatetime)/diff) > (d->totalSize-d->sentListEntries))
00614 listEntryCurrentSize=d->totalSize-d->sentListEntries+1;
00615
00616
00617 else if (diff < minimum_updatetime)
00618 listEntryCurrentSize = (pendingListEntries.count() * maximum_updatetime) / diff;
00619 else
00620 _ready=true;
00621 }
00622 }
00623 if (_ready) {
00624 listEntries( pendingListEntries );
00625 pendingListEntries.clear();
00626
00627 gettimeofday(&tp, 0);
00628 listEntry_sec = tp.tv_sec;
00629 listEntry_usec = tp.tv_usec;
00630 }
00631 }
00632
00633 void SlaveBase::listEntries( const UDSEntryList& list )
00634 {
00635 KIO_DATA << (uint)list.count();
00636 UDSEntryListConstIterator it = list.begin();
00637 UDSEntryListConstIterator end = list.end();
00638 for (; it != end; ++it)
00639 stream << *it;
00640 slaveWriteError = false;
00641 m_pConnection->send( MSG_LIST_ENTRIES, data);
00642 if (slaveWriteError) exit();
00643 d->sentListEntries+=(uint)list.count();
00644 }
00645
00646 void SlaveBase::sendAuthenticationKey( const QCString& key,
00647 const QCString& group,
00648 bool keepPass )
00649 {
00650 KIO_DATA << key << group << keepPass;
00651 m_pConnection->send( MSG_AUTH_KEY, data );
00652 }
00653
00654 void SlaveBase::delCachedAuthentication( const QString& key )
00655 {
00656 KIO_DATA << key.utf8() ;
00657 m_pConnection->send( MSG_DEL_AUTH_KEY, data );
00658 }
00659
00660 void SlaveBase::sigsegv_handler (int)
00661 {
00662 signal(SIGSEGV,SIG_IGN);
00663
00664
00665 write(2, "kioslave : ###############SEG FAULT#############\n", 49);
00666 ::exit(1);
00667 }
00668
00669 void SlaveBase::sigpipe_handler (int)
00670 {
00671 signal(SIGPIPE,SIG_IGN);
00672
00673
00674
00675
00676 kdDebug(7019) << "SIGPIPE" << endl;
00677 signal(SIGPIPE,&sigpipe_handler);
00678 slaveWriteError = true;
00679 }
00680
00681 void SlaveBase::setHost(QString const &, int, QString const &, QString const &)
00682 {
00683 }
00684
00685 void SlaveBase::openConnection(void)
00686 { error( ERR_UNSUPPORTED_ACTION, i18n("Opening connections is not supported with the protocol %1" ).arg(mProtocol)); }
00687 void SlaveBase::closeConnection(void)
00688 { }
00689 void SlaveBase::stat(KURL const &)
00690 { error( ERR_UNSUPPORTED_ACTION, i18n("Accessing files is not supported with the protocol %1").arg(mProtocol) ); }
00691 void SlaveBase::put(KURL const &, int, bool, bool)
00692 { error( ERR_UNSUPPORTED_ACTION, i18n("Writing to %1 is not supported").arg(mProtocol) ); }
00693 void SlaveBase::special(const QByteArray &)
00694 { error( ERR_UNSUPPORTED_ACTION, i18n("There are no special actions available for protocol %1").arg(mProtocol) ); }
00695 void SlaveBase::listDir(KURL const &)
00696 { error( ERR_UNSUPPORTED_ACTION, i18n("Listing directories is not supported for protocol %1").arg(mProtocol) ); }
00697 void SlaveBase::get(KURL const & )
00698 { error( ERR_UNSUPPORTED_ACTION, i18n("Retrieving data from %1 is not supported").arg(mProtocol) ); }
00699 void SlaveBase::mimetype(KURL const &url)
00700 { get(url); }
00701 void SlaveBase::rename(KURL const &, KURL const &, bool)
00702 { error( ERR_UNSUPPORTED_ACTION, i18n("Renaming or moving files within %1 is not supported").arg(mProtocol) ); }
00703 void SlaveBase::symlink(QString const &, KURL const &, bool)
00704 { error( ERR_UNSUPPORTED_ACTION, i18n("Creating symlinks is not supported with protocol %1").arg(mProtocol) ); }
00705 void SlaveBase::copy(KURL const &, KURL const &, int, bool)
00706 { error( ERR_UNSUPPORTED_ACTION, i18n("Copying files within %1 is not supported").arg(mProtocol) ); }
00707 void SlaveBase::del(KURL const &, bool)
00708 { error( ERR_UNSUPPORTED_ACTION, i18n("Deleting files from %1 is not supported").arg(mProtocol) ); }
00709 void SlaveBase::mkdir(KURL const &, int)
00710 { error( ERR_UNSUPPORTED_ACTION, i18n("Creating directories is not supported with protocol %1").arg(mProtocol) ); }
00711 void SlaveBase::chmod(KURL const &, int)
00712 { error( ERR_UNSUPPORTED_ACTION, i18n("Changing the attributes of files is not supported with protocol %1").arg(mProtocol) ); }
00713 void SlaveBase::setSubURL(KURL const &)
00714 { error( ERR_UNSUPPORTED_ACTION, i18n("Using sub-URLs with %1 is not supported").arg(mProtocol) ); }
00715 void SlaveBase::multiGet(const QByteArray &)
00716 { error( ERR_UNSUPPORTED_ACTION, i18n("Multiple get is not supported with protocol %1").arg(mProtocol) ); }
00717
00718
00719 void SlaveBase::slave_status()
00720 { slaveStatus( QString::null, false ); }
00721
00722 void SlaveBase::reparseConfiguration()
00723 {
00724 }
00725
00726 bool SlaveBase::dispatch()
00727 {
00728 assert( m_pConnection );
00729
00730 int cmd;
00731 QByteArray data;
00732 if ( m_pConnection->read( &cmd, data ) == -1 )
00733 {
00734 kdDebug(7019) << "SlaveBase::dispatch() has read error." << endl;
00735 return false;
00736 }
00737
00738 dispatch( cmd, data );
00739 return true;
00740 }
00741
00742 bool SlaveBase::openPassDlg( AuthInfo& info )
00743 {
00744 return openPassDlg(info, QString::null);
00745 }
00746
00747 bool SlaveBase::openPassDlg( AuthInfo& info, const QString &errorMsg )
00748 {
00749 kdDebug(7019) << "SlaveBase::OpenPassDlg User= " << info.username << endl;
00750
00751 QCString replyType;
00752 QByteArray params;
00753 QByteArray reply;
00754 AuthInfo authResult;
00755 long windowId = metaData("window-id").toLong();
00756
00757 (void) dcopClient();
00758
00759 QDataStream stream(params, IO_WriteOnly);
00760 stream << info << errorMsg << windowId << s_seqNr;
00761
00762 if (!d->dcopClient->call( "kded", "kpasswdserver", "queryAuthInfo(KIO::AuthInfo, QString, long int, long int)",
00763 params, replyType, reply ) )
00764 {
00765 kdWarning(7019) << "Can't communicate with kded!" << endl;
00766 return false;
00767 }
00768
00769 if ( replyType == "KIO::AuthInfo" )
00770 {
00771 QDataStream stream2( reply, IO_ReadOnly );
00772 stream2 >> authResult >> s_seqNr;
00773 }
00774 else
00775 {
00776 kdError(7019) << "DCOP function queryAuthInfo(...) returns "
00777 << replyType << ", expected KIO::AuthInfo" << endl;
00778 return false;
00779 }
00780
00781 if (!authResult.isModified())
00782 return false;
00783
00784 info = authResult;
00785 return true;
00786 }
00787
00788 int SlaveBase::messageBox( MessageBoxType type, const QString &text, const QString &caption,
00789 const QString &buttonYes, const QString &buttonNo )
00790 {
00791 kdDebug(7019) << "messageBox " << type << " " << text << " - " << caption << buttonYes << buttonNo << endl;
00792 KIO_DATA << (int)type << text << caption << buttonYes << buttonNo;
00793 m_pConnection->send( INF_MESSAGEBOX, data );
00794 if ( waitForAnswer( CMD_MESSAGEBOXANSWER, 0, data ) != -1 )
00795 {
00796 QDataStream stream( data, IO_ReadOnly );
00797 int answer;
00798 stream >> answer;
00799 kdDebug(7019) << "got messagebox answer" << answer << endl;
00800 return answer;
00801 } else
00802 return 0;
00803 }
00804
00805 bool SlaveBase::canResume( KIO::filesize_t offset )
00806 {
00807 kdDebug(7019) << "SlaveBase::canResume offset=" << KIO::number(offset) << endl;
00808 d->needSendCanResume = false;
00809 KIO_DATA << KIO_FILESIZE_T(offset);
00810 m_pConnection->send( MSG_RESUME, data );
00811 if ( offset )
00812 {
00813 int cmd;
00814 if ( waitForAnswer( CMD_RESUMEANSWER, CMD_NONE, data, &cmd ) != -1 )
00815 {
00816 kdDebug(7019) << "SlaveBase::canResume returning " << (cmd == CMD_RESUMEANSWER) << endl;
00817 return cmd == CMD_RESUMEANSWER;
00818 } else
00819 return false;
00820 }
00821 else
00822 return true;
00823 }
00824
00825
00826
00827 int SlaveBase::waitForAnswer( int expected1, int expected2, QByteArray & data, int *pCmd )
00828 {
00829 int cmd, result;
00830 for (;;)
00831 {
00832 result = m_pConnection->read( &cmd, data );
00833 if ( result == -1 )
00834 {
00835 kdDebug(7019) << "SlaveBase::waitForAnswer has read error." << endl;
00836 return -1;
00837 }
00838 if ( cmd == expected1 || cmd == expected2 )
00839 {
00840 if ( pCmd ) *pCmd = cmd;
00841 return result;
00842 }
00843 if ( isSubCommand(cmd) )
00844 {
00845 dispatch( cmd, data );
00846 }
00847 else
00848 {
00849 kdWarning() << "Got cmd " << cmd << " while waiting for an answer!" << endl;
00850 }
00851 }
00852 }
00853
00854
00855 int SlaveBase::readData( QByteArray &buffer)
00856 {
00857 int result = waitForAnswer( MSG_DATA, 0, buffer );
00858
00859 return result;
00860 }
00861
00862 void SlaveBase::setTimeoutSpecialCommand(int timeout, const QByteArray &data)
00863 {
00864 if (timeout > 0)
00865 d->timeout = time(0)+(time_t)timeout;
00866 else if (timeout == 0)
00867 d->timeout = 1;
00868 else
00869 d->timeout = 0;
00870
00871 d->timeoutData = data;
00872 }
00873
00874 void SlaveBase::dispatch( int command, const QByteArray &data )
00875 {
00876 QDataStream stream( data, IO_ReadOnly );
00877
00878 KURL url;
00879 int i;
00880
00881 switch( command ) {
00882 case CMD_HOST: {
00883
00884 s_seqNr = 0;
00885 QString passwd;
00886 QString host, user;
00887 stream >> host >> i >> user >> passwd;
00888 setHost( host, i, user, passwd );
00889 }
00890 break;
00891 case CMD_CONNECT:
00892 openConnection( );
00893 break;
00894 case CMD_DISCONNECT:
00895 closeConnection( );
00896 break;
00897 case CMD_SLAVE_STATUS:
00898 slave_status();
00899 break;
00900 case CMD_SLAVE_CONNECT:
00901 {
00902 d->onHold = false;
00903 QString app_socket;
00904 QDataStream stream( data, IO_ReadOnly);
00905 stream >> app_socket;
00906 appconn->send( MSG_SLAVE_ACK );
00907 disconnectSlave();
00908 mConnectedToApp = true;
00909 connectSlave(app_socket);
00910 } break;
00911 case CMD_SLAVE_HOLD:
00912 {
00913 KURL url;
00914 QDataStream stream( data, IO_ReadOnly);
00915 stream >> url;
00916 d->onHoldUrl = url;
00917 d->onHold = true;
00918 disconnectSlave();
00919 mConnectedToApp = false;
00920
00921 connectSlave(mPoolSocket);
00922 } break;
00923 case CMD_REPARSECONFIGURATION:
00924 reparseConfiguration();
00925 break;
00926 case CMD_CONFIG:
00927 stream >> d->configData;
00928 KSocks::setConfig(d->config);
00929 break;
00930 case CMD_GET:
00931 {
00932 stream >> url;
00933 get( url );
00934 } break;
00935 case CMD_PUT:
00936 {
00937 int permissions;
00938 Q_INT8 iOverwrite, iResume;
00939 stream >> url >> iOverwrite >> iResume >> permissions;
00940 bool overwrite = ( iOverwrite != 0 );
00941 bool resume = ( iResume != 0 );
00942
00943
00944
00945
00946 d->needSendCanResume = true ;
00947
00948 put( url, permissions, overwrite, resume);
00949 } break;
00950 case CMD_STAT:
00951 stream >> url;
00952 stat( url );
00953 break;
00954 case CMD_MIMETYPE:
00955 stream >> url;
00956 mimetype( url );
00957 break;
00958 case CMD_LISTDIR:
00959 stream >> url;
00960 listDir( url );
00961 break;
00962 case CMD_MKDIR:
00963 stream >> url >> i;
00964 mkdir( url, i );
00965 break;
00966 case CMD_RENAME:
00967 {
00968 Q_INT8 iOverwrite;
00969 KURL url2;
00970 stream >> url >> url2 >> iOverwrite;
00971 bool overwrite = (iOverwrite != 0);
00972 rename( url, url2, overwrite );
00973 } break;
00974 case CMD_SYMLINK:
00975 {
00976 Q_INT8 iOverwrite;
00977 QString target;
00978 stream >> target >> url >> iOverwrite;
00979 bool overwrite = (iOverwrite != 0);
00980 symlink( target, url, overwrite );
00981 } break;
00982 case CMD_COPY:
00983 {
00984 int permissions;
00985 Q_INT8 iOverwrite;
00986 KURL url2;
00987 stream >> url >> url2 >> permissions >> iOverwrite;
00988 bool overwrite = (iOverwrite != 0);
00989 copy( url, url2, permissions, overwrite );
00990 } break;
00991 case CMD_DEL:
00992 {
00993 Q_INT8 isFile;
00994 stream >> url >> isFile;
00995 del( url, isFile != 0);
00996 } break;
00997 case CMD_CHMOD:
00998 stream >> url >> i;
00999 chmod( url, i);
01000 break;
01001 case CMD_SPECIAL:
01002 special( data );
01003 break;
01004 case CMD_META_DATA:
01005
01006 stream >> mIncomingMetaData;
01007 break;
01008 case CMD_SUBURL:
01009 stream >> url;
01010 setSubURL(url);
01011 break;
01012 case CMD_NONE:
01013 fprintf(stderr, "Got unexpected CMD_NONE!\n");
01014 break;
01015 case CMD_MULTI_GET:
01016 multiGet( data );
01017 break;
01018 default:
01019
01020
01021 break;
01022 }
01023 }
01024
01025 QString SlaveBase::createAuthCacheKey( const KURL& url )
01026 {
01027 if( url.isMalformed() )
01028 return QString::null;
01029
01030
01031 QString key = url.protocol();
01032 key += '-';
01033 key += url.host();
01034 int port = url.port();
01035 if( port )
01036 {
01037 key += ':';
01038 key += QString::number(port);
01039 }
01040
01041 return key;
01042 }
01043
01044 bool SlaveBase::pingCacheDaemon() const
01045 {
01046
01047 KDEsuClient client;
01048 int sucess = client.ping();
01049 if( sucess == -1 )
01050 {
01051 sucess = client.startServer();
01052 if( sucess == -1 )
01053 {
01054 kdDebug(7019) << "Cannot start a new deamon!!" << endl;
01055 return false;
01056 }
01057 kdDebug(7019) << "Sucessfully started new cache deamon!!" << endl;
01058 }
01059 return true;
01060 }
01061
01062 bool SlaveBase::checkCachedAuthentication( AuthInfo& info )
01063 {
01064 QCString replyType;
01065 QByteArray params;
01066 QByteArray reply;
01067 AuthInfo authResult;
01068 long windowId = metaData("window-id").toLong();
01069
01070 kdDebug(7019) << "SlaveBase::checkCachedAuthInfo window = " << windowId << " url = " << info.url.url() << endl;
01071
01072 (void) dcopClient();
01073
01074 QDataStream stream(params, IO_WriteOnly);
01075 stream << info << windowId;
01076
01077 if ( !d->dcopClient->call( "kded", "kpasswdserver", "checkAuthInfo(KIO::AuthInfo, long int)",
01078 params, replyType, reply ) )
01079 {
01080 kdWarning(7019) << "Can't communicate with kded!" << endl;
01081 return false;
01082 }
01083
01084 if ( replyType == "KIO::AuthInfo" )
01085 {
01086 QDataStream stream2( reply, IO_ReadOnly );
01087 stream2 >> authResult;
01088 }
01089 else
01090 {
01091 kdError(7019) << "DCOP function checkAuthInfo(...) returns "
01092 << replyType << ", expected KIO::AuthInfo" << endl;
01093 return false;
01094 }
01095 if (!authResult.isModified())
01096 {
01097 return false;
01098 }
01099
01100 info = authResult;
01101 return true;
01102 }
01103
01104 bool SlaveBase::storeAuthInfo( const QCString&, const QCString&,
01105 const AuthInfo& )
01106 {
01107
01108 return false;
01109 }
01110
01111 bool SlaveBase::cacheAuthentication( const AuthInfo& info )
01112 {
01113 QByteArray params;
01114 long windowId = metaData("window-id").toLong();
01115
01116 (void) dcopClient();
01117
01118 QDataStream stream(params, IO_WriteOnly);
01119 stream << info << windowId;
01120
01121 d->dcopClient->send( "kded", "kpasswdserver", "addAuthInfo(KIO::AuthInfo, long int)", params );
01122
01123 return true;
01124 }
01125
01126 void SlaveBase::setMultipleAuthCaching( bool enable )
01127 {
01128 d->multipleAuthCaching = enable;
01129 }
01130
01131 bool SlaveBase::multipleAuthCaching() const
01132 {
01133 return d->multipleAuthCaching;
01134 }
01135
01136 int SlaveBase::connectTimeout()
01137 {
01138 bool ok;
01139 QString tmp = metaData("ConnectTimeout");
01140 int result = tmp.toInt(&ok);
01141 if (ok)
01142 return result;
01143 return DEFAULT_CONNECT_TIMEOUT;
01144 }
01145
01146 int SlaveBase::proxyConnectTimeout()
01147 {
01148 bool ok;
01149 QString tmp = metaData("ProxyConnectTimeout");
01150 int result = tmp.toInt(&ok);
01151 if (ok)
01152 return result;
01153 return DEFAULT_PROXY_CONNECT_TIMEOUT;
01154 }
01155
01156
01157 int SlaveBase::responseTimeout()
01158 {
01159 bool ok;
01160 QString tmp = metaData("ResponseTimeout");
01161 int result = tmp.toInt(&ok);
01162 if (ok)
01163 return result;
01164 return DEFAULT_RESPONSE_TIMEOUT;
01165 }
01166
01167
01168 int SlaveBase::readTimeout()
01169 {
01170 bool ok;
01171 QString tmp = metaData("ReadTimeout");
01172 int result = tmp.toInt(&ok);
01173 if (ok)
01174 return result;
01175 return DEFAULT_READ_TIMEOUT;
01176 }
01177
01178 bool SlaveBase::wasKilled() const
01179 {
01180 return d->wasKilled;
01181 };
01182
01183 void SlaveBase::setKillFlag()
01184 {
01185 d->wasKilled=true;
01186 };
01187
01188 void SlaveBase::virtual_hook( int, void* )
01189 { }
01190