• Skip to content
  • Skip to link menu
KDE 4.6 API Reference
  • KDE API Reference
  • kdelibs
  • KDE Home
  • Contact Us
 

KIO

slaveinterface.cpp

Go to the documentation of this file.
00001 /* This file is part of the KDE libraries
00002    Copyright (C) 2000 David Faure <faure@kde.org>
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License version 2 as published by the Free Software Foundation.
00007 
00008    This library is distributed in the hope that it will be useful,
00009    but WITHOUT ANY WARRANTY; without even the implied warranty of
00010    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011    Library General Public License for more details.
00012 
00013    You should have received a copy of the GNU Library General Public License
00014    along with this library; see the file COPYING.LIB.  If not, write to
00015    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00016    Boston, MA 02110-1301, USA.
00017 */
00018 
00019 #include "slaveinterface.h"
00020 #include "slaveinterface_p.h"
00021 
00022 #include "slavebase.h"
00023 #include "connection.h"
00024 #include "hostinfo_p.h"
00025 #include <errno.h>
00026 #include <assert.h>
00027 #include <kdebug.h>
00028 #include <stdlib.h>
00029 #include <sys/time.h>
00030 #include <unistd.h>
00031 #include <signal.h>
00032 #include <klocale.h>
00033 #include <kapplication.h>
00034 #include <ksslinfodialog.h>
00035 #include <kmessagebox.h>
00036 #include <time.h>
00037 #include <QtDBus/QtDBus>
00038 #include <QtCore/QPointer>
00039 #include <QtNetwork/QSslCertificate>
00040 #include <QtNetwork/QSslError>
00041 
00042 using namespace KIO;
00043 
00044 
00045 SlaveInterface::SlaveInterface(SlaveInterfacePrivate &dd, QObject *parent)
00046     : QObject(parent), d_ptr(&dd)
00047 {
00048     connect(&d_ptr->speed_timer, SIGNAL(timeout()), SLOT(calcSpeed()));
00049 }
00050 
00051 SlaveInterface::~SlaveInterface()
00052 {
00053     // Note: no kDebug() here (scheduler is deleted very late)
00054 
00055     delete d_ptr;
00056 }
00057 
00058 void SlaveInterface::setConnection( Connection* connection )
00059 {
00060     Q_D(SlaveInterface);
00061     d->connection = connection;
00062 }
00063 
00064 Connection *SlaveInterface::connection() const
00065 {
00066     const Q_D(SlaveInterface);
00067     return d->connection;
00068 }
00069 
00070 static KIO::filesize_t readFilesize_t(QDataStream &stream)
00071 {
00072     KIO::filesize_t result;
00073     stream >> result;
00074     return result;
00075 }
00076 
00077 bool SlaveInterface::dispatch()
00078 {
00079     Q_D(SlaveInterface);
00080     assert( d->connection );
00081 
00082     int cmd;
00083     QByteArray data;
00084 
00085     int ret = d->connection->read( &cmd, data );
00086     if (ret == -1)
00087       return false;
00088 
00089     return dispatch( cmd, data );
00090 }
00091 
00092 void SlaveInterface::calcSpeed()
00093 {
00094     Q_D(SlaveInterface);
00095     if (d->slave_calcs_speed) {
00096         d->speed_timer.stop();
00097         return;
00098     }
00099 
00100     struct timeval tv;
00101     gettimeofday(&tv, 0);
00102 
00103     long diff = ((tv.tv_sec - d->start_time.tv_sec) * 1000000 +
00104                   tv.tv_usec - d->start_time.tv_usec) / 1000;
00105     if (diff - d->last_time >= 900) {
00106         d->last_time = diff;
00107         if (d->nums == max_nums) {
00108             // let's hope gcc can optimize that well enough
00109             // otherwise I'd try memcpy :)
00110             for (unsigned int i = 1; i < max_nums; ++i) {
00111                 d->times[i-1] = d->times[i];
00112                 d->sizes[i-1] = d->sizes[i];
00113             }
00114             d->nums--;
00115         }
00116         d->times[d->nums] = diff;
00117         d->sizes[d->nums++] = d->filesize - d->offset;
00118 
00119         KIO::filesize_t lspeed = 1000 * (d->sizes[d->nums-1] - d->sizes[0]) / (d->times[d->nums-1] - d->times[0]);
00120 
00121 //      kDebug() << (long)d->filesize << diff
00122 //          << long(d->sizes[d->nums-1] - d->sizes[0])
00123 //          << d->times[d->nums-1] - d->times[0]
00124 //          << long(lspeed) << double(d->filesize) / diff
00125 //          << convertSize(lspeed)
00126 //          << convertSize(long(double(d->filesize) / diff) * 1000);
00127 
00128         if (!lspeed) {
00129             d->nums = 1;
00130             d->times[0] = diff;
00131             d->sizes[0] = d->filesize - d->offset;
00132         }
00133         emit speed(lspeed);
00134     }
00135 }
00136 
00137 #ifndef KDE_USE_FINAL // already defined in slavebase.cpp
00138 /*
00139  * Map pid_t to a signed integer type that makes sense for QByteArray;
00140  * only the most common sizes 16 bit and 32 bit are special-cased.
00141  */
00142 template<int T> struct PIDType { typedef pid_t PID_t; } ;
00143 template<> struct PIDType<2> { typedef qint16 PID_t; } ;
00144 template<> struct PIDType<4> { typedef qint32 PID_t; } ;
00145 #endif
00146 
00147 bool SlaveInterface::dispatch(int _cmd, const QByteArray &rawdata)
00148 {
00149     Q_D(SlaveInterface);
00150     //kDebug(7007) << "dispatch " << _cmd;
00151 
00152     QDataStream stream(rawdata);
00153 
00154     QString str1;
00155     qint32 i;
00156     qint8 b;
00157     quint32 ul;
00158 
00159     switch(_cmd) {
00160     case MSG_DATA:
00161         emit data(rawdata);
00162         break;
00163     case MSG_DATA_REQ:
00164         emit dataReq();
00165         break;
00166     case MSG_OPENED:
00167         emit open();
00168         break;
00169     case MSG_FINISHED:
00170         //kDebug(7007) << "Finished [this = " << this << "]";
00171         d->offset = 0;
00172         d->speed_timer.stop();
00173         emit finished();
00174         break;
00175     case MSG_STAT_ENTRY: {
00176         UDSEntry entry;
00177         stream >> entry;
00178         emit statEntry(entry);
00179         break;
00180     }
00181     case MSG_LIST_ENTRIES: {
00182         quint32 count;
00183         stream >> count;
00184 
00185         UDSEntryList list;
00186         UDSEntry entry;
00187         for (uint i = 0; i < count; i++) {
00188             stream >> entry;
00189             list.append(entry);
00190         }
00191         emit listEntries(list);
00192         break;
00193     }
00194     case MSG_RESUME: { // From the put job
00195         d->offset = readFilesize_t(stream);
00196         emit canResume(d->offset);
00197         break;
00198     }
00199     case MSG_CANRESUME: // From the get job
00200         d->filesize = d->offset;
00201         emit canResume(0); // the arg doesn't matter
00202         break;
00203     case MSG_ERROR:
00204         stream >> i >> str1;
00205         kDebug(7007) << "error " << i << " " << str1;
00206         emit error(i, str1);
00207         break;
00208     case MSG_SLAVE_STATUS: {
00209         PIDType<sizeof(pid_t)>::PID_t stream_pid;
00210         pid_t pid;
00211         QByteArray protocol;
00212         stream >> stream_pid >> protocol >> str1 >> b;
00213         pid = stream_pid;
00214         emit slaveStatus(pid, protocol, str1, (b != 0));
00215         break;
00216     }
00217     case MSG_CONNECTED:
00218         emit connected();
00219         break;
00220     case MSG_WRITTEN: {
00221         KIO::filesize_t size = readFilesize_t(stream);
00222         emit written(size);
00223         break;
00224     }
00225     case INF_TOTAL_SIZE: {
00226         KIO::filesize_t size = readFilesize_t(stream);
00227         gettimeofday(&d->start_time, 0);
00228         d->last_time = 0;
00229         d->filesize = d->offset;
00230         d->sizes[0] = d->filesize - d->offset;
00231         d->times[0] = 0;
00232         d->nums = 1;
00233         d->speed_timer.start(1000);
00234         d->slave_calcs_speed = false;
00235         emit totalSize(size);
00236         break;
00237     }
00238     case INF_PROCESSED_SIZE: {
00239         KIO::filesize_t size = readFilesize_t(stream);
00240         emit processedSize( size );
00241         d->filesize = size;
00242         break;
00243     }
00244     case INF_POSITION: {
00245         KIO::filesize_t pos = readFilesize_t(stream);
00246         emit position(pos);
00247         break;
00248     }
00249     case INF_SPEED:
00250         stream >> ul;
00251         d->slave_calcs_speed = true;
00252         d->speed_timer.stop();
00253         emit speed( ul );
00254         break;
00255     case INF_GETTING_FILE:
00256         break;
00257     case INF_ERROR_PAGE:
00258         emit errorPage();
00259         break;
00260     case INF_REDIRECTION: {
00261         KUrl url;
00262         stream >> url;
00263         emit redirection( url );
00264         break;
00265     }
00266     case INF_MIME_TYPE:
00267         stream >> str1;
00268         emit mimeType(str1);
00269         if (!d->connection->suspended())
00270             d->connection->sendnow(CMD_NONE, QByteArray());
00271         break;
00272     case INF_WARNING:
00273         stream >> str1;
00274         emit warning(str1);
00275         break;
00276     case INF_MESSAGEBOX: {
00277         kDebug(7007) << "needs a msg box";
00278         QString text, caption, buttonYes, buttonNo, dontAskAgainName;
00279         int type;
00280         stream >> type >> text >> caption >> buttonYes >> buttonNo;
00281         if (stream.atEnd()) {
00282             messageBox(type, text, caption, buttonYes, buttonNo);
00283         } else {
00284             stream >> dontAskAgainName;
00285             messageBox(type, text, caption, buttonYes, buttonNo, dontAskAgainName);
00286         }
00287         break;
00288     }
00289     case INF_INFOMESSAGE: {
00290         QString msg;
00291         stream >> msg;
00292         emit infoMessage(msg);
00293         break;
00294     }
00295     case INF_META_DATA: {
00296         MetaData m;
00297         stream >> m;
00298         if (m.contains(QLatin1String("ssl_in_use"))) {
00299             const QLatin1String ssl_("ssl_");
00300             const MetaData constM = m;
00301             for (MetaData::ConstIterator it = constM.lowerBound(ssl_); it != constM.constEnd(); ++it) {
00302                 if (it.key().startsWith(ssl_)) {
00303                     d->sslMetaData.insert(it.key(), it.value());
00304                 } else {
00305                     // we're past the ssl_* entries; remember that QMap is ordered.
00306                     break;
00307                 }
00308             }
00309         }
00310         emit metaData(m);
00311         break;
00312     }
00313     case MSG_NET_REQUEST: {
00314         QString host;
00315         QString slaveid;
00316         stream >> host >> slaveid;
00317         requestNetwork(host, slaveid);
00318         break;
00319     }
00320     case MSG_NET_DROP: {
00321         QString host;
00322         QString slaveid;
00323         stream >> host >> slaveid;
00324         dropNetwork(host, slaveid);
00325         break;
00326     }
00327     case MSG_NEED_SUBURL_DATA: {
00328         emit needSubUrlData();
00329         break;
00330     }
00331     case MSG_HOST_INFO_REQ: {
00332         QString hostName;
00333         stream >> hostName;
00334         HostInfo::lookupHost(hostName, this, SLOT(slotHostInfo(QHostInfo)));
00335         break;
00336     }
00337     default:
00338         kWarning(7007) << "Slave sends unknown command (" << _cmd << "), dropping slave";
00339         return false;
00340     }
00341     return true;
00342 }
00343 
00344 void SlaveInterface::setOffset( KIO::filesize_t o)
00345 {
00346     Q_D(SlaveInterface);
00347     d->offset = o;
00348 }
00349 
00350 KIO::filesize_t SlaveInterface::offset() const
00351 {
00352     const Q_D(SlaveInterface);
00353     return d->offset;
00354 }
00355 
00356 void SlaveInterface::requestNetwork(const QString &host, const QString &slaveid)
00357 {
00358     Q_D(SlaveInterface);
00359     kDebug(7007) << "requestNetwork " << host << slaveid;
00360     QByteArray packedArgs;
00361     QDataStream stream( &packedArgs, QIODevice::WriteOnly );
00362     stream << true;
00363     d->connection->sendnow( INF_NETWORK_STATUS, packedArgs );
00364 }
00365 
00366 void SlaveInterface::dropNetwork(const QString &host, const QString &slaveid)
00367 {
00368     kDebug(7007) << "dropNetwork " << host << slaveid;
00369 }
00370 
00371 void SlaveInterface::sendResumeAnswer( bool resume )
00372 {
00373     Q_D(SlaveInterface);
00374     kDebug(7007) << "ok for resuming:" << resume;
00375     d->connection->sendnow( resume ? CMD_RESUMEANSWER : CMD_NONE, QByteArray() );
00376 }
00377 
00378 void SlaveInterface::messageBox( int type, const QString &text, const QString &_caption,
00379                                  const QString &buttonYes, const QString &buttonNo )
00380 {
00381     messageBox( type, text, _caption, buttonYes, buttonNo, QString() );
00382 }
00383 
00384 void SlaveInterface::messageBox( int type, const QString &text, const QString &caption,
00385                                  const QString &buttonYes, const QString &buttonNo, const QString &dontAskAgainName )
00386 {
00387     Q_D(SlaveInterface);
00388     kDebug(7007) << "messageBox " << type << " " << text << " - " << caption << " " << dontAskAgainName;
00389     QByteArray packedArgs;
00390     QDataStream stream( &packedArgs, QIODevice::WriteOnly );
00391 
00392     QPointer<SlaveInterface> me = this;
00393     if (d->connection) d->connection->suspend();
00394     int result = d->messageBox( type, text, caption, buttonYes, buttonNo, dontAskAgainName );
00395     if ( me && d->connection ) // Don't do anything if deleted meanwhile
00396     {
00397         d->connection->resume();
00398         kDebug(7007) << this << " SlaveInterface result=" << result;
00399         stream << result;
00400         d->connection->sendnow( CMD_MESSAGEBOXANSWER, packedArgs );
00401     }
00402 }
00403 
00404 int SlaveInterfacePrivate::messageBox(int type, const QString &text,
00405                                       const QString &caption, const QString &buttonYes,
00406                                       const QString &buttonNo, const QString &dontAskAgainName)
00407 {
00408     kDebug() << type << text << "caption=" << caption;
00409     int result = -1;
00410     KConfig *config = new KConfig("kioslaverc");
00411     KMessageBox::setDontShowAskAgainConfig(config);
00412 
00413     // SMELL: the braindead way to support button icons
00414     KGuiItem buttonYesGui, buttonNoGui;
00415     
00416     if (buttonYes == i18n("&Details"))
00417         buttonYesGui = KGuiItem(buttonYes, "help-about");
00418     else if (buttonYes == i18n("&Forever"))
00419         buttonYesGui = KGuiItem(buttonYes, "flag-green");
00420     else
00421         buttonYesGui = KGuiItem(buttonYes);
00422 
00423     if (buttonNo == i18n("Co&ntinue"))
00424         buttonNoGui = KGuiItem(buttonNo, "arrow-right");
00425     else if (buttonNo == i18n("&Current Session only"))
00426         buttonNoGui = KGuiItem(buttonNo, "chronometer");
00427     else
00428         buttonNoGui = KGuiItem(buttonNo);
00429 
00430     switch (type) {
00431     case KIO::SlaveBase::QuestionYesNo:
00432         result = KMessageBox::questionYesNo(
00433                      0, text, caption, buttonYesGui,
00434                      buttonNoGui, dontAskAgainName);
00435         break;
00436     case KIO::SlaveBase::WarningYesNo:
00437         result = KMessageBox::warningYesNo(
00438                      0, text, caption, buttonYesGui,
00439                      buttonNoGui, dontAskAgainName);
00440         break;
00441     case KIO::SlaveBase::WarningContinueCancel:
00442         result = KMessageBox::warningContinueCancel(
00443                      0, text, caption, buttonYesGui,
00444                      KStandardGuiItem::cancel(), dontAskAgainName);
00445         break;
00446     case KIO::SlaveBase::WarningYesNoCancel:
00447         result = KMessageBox::warningYesNoCancel(
00448                      0, text, caption, buttonYesGui, buttonNoGui,
00449                      KStandardGuiItem::cancel(), dontAskAgainName);
00450         break;
00451     case KIO::SlaveBase::Information:
00452         KMessageBox::information(0, text, caption, dontAskAgainName);
00453         result = 1; // whatever
00454         break;
00455     case KIO::SlaveBase::SSLMessageBox:
00456     {
00457         KIO::MetaData meta = sslMetaData;
00458         KSslInfoDialog *kid = new KSslInfoDialog(0);
00459         //### this is boilerplate code and appears in khtml_part.cpp almost unchanged!
00460         QStringList sl = meta["ssl_peer_chain"].split('\x01', QString::SkipEmptyParts);
00461         QList<QSslCertificate> certChain;
00462         bool decodedOk = true;
00463         foreach (const QString &s, sl) {
00464             certChain.append(QSslCertificate(s.toAscii())); //or is it toLocal8Bit or whatever?
00465             if (certChain.last().isNull()) {
00466                 decodedOk = false;
00467                 break;
00468             }
00469         }
00470 
00471         if (decodedOk || true/*H4X*/) {
00472             kid->setSslInfo(certChain,
00473                             meta["ssl_peer_ip"],
00474                             text, // the URL
00475                             meta["ssl_protocol_version"],
00476                             meta["ssl_cipher"],
00477                             meta["ssl_cipher_used_bits"].toInt(),
00478                             meta["ssl_cipher_bits"].toInt(),
00479                             KSslInfoDialog::errorsFromString(meta["ssl_cert_errors"]));
00480             kDebug(7024) << "Showing SSL Info dialog";
00481             kid->exec();
00482             kDebug(7024) << "SSL Info dialog closed";
00483         } else {
00484             KMessageBox::information(0, i18n("The peer SSL certificate chain "
00485                                              "appears to be corrupt."),
00486                                      i18n("SSL"));
00487         }
00488         // KSslInfoDialog deletes itself (Qt::WA_DeleteOnClose).
00489         result = 1; // whatever
00490         break;
00491     }
00492     default:
00493         kWarning() << "unknown type" << type;
00494         result = 0;
00495         break;
00496     }
00497     KMessageBox::setDontShowAskAgainConfig(0);
00498     delete config;
00499     return result;
00500 }
00501 
00502 void SlaveInterfacePrivate::slotHostInfo(const QHostInfo& info)
00503 {
00504     QByteArray data;
00505     QDataStream stream(&data, QIODevice::WriteOnly);
00506     stream <<  info.hostName() << info.addresses() << info.error() << info.errorString();
00507     connection->send(CMD_HOST_INFO, data);
00508 }
00509 
00510 #include "slaveinterface.moc"

KIO

Skip menu "KIO"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.7.3
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal