<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Rich on KDE Blogs</title><link>https://blogs.kde.org/authors/rich/</link><description>Recent content in Rich on KDE Blogs</description><generator>Hugo -- gohugo.io</generator><language>en</language><lastBuildDate>Fri, 14 Aug 2026 17:14:25 -0400</lastBuildDate><atom:link href="https://blogs.kde.org/authors/rich/index.xml" rel="self" type="application/rss+xml"/><item><title>A trip down memory lane</title><link>https://blogs.kde.org/2012/11/17/trip-down-memory-lane/</link><pubDate>Sat, 17 Nov 2012 00:00:00 +0000</pubDate><author>Rich</author><guid>https://blogs.kde.org/2012/11/17/trip-down-memory-lane/</guid><description>&lt;p&gt;I was digging through some old backups on Friday looking to see if I had any old versions of the Qt source code lying around after Eirik mentioned during his devdays talk that the release tar balls for lots of the early releases including Qt 1.0 had got lost... I didn't find those, but I found some gems I didn't know I had.&lt;/p&gt;
&lt;p&gt;
First, there's a presentation on the &lt;a
href="http://xmelegance.org/KDE-internals/"&gt;KDE internals&lt;/a&gt; I don't know where I gave, I suspect it was at MANLUG (the Manchester Linux User Group).
&lt;p&gt;
Next, there's a presentation &lt;a href="http://xmelegance.org/simplinux-1999/The%20design%20of%20the%20K%20Desktop%20Environment/"&gt;The design of the K Desktop Environment&lt;/a&gt; I gave at Simplinux in Faro, Portugal back in 1999. This one has a bit more depth than the first It's from back before we released KDE 2.0. This one talks about us using CORBA. The biggest thing in retrospect that happened at this conference is I met Nuno Pinheiro KDE's artist in chief. The colour scheme of the slides might make your eyes hurt (that's why Nuno's so important), I recommend the text version myself!
&lt;p&gt;
Finally there's a presentation &lt;a href="http://xmelegance.org/KDE2-Technologies.pdf"&gt;The Technology Behind KDE 2.0&lt;/a&gt; that was given after the release of KDE 2.0 but before the release of KDE 2.1. I've no idea where I gave this one. It mentions the removal of CORBA, and brings in important tools like KSycoca that we still use today. It also talks about &lt;strike&gt;DBUS&lt;/strike&gt;DCOP which was the conceptual parent of the DBUS API that is used all over linux today.
&lt;p&gt;
A nice little trip down memory lane I hope you'll agree.
&lt;!--break--&gt;
&lt;p&gt;Edit: Changed to a pdf link for the last one since google docs required a sign in.&lt;/p&gt;</description></item><item><title>An Unexpected Journey</title><link>https://blogs.kde.org/2012/05/19/unexpected-journey/</link><pubDate>Sat, 19 May 2012 00:00:00 +0000</pubDate><author>Rich</author><guid>https://blogs.kde.org/2012/05/19/unexpected-journey/</guid><description>&lt;p&gt;Recently, when building qt5, I'd started noticing some very strange errors from the configure script. The errors seemed to indicate that an awk script was being used as a filename - very strange. Even stranger was that other people weren't hitting this issue - just me. Never a good sign. Today, I finally got around to debugging it and the issue was rather weird.&lt;/p&gt;
&lt;p&gt;
My initial thought was that my version of bash was incompatible with the script in some way, so I copied the code for the function that was erroring and made a standalone version - it worked fine. &lt;p&gt; I then tried to run the configure script using sh -x to watch it was doing, but unfortunately that seemed to confuse the script. Finally, I started to read the code. The relevant function reads:
&lt;pre&gt;

$awk ' BEGIN {

lots of awk

} '
&lt;/pre&gt;
&lt;p&gt;Finally, I spotted that $awk was not being set. If you look at the script then you can see that the qt5 configure looks for gawk, nawk then finally awk. So, the obvious step was to see if I had a version of awk installed. Using 'which' told me I didn't have one, but using rpm -q told me I did - curiouser and curiouser.&lt;/p&gt;
&lt;p&gt;
I checked what the gawk package installed and I could see that at least part of it was there, but running it gave an IO error - very weird. In fact, I could see that I was running a symlink that pointed to a file that wasn't there. At this point, I assumed a bad update of some kind, so I ran:
&lt;pre&gt;
zypper install gawk
&lt;/pre&gt;
&lt;p&gt;It said my gawk was the lastest. I then tried&lt;/p&gt;
&lt;pre&gt;
zypper install -f gawk
&lt;/pre&gt;
&lt;p&gt;to force the install and it gave an IO error. Spot the pattern? Every
time I try to do stuff to the gawk binary I get an IO error. At this point, I looked at /var/log/messages and saw a lot of messages like this:&lt;/p&gt;
&lt;pre&gt;
May 19 18:51:06 linux-h33o kernel: [ 58.719815] EXT4-fs error (device
sda6): ext4_ext_check_inode:403: inode #393297: comm rpm: bad header/extent:
invalid magic - magic 0, entries 0, max 0(0), depth 0(0)
&lt;/pre&gt;
&lt;p&gt;Not good.&lt;/p&gt;
&lt;p&gt;
This seemed like some kind of file system corruption, so I backed up my files immediately before I carried on investigating. Running fsck from a rescue system showed a few errors, but nothing major, and all were fixable. After allowing the repair I rebooted, sure in the knowledge that the problem was solved.
&lt;p&gt;
All I needed to do was reinstall the corrupted gawk package:
&lt;pre&gt;
linux-h33o:/home/rich/src # zypper install -f gawk Loading repository
data...
Reading installed packages...
Forcing installation of 'gawk-4.0.0-3.1.2.x86_64' from repository 'openSUSE-12.1-Oss'.
Resolving package dependencies...

The following package is going to be reinstalled: gawk

1 package to reinstall.
Overall download size: 820.0 KiB.
No additional space will be used or freed after the operation. Continue? [y/n/?] (y):
Installing:
gawk-4.0.0-3.1.2 [error] Installation of gawk-4.0.0-3.1.2 failed: (with
--nodeps --force)
Error: Subprocess failed. Error: RPM failed: error:
unpacking of archive failed on file /bin/gawk: cpio: rename failed -
Input/output error error:
gawk-4.0.0-3.1.2.x86_64: install failed
&lt;/pre&gt;
&lt;p&gt;Oh dear. It's not good when fsck says the file system is ok, but the driver disagrees.&lt;/p&gt;
&lt;p&gt;
At this point, I started doing some serious googling to figure out wtf was going on. Happily, I came across the following bug report that let me resolve the issue https://bugzilla.kernel.org/show_bug.cgi?id=32182 . By following the debugfs steps described, I was able to kill the bad inode. Thank fully this fixed my file system.
&lt;p&gt;
So what can we learn from this? Obviously, we can learn that the configure script wasn't the source of the problem, but simply the way it manifested. It also shows that the configure script has a bug in that it doesn't report when awk is missing. We can also learn that a bit of googling can solve a lot of problems.
&lt;p&gt;
A final point to note if anyone is considering doing evil things with debugfs like this is that as soon as I figured out I had a corrupt file system I made a backup. This gives you a nice warm glow inside as you know you can attempt things that would otherwise be insanely risky.
&lt;!--break--&gt;</description></item><item><title>What's New in Qt 5 for SSL?</title><link>https://blogs.kde.org/2012/04/14/whats-new-qt-5-ssl/</link><pubDate>Sat, 14 Apr 2012 00:00:00 +0000</pubDate><author>Rich</author><guid>https://blogs.kde.org/2012/04/14/whats-new-qt-5-ssl/</guid><description>&lt;p&gt;With the availability of the Qt 5 alpha, I thought I'd try to summarise what's been done in the SSL stack. Most of the changes in Qt 5 for SSL are incremental improvements, or things that will form the basis of future changes. In this post I'll try to highlight the main changes:&lt;/p&gt;
&lt;li&gt;QSslCertificate::subjectInfo() and QSslCertificate::issuerInfo() now return a QStringList instead of a QString
&lt;p&gt;It's pretty common for a certificate to contain more than entry of a specific type, but in Qt 4 the API only let you access the first one.&lt;/p&gt;
&lt;li&gt;QSslCertificate::isValid() has been deprecated.
&lt;p&gt;Originally this method was just used to check the validity of the dates for which a certificate was valid, when the certificate blacklist was introduced to deal with issues such as the Commodo compromise, checking for blacklisted certificates was added too. Unfortunately the name of the method gave the misleading impression that simply calling it was enough check the validity of a certificate - it isn't. There is now a new isBlacklisted() method which can be used to check if a certificate is blacklisted (and checking the dates is trivial anyway).&lt;/p&gt;
&lt;li&gt;QSslCertificate::alternateSubjectNames() is deprecated and replaced by QSslCertificate::subjectAlternativeNames().
&lt;p&gt;The new name reflects the actual name of this field in the RFCs etc.&lt;/p&gt;
&lt;li&gt;The QSsl::TlsV1 enum value was renamed to QSsl::TlsV1_0
&lt;p&gt;Since there are now multiple versions of TLS this is a pretty obvious change.&lt;/p&gt;
&lt;li&gt;QSslCertificate::serialNumber() now always returns the serial number in hexadecimal format.
&lt;p&gt;The old code returned the serial number as a hex string if it was long, but as an integer if it was short. For consistency we now always use the same format.&lt;/p&gt;
&lt;li&gt;The openssl network backend now reads the ssl configuration file allowing the use of openssl engines.
&lt;p&gt;This change means that people wanting to use openssl engines such as hardware accelerators can do so using their openssl config file and Qt will respect the setting. This was possible before, but required setting a flag at compile time.&lt;/p&gt;
&lt;li&gt;QSSlCertificate::toText()
&lt;p&gt;There's now a method to convert a certificate to human readable text (for certain values of human).&lt;/p&gt;
&lt;li&gt;QsslCertificate::verify()
&lt;p&gt;There is now a method to verify a certificate chains validity. This means that you can check a certificate chain against the root store directly.&lt;/p&gt;
&lt;li&gt;QSslCertificate::extensions()
&lt;p&gt;X.509 certificates can contain extensions (and almost all do). Qt previously only supported the subject alternative name extension. In Qt 5 this new method returns a list of all extensions, and does its best to convert them into a sensible structure. Some extensions such as basicConstraints and subjectKeyIdentifier (for example) are supported to the extent that the structure is defined. Other extensions can also be accessed, though the structure of the information returned may change between versions.&lt;/p&gt;
&lt;p&gt;
This change isn't massively useful in itself, but it provides a foundation for future improvements.
&lt;li&gt;QSslSocket can now pause on ssl errors
&lt;p&gt;Currently, a nested event loop is required in order to process the sslErrors signal from QSslSocket. In Qt 5, you can use the setPauseMode() method of QAbstractSocket to tell the socket to pause when the error signal is emitted. This means that no data will be transmitted until you tell the socket to continue, allowing the nested event loop to be avoided.&lt;/p&gt;
&lt;p&gt;
It is intended to extend this facility to cover authentication requests too. In future, you will probably also be able to request that the socket be paused at the end of the handshake even if there were no errors so you can perform future checks. Unfortunately time constraints meant that only the first step described above was completed (and that QNetworkAccessManager does not make use of this facility).
&lt;li&gt;QSslConfiguration::setSslOption()
&lt;p&gt;In Qt5 you can enable and disable various bug workarounds etc. using this method. This change was backported to 4.8.&lt;/p&gt;
&lt;li&gt;New QT_NO_SSL define
&lt;p&gt;In older versions of Qt you could make code conditional on SSL support being available using #ifdef QT_NO_OPENSSL, but this is tied to the openssl backend. In order to allow for additional backends in the future such as one using GnuTLS there is now a QT_NO_SSL define too. This means that unless you actually depend on the openssl backend (eg. because you are using the native handles to perform additional openssl calls yourself) you should use QT_NO_SSL.&lt;/p&gt;
&lt;li&gt;Support for opaque QSslKeys
&lt;p&gt;Qt 5 adds support for a new type of QSslKey that is 'opaque' this new type can be used to build things like PKCS#11 support into code using Qt. An example of this is at &lt;a href="http://git.iksaif.net/?p=qsslkey-p11.git;a=tree"&gt;http://git.iksaif.net/?p=qsslkey-p11.git;a=tree&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;
In addition to these new features, there have also been lots of bug fixes etc. too, but you can see those in the bug tracker.
&lt;!--break--&gt;</description></item><item><title>Using GnuTLS with QTcpSocket</title><link>https://blogs.kde.org/2012/01/14/using-gnutls-qtcpsocket/</link><pubDate>Sat, 14 Jan 2012 00:00:00 +0000</pubDate><author>Rich</author><guid>https://blogs.kde.org/2012/01/14/using-gnutls-qtcpsocket/</guid><description>&lt;p&gt;It's been quite a while since I last wrote a blog post, but it's not because I haven't been coding, in fact quite the opposite. The Qt opengov project is finally underway and I've been doing quite a lot of work on the various SSL classes. I'm now an official Qt approver, so as you can see the process of getting non-nokia developers the ability to commit to Qt is working.&lt;/p&gt;
&lt;p&gt;In Qt 4.x and currently in Qt5 even though the various QSsl classes provide an abstraction from the underlying SSL implementation, there is only one backend and it uses openssl. I recently made a change that means we can add new backends during the Qt5 life time by separating the concepts of SSL support from the availability of SSL - of course this doesn't change anything if openssl is the only game in town.&lt;/p&gt;
&lt;p&gt;Over the last couple of weekends, I've been investigating GnuTLS as a
potential implementation that could form the basis of a second backend. I started with the easy part - handling X.509 certificates, and last weekend managed to implement some code that showed that we could implement this part of the Qt API using GnuTLS. I did hit some issues of course, but most were minor. The GnuTLS maintainer Nikos Mavrogiannopoulos has already fixed the minor documentation issues I spotted, and has even implemented a couple of features that I found were missing - definitely a sign that this library is being actively maintained I think you'll agree.&lt;/p&gt;
&lt;p&gt;Today I attempted the more challenging task of trying to make GnuTLS work through a QTcpSocket. This integration is essential for using the library in Qt since without it features such as proxy support etc. would not be available - it really is a 'must have'. As you might guess from the fact I'm bothering to blog about it the results were positive, so let's take a look.&lt;/p&gt;
&lt;p&gt;What I've done for this prototype is implement a QObject that provides the same basic outline as a QIODevice subclass. In order to keep things simple, I haven't yet tried to make something that is tied to that specific API at this point. I've also not tried to integrate this into QSslSocket, instead this code aims to demonstrate that doing so will be feasible in future.&lt;/p&gt;
&lt;p&gt;The API I've implemented is reasonably close to what QSslSocket offers, the header file should make it clear that most of what you'd expect is there:&lt;/p&gt;
&lt;pre&gt;
class SslSocket : public QObject
{
 Q_OBJECT

public:
 SslSocket(QObject *parent=0);
 ~SslSocket();

 QByteArray read(qint64 maxsize);
 
public slots:
 void connectToHost(const QString &amp;hostname, int port);
 void startHandshake();

 qint64 write(const QByteArray &amp;data);

signals:
 void handshakeComplete();
 void readyRead();
 void error();

private slots:
 void dataReceived();

private:
 void setupSession();
 void handshakeInternal();

 ssize_t readInternal(void *buffer, size_t length);
 ssize_t writeInternal(const void *buffer, size_t length);
 ssize_t writeVectorInternal(const giovec_t *iov, int iovcnt);

 static ssize_t read_callback(gnutls_transport_ptr_t transport, void *buffer, size_t length);
 static ssize_t write_callback(gnutls_transport_ptr_t transport, const void *buffer, size_t length);
 static ssize_t write_vector_callback(gnutls_transport_ptr_t transport, const giovec_t *iov, int iovcnt);

 SslSocketPrivate *d;
};
&lt;/pre&gt;
&lt;p&gt;Now you've seen the header, let's take a look at the implementation. The first method we'll look at is the one that performs the initial setup of our SSL session. This happens before we even attempt to send any data to the server since once of the things we're going to do is change the way data is sent to run it via QTcpSocket:&lt;/p&gt;
&lt;pre&gt;
void SslSocket::setupSession()
{
 qDebug() &amp;lt;&amp;lt; "Initialise client session";

 // Setup the trust store
 gnutls_certificate_allocate_credentials(&amp;amp;d-&gt;x509cred);
 gnutls_certificate_set_x509_trust_file(d-&gt;x509cred, "/etc/ssl/ca-bundle.pem", GNUTLS_X509_FMT_PEM);

 // Configure the session
 gnutls_init(&amp;amp;d-&gt;session, GNUTLS_CLIENT);
 gnutls_credentials_set(d-&gt;session, GNUTLS_CRD_CERTIFICATE, d-&gt;x509cred);

 const char *err;
 gnutls_priority_init(&amp;amp;d-&gt;priority_cache, "NORMAL", &amp;amp;err);
 gnutls_priority_set(d-&gt;session, d-&gt;priority_cache);

 // Setup the transport functions to use QTcpSocket
 gnutls_transport_set_ptr(d-&gt;session, this);
 gnutls_transport_set_pull_function(d-&gt;session, read_callback);
 gnutls_transport_set_push_function(d-&gt;session, write_callback);
}
&lt;/pre&gt;
&lt;p&gt;The first thing this method does is setup the trust store, and point it to the location of the CA bundle on my opensuse 12.1 system. In fact, this is a total waste of time, since verifying the certificate isn't something I've implemented yet! The next part is rather more useful however, we initialise a session and tell GnuTLS that we're acting as an SSL client. After this, we set the priority of the various ciphers etc. that are available. This step seemed unimportant, but I discovered that if you fail to do it then rather than using a sane default, GnuTLS dies with an internal error. The last setup step we do is to tell the library that we want to use our own functions to send and receive data rather than using the built-in ones.&lt;/p&gt;
&lt;p&gt;For each of the read and write functions, we provide a callback. This is a static method (since a pointer-to-member-function is a no-no for reasons I won't go into). Our static method then calls the member function that implements our callback:&lt;/p&gt;
&lt;pre&gt;
ssize_t SslSocket::read_callback(gnutls_transport_ptr_t transport, void *buffer, size_t length)
{
 SslSocket *self = static_cast&amp;lt;SslSocket *&gt;(transport);
 return self-&gt;readInternal(buffer, length);
}

ssize_t SslSocket::readInternal(void *buffer, size_t length)
{
 qDebug() &amp;lt;&amp;lt; "readInternal, length" &amp;lt;&amp;lt; length &amp;lt;&amp;lt; ", available" &amp;lt;&amp;lt; d-&gt;socket-&gt;bytesAvailable();

 if (d-&gt;socket-&gt;bytesAvailable() &amp;lt; qint64(length)) {
 gnutls_transport_set_errno(d-&gt;session, EAGAIN);
 return -1;
 }

 return d-&gt;socket-&gt;read(static_cast&amp;lt;char *&gt;(buffer), length);
}
&lt;/pre&gt;
&lt;p&gt;As you can see the static function simply casts the user data pointer (which we provided using gnutls_transport_set_ptr earlier) to our class, then calls the appropriate method. The read implementation simply sees if we have enough bytes in our socket's buffer to satisfy the request, and if not tells the library to try again. If we do, then naturally we read the data. The data we need can only become available when the eventloop is running since that's when QTcpSocket performs its data transfers. If we simply retried immediately then
we'd see no more data than we did during our first attempt.&lt;/p&gt;
&lt;p&gt;The write function is similar, but since QTcpSocket has buffering of its own we can simply perform the write as requested. My real implementation supports a slightly more complex form of the write function that can process requests to write several blocks of data at once, but the basic concept is the same.&lt;/p&gt;
&lt;p&gt;In order to allow the retry behaviour I mention above, there's a simple state machine. The SslSocket has the following basic states:&lt;/p&gt;
&lt;pre&gt;
enum State
{
 Disconnected,
 Connecting,
 Handshaking,
 Encrypted
};
&lt;/pre&gt;
&lt;p&gt;If new data is received then we look the state and retry the relevant
operation as follows:&lt;/p&gt;
&lt;pre&gt;
void SslSocket::dataReceived()
{
 qDebug() &amp;lt;&amp;lt; "dataReceived() state is " &amp;lt;&amp;lt; d-&gt;state;

 if (d-&gt;state == Handshaking) {
 handshakeInternal();
 }
 else if (d-&gt;state == Encrypted) {
 emit readyRead();
 }
}
&lt;/pre&gt;
&lt;p&gt;The handshakeInternal() method is the one that actually performs the SSL handshake, and as you can see if we're in the appropriate state then we retry each time more data is received. The actual implementation is pretty simple:&lt;/p&gt;
&lt;pre&gt;
void SslSocket::handshakeInternal()
{
 qDebug() &amp;lt;&amp;lt; "start handshake, state is" &amp;lt;&amp;lt; d-&gt;state;
 int result = gnutls_handshake(d-&gt;session);
 qDebug() &amp;lt;&amp;lt; "shake result" &amp;lt;&amp;lt; gnutls_strerror(result) &amp;lt;&amp;lt; result;

 if (result == 0) {
 qDebug() &amp;lt;&amp;lt; "handshake completed";
 d-&gt;state = Encrypted;
 emit handshakeComplete();
 }
 else if (gnutls_error_is_fatal(result)) {
 qDebug() &amp;lt;&amp;lt; "fatal error in handshake";
 emit error();
 d-&gt;socket-&gt;disconnect();
 d-&gt;state = Disconnected;
 }
}
&lt;/pre&gt;
&lt;p&gt;As you can see, once we get a real result from the handshake (ie. one that can't be solved with more data) then we emit either the handshakeComplete() signals or the error() signal and update the state of the SslSocket. If the handshake is completed successfully then we can now send and receive encrypted data.&lt;/p&gt;
&lt;p&gt;The read and write methods are similar. In both cases, we need to consider the possibility that we need to retry (indicated by either an interrupted, or again error). The implementations are as follows:&lt;/p&gt;
&lt;pre&gt;
QByteArray SslSocket::read(qint64 maxsize)
{
 QByteArray buffer;

 if (d-&gt;state != Encrypted) {
 qFatal("Write before encrypted is not supported yet");
 return buffer;
 }

 buffer.resize(maxsize); // ### This could get pretty big!
 ssize_t result;
 do {
 result = gnutls_record_recv(d-&gt;session, buffer.data(), maxsize);
 } while( result == GNUTLS_E_INTERRUPTED || result == GNUTLS_E_AGAIN );

 buffer.truncate(result);

 return buffer;
}

qint64 SslSocket::write(const QByteArray &amp;data)
{
 qDebug() &amp;lt;&amp;lt; "write";

 if (d-&gt;state != Encrypted) {
 qFatal("Write before encrypted is not supported yet");
 return -1;
 }

 ssize_t result;
 do {
 // ### It's possible that this could fail due to the need to read some data
 // for example if a renegotiation is underway. Not sure.
 result = gnutls_record_send(d-&gt;session, data.constData(), data.size());
 qDebug() &amp;lt;&amp;lt; "write result" &amp;lt;&amp;lt; result;
 } while( result == GNUTLS_E_INTERRUPTED || result == GNUTLS_E_AGAIN );

 return result;
}
&lt;/pre&gt;
&lt;p&gt;In order to test this, I wrote a very simple class that will perform an HTTP GET and read the response. The result is that we can can connect to an HTTPS server and see the root page - not very exciting I guess but a sign that everything is working!&lt;/p&gt;
&lt;pre&gt;
GetSlash::GetSlash(SslSocket *sock)
 : QObject()
{
 this-&gt;sock = sock;
 connect(sock, SIGNAL(handshakeComplete()), this, SLOT(start()));
 connect(sock, SIGNAL(readyRead()), this, SLOT(gotData()));
}

void GetSlash::start()
{
 sock-&gt;write(QByteArray("GET / HTTP/1.0\n\n"));
}

void GetSlash::gotData()
{
 QByteArray result = sock-&gt;read(2000);
 qDebug() &amp;lt;&amp;lt; result;
}
&lt;/pre&gt;
&lt;p&gt;Finally there's a basic main() function that ties all this together, and a little bit of code to log what's going on. The end result is that I now feel confident that we could implement a working backend for QSslSocket etc. using GnuTLS without too much trouble.&lt;/p&gt;
&lt;p&gt;I'll add the code to my normal qt-examples repository later, but if anyone needs it (or earlier experiment experimenting with the certificate APIs) then just let me know.&lt;/p&gt;
&lt;p&gt;EDIT: The code is now available here &lt;a href="https://gitorious.org/qt-examples/qt-examples/commit/40e57647242079745c46d84e15d92f2093af300f"&gt;https://gitorious.org/qt-examples/qt-examples/commit/40e57647242079745c46d84e15d92f2093af300f&lt;/a&gt;&lt;/p&gt;
&lt;!--break--&gt;</description></item><item><title>Qt SSL Update</title><link>https://blogs.kde.org/2011/11/06/qt-ssl-update/</link><pubDate>Sun, 06 Nov 2011 00:00:00 +0000</pubDate><author>Rich</author><guid>https://blogs.kde.org/2011/11/06/qt-ssl-update/</guid><description>&lt;p&gt;It's been a while since I blogged, so I thought I'd post an update on what I've been up to.&lt;/p&gt;
&lt;p&gt;Along with nearly a thousand other Qt developers, I headed over to Munich for the Qt Dev Days. It was my first time at the event, and I was surprised just how big it was. There were a lot of interesting talks, with highlights including Jens' talks on Qt Quick components for the desktop and using QML for rapid prototyping and Peter's talk on Secure Networking.&lt;/p&gt;
&lt;p&gt;Before all the talks however, we had a day full of Qt contributor sessions. This included a lot of discussions about how the open governance model should work, and also technical sessions on individual areas. I've posted my notes from a couple of sessions to the new Development mailing list, including my notes from the various discussions on SSL.&lt;/p&gt;
&lt;p&gt;I'd like to thank the KDE eV for sponsoring my travel and hotel, Nokia for my Dev Days pass (and a shiny new N9), and my own company, Westpoint, for letting me attend.&lt;/p&gt;
&lt;p&gt;In terms of coding, I've been fairly busy too. I've recently added support for disabling fancy new features of SSL/TLS like session tickets, compression and server name indication that since they're so shiny and new (ahem, most of them are ten years old at least) seem to be incompatible with various expensive SSL accelerators. This change has been backported to Qt 4.8 so we should be able to use it in KDE 4.x too.&lt;/p&gt;
&lt;p&gt;I've also made a few changes that are only in the Qt 5.0 branch since they're really too big a change to slip into the 4.8 tree at this stage. The major one is the ability to verify a certificate chain without needing to connect to a server.&lt;/p&gt;
&lt;p&gt;Most recently, I've written a pretty large improvement to the handling of certificates to add support for certificate extensions. This change has been handled under the open governance system using gerrit, which has resulted in a much faster turn-around than the previous gitorious based approach of merge requests. The new code makes it possible to access all the certificate extensions, with a design that makes it easy to extend as new ones are required. The change is currently in the process of getting merged, and assuming I don't get bitten by an old openssl version on one of the test platforms should be in the main tree tonight.&lt;/p&gt;
&lt;p&gt;I have a bunch of further improvements to the SSL support in progress, with my work on adding OCSP support being one of my main targets. There are several other low-hanging fruit like the bug work arounds I mentioned too though, so I'll probably try to address some of those as well.&lt;/p&gt;
&lt;p&gt;If you're working on a KDE application and Qt's SSL support doesn't offer what you need, then please let me know so that I can make sure that what you're missing gets added to the todo list.&lt;/p&gt;
&lt;!--break--&gt;</description></item><item><title>SSL at the Qt Contributor Summit</title><link>https://blogs.kde.org/2011/07/03/ssl-qt-contributor-summit/</link><pubDate>Sun, 03 Jul 2011 00:00:00 +0000</pubDate><author>Rich</author><guid>https://blogs.kde.org/2011/07/03/ssl-qt-contributor-summit/</guid><description>&lt;p&gt;I haven't written any posts for a few weeks, so I figure it's time for an update. I, along with a bunch of other people who hack on Qt, attended the Qt Contributor Summit in Berlin. This was a very useful event, since it brought together a good mixture of both Nokia developers and external developers - as I would have hoped, KDE was one of the most common afiliations. One of the main things I wanted to do during the event was get together with the people responsible for the Qt SSL code and ensure that the plans for Qt5 will meet the needs of KDE (and others who want non-trivial SSL usage).&lt;/p&gt;
&lt;p&gt;The discussions with Peter and Markus (the guys responsible for this code) were very productive, to the point that the only reason we didn't get a couple of the smaller items merged then and there were that they didn't have access to the Nokia internal network to do it. Peter, Markus and I have been tracking the stuff we'd like to see sorted in Qt's SSL for quite some time in a wiki page at &lt;a href="http://developer.qt.nokia.com/wiki/Improving_Qts_SSL_Support"&gt;&lt;a href="http://developer.qt.nokia.com/wiki/Improving_Qts_SSL_Support"&gt;http://developer.qt.nokia.com/wiki/Improving_Qts_SSL_Support&lt;/a&gt;&lt;/a&gt; and after the discussions, I forsee few problems in getting any of the improvements on the list incorporated into Qt.&lt;/p&gt;
&lt;p&gt;One complex area we touched on was the possibility of changing the Qt APIs so that the various authentication required, and ssl certificate errors signals can be handled without a nested event loop. We even managed to figure out a way of doing this that would remain backwards compatible with code using the current API, so I have some hope that this can be achieved.&lt;/p&gt;
&lt;p&gt;Following the conference I've already had a couple of merge requests approved - printing certs as text &lt;a href="https://qt.gitorious.org/qt/qtbase/merge_requests/2"&gt;&lt;a href="https://qt.gitorious.org/qt/qtbase/merge_requests/2"&gt;https://qt.gitorious.org/qt/qtbase/merge_requests/2&lt;/a&gt;&lt;/a&gt; and support for duplicated elements in certificate names &lt;a href="https://qt.gitorious.org/qt/qtbase/merge_requests/5"&gt;&lt;a href="https://qt.gitorious.org/qt/qtbase/merge_requests/5"&gt;https://qt.gitorious.org/qt/qtbase/merge_requests/5&lt;/a&gt;&lt;/a&gt; (source incompatible with Qt 4). Currently I'm finishing off the code for validation of certificate chains (when not connecting to a server) which should be done in the next week or two, the code is at &lt;a href="https://qt.gitorious.org/~rich/qt/richs-qtbase/commits/verify-certificate"&gt;&lt;a href="https://qt.gitorious.org/~rich/qt/richs-qtbase/commits/verify-certificate"&gt;https://qt.gitorious.org/~rich/qt/richs-qtbase/commits/verify-certificate&lt;/a&gt;&lt;/a&gt; if you want to look.&lt;/p&gt;
&lt;p&gt;Once I've completed the changes above, I currently trying to decide between access to certificate extensions, EV certificate support and finishing integrating my OCSP code.&lt;/p&gt;
&lt;!--break--&gt;</description></item><item><title>Improving SSL Security with Certificate Change Notification</title><link>https://blogs.kde.org/2011/05/22/improving-ssl-security-certificate-change-notification/</link><pubDate>Sun, 22 May 2011 00:00:00 +0000</pubDate><author>Rich</author><guid>https://blogs.kde.org/2011/05/22/improving-ssl-security-certificate-change-notification/</guid><description>&lt;p&gt;Improving the security of SSL is a hot topic these days, and trust in certifcate authorities is rightly at an all time low. One way of improving the situation that doesn't rely on believing that a 3rd party will actually do their job properly is to notify users when the certificate for a site changes. There are already extensions for some browsers that offer this facility, so I sat down today to write a proof of concept that looked at how this implemented in Qt.&lt;/p&gt;
&lt;p&gt;What I've implemented is a class that can simply be plugged into QSslSocket based code to give the user a warning if the certificate for a site has changed since their last visit. The monitor class can keep track of many sockets and the cache is persistent. The idea is that the application tells the certificate monitor about the SSL socket, so that it becomes monitored by calling the addSocket() method, this method simply adds the socket to a QSignalMapper:&lt;/p&gt;
&lt;pre&gt;
void SslCertificateMonitor::addSocket(QSslSocket *socket)
{
 d-&gt;mapper-&gt;setMapping(socket, socket);
 connect(socket, SIGNAL(encrypted()), d-&gt;mapper, SLOT(map()));
}
&lt;/pre&gt;
&lt;p&gt;As you can see, we're connecting to the encrypted() signal of the socket in order to ensure that we get informed as soon as the SSL handshake is complete, and before any sensitive data (like cookies) are transmitted to the client. Unfortunately, this is also the cause of one of the problems of the implementation with the current Qt APIs as I'll describe later.&lt;/p&gt;
&lt;p&gt;The core of the implementation is the socketReady() method which is called whenever the encrypted() signal for a socket we're monitoring is emitted. We'll take a look at the method a chunk at a time:&lt;/p&gt;
&lt;pre&gt;
void SslCertificateMonitor::socketReady(QObject *sockobj)
{
 QSslSocket *sock = qobject_cast&amp;lt;QSslSocket *&gt;(sockobj);
 if (!sock)
 return;

 QString peerName = sock-&gt;peerName();
 if (peerName == d-&gt;lastPeerAccepted)
 return; // Fast path for most recently accepted certificate
&lt;/pre&gt;
&lt;p&gt;Since we're using QSignalMapper to let us know which socket we're dealing with in any given call, we first cast the QObject pointer we're given down to a QSslSocket. This means we can now call all the SSL functions. First we extract the name of the 'peer' (this is a fancy name for the site we're connecting to). The next two lines are actually part of an optimisation - since we'll often get repeated calls for the same site, I've added a simple single-entry cache that lets us quickly handle two requests that follow one after the other. A more complete implementation of this concept would probably use a slightly larger cache. If we've just accepted the site, then we know that there's no need to go through the full set of checks again, so we simply approve it immediately.&lt;/p&gt;
&lt;p&gt;The next step is to check that the cache itself exists, and if not then create it. In this example, the cache is simply a directory that contains a file named after the host being visited. In the file, we store a cryptographic hash of the certificate that was used.&lt;/p&gt;
&lt;pre&gt;
 if (!hasCertificateCache()) {
 bool ok = createCertificateCache();
 if (!ok)
 return;
 }
&lt;/pre&gt;
&lt;p&gt;Finally, we get to the real meat of the class - the algorithm that determines if we should warn the user. This checks if we have a cached value, and if so checks for differences. If the certificate has changed then the signal certificateWarning() is emitted.&lt;/p&gt;
&lt;pre&gt;
 QSslCertificate certificate = sock-&gt;peerCertificate();

 // Have we been here before?
 if (hasCachedCertificate(peerName)) {
 if (isMatchingCertificate(peerName, certificate)) {
 d-&gt;lastPeerAccepted = peerName;
 return; // All is well
 }

 // Cert has changed
 d-&gt;acceptCurrent = false;
 QString message = tr("The certificate for %1 has changed since you previously visited, " \
 "it could be that someone is trying to intercept your communication.");
 message = message.arg(peerName);
 emit certificateWarning(peerName, message);
 }
 else {
 // The certificate is new. We don't show anything to user because then
 // we're simply training them to click through our warning message without
 // thinking.
 d-&gt;acceptCurrent = true;
 }
&lt;/pre&gt;
&lt;p&gt;People using the class need to connect to the certificateWarning() signal, and if they wish the connection to be approved should call the acceptCertificate() method. This operates in a similar way to the QSslCertificate ignoreSslErrors() method, ie. expecting the client to use a nested event loop (such as a modal dialog) to interact with the user. If the acceptCertificate() method is called then the value of acceptCurrent will be set true. The value of this variable governs what we do next:&lt;/p&gt;
&lt;pre&gt;
 // If the user has chosen to accept the certificate or the certficate is new
 // then we store the updated entry.
 if (d-&gt;acceptCurrent) {
 d-&gt;lastPeerAccepted = peerName;
 addCertificate(peerName, certificate);
 }
 else {
 // Certficate has been considered dangerous by the user
 sock-&gt;abort();
 }
&lt;/pre&gt;
&lt;p&gt;The code above is the core of the entire implementation, but we should take a look at the internals of two of the functions it uses: the method for writing an entry into the cache, and the method for checking for changes. Both of the methods are very simple, adding a certificate to the cache is simply a matter of writing the certificate digest to a file:&lt;/p&gt;
&lt;pre&gt;
void SslCertificateMonitor::addCertificate(const QString &amp;amp;peerName, const QSslCertificate &amp;amp;cert)
{
 QString cacheEntry = d-&gt;cacheDir + QLatin1Char('/') + peerName;
 QFile f( cacheEntry );
 if (!f.open(QIODevice::WriteOnly))
 return;

 f.write(cert.digest());
 f.close();
}
&lt;/pre&gt;
&lt;p&gt;Checking if the certificate has changed is just as easy - we just compute the digest of the certificate the site has provided and compare it with the value we recorded previously:&lt;/p&gt;
&lt;pre&gt;
bool SslCertificateMonitor::isMatchingCertificate(const QString &amp;amp;peerName, const QSslCertificate &amp;amp;cert)
{
 QString cacheEntry = d-&gt;cacheDir + QLatin1Char('/') + peerName;
 QFile f( cacheEntry );
 if (!f.open(QIODevice::ReadOnly))
 return false;

 QByteArray oldDigest = f.readAll();
 f.close();

 if (oldDigest != cert.digest())
 return false;

 return true;
}
&lt;/pre&gt;
&lt;p&gt;In order to test the code worked, I wrote a simple app that will connect via SSL and dump the response. The code that integrates the monitor is simple:&lt;/p&gt;
&lt;pre&gt;
MonitorTest::MonitorTest()
 : QWidget()
{
 monitor = new SslCertificateMonitor(this);
 connect(monitor, SIGNAL(certificateWarning(const QString &amp;amp;, const QString &amp;amp;)),
 SLOT(certificateWarning(const QString &amp;amp;, const QString &amp;amp;)));
&lt;/pre&gt;
&lt;p&gt;This creates the monitor and connects the warning signal to the slot that will inform the user about the issue. When we actually create a socket, we have to call:&lt;/p&gt;
&lt;pre&gt;
 monitor-&gt;addSocket(sock);
&lt;/pre&gt;
&lt;p&gt;This tells the monitor to watch the certificates for our socket. Finally, we have to let the user choose what to do when a changed certificate is spotted. In the example, this is as simple as displaying a dialog:&lt;/p&gt;
&lt;pre&gt;
void MonitorTest::certificateWarning(const QString &amp;amp;host, const QString &amp;amp;message)
{
 QMessageBox::StandardButton result =
 QMessageBox::warning( this,
 tr("Certificate for %1 has changed").arg(host),
 message + QLatin1String("\n\nAre you sure you wish to continue?"),
 QMessageBox::Yes | QMessageBox::No );

 if (result == QMessageBox::Yes)
 monitor-&gt;acceptCertificate();
}
&lt;/pre&gt;
&lt;p&gt;This means that when a certificate is found to have changed, the user sees a message like the one in the screenshot below:&lt;/p&gt;
&lt;img src="http://xmelegance.org/devel/sslcertmonitor.png"&gt;
&lt;p&gt;As you can see, this proves that the basic concept works ok. Unfortunately there are some major API limitations that mean this code isn't as useful in practice as it could be:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It cannot be extended to QNetworkAccessManager right now as that neither gives us access to the underlying QSslSocket nor provides a function for encrypted() that is analogous to the sslError() forwarding function.
&lt;li&gt; Since we need to tap the encrypted() signal, it's not safe for the application to send data in response to this signal (which is the way it is normally used). We really need to have a signal that works immediately prior to the one the application uses, or get the application to use a signal sent by this class.
&lt;/ul&gt;
&lt;p&gt;In addition there are some easily fixable issues, for example it doesn't track the date or anything else from the certificate. This could easily be added though eg. by using the modification time on the cache entry. This is a good time however to be finding that there are API issues since there are plans for a reworking of the QSslSocket APIs for Qt5. Hopefully experiments like this will let us significantly improve things for the future.&lt;/p&gt;
&lt;p&gt;The code as usual is in my &lt;a href="https://gitorious.org/qt-examples/qt-examples/trees/master/sslcertmonitor"&gt;qt-examples&lt;/a&gt; gitorious repository.&lt;/p&gt;
&lt;!--break--&gt;</description></item><item><title>QPcap - A Qt-Style Wrapper Around libpcap</title><link>https://blogs.kde.org/2011/03/19/qpcap-qt-style-wrapper-around-libpcap/</link><pubDate>Sat, 19 Mar 2011 00:00:00 +0000</pubDate><author>Rich</author><guid>https://blogs.kde.org/2011/03/19/qpcap-qt-style-wrapper-around-libpcap/</guid><description>&lt;p&gt;I've been working on a new library for the last couple of weeks that provides a Qt style API for libpcap. For those who aren't familiar with it, libpcap is the library used for capturing raw packets used by tools like tcpdump and wireshark. The pcap library has been around for years, and is built in C rather than C++. The API is pretty simple, but it's not one that can be trivially integrated into a gui application. The aim of the library I've been working on is to make using packet capture in Qt programs a simple matter of using a QObject and connecting to its slots.&lt;/p&gt;
&lt;p&gt;Developing a wrapper for a C api is a fairly common activity for C++ developers, though not one that is done every day. My aim here is to provide an API that feel familiar to developers using Qt, so I've tried to provide something that uses the Qt style rather than simply wrapping the pcap methods into a C++ class. A side effect of this is that it will probably seem a little bit unfamiliar to people who know libpcap but, I feel that the benefit of making something that is easy to use by Qt developers outweighs this.&lt;/p&gt;
&lt;p&gt;I'm only going to cover two aspects of the pcap wrapper in my post today: how the packet processing is triggered, and how the callback used by pcap is converted into a Qt-style signal. I'll do another post later about how the wrappers around the packet data work, but for now that's still in flux so writing about it seems a bit pointless.&lt;/p&gt;
&lt;p&gt;A pcap capture sits there grabbing data from the wire, but doesn't do anything until you call pcap_dispatch. One approach we could take would be to repeatedly call this function, but this would lead to high cpu load as we'd often find there was no work to do. Fortunately on unix platforms pcap provides a function that gives us a file descriptor we can use for the select() system call - pcap_get_selectable_fd(). Qt, like other modern gui toolkits provides a way for us to integrate file descriptors into the select call of their event loop. In Qt, this comes in the form of the QSocketNotifier class.&lt;/p&gt;
&lt;p&gt;In qpcap, I've used QSocketNotifier to know when I should call pcap_dispatch. This means we can process the packets and won't be burning CPU time pointlessly. The code that sets this up is in QPcap::start() as follows:&lt;/p&gt;
&lt;pre&gt;
 int fd = pcap_get_selectable_fd(d-&gt;handle);
 d-&gt;notifier = new QSocketNotifier( fd, QSocketNotifier::Read, this );
 connect( d-&gt;notifier, SIGNAL(activated(int)), this, SLOT(dataAvailable()) );
 d-&gt;notifier-&gt;setEnabled(true);
&lt;/pre&gt;
&lt;p&gt;The dataAvailable() slot this code calls is at the heart of QPcap, but is trivial. It just calls the pcap_dispatch method we referred to earlier. All the work is done by the callback function passed to it which is called once for each packet received.&lt;/p&gt;
&lt;pre&gt;
void QPcap::dataAvailable()
{
 pcap_dispatch( d-&gt;handle, -1 /* all packets*/, (pcap_handler)&amp;amp;QPcap::packet_callback, (uchar *)this );
}
&lt;/pre&gt;
&lt;p&gt;The callback function used by pcap_dispatch is a static method of QPcap. This is required to avoid issues with the difference between the calling conventions of C++ methods (which have the implicit 'this' argument) and C functions. We use the user data argument of the pcap_dispatch function to let us know which instance of QPcap should be notified. After setting the header and packet members of our data object, we trigger the packetReady() signals so that objects connected to our class will be informed.&lt;/p&gt;
&lt;pre&gt;
void QPcap::packet_callback( uchar *self, const pcap_pkthdr *header, const uchar *packet )
{
 QPcap *qpcap = reinterpret_cast&amp;lt;QPcap *&gt;(self);
 qpcap-&gt;d-&gt;header.header = header;
 qpcap-&gt;d-&gt;packet = packet;

 qpcap-&gt;packetReady();
 qpcap-&gt;packetReady( qpcap-&gt;d-&gt;packet );
}
&lt;/pre&gt;
&lt;p&gt;This post only covers a couple of functions of qpcap, if you want to look at it in more detail, then the code is available on gitorious at &lt;a href="http://gitorious.org/qpcap/qpcap/"&gt;&lt;a href="http://gitorious.org/qpcap/qpcap/"&gt;http://gitorious.org/qpcap/qpcap/&lt;/a&gt;&lt;/a&gt;. I'll be writing at least one more post covering the wrapper classes offered by the library for accessing packets, but I'll leave that until the classes are a bit more complete.&lt;/p&gt;
&lt;!--break--&gt;</description></item><item><title>Loading and Scaling Images in a Thread</title><link>https://blogs.kde.org/2011/01/22/loading-and-scaling-images-thread/</link><pubDate>Sat, 22 Jan 2011 00:00:00 +0000</pubDate><author>Rich</author><guid>https://blogs.kde.org/2011/01/22/loading-and-scaling-images-thread/</guid><description>&lt;p&gt;In a previous blog post, I showed a simple example of using threads to perform complex calculations (SHA hashes) in a worker thread. I used them there because generating the hash of a DVD ISO can take a while, and GUIs that block make everyone cry. In this post, I'll use the same technique to load and scale an image whilst still letting my GUI startup instantly.&lt;/p&gt;
&lt;p&gt;
To begin with, lets look at the declaration of my Resizer class - this is the class that does most of the work. As you can see it's just a normal QObject, and provides slots to let us specify the input, target size etc. It also has a couple of signals one to provide the result of the work, and another to indicate that something went wrong. One thing to note is that the API is based around QImage not QPixmap, that's because it will be running outside the main thread, meaning GUI classes like QPixmap cannot be used safely.
&lt;pre&gt;
class Resizer : public QObject
{
 Q_OBJECT
public:
 Resizer( QObject *parent=0 );
 ~Resizer();
&lt;p&gt;public slots:
void setSize( const QSize &amp;amp;size );
void setAspectRatioMode( const Qt::AspectRatioMode mode );&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;void setInput( const QImage &amp;amp;amp;input );
void setInput( const QString &amp;amp;amp;filename );

void start();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;signals:
void error();
void finished( const QImage &amp;amp;output );&lt;/p&gt;
&lt;p&gt;private:
struct ResizerPrivate *d;
};
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The implementation is pretty simple, I'll skip over the setters etc., since they simple do what you'd expect. In fact the only interesting method is the start() slot since that's where all the work is done.&lt;/p&gt;
&lt;pre&gt;
struct ResizerPrivate
{
 QSize size;
 Qt::AspectRatioMode aspectMode;
 QImage input;
 QString inputFilename;
};

void Resizer::start()
{
 if ( !d-&gt;inputFilename.isEmpty() ) {
 d-&gt;input.load( d-&gt;inputFilename );
 }

 if ( d-&gt;input.isNull() ) {
 emit error();
 return; 
 }

 QImage output = d-&gt;input.scaled( d-&gt;size, d-&gt;aspectMode, Qt::SmoothTransformation );
 emit finished( output );
}
&lt;/pre&gt;
&lt;p&gt;The start() method first looks to see if a filename has been provided, if it has then it tries to load it. If the load failed (or the user has provided no input at all) then the error signal is emitted and we return. Finally, if we have an image to work with, we perform a smooth scaling operation then emit the finished() slot with the result. As you can see, we haven't had to do anything special to deal with threads, since we're using signals to return our scaled image.&lt;/p&gt;
&lt;p&gt;
The main function of this example is where all the threading is dealt with. The Viewer class is simply a UI file that wraps a QLabel and provides a slot that will set the label's pixmap based on a QImage.
&lt;pre&gt;
int main( int argc, char **argv )
{
 QApplication app( argc, argv );
&lt;pre&gt;&lt;code&gt;if ( argc != 2 ) {
 printf( &amp;quot;Usage: %s &amp;lt;filename&amp;gt;\n&amp;quot;, argv[0] );
 return 1;
}

Viewer *view = new Viewer();

QThread *thread = new QThread();
Resizer *resizer = new Resizer();
resizer-&amp;gt;moveToThread( thread );

QObject::connect( thread, SIGNAL(started()), resizer, SLOT(start()) );
QObject::connect( resizer, SIGNAL(finished(const QImage &amp;amp;amp;)), view, SLOT(setImage(const QImage &amp;amp;amp;)) );

view-&amp;gt;show();

resizer-&amp;gt;setInput( QString::fromLocal8Bit(argv[1]) );
resizer-&amp;gt;setSize( QSize(400,400) );

thread-&amp;gt;start();

return app.exec();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}
&lt;/pre&gt;
The first interesting thing we do is create the QThread, note that we are using it directly here rather than subclassing it. We then create our Resizer object. When we've done that, we move it into our QThread, this will ensure that it runs there. Next, we connect the thread's started() signal to our start() method so that we'll begin loading and scaling as soon as the thread is run. We also connect our finished() signal (which will be in our thread) to the view (which will be in the main thread). Qt will automatically ensure that the image is passed safely from one thread to the other.&lt;/p&gt;
&lt;p&gt;
Since we haven't started our thread yet, we can safely set the input and size directly rather than calling these methods as slots. If we wanted to change these while the thread was running (which our resizer doesn't really support in this case) then we'd want to use signals or QMetaObject's invokeMethod() in order to do so safely.
&lt;p&gt;
Finally, we start() our thread then start the event loop. When the thread starts, the started() signal is emitted, which will trigger our resizer to begin processing. Because this is happenning asynchronously, our GUI will display immediately even if we're loading and scaling very large images. The same technique can be used in many scenarios, for example if you have expensive startup operations that need to be performed by your application, then you might want to consider using this technique.
&lt;p&gt;
As usual, the code is in &lt;a href="http://gitorious.org/qt-examples/qt-examples/trees/master/threaded-resize"&gt;my gitorious repository&lt;/a&gt;.
&lt;!--break--&gt;</description></item><item><title>Getting the details of an SSL connection</title><link>https://blogs.kde.org/2011/01/09/getting-details-ssl-connection/</link><pubDate>Sun, 09 Jan 2011 00:00:00 +0000</pubDate><author>Rich</author><guid>https://blogs.kde.org/2011/01/09/getting-details-ssl-connection/</guid><description>&lt;p&gt;SSL is a pretty complex topic, and whilst Qt makes the APIs pretty easy to use, there's a lot going on underneath and it can be hard to debug. In order to make life a bit easier, I've written a simple tool that will connect to an SSL service then dump every piece of information Qt makes available concerning it. Of course the aim here is both that the tool be useful in itself, and also that it provide a good illustration of how to use the APIs concerned.&lt;/p&gt;
&lt;p&gt;
The first step, naturally enough, is to connect to the service using SSL - as you might expect, this uses the QSslSocket class. In order to be informed if we manage to connect successfully, or if we hit a problem we connect to some useful signals/
&lt;ul&gt;
&lt;li&gt;encrypted() - This is emitted if we manage to successfuly connect to the service.&lt;/li&gt;
&lt;li&gt;sslErrors(const QList&amp;lt;QSslError&gt; &amp;amp;) - This is emitted if there are problems establishing a secure connection.&lt;/li&gt;
&lt;li&gt;error(QAbstractSocket::SocketError) - This is emitted if the connection fails. It is declared in QAbstractSocket. Note that ssl errors can get reported here too.&lt;/li&gt;
&lt;/ul&gt;
The connectToHost() method is the one that triggers the actual connection, and by default performs the SSL handshake etc. for us:
&lt;pre&gt;
void Connector::connectToHost()
{
 qDebug() &amp;lt;&amp;lt; "Connecting...";
&lt;pre&gt;&lt;code&gt;d-&amp;gt;sock = new QSslSocket(this);
connect( d-&amp;gt;sock, SIGNAL(encrypted()), this, SLOT(ready()) );
connect( d-&amp;gt;sock, SIGNAL(error(QAbstractSocket::SocketError)),
 this, SLOT(socketError(QAbstractSocket::SocketError)) );
connect( d-&amp;gt;sock, SIGNAL(sslErrors(const QList&amp;amp;lt;QSslError&amp;gt; &amp;amp;amp;)),
 this, SLOT(sslError(const QList&amp;amp;lt;QSslError&amp;gt; &amp;amp;amp;)) );
d-&amp;gt;sock-&amp;gt;connectToHostEncrypted( d-&amp;gt;host, d-&amp;gt;port );
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}
&lt;/pre&gt;
If we get an error during the connection, then one of the two error handling slots we've connected gets called. If it's a socket error then we have a problem such as a refused connection we can't do much, however if it's an error caused by one of the SSL checks then we handle it differently. Normally, we should act as Qt does by default and treat SSL errors as hard errors - if we don't then SSL is unable to protect us against attacks. For the purposes of this example however, we want to be more lenient since we're specifically writing a way to figure out what's going on. As a result, our SSL error handling looks like this:&lt;/p&gt;
&lt;pre&gt;
void Connector::sslError( const QList&amp;lt;QSslError&gt; &amp;errors )
{
 foreach( const QSslError &amp;error, errors ) {
 qDebug() &amp;lt;&amp;lt; "SSL Error: " &amp;lt;&amp;lt; error.errorString();
 }

 // This is only used because we are interested in dumping all the info
 // do NOT use if you want real security (it introduces man-in-the-middle
 // attacks).
 d-&gt;sock-&gt;ignoreSslErrors();
&lt;/pre&gt;
&lt;p&gt;If we manage to establish the connection ok, then we'll call a couple of functions that tell us the details. The first gives us the SSL certificate used by the remote server we've connected to, the second tells us the cipher we're using. We'll pass these to a couple of functions that print out the details, then terminate the application:&lt;/p&gt;
&lt;pre&gt;
void Connector::ready()
{
 qDebug() &amp;lt;&amp;lt; " === Peer Certificate ===";

 QSslCertificate cert = d-&gt;sock-&gt;peerCertificate();
 dumpCertificate( cert );

 QSslCipher cipher = d-&gt;sock-&gt;sessionCipher();
 dumpCipher( cipher );

 qDebug() &amp;lt;&amp;lt; "Done";

 qApp-&gt;quit();
}
&lt;/pre&gt;
&lt;p&gt;First, we'll look at how we dump the information about the cipher we're using. QSslCipher provides accessors that let us see the details - it's worth remembering that users will not be able to understand this information, so any interface for general use should be designed with rather more care.&lt;/p&gt;
&lt;pre&gt;
void Connector::dumpCipher( const QSslCipher &amp;amp;cipher )
{
 qDebug() &amp;lt;&amp;lt; "\n== Cipher ==";

 qDebug() &amp;lt;&amp;lt; "Authentication:\t\t" &amp;lt;&amp;lt; cipher.authenticationMethod();
 qDebug() &amp;lt;&amp;lt; "Encryption:\t\t" &amp;lt;&amp;lt; cipher.encryptionMethod();
 qDebug() &amp;lt;&amp;lt; "Key Exchange:\t\t" &amp;lt;&amp;lt; cipher.keyExchangeMethod();
 qDebug() &amp;lt;&amp;lt; "Cipher Name:\t\t" &amp;lt;&amp;lt; cipher.name();
 qDebug() &amp;lt;&amp;lt; "Protocol:\t\t" &amp;lt;&amp;lt; cipher.protocolString();
 qDebug() &amp;lt;&amp;lt; "Supported Bits:\t\t" &amp;lt;&amp;lt; cipher.supportedBits();
 qDebug() &amp;lt;&amp;lt; "Used Bits:\t\t" &amp;lt;&amp;lt; cipher.usedBits();
}
&lt;/pre&gt;
&lt;p&gt;Now let's take a look at how we dump the certificate information. A certificate contains a lot of information (not all of which is accessible using Qt's API). In order to make the output managable, I've grouped it into three sections - information about the subject, information about the issuer, and finally information about the certificate itself.&lt;/p&gt;
&lt;p&gt;
The first thing we do is dump the certificate itself in a format known as PEM which a base64 string. Then we move onto the subject. We have quite a bit of information about the subject of a certificate, but two parts are particularly important for SSL - the common name and the subject alternative names. These two fields are the ones that are matched against the name of the host we're connecting to in order to determine if the certificate is valid for this host. After the information about the subject, we dump similar information about the issuer. Finally we display the information about the certificate itself which here is primarily just the dates for which it is valid.
&lt;pre&gt;	
void Connector::dumpCertificate( const QSslCertificate &amp;amp;cert )
{
 qDebug() &amp;lt;&amp;lt; cert.toPem();
&lt;pre&gt;&lt;code&gt;qDebug() &amp;amp;lt;&amp;amp;lt; &amp;quot;== Subject Info ==\b&amp;quot;;
qDebug() &amp;amp;lt;&amp;amp;lt; &amp;quot;CommonName:\t\t&amp;quot; &amp;amp;lt;&amp;amp;lt; cert.subjectInfo( QSslCertificate::CommonName );
qDebug() &amp;amp;lt;&amp;amp;lt; &amp;quot;Organization:\t\t&amp;quot; &amp;amp;lt;&amp;amp;lt; cert.subjectInfo( QSslCertificate::Organization );
qDebug() &amp;amp;lt;&amp;amp;lt; &amp;quot;LocalityName:\t\t&amp;quot; &amp;amp;lt;&amp;amp;lt; cert.subjectInfo( QSslCertificate::LocalityName );
qDebug() &amp;amp;lt;&amp;amp;lt; &amp;quot;OrganizationalUnitName:\t&amp;quot; &amp;amp;lt;&amp;amp;lt; cert.subjectInfo( QSslCertificate::OrganizationalUnitName );
qDebug() &amp;amp;lt;&amp;amp;lt; &amp;quot;StateOrProvinceName:\t&amp;quot; &amp;amp;lt;&amp;amp;lt; cert.subjectInfo( QSslCertificate::StateOrProvinceName );

QMultiMap&amp;amp;lt;QSsl::AlternateNameEntryType, QString&amp;gt; altNames = cert.alternateSubjectNames();
if ( !altNames.isEmpty() ) {
 qDebug() &amp;amp;lt;&amp;amp;lt; &amp;quot;Alternate Subject Names (DNS):&amp;quot;;
 foreach (const QString &amp;amp;altName, altNames.values(QSsl::DnsEntry)) {
 qDebug() &amp;amp;lt;&amp;amp;lt; altName;
 }

 qDebug() &amp;amp;lt;&amp;amp;lt; &amp;quot;Alternate Subject Names (Email):&amp;quot;;
 foreach (const QString &amp;amp;altName, altNames.values(QSsl::EmailEntry)) {
 qDebug() &amp;amp;lt;&amp;amp;lt; altName;
 }
}

qDebug() &amp;amp;lt;&amp;amp;lt; &amp;quot;\n== Issuer Info ==&amp;quot;;
qDebug() &amp;amp;lt;&amp;amp;lt; &amp;quot;CommonName:\t\t&amp;quot; &amp;amp;lt;&amp;amp;lt; cert.issuerInfo( QSslCertificate::CommonName );
qDebug() &amp;amp;lt;&amp;amp;lt; &amp;quot;Organization:\t\t&amp;quot; &amp;amp;lt;&amp;amp;lt; cert.issuerInfo( QSslCertificate::Organization );
qDebug() &amp;amp;lt;&amp;amp;lt; &amp;quot;LocalityName:\t\t&amp;quot; &amp;amp;lt;&amp;amp;lt; cert.issuerInfo( QSslCertificate::LocalityName );
qDebug() &amp;amp;lt;&amp;amp;lt; &amp;quot;OrganizationalUnitName:\t&amp;quot; &amp;amp;lt;&amp;amp;lt; cert.issuerInfo( QSslCertificate::OrganizationalUnitName );
qDebug() &amp;amp;lt;&amp;amp;lt; &amp;quot;StateOrProvinceName:\t&amp;quot; &amp;amp;lt;&amp;amp;lt; cert.issuerInfo( QSslCertificate::StateOrProvinceName );

qDebug() &amp;amp;lt;&amp;amp;lt; &amp;quot;\n== Certificate ==&amp;quot;;
//qDebug() &amp;amp;lt;&amp;amp;lt; &amp;quot;Serial Number:\t\t&amp;quot; &amp;amp;lt;&amp;amp;lt; cert.serialNumber(); // This seems buggy
qDebug() &amp;amp;lt;&amp;amp;lt; &amp;quot;Effective Date:\t\t&amp;quot; &amp;amp;lt;&amp;amp;lt; cert.effectiveDate().toString();
qDebug() &amp;amp;lt;&amp;amp;lt; &amp;quot;Expiry Date:\t\t&amp;quot; &amp;amp;lt;&amp;amp;lt; cert.expiryDate().toString();
qDebug() &amp;amp;lt;&amp;amp;lt; &amp;quot;Valid:\t\t\t&amp;quot; &amp;amp;lt;&amp;amp;lt; (cert.isValid() ? &amp;quot;Yes&amp;quot; : &amp;quot;No&amp;quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}
&lt;/pre&gt;
The end result of all this is a small command line tool that will connect to the host specified and dump all this information. It should be useful for debugging any issues that may be encountered when connecting to an SSL site using Qt. There are a number of possibile enhancements that could be made (eg. dumping the whole certificate chain) but even now, the output of this tool should make tracking down SSL issues in Qt applications a lot simpler. The code, as ever, is in my &lt;a href="http://gitorious.org/qt-examples/qt-examples/trees/master/sslinfo"&gt;qt-examples&lt;/a&gt; gitorious repository. An example of the output generated is &lt;a href="http://xmelegance.org/devel/sslinfo.txt"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;!--break--&gt;</description></item><item><title>Rendering UI files to PDF</title><link>https://blogs.kde.org/2011/01/03/rendering-ui-files-pdf/</link><pubDate>Mon, 03 Jan 2011 00:00:00 +0000</pubDate><author>Rich</author><guid>https://blogs.kde.org/2011/01/03/rendering-ui-files-pdf/</guid><description>&lt;p&gt;As a followup to my previous blog post about rendering widgets to SVG, lets take a look at rendering them to PDF. I won't go into as much detail as the previous blog post since the code is mostly the same. This time, instead of a renderToSvg() method, we have a renderToPdf() method. All the rest of the code is basically the same as the previous example.&lt;/p&gt;
&lt;p&gt;
The renderToPdf() method makes use of the ability of QPrinter to generate PDF files (incidentally, it can also generate postscript). The important part of the code is as follows:
&lt;pre&gt;
 QPrinter pdf;
 pdf.setOutputFormat( QPrinter::PdfFormat );
 pdf.setOutputFileName( pdfFile );
 QPainter p;
 p.begin(&amp;amp;pdf);
 target-&gt;render(&amp;amp;p);
 p.end();
&lt;/pre&gt;
We create a printer (using the default printing mode etc.), then tell it to use PDF output. Next we set the output filename. Finally, we render the widget as before. Like QSvgGenerator, QPrinter is a QPaintDevice so the API is just the same. The output file can be seen at &lt;a
 href="http://xmelegance.org/devel/networkrequests.pdf"&gt;http://xmelegance.org/devel/networkrequests.pdf&lt;/a&gt;, and the code is in gitorious &lt;a href="http://gitorious.org/qt-examples/qt-examples/trees/master/uifile-fun2/"&gt;qt-examples repository&lt;/a&gt; as before.
&lt;p&gt;
I mentioned in my previous post that QImage is also a QPaintDevice, so an exercise I'm leaving to you is to make 3rd version of the code that will render widgets to an image.
&lt;!--break--&gt;</description></item><item><title>Rendering UI files to SVG</title><link>https://blogs.kde.org/2011/01/03/rendering-ui-files-svg/</link><pubDate>Mon, 03 Jan 2011 00:00:00 +0000</pubDate><author>Rich</author><guid>https://blogs.kde.org/2011/01/03/rendering-ui-files-svg/</guid><description>&lt;p&gt;In response to a question on IRC yesterday, here's a quick example for the New
Year - rendering designer's UI files to SVG using QSvgGenerator. As usual, the
code is simple since Qt gives us everything we need.&lt;/p&gt;
&lt;p&gt;
The main program loads the UI file shows it, it also sets up our SVG
capture. Loading the UI file is done using QUiLoader allowing us to load any
file specified on the command line. We then figure out what to call the SVG
file we're going to generate. Next we setup our Renderer object by telling it
what to capture and the name of the file to write it to. In order to ensure
the UI is ready, we use a single shot timer to trigger the capture one second
after the application starts:
&lt;pre&gt;
int main( int argc, char **argv )
{
 QApplication app( argc, argv );
&lt;pre&gt;&lt;code&gt;QString filename = QString::fromLocal8Bit( argv[1] );
QUiLoader loader;
QFile f( filename );
if ( !f.open(QIODevice::ReadOnly) )
return 1;

QWidget *ui = loader.load( &amp;amp;amp;f );
if ( !ui )
return 1;

QString svgFile = filename.remove(&amp;quot;.ui&amp;quot;);
svgFile = svgFile.append(&amp;quot;.svg&amp;quot;);

Renderer render;
render.setTarget(ui);
render.setSvgFile(svgFile);
QTimer::singleShot( 1000, &amp;amp;amp;render, SLOT(start()));

ui-&amp;gt;show();
app.exec();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}
&lt;/pre&gt;
The implementation of the actual capture is simple too, and is all handled by
a single method 'renderToSvg()'. This method creates the generator and tells
it the filename to use. Then it creates a QPainter and sets up drawing onto
the QSvgGenerator - this is possible because QSvgGenerator is a QPaintDevice
(like QWidget, QImage etc.). Finally we call the render() method of the widget
we're capturing in order to perform the actual drawing.&lt;/p&gt;
&lt;pre&gt;
bool Renderer::renderToSvg()
{
 if (svgFile.isEmpty()) {
 qDebug() &lt;&lt; "No svg file set";
 return false;
 }

 QSvgGenerator svg;
 svg.setFileName(svgFile);
 QPainter p;
 p.begin(&amp;amp;svg);
 target-&gt;render(&amp;amp;p);
 p.end();
 
 return true;
}
&lt;/pre&gt;
&lt;p&gt;
The result of running this on a simple UI file can be seen at &lt;a
 href="http://xmelegance.org/devel/networkrequests.svg"&gt;http://xmelegance.org/devel/networkrequests.svg&lt;/a&gt;.
The code itself is available from my gitorious &lt;a href="http://gitorious.org/qt-examples/qt-examples/trees/master/uifile-fun/"&gt;qt-examples repository&lt;/a&gt; as normal.
&lt;p&gt;
When I first wrote the above code, I tried to get the widget to render
directly to the svg file, but this turned out to hit QTBUG-2278. The code
that triggers the bug was:
&lt;pre&gt;
 QSvgGenerator svg;
 svg.setFileName(svgFile);
 target-&gt;render(&amp;amp;svg);
&lt;/pre&gt;
So if I were you, I'd create the painter myself!
&lt;!--break--&gt;</description></item><item><title>Implementing a Reusable Custom QNetworkReply</title><link>https://blogs.kde.org/2010/08/28/implementing-reusable-custom-qnetworkreply/</link><pubDate>Sat, 28 Aug 2010 00:00:00 +0000</pubDate><author>Rich</author><guid>https://blogs.kde.org/2010/08/28/implementing-reusable-custom-qnetworkreply/</guid><description>&lt;p&gt;In my last blog post, I showed how to use a proxy QNetworkAccessManager to restrict network accesses to sites included in a whitelist. One limitation the previous version had is that it stopped the disallowed requests by rewriting the request itself to be to an invalid url. This then caused the default implementation of QNetworkAccessManager to generate an error reply for us. This post will look at how to create a custom reply directly, to allow us to display messages to the user etc. or even provide 'virtual' content.&lt;/p&gt;
&lt;p&gt;The approach I've taken is to try to write a reusable utility class for sending basic network replies. I've called the class QCustomNetworkReply since if there's a reasonable level of support then I'll try to work it up into a merge request for Qt. To begin with, lets see how the whitelisting proxy looks now that it uses the new class:&lt;/p&gt;
&lt;pre&gt;
QNetworkReply *WhiteListNetworkAccessManager::createRequest( Operation op,
 const QNetworkRequest &amp;amp;req,
 QIODevice *outgoingData )
{
 // If host is not whitelisted then kill it
 if ( !isAllowed( req.url().host() ) ) {
 QCustomNetworkReply *reply = new QCustomNetworkReply();
 reply-&gt;setHttpStatusCode( 403, "Forbidden" );
 reply-&gt;setContentType("text/html");
 reply-&gt;setContent( QString("&amp;lt;html&gt;&amp;lt;body&gt;&amp;lt;h1&gt;That url is not in the whitelist&amp;lt;/h1&gt;&amp;lt;/body&gt;&amp;lt;/html&gt;") );

 return reply;
 }

 QNetworkReply *reply = QNetworkAccessManager::createRequest( op, myReq, outgoingData );
 return reply;
}
&lt;/pre&gt;
&lt;p&gt;The new code operates if the request is to be disallowed. First it creates our custom reply, it then specifies the HTTP response code to send. Finally it sets up the content type and the content itself. Finally, we return our custom reply. As you can see, the API of the QCustomNetworkReply class is fairly simple to use (in fact the only required part is setting the content).&lt;/p&gt;
&lt;p&gt;Now we've seen how it's used, lets take a look at how the custom network reply works. The class declaration is fairly simple:&lt;/p&gt;
&lt;pre&gt;
class QCustomNetworkReply : public QNetworkReply
{
 Q_OBJECT

public:
 QCustomNetworkReply( QObject *parent=0 );
 ~QCustomNetworkReply();

 void setHttpStatusCode( int code, const QByteArray &amp;amp;statusText = QByteArray() );
 void setHeader( QNetworkRequest::KnownHeaders header, const QVariant &amp;amp;value );
 void setContentType( const QByteArray &amp;amp;contentType );

 void setContent( const QString &amp;amp;content );
 void setContent( const QByteArray &amp;amp;content );

 void abort();
 qint64 bytesAvailable() const;
 bool isSequential() const;

protected:
 qint64 readData(char *data, qint64 maxSize);

private:
 struct QCustomNetworkReplyPrivate *d;
};
&lt;/pre&gt;
&lt;p&gt;The first group of methods are those for setting the various headers on our response. They are really just convenience wrappers around existing methods (for example making some protected functionality public). I won't go into any more detail about them since the implementations are obvious looking at the source. The two setContent methods are where things start to get interesting:&lt;/p&gt;
&lt;pre&gt;
void QCustomNetworkReply::setContent( const QString &amp;amp;content )
{
 setContent(content.toUtf8());
}

void QCustomNetworkReply::setContent( const QByteArray &amp;amp;content )
{
 d-&gt;content = content;
 d-&gt;offset = 0;

 open(ReadOnly | Unbuffered);
 setHeader(QNetworkRequest::ContentLengthHeader, QVariant(content.size()));

 QTimer::singleShot( 0, this, SIGNAL(readyRead()) );
 QTimer::singleShot( 0, this, SIGNAL(finished()) );
}
&lt;/pre&gt;
&lt;p&gt;The first method is simple a convenience and allows us to use a QString rather than a bytearray for the content, yhe second is where the real action is. First, we store the content. Next, we zero the offet that stores how much data has been read from our reply (remember a QNetworkReply is a QIODevice) and open our io device. Now that we have the content, we also set the response header that specifies the amount of data we have. Finally, we use two single shot timers to cause the readyRead() and finished() signal to be emitted when the event loop is reentered. We can't simply emit these signals immediately since the reply has not yet been returned by our QNetworkAccessManager, so nothing is listening for them.&lt;/p&gt;
&lt;p&gt;The final part of the code is to provide a basic implementation of a QIODevice to allow the stored content to be read back out:&lt;/p&gt;
&lt;pre&gt;
void QCustomNetworkReply::abort()
{
 // NOOP
}


qint64 QCustomNetworkReply::bytesAvailable() const
{
 return d-&gt;content.size() - d-&gt;offset;
}

bool QCustomNetworkReply::isSequential() const
{
 return true;
}


qint64 QCustomNetworkReply::readData(char *data, qint64 maxSize)
{
 if (d-&gt;offset &gt;= d-&gt;content.size())
 return -1;

 qint64 number = qMin(maxSize, d-&gt;content.size() - d-&gt;offset);
 memcpy(data, d-&gt;content.constData() + d-&gt;offset, number);
 d-&gt;offset += number;

 return number;
}
&lt;/pre&gt;
&lt;p&gt;That's all there is to it - see all fairly straight forward. The nice part is that now we have the QCustomNetworkReply, we don't need to do any of that work again and can simply reuse this class whenever we want to send data directly to clients of QNetworkAccessManager. As usual, the code is available from my qt-examples git repository at &lt;a href="http://gitorious.org/qt-examples/"&gt;&lt;a href="http://gitorious.org/qt-examples/"&gt;http://gitorious.org/qt-examples/&lt;/a&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;!--break--&gt;</description></item><item><title>A White-listing QNetworkAccessManager</title><link>https://blogs.kde.org/2010/06/05/white-listing-qnetworkaccessmanager/</link><pubDate>Sat, 05 Jun 2010 00:00:00 +0000</pubDate><author>Rich</author><guid>https://blogs.kde.org/2010/06/05/white-listing-qnetworkaccessmanager/</guid><description>&lt;p&gt;My last blog post showed how a proxy class can be used to monitor the requests being made by a QNetworkAccessManager, and illustrated it using an example that displayed those requests graphically. This post will cover another use of proxy QNetworkAccessManagers, specifically modifying requests and responses. The example we'll use is a very simple one, we'll look at a class that will restrict a QNetworkAccessManager so that it can only access domains listed in a white-list.&lt;/p&gt;
&lt;p&gt;
Before we start, lets consider the reasons why restricting the domains a QNetworkAccessManager can access might be useful. One major use is when developing hybrid applications using QtWebkit - restricting the domains that can be accessed allows you to expose internal facilities to Javascript without allowing data to be transmited to arbitrary sites. Another use is in system's like Plasma where it would allow applets to be restricted to certain domains. The example we'll use is a mini-browser that can only access www.kde.org.
&lt;p&gt;
The class definition for our white-listing manager is very simple. It has a method to add domains to the whitelist, and one to test if a domain is white-listed. The only other method is the reimplementation of createRequest().
&lt;pre&gt;
class WhiteListNetworkAccessManager : public QNetworkAccessManager
{
 Q_OBJECT

public:
 explicit WhiteListNetworkAccessManager( QObject *parent = 0 );

 bool isAllowed( const QString &amp;amp;domain );

public slots:
 void addDomain( const QString &amp;amp;domain );

protected:
 QNetworkReply *createRequest( Operation op,
 const QNetworkRequest &amp;amp;req,
 QIODevice *outgoingData );

private:
 QMap&amp;lt;QString, int&gt; allowedDomains;
}
&lt;/pre&gt;
&lt;p&gt;Looking at the two methods to manage the white-list first, we can see that they're both trivial. The first simply adds a domain to the map of allowed domains, the second tests if the map contains the specified domain as a key:&lt;/p&gt;
&lt;pre&gt;
void WhiteListNetworkAccessManager::addDomain( const QString &amp;amp;domain )
{
 allowedDomains.insert( domain, 1 );
}

bool WhiteListNetworkAccessManager::isAllowed( const QString &amp;amp;domain )
{
 return (allowedDomains[domain] == 1); // Rely on Qt's default of 0 for non-existent ints
}
&lt;/pre&gt;
&lt;p&gt;The only non-trivial part of this is that we rely on knowing that QMap will return a default value of 0 for maps with int based values if the key is not present.&lt;/p&gt;
&lt;p&gt;
The final method of our class is almost as trivial as these, it checks if the domain a request is being made to is on the white-list and if it is hands the request to the base-class. If however the request is to a non-allowed domain, it modifies the request to use an invalid url (one with an unsupported protocol). This causes the base-class implementation of the method to fail the request. It would be possible for us to create a response object of our own instead, but this would require quite a lot more code as we'd need to implement the full API of QNetworkReply. This might be the topic of a further example, but it's not required here.
&lt;pre&gt;
QNetworkReply *WhiteListNetworkAccessManager::createRequest( Operation op,
 const QNetworkRequest &amp;amp;req,
 QIODevice *outgoingData )
{
 QNetworkRequest myReq( req );

 // If host is not whitelisted then kill it
 if ( !isAllowed( req.url().host() ) ) {
 myReq.setUrl( QUrl( QString("forbidden://localhost/") ) );
 }

 QNetworkReply *reply = QNetworkAccessManager::createRequest( op, myReq, outgoingData );

 return reply;
}
&lt;/pre&gt;
&lt;p&gt;We've now covered the full implemtation of our class - that really is all there is to it. Using it is simply a matter of telling a QWebView to use it, and adding some domains to the white-list. An example usage is shown below:&lt;/p&gt;
&lt;pre&gt;
 QWebView view;
 WhiteListNetworkAccessManager proxy;

 proxy.addDomain( QString("www.kde.org") );
 view.page()-&gt;setNetworkAccessManager( &amp;proxy );
&lt;/pre&gt;
&lt;p&gt;As usual, the full source code for this example can be found in my gitorious repository a &lt;a href="http://gitorious.org/qt-examples/qt-examples/trees/master"&gt;&lt;a href="http://gitorious.org/qt-examples/qt-examples/trees/master"&gt;http://gitorious.org/qt-examples/qt-examples/trees/master&lt;/a&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;!--break--&gt;</description></item><item><title>QNetworkAccessManager Proxy Classes</title><link>https://blogs.kde.org/2010/05/01/qnetworkaccessmanager-proxy-classes/</link><pubDate>Sat, 01 May 2010 00:00:00 +0000</pubDate><author>Rich</author><guid>https://blogs.kde.org/2010/05/01/qnetworkaccessmanager-proxy-classes/</guid><description>&lt;p&gt;This blog post will demonstrate how you can tap into QNetworkAccessManager (QNAM), the class is used by QtWebkit for all its networking. QNAM is also the recommended API for high-level networking protocols such as HTTP in Qt. The class is very simple, but provides some powerful features like disk caching, cookie handling, and support for Socks and HTTP proxies. There are many cases when it is useful to be able to watch the requests being made through QNAM, and this can be acheived using a proxy QNAM class.&lt;/p&gt;
&lt;p&gt;To illustrate the technique I'll use a simple proxy class to capture the requests as they are made, and display the information from the request and the response. The code was originally written foor the Arora web browser, but I've separated it out into a reusable stand-alone example. The result will be a display like this:&lt;/p&gt;
&lt;img src="http://xmelegance.org/devel/networkaccessmanagerproxy.png"&gt;
&lt;p&gt;I won't describe the implementation of the viewer itself, but instead will focus on the proxy class, which is incredibly simple. The core method that QNAM uses is createRequest(). This method is used to implement various convenience functions like get() and post() and is where we need to take control. Our reimplementation is shown below in full:&lt;/p&gt;
&lt;pre&gt;
QNetworkReply *NetworkAccessManagerProxy::createRequest( Operation op,
 const QNetworkRequest &amp;req,
 QIODevice * outgoingData )
{
 QNetworkReply *reply = QNetworkAccessManager::createRequest( op, req, outgoingData );
 viewer-&gt;addRequest( op, req, outgoingData, reply );
 return reply;
}
&lt;/pre&gt;
&lt;p&gt;All we're doing is calling the baseclass implementation and passing the information about the request to our viewer. It's really that simple. If we wanted to though, we could return a custom QNetworkReply which would let us directly control what happens to the request. This technique can be used to do things like restrict access of a browser to certain white-listed addresses, or to modify the content returned.&lt;/p&gt;
&lt;p&gt;Making QtWebkit use our proxy class is simply a matter of calling setNetworkAccessManager, which we do in our main() function. The entire main function is shown below:&lt;/p&gt;
&lt;pre&gt;
int main( int argc, char **argv )
{
 QApplication app( argc, argv );
 QWebView view;

 NetworkAccessManagerProxy proxy;
 NetworkAccessViewer viewer;
 proxy.setNetworkAccessViewer( &amp;viewer );

 view.page()-&gt;setNetworkAccessManager( &amp;proxy );

 view.setUrl( QUrl("http://www.kde.org/") );
 view.show();

 return app.exec();
}
&lt;/pre&gt;
&lt;p&gt;Hopefully this is enough information to show just how easy using this powerful technique can be. In future I hope to provide a few further examples that show more complex proxy classes. As usual I've put all the code in my qt-example git repository on gitorious at &lt;a href="http://gitorious.org/qt-examples/"&gt;&lt;a href="http://gitorious.org/qt-examples/"&gt;http://gitorious.org/qt-examples/&lt;/a&gt;&lt;/a&gt;, enjoy.&lt;/p&gt;
&lt;!--break--&gt;</description></item><item><title>Tokamak4 - A New Hope</title><link>https://blogs.kde.org/2010/02/24/tokamak4-new-hope/</link><pubDate>Wed, 24 Feb 2010 00:00:00 +0000</pubDate><author>Rich</author><guid>https://blogs.kde.org/2010/02/24/tokamak4-new-hope/</guid><description>&lt;p&gt;Today I'm leaving Tokamak 4, so I thought I'd write a post about what I've been up to while I've been here.&lt;/p&gt;
&lt;p&gt;
The first day or so I spent getting my machine sorted out as trunk was causing some issues with my graphics driver leading to a hang in the DRI layer of the kernel. I also had a chance to triage some ksnapshot bug reports and look over some patches.
&lt;p&gt;
The next day was largely taken up with talks about the current status of the various parts of plasma, kwin and related technologies. We got a little hacking done but not much as it was more important to make sure we're all coordinating our development.
&lt;p&gt;
The remaining days became a bit of a blur, so in no particular order:
&lt;ul&gt;
&lt;li&gt;I refactored the plasma javascript scriptengine to make it easier to use it with QScriptEngines that are created externally. This is required before we can integrate things like QML.
&lt;li&gt;Worked out what is required for QML integration to be implemented in a way that is compatible with our existing javascript bindings etc. This will require some small changes to the API offered by Qt for QML, which may be a problem. If we don't get those changes then QML is likely to be trapped outside the main engine which will reduce what it can do unless we write
another set of bindings.
&lt;li&gt;Made some fixes to the webslice applet to improve error handling.
&lt;li&gt;Started work on an idea I've had in the back of my head for a while, I won't say too much about it here, but I'll include a pretty picture to whet your appetite:
&lt;br&gt;
&lt;img src="http://xmelegance.org/devel/webwatcher3.png"&gt;
&lt;p&gt;
In addition to this I've taken part in lots of discussions on topics ranging from activities/contexts, scripting of animations, silk and more. I'd like to thank Will and the rest of the openSuSE team for making this such a pleasant and productive sprint.
&lt;!--break--&gt;</description></item><item><title>A Simple Threading Example</title><link>https://blogs.kde.org/2010/01/14/simple-threading-example/</link><pubDate>Thu, 14 Jan 2010 00:00:00 +0000</pubDate><author>Rich</author><guid>https://blogs.kde.org/2010/01/14/simple-threading-example/</guid><description>&lt;p&gt;A topic that I've not mentioned in any of my blog posts is threading, not because I have anything against it, simply because a simple use-case hadn't come up. Today I was coding something easy to describe, where using threads was a good solution, so let's take a look at it.&lt;/p&gt;
&lt;p&gt;The problem I needed to solve was to calculate cryptographic hashes of files that could be very large - for example 4 gigabyte DVD isos. As with any graphical application it is very important to ensure that the GUI remains responsive while this work is done. Since the problem involves very little communication between the part of the application calculating the hash, and the rest of the code a worker thread is an ideal solution.&lt;/p&gt;
&lt;p&gt;The code that actually does the work is very simple, it uses the handy QCryptographicHash class to do the work (stored in the variable hasher):&lt;/p&gt;
&lt;pre&gt;
HasherThread::HasherThread(QObject *parent) :
 QThread(parent)
{
 hasher = new QCryptographicHash( QCryptographicHash::Sha1 );
}

void HasherThread::run()
{
 QFile f( filename );
 if ( !f.open(QIODevice::ReadOnly) ) {
 emit error( QString("Unable to open file %1").arg(filename) );
 return;
 }

 hasher-&gt;reset();

 char buffer[16*1024];
 qint64 count;
 do {
 count = f.read( buffer, sizeof(buffer) );
 if ( count == -1 ) {
 emit error( QString("Read error") );
 break;
 }
 hasher-&gt;addData( buffer, count );
 } while( !f.atEnd() );

 emit completed( hasher-&gt;result().toHex() );
}
&lt;/pre&gt;
&lt;p&gt;The code opens the file to be hashed, then reads through it in 16K chunks which it passes to the hasher. If this code were executed in the application's gui thread then this would cause the interface to freeze until the hash was ready, but the code lives in a class that inherits QThread.&lt;/p&gt;
&lt;p&gt;One important feature to note about the code above is that the communication with the rest of the application is via signals (the error and completed signals to be precise). This is very important as it means that when we use the class, we can simply use it like this:&lt;/p&gt;
&lt;pre&gt;
 hasherThread = new HasherThread( this );
 connect( hasherThread, SIGNAL(error(const QString &amp;)),
 ui-&gt;resultEdit, SLOT(setText(const QString &amp;)) );
 connect( hasherThread, SIGNAL(completed(const QString &amp;)),
 ui-&gt;resultEdit, SLOT(setText(const QString &amp;)) );
&lt;/pre&gt;
&lt;p&gt;The special thing in the code above, is that we didn't have to do anything special - Qt just solved our inter-thread communication issues for us. What I mean, it that if our code had simply tried to output the result by calling ui-&amp;gt;resultEdit-&amp;gt;setText() directly then we would be attempting to access the GUI from outside the GUI thread which would most likely cause our application to crash. Instead, since we're using the default type of connections 'AutoConnection', what this means is that Qt will spot if the thread in which a signal is emitted is different from the one in which it is received and handle the necessary synchronisation for us - nice!&lt;/p&gt;
&lt;!--break--&gt;</description></item><item><title>Cutting the Web Down to Size</title><link>https://blogs.kde.org/2009/10/20/cutting-web-down-size/</link><pubDate>Tue, 20 Oct 2009 00:00:00 +0000</pubDate><author>Rich</author><guid>https://blogs.kde.org/2009/10/20/cutting-web-down-size/</guid><description>&lt;p&gt;A feature that has been floating around in a few places but hasn't been a
significant feature in KDE is web slicing. This is the ability to take a piece
of a web page (commonly a div) and render it as a standalone object. It's
useful for stuff like putting a weather forcast on your desktop, watching new
comments on a forum etc. This weekend I made a start on implementing it as
tool for &lt;a href="http://techbase.kde.org/Projects/Silk"&gt;Project Silk&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The first version I wrote was pretty simple - it lets you specify the element
you want rendered, then presents it to the client application as a
QPixmap. This was fairly easy thanks to the new QWebElement API, the core of
the code is as simple as this:&lt;/p&gt;
&lt;pre&gt;
QPixmap Slicer::renderElement( const QString &amp;amp;selector )
{
 QWebFrame *frame = d-&amp;gt;page-&amp;gt;mainFrame();
 d-&amp;gt;page-&amp;gt;setViewportSize( frame-&amp;gt;contentsSize() );

 QWebElement element = frame-&amp;gt;findFirstElement( selector );
 if ( element.isNull() )
	return QPixmap();

 QRect rect = element.geometry();
 QPixmap result = QPixmap( rect.size() );
 result.fill( Qt::white );

 QPainter painter( &amp;result );
 painter.translate( -rect.x(), -rect.y() );
 frame-&amp;gt;render( &amp;amp;painter, QRegion(rect) );

 return result;
}
&lt;/pre&gt;
&lt;p&gt;This is enough to let you specify a CSS selector and render it to a pixmap
thanks to the nice API of QWebElement. Doing the same using the DOM API would
be simple enough, but a lot more verbose (and probably less flexible). The
code above was enough for me to make it trivial to write tools that present a
slice of a web page as part of their UI.&lt;/p&gt;
&lt;p&gt;As ever in life, some people are never satisfied so a common response was
to ask if I could make it so the slice is interactive. This is a bit of a can of worms
as everyone has their own definition - eg. simply responding to requests from
the page to repaint could be trivially added to the code above and would offer
the same functionality as that I'm told MacOS offers. Rather than try the
half-way solution, I wrote a prototype that actually gives you a fully
interactive slice - eg. you can type into the form elements. It's not
production quality, but it proves the point. You can see the result below:&lt;/p&gt;
&lt;img align="center" src="http://xmelegance.org/devel/webslice.png"&gt;
&lt;p&gt;Around the point I got this working, Kenneth let me know that a commit had
just landed in QtWebkit that would make the earlier version even simpler -
there's now a render() method on QWebElement that does exactly the same thing
my original code did. This is great news, as that solution is the correct one
for a lot of use-cases.&lt;/p&gt;
&lt;p&gt;Of course, by this time, I was quite tired but Sebas was still feeling
lively. The result is that 'live slice' code gained support for being embedded
in QGraphicsView overnight using the new QGraphicsWebView. There's a support
class that makes it available as a widget like before, but the implementation
is using this (new in 4.6) class. All in all this means we can nicely
integrate this functionality into apps using QGraphicsView like plasma or
amarok, and into QWidget based apps too.&lt;/p&gt;
&lt;p&gt;All in all, a successful couple of days in the stealthy advance of project
silk.&lt;/p&gt;
&lt;!--break--&gt;</description></item><item><title>Adding custom objects to Qt Webkit</title><link>https://blogs.kde.org/2009/07/05/adding-custom-objects-qt-webkit/</link><pubDate>Sun, 05 Jul 2009 00:00:00 +0000</pubDate><author>Rich</author><guid>https://blogs.kde.org/2009/07/05/adding-custom-objects-qt-webkit/</guid><description>&lt;p&gt;One question I've seen come up several times on #qt and qt-interest is how to
add custom (application specific) APIs to those available by default in
QtWebKit. This is actually pretty easy (once you know how) as I'll show
below. This post will show a simple example of how to make an object available
from javascript, including calling methods on the object and returning values
from C++.&lt;/p&gt;
&lt;p&gt;
There are two things you really need to know in order to perform this
integration, the first is the addToJavaScriptWindowObject() method of
QWebFrame, this allows will make the specified QObject visible from
javascript. The second thing you need to know is that objects published in
this way will vanish each time the javascript window object is cleared -
ie. every time the user navigates to a new page. To prevent this from causing
problems, QWebFrame provides a signal that tells you whenever the object is
cleared allowing you to re-add your custom API. This is actually much simpler
than it sounds!
&lt;p&gt;
The core of this is really implemented in two methods in the example, they're
shown below:
&lt;pre&gt;
void MyApi::setWebView( QWebView *view )
{
 QWebPage *page = view-&gt;page();
 frame = page-&amp;gt;mainFrame();

 attachObject();
 connect( frame, SIGNAL(javaScriptWindowObjectCleared()), this, SLOT(attachObject()) );
}

void MyApi::attachObject()
{
 frame-&amp;gt;addToJavaScriptWindowObject( QString("MyApi"), this );
}
&lt;/pre&gt;
&lt;p&gt;This code is all that you need in order to make all of the public slots of the
MyApi object visible to javascript. The MyApi class provides two public slots:&lt;/p&gt;
&lt;pre&gt;
public slots:
 void doSomething( const QString &amp;param );
 int doSums( int a, int b );
&lt;/pre&gt;
&lt;p&gt;The first slot simply logs a message to the debug output, the second returns
the sum of its two arguments (yes, slots can return things!). They're called
from javascript like this:&lt;/p&gt;
&lt;pre&gt;
 MyApi.doSomething( 'Hello from JS page 2!!!!' );

 sum = MyApi.doSums( 2, 3 );
 alert( 'C++ says the sum is ' + sum );
&lt;/pre&gt;
&lt;p&gt;And that's all there is to it! You can download the code from &lt;a
href="http://xmelegance.org/devel/qtwebkitextension.tar.gz"&gt;&lt;a href="http://xmelegance.org/devel/qtwebkitextension.tar.gz"&gt;http://xmelegance.org/devel/qtwebkitextension.tar.gz&lt;/a&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;!--break--&gt;</description></item><item><title>First Hack with ItemsViewsNG</title><link>https://blogs.kde.org/2009/04/10/first-hack-itemsviewsng/</link><pubDate>Fri, 10 Apr 2009 00:00:00 +0000</pubDate><author>Rich</author><guid>https://blogs.kde.org/2009/04/10/first-hack-itemsviewsng/</guid><description>&lt;p&gt;People reading planet will have seen Thomas Zander's post about the new ItemViews framework the Trolls^H^H^HQt Software guys have been working on. It's very experimental right now, but I thought I'd have a quick look. I decided that a fun hack to write would be to take a standard listview that displays a list of URLs (boring!) and write a custom view that instead displays the rendered web page. I only spent a couple of hours on it, so the code is a hack (eg. you need to resize it to get the pages to display once they've loaded) but the results look ok. The whole &lt;a href="http://xmelegance.org/devel/weblist.tar.gz"&gt;code for this example&lt;/a&gt; comes in under 120 lines.
&lt;br&gt;
&lt;img src="http://xmelegance.org/devel/itemviewsng2.png"&gt;&lt;/p&gt;
&lt;p&gt;So, that's my hack in response to Thomas's challenge, who's next?&lt;/p&gt;
&lt;p&gt;Here's an &lt;a href="http://xmelegance.org/devel/weblist2.tar.gz"&gt;updated version&lt;/a&gt; that correctly updates the items when the page is loaded without requiring a resize.&lt;/p&gt;
&lt;p&gt;And now &lt;a href="http://xmelegance.org/devel/weblist3.tar.gz"&gt;version 3&lt;/a&gt; that disables the scrollbars in the previews making things look &lt;a href="http://xmelegance.org/devel/itemviewsng3.png"&gt;a lot nicer&lt;/a&gt;.&lt;/p&gt;
&lt;!--break--&gt;</description></item></channel></rss>