Blogs

    awinterz's picture

    Don't Forget to Resolve Your Own Bugs

    2012
    28
    Jan

    A gentle reminder: please occassionally check back on bugs you've reported and resolve them if they have been fixed in recent versions.

    Sometimes we developers fix bugs but forget to resolve them ourselves; sometimes bugs are fixed by newer versions of other software we depend on; sometimes bugs are fixed as consequences of other fixes.

    So help us out and resolve your own bugs when possible.

    Thanks.

    jriddell's picture

    Plasma and KDE Applications 4.8 on Kubuntu

    2012
    27
    Jan

    Kubuntu has packages for 4.8 bringing updates to Plasma workspaces and a load of KDE Applications.

    To quote a nice user posting on kde-devel

    "I upgraded to Ubuntu's Precise Alpha 1 a few days ago. After the upgrade completed, I tried out KDE 4.8 RC 2. It worked great until the final release of KDE 4.8 Final. KDE 4.8 Final is even better than the RC!"

    or later in the same thread

    "KDE 4.8 is rocking for me too.Using the Kubuntu PPA's on Sandy Bridge system and it's just lightning fast to do anything. "

    jaroslaw staniek's picture

    Q-Fridges - we're hiring!

    2012
    24
    Jan

    There are job offers floating sporadically on planetkde so I guess this one would fit too especially that there are many related technologies involved.

    You may remember my story about some crazy Qt device. Now there is apparent expansion both vertically and to other types of high-end devices, so:

    This offer is for permanent jobs in Warsaw office, rather for Polish speakers. More on my Polish blog.

    boemann's picture

    Calligra Words junior jobs

    2012
    21
    Jan

    I often get asked about junior jobs in Calligra Words. I ususally say no, but now I actually have some.

    The reason I say no is that there are no easy jobs left, and so jobs would take much more of my time than I would like. And I also don't want to purposely leave unfinished stuff behind.

    Anyway here is a brief synopsis of the junior job: We have code that applies bold, italic etc, and it works, except it doesn't respect table cell protection. The job consists of repeating an example I've already made to the application of bold, italic and several other similar things.

    It's pretty easy copy,paste,edit and will give you practical experience with the visitor pattern

    alexander neundorf's picture

    Looking for a student job in an Open Source project in Germany ?

    2012
    20
    Jan

    You are a student, you would like to contribute to an Open Source project, and get paid for it ?

    Then I may have something for you.
    At my job at Fraunhofer in Kaiserslautern we are using the CDash testing server for testing the software we develop - various different High Performance applications for Linux clusters.

    pstirnweiss's picture

    Calligra Words style selection combo

    2012
    18
    Jan

    Since Monday, a feature I have been working on for quite a while has been merged into Calligra master. This is the style selection combo box.
    Until Monday, the style selection widget was a home brewed widget based on QFrame. It wasn't optimal and that is a British understatement. Now this widget is still home brewed, but based on a QComboBox.

    rich's picture

    Using GnuTLS with QTcpSocket

    2012
    14
    Jan

    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.

    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.

    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.

    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.

    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.

    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:

    class SslSocket : public QObject
    {
        Q_OBJECT
    
    public:
        SslSocket(QObject *parent=0);
        ~SslSocket();
    
        QByteArray read(qint64 maxsize);
        
    public slots:
        void connectToHost(const QString &hostname, int port);
        void startHandshake();
    
        qint64 write(const QByteArray &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;
    };
    

    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:

    void SslSocket::setupSession()
    {
        qDebug() << "Initialise client session";
    
        // Setup the trust store
        gnutls_certificate_allocate_credentials(&d->x509cred);
        gnutls_certificate_set_x509_trust_file(d->x509cred, "/etc/ssl/ca-bundle.pem", GNUTLS_X509_FMT_PEM);
    
        // Configure the session
        gnutls_init(&d->session, GNUTLS_CLIENT);
        gnutls_credentials_set(d->session, GNUTLS_CRD_CERTIFICATE, d->x509cred);
    
        const char *err;
        gnutls_priority_init(&d->priority_cache, "NORMAL", &err);
        gnutls_priority_set(d->session, d->priority_cache);
    
        // Setup the transport functions to use QTcpSocket
        gnutls_transport_set_ptr(d->session, this);
        gnutls_transport_set_pull_function(d->session, read_callback);
        gnutls_transport_set_push_function(d->session, write_callback);
    }
    

    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.

    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:

    ssize_t SslSocket::read_callback(gnutls_transport_ptr_t transport, void *buffer, size_t length)
    {
        SslSocket *self = static_cast<SslSocket *>(transport);
        return self->readInternal(buffer, length);
    }
    
    ssize_t SslSocket::readInternal(void *buffer, size_t length)
    {
        qDebug() << "readInternal, length" << length << ", available" << d->socket->bytesAvailable();
    
        if (d->socket->bytesAvailable() < qint64(length)) {
            gnutls_transport_set_errno(d->session, EAGAIN);
            return -1;
        }
    
        return d->socket->read(static_cast<char *>(buffer), length);
    }
    

    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.

    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.

    In order to allow the retry behaviour I mention above, there's a simple state machine. The SslSocket has the following basic states:

    enum State
    {
        Disconnected,
        Connecting,
        Handshaking,
        Encrypted
    };
    

    If new data is received then we look the state and retry the relevant
    operation as follows:

    void SslSocket::dataReceived()
    {
        qDebug() << "dataReceived() state is " << d->state;
    
        if (d->state == Handshaking) {
            handshakeInternal();
        }
        else if (d->state == Encrypted) {
            emit readyRead();
        }
    }
    

    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:

    void SslSocket::handshakeInternal()
    {
        qDebug() << "start handshake, state is" << d->state;
        int result = gnutls_handshake(d->session);
        qDebug() << "shake result" << gnutls_strerror(result) << result;
    
        if (result == 0) {
            qDebug() << "handshake completed";
            d->state = Encrypted;
            emit handshakeComplete();
        }
        else if (gnutls_error_is_fatal(result)) {
            qDebug() << "fatal error in handshake";
            emit error();
            d->socket->disconnect();
            d->state = Disconnected;
        }
    }
    

    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.

    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:

    QByteArray SslSocket::read(qint64 maxsize)
    {
        QByteArray buffer;
    
        if (d->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->session, buffer.data(), maxsize);
        } while( result == GNUTLS_E_INTERRUPTED || result == GNUTLS_E_AGAIN );
    
        buffer.truncate(result);
    
        return buffer;
    }
    
    qint64 SslSocket::write(const QByteArray &data)
    {
        qDebug() << "write";
    
        if (d->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->session, data.constData(), data.size());
            qDebug() << "write result" << result;
        } while( result == GNUTLS_E_INTERRUPTED || result == GNUTLS_E_AGAIN );
    
        return result;
    }
    

    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!

    GetSlash::GetSlash(SslSocket *sock)
        : QObject()
    {
        this->sock = sock;
        connect(sock, SIGNAL(handshakeComplete()), this, SLOT(start()));
        connect(sock, SIGNAL(readyRead()), this, SLOT(gotData()));
    }
    
    void GetSlash::start()
    {
        sock->write(QByteArray("GET / HTTP/1.0\n\n"));
    }
    
    void GetSlash::gotData()
    {
        QByteArray result = sock->read(2000);
        qDebug() << result;
    }
    

    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.

    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.

    EDIT: The code is now available here https://gitorious.org/qt-examples/qt-examples/commit/40e57647242079745c46d84e15d92f2093af300f

    boemann's picture

    jhk where are you

    2012
    13
    Jan

    Have anyone seen user jhk or know what his real name or email is

    If so then please leave a note either here or on irc #calligra

    He has started some work on Calligra Words that I'm really interested in and I havn't seen him since middle of december.

    mkruisselbrink's picture

    Calligra on Android

    2012
    12
    Jan

    As most of you are probably well aware, since quite a while it is not very hard to write Qt applications to run on Android devices. A couple of weeks ago we at KO GmbH decided to look into how hard it would be to get KDE applications to run, and more specifically, if it would be possible to run Calligra with one of its mobile UI's on an android device.

    khindenburg's picture

    Konsole's vttest results

    2012
    6
    Jan

    I finally got around to running vttest [1] in Konsole (4.8/master) [2].

    The most noticeable issue is the the console resizing commands don't work [3].