00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
#include "kio/slaveinterface.h"
00020
#include "kio/slavebase.h"
00021
#include "kio/connection.h"
00022
#include <errno.h>
00023
#include <assert.h>
00024
#include <kdebug.h>
00025
#include <stdlib.h>
00026
#include <sys/time.h>
00027
#include <unistd.h>
00028
#include <signal.h>
00029
#include <kio/observer.h>
00030
#include <kapplication.h>
00031
#include <dcopclient.h>
00032
#include <time.h>
00033
#include <qtimer.h>
00034
00035
using namespace KIO;
00036
00037
00038
QDataStream &operator <<(
QDataStream &s,
const KIO::UDSEntry &e )
00039 {
00040
00041
00042
00043
00044
if (
sizeof(
long) == 8)
00045 {
00046 s << (Q_UINT32)e.
size();
00047 KIO::UDSEntry::ConstIterator it = e.
begin();
00048
for( ; it != e.
end(); ++it )
00049 s << *it;
00050
return s;
00051 }
00052
00053 Q_UINT32 size = 0;
00054 KIO::UDSEntry::ConstIterator it = e.
begin();
00055
for( ; it != e.
end(); ++it )
00056 {
00057 size++;
00058
if ((*it).m_uds == KIO::UDS_SIZE)
00059 size++;
00060 }
00061 s << size;
00062 it = e.
begin();
00063
for( ; it != e.
end(); ++it )
00064 {
00065
if ((*it).m_uds == KIO::UDS_SIZE)
00066 {
00067 KIO::UDSAtom a;
00068 a.m_uds = KIO::UDS_SIZE_LARGE;
00069 a.m_long = (*it).m_long >> 32;
00070 s << a;
00071 }
00072 s << *it;
00073 }
00074
return s;
00075 }
00076
00077
QDataStream &operator >>(
QDataStream &s,
KIO::UDSEntry &e )
00078 {
00079 e.
clear();
00080 Q_UINT32 size;
00081 s >> size;
00082
00083
00084
00085
00086
00087
if (
sizeof(
long) == 8)
00088 {
00089
for(Q_UINT32 i = 0; i < size; i++)
00090 {
00091 KIO::UDSAtom a;
00092 s >> a;
00093 e.
append(a);
00094 }
00095 }
00096
else
00097 {
00098
long long msb = 0;
00099
for(Q_UINT32 i = 0; i < size; i++)
00100 {
00101 KIO::UDSAtom a;
00102 s >> a;
00103
if (a.m_uds == KIO::UDS_SIZE_LARGE)
00104 {
00105 msb = a.m_long;
00106 }
00107
else
00108 {
00109
if (a.m_uds == KIO::UDS_SIZE)
00110 {
00111
if (a.m_long < 0)
00112 a.m_long += (
long long) 1 << 32;
00113 a.m_long += msb << 32;
00114 }
00115 e.
append(a);
00116 msb = 0;
00117 }
00118 }
00119 }
00120
return s;
00121 }
00122
00123
static const unsigned int max_nums = 8;
00124
00125
class KIO::SlaveInterfacePrivate
00126 {
00127
public:
00128 SlaveInterfacePrivate() {
00129 slave_calcs_speed =
false;
00130 start_time.tv_sec = 0;
00131 start_time.tv_usec = 0;
00132 last_time = 0;
00133 nums = 0;
00134 filesize = 0;
00135 offset = 0;
00136 }
00137
bool slave_calcs_speed;
00138
struct timeval start_time;
00139 uint nums;
00140
long times[max_nums];
00141
KIO::filesize_t sizes[max_nums];
00142 size_t last_time;
00143
KIO::filesize_t filesize, offset;
00144
00145
QTimer speed_timer;
00146 };
00147
00149
00150 SlaveInterface::SlaveInterface(
Connection * connection )
00151 {
00152 m_pConnection = connection;
00153 m_progressId = 0;
00154
00155 d =
new SlaveInterfacePrivate;
00156
connect(&d->speed_timer, SIGNAL(timeout()), SLOT(calcSpeed()));
00157 }
00158
00159 SlaveInterface::~SlaveInterface()
00160 {
00161
00162 m_pConnection = 0;
00163
00164
delete d;
00165 }
00166
00167
static KIO::filesize_t readFilesize_t(
QDataStream &stream)
00168 {
00169
KIO::filesize_t result;
00170
unsigned long ul;
00171 stream >> ul;
00172 result = ul;
00173
if (stream.
atEnd())
00174
return result;
00175 stream >> ul;
00176 result += ((
KIO::filesize_t)ul) << 32;
00177
return result;
00178 }
00179
00180
00181
bool SlaveInterface::dispatch()
00182 {
00183 assert( m_pConnection );
00184
00185
int cmd;
00186
QByteArray data;
00187
00188
if (m_pConnection->
read( &cmd, data ) == -1)
00189
return false;
00190
00191
return dispatch( cmd, data );
00192 }
00193
00194
void SlaveInterface::calcSpeed()
00195 {
00196
if (d->slave_calcs_speed) {
00197 d->speed_timer.stop();
00198
return;
00199 }
00200
00201
struct timeval tv;
00202 gettimeofday(&tv, 0);
00203
00204
long diff = ((tv.tv_sec - d->start_time.tv_sec) * 1000000 +
00205 tv.tv_usec - d->start_time.tv_usec) / 1000;
00206
if (diff - d->last_time >= 900) {
00207 d->last_time = diff;
00208
if (d->nums == max_nums) {
00209
00210
00211
for (
unsigned int i = 1; i < max_nums; ++i) {
00212 d->times[i-1] = d->times[i];
00213 d->sizes[i-1] = d->sizes[i];
00214 }
00215 d->nums--;
00216 }
00217 d->times[d->nums] = diff;
00218 d->sizes[d->nums++] = d->filesize;
00219
00220
KIO::filesize_t lspeed = 1000 * (d->sizes[d->nums-1] - d->sizes[0]) / (d->times[d->nums-1] - d->times[0]);
00221
00222
00223
00224
if (!lspeed) {
00225 d->nums = 1;
00226 d->times[0] = diff;
00227 d->sizes[0] = d->filesize;
00228 }
00229 emit speed(lspeed);
00230 }
00231 }
00232
00233
bool SlaveInterface::dispatch(
int _cmd,
const QByteArray &rawdata )
00234 {
00235
00236
00237
QDataStream stream( rawdata, IO_ReadOnly );
00238
00239
QString str1;
00240
int i;
00241 Q_INT8 b;
00242
unsigned long ul;
00243
00244
switch( _cmd ) {
00245
case MSG_DATA:
00246 emit data( rawdata );
00247
break;
00248
case MSG_DATA_REQ:
00249 emit dataReq();
00250
break;
00251
case MSG_FINISHED:
00252
00253 d->offset = 0;
00254 d->speed_timer.stop();
00255 emit finished();
00256
break;
00257
case MSG_STAT_ENTRY:
00258 {
00259
UDSEntry entry;
00260 stream >> entry;
00261 emit statEntry(entry);
00262 }
00263
break;
00264
case MSG_LIST_ENTRIES:
00265 {
00266 uint count;
00267 stream >> count;
00268
00269
UDSEntryList list;
00270
UDSEntry entry;
00271
for (uint i = 0; i < count; i++) {
00272 stream >> entry;
00273 list.
append(entry);
00274 }
00275 emit listEntries(list);
00276
00277 }
00278
break;
00279
case MSG_RESUME:
00280 {
00281
KIO::filesize_t offset = readFilesize_t(stream);
00282 emit canResume( offset );
00283 }
00284
break;
00285
case MSG_CANRESUME:
00286 d->filesize = d->offset;
00287 emit canResume(0);
00288
break;
00289
case MSG_ERROR:
00290 stream >> i >> str1;
00291
kdDebug(7007) <<
"error " << i <<
" " << str1 <<
endl;
00292 emit error( i, str1 );
00293
break;
00294
case MSG_SLAVE_STATUS:
00295 {
00296 pid_t pid;
00297
QCString protocol;
00298 stream >> pid >> protocol >> str1 >> b;
00299 emit slaveStatus(pid, protocol, str1, (b != 0));
00300 }
00301
break;
00302
case MSG_CONNECTED:
00303 emit connected();
00304
break;
00305
00306
case INF_TOTAL_SIZE:
00307 {
00308
KIO::filesize_t size = readFilesize_t(stream);
00309 gettimeofday(&d->start_time, 0);
00310 d->last_time = 0;
00311 d->filesize = d->offset;
00312 d->sizes[0] = d->filesize;
00313 d->times[0] = 0;
00314 d->nums = 1;
00315 d->speed_timer.start(1000);
00316 d->slave_calcs_speed =
false;
00317 emit totalSize( size );
00318 }
00319
break;
00320
case INF_PROCESSED_SIZE:
00321 {
00322
KIO::filesize_t size = readFilesize_t(stream);
00323 emit processedSize( size );
00324 d->filesize = size;
00325 }
00326
break;
00327
case INF_SPEED:
00328 stream >> ul;
00329 d->slave_calcs_speed =
true;
00330 d->speed_timer.stop();
00331
00332 emit speed( ul );
00333
break;
00334
case INF_GETTING_FILE:
00335
break;
00336
case INF_ERROR_PAGE:
00337 emit errorPage();
00338
break;
00339
case INF_REDIRECTION:
00340 {
00341
KURL url;
00342 stream >> url;
00343
00344 emit redirection( url );
00345 }
00346
break;
00347
case INF_MIME_TYPE:
00348 stream >> str1;
00349
00350 emit mimeType( str1 );
00351
if (!m_pConnection->
suspended())
00352 m_pConnection->
sendnow( CMD_NONE,
QByteArray() );
00353
break;
00354
case INF_WARNING:
00355 stream >> str1;
00356
00357 emit warning( str1 );
00358
break;
00359
case INF_NEED_PASSWD: {
00360
AuthInfo info;
00361 stream >> info;
00362
openPassDlg( info );
00363
break;
00364 }
00365
case INF_MESSAGEBOX: {
00366
kdDebug(7007) <<
"needs a msg box" <<
endl;
00367
QString text, caption, buttonYes, buttonNo;
00368
int type;
00369 stream >> type >> text >> caption >> buttonYes >> buttonNo;
00370 messageBox(type, text, caption, buttonYes, buttonNo);
00371
break;
00372 }
00373
case INF_INFOMESSAGE: {
00374
QString msg;
00375 stream >> msg;
00376 infoMessage(msg);
00377
break;
00378 }
00379
case INF_META_DATA: {
00380
MetaData meta_data;
00381 stream >> meta_data;
00382 metaData(meta_data);
00383
break;
00384 }
00385
case MSG_NET_REQUEST: {
00386
QString host;
00387
QString slaveid;
00388 stream >> host >> slaveid;
00389 requestNetwork(host, slaveid);
00390
break;
00391 }
00392
case MSG_NET_DROP: {
00393
QString host;
00394
QString slaveid;
00395 stream >> host >> slaveid;
00396 dropNetwork(host, slaveid);
00397
break;
00398 }
00399
case MSG_NEED_SUBURL_DATA: {
00400 emit needSubURLData();
00401
break;
00402 }
00403
case MSG_AUTH_KEY: {
00404
bool keep;
00405
QCString key, group;
00406 stream >>
key >> group >> keep;
00407
kdDebug(7007) <<
"Got auth-key: " <<
key <<
endl
00408 <<
" group-key: " << group <<
endl
00409 <<
" keep password: " << keep <<
endl;
00410 emit
authorizationKey( key, group, keep );
00411
break;
00412 }
00413
case MSG_DEL_AUTH_KEY: {
00414
QCString key;
00415 stream >>
key;
00416
kdDebug(7007) <<
"Delete auth-key: " <<
key <<
endl;
00417 emit
delAuthorization( key );
00418 }
00419
default:
00420
kdWarning(7007) <<
"Slave sends unknown command (" << _cmd <<
"), dropping slave" <<
endl;
00421
return false;
00422 }
00423
return true;
00424 }
00425
00426
void SlaveInterface::setOffset(
KIO::filesize_t o)
00427 {
00428 d->offset = o;
00429 }
00430
00431
KIO::filesize_t SlaveInterface::offset()
const {
return d->offset; }
00432
00433
void SlaveInterface::requestNetwork(
const QString &host,
const QString &slaveid)
00434 {
00435
kdDebug(7007) <<
"requestNetwork " << host << slaveid <<
endl;
00436
QByteArray packedArgs;
00437
QDataStream stream( packedArgs, IO_WriteOnly );
00438 stream <<
true;
00439 m_pConnection->
sendnow( INF_NETWORK_STATUS, packedArgs );
00440 }
00441
00442
void SlaveInterface::dropNetwork(
const QString &host,
const QString &slaveid)
00443 {
00444
kdDebug(7007) <<
"dropNetwork " << host << slaveid <<
endl;
00445 }
00446
00447
void SlaveInterface::sendResumeAnswer(
bool resume )
00448 {
00449
kdDebug(7007) <<
"SlaveInterface::sendResumeAnswer ok for resuming :" << resume <<
endl;
00450 m_pConnection->
sendnow( resume ? CMD_RESUMEANSWER : CMD_NONE,
QByteArray() );
00451 }
00452
00453 void SlaveInterface::openPassDlg(
const QString& prompt,
const QString& user,
bool readOnly )
00454 {
00455
AuthInfo info;
00456 info.
prompt = prompt;
00457 info.
username = user;
00458 info.
readOnly = readOnly;
00459
openPassDlg( info );
00460 }
00461
00462 void SlaveInterface::openPassDlg(
const QString& prompt,
const QString& user,
00463
const QString& caption,
const QString& comment,
00464
const QString& label,
bool readOnly )
00465 {
00466
AuthInfo info;
00467 info.
prompt = prompt;
00468 info.
username = user;
00469 info.
caption = caption;
00470 info.
comment = comment;
00471 info.
commentLabel = label;
00472 info.
readOnly = readOnly;
00473
openPassDlg( info );
00474 }
00475
00476 void SlaveInterface::openPassDlg(
AuthInfo& info )
00477 {
00478
kdDebug(7007) <<
"SlaveInterface::openPassDlg: "
00479 <<
"User= " << info.
username
00480 <<
", Message= " << info.
prompt <<
endl;
00481
bool result =
Observer::self()->
openPassDlg( info );
00482
if ( m_pConnection )
00483 {
00484
QByteArray data;
00485
QDataStream stream( data, IO_WriteOnly );
00486
if ( result )
00487 {
00488 stream << info;
00489
kdDebug(7007) <<
"SlaveInterface:::openPassDlg got: "
00490 <<
"User= " << info.username
00491 <<
", Password= [hidden]" <<
endl;
00492 m_pConnection->
sendnow( CMD_USERPASS, data );
00493 }
00494
else
00495 m_pConnection->
sendnow( CMD_NONE, data );
00496 }
00497 }
00498
00499
void SlaveInterface::messageBox(
int type,
const QString &text,
const QString &_caption,
00500
const QString &buttonYes,
const QString &buttonNo )
00501 {
00502
kdDebug(7007) <<
"messageBox " << type <<
" " << text <<
" - " << _caption <<
endl;
00503
QByteArray packedArgs;
00504
QDataStream stream( packedArgs, IO_WriteOnly );
00505
00506
QString caption( _caption );
00507
if ( type == KIO::SlaveBase::SSLMessageBox )
00508 caption =
QString::fromUtf8(kapp->dcopClient()->appId());
00509
00510 emit needProgressId();
00511
kdDebug(7007) <<
"SlaveInterface::messageBox m_progressId=" << m_progressId <<
endl;
00512
int result =
Observer::messageBox( m_progressId, type, text, caption, buttonYes, buttonNo );
00513
if ( m_pConnection )
00514 {
00515
kdDebug(7007) <<
this <<
" SlaveInterface result=" << result <<
endl;
00516 stream << result;
00517 m_pConnection->
sendnow( CMD_MESSAGEBOXANSWER, packedArgs );
00518 }
00519 }
00520
00521
00522
00523
void SlaveInterface::sigpipe_handler(
int)
00524 {
00525
int saved_errno = errno;
00526
00527
#ifndef NDEBUG
00528
char msg[1000];
00529 sprintf(msg,
"*** SIGPIPE *** (ignored, pid = %ld)\n", (
long) getpid());
00530 write(2, msg, strlen(msg));
00531
#endif
00532
00533
00534
00535 errno = saved_errno;
00536 }
00537
00538
void SlaveInterface::virtual_hook(
int,
void* )
00539 { }
00540
00541
#include "slaveinterface.moc"