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