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