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