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