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