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

KIO

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

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • 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.5
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