Mercurial > trustbridge
diff ui/sslconnection_curl.cpp @ 910:eaed02defe6a
More SSLConnection refactoring. Fixes curl downloader.
author | Andre Heinecke <andre.heinecke@intevation.de> |
---|---|
date | Mon, 18 Aug 2014 18:51:33 +0200 |
parents | d1c951b3012d |
children | a55c6cf54365 |
line wrap: on
line diff
--- a/ui/sslconnection_curl.cpp Thu Aug 14 11:24:13 2014 +0200 +++ b/ui/sslconnection_curl.cpp Mon Aug 18 18:51:33 2014 +0200 @@ -7,9 +7,17 @@ */ #include "sslconnection_curl.h" +#include <QSaveFile> #define CONNECTION_DEBUG +/**@def Wrapper macro around curl_easy_setopt invocation */ +#define CURL_SETOPT(x, y, z) \ + if (curl_easy_setopt(mCurl, x, y) != CURLE_OK) { \ + qDebug() << "Setopt failed"; \ + z; \ + } + SSLConnectionCurl::SSLConnectionCurl(const QString& url, const QByteArray& certificate): SSLConnection (url, certificate), @@ -23,11 +31,6 @@ return; } - if (curl_easy_setopt(mCurl, CURLOPT_URL, QUrl(url).toEncoded().constData()) != CURLE_OK) { - qDebug() << "Setting url failed"; - return; - } - if (curl_easy_setopt(mCurl, CURLOPT_SSL_VERIFYPEER, 1L) != CURLE_OK) { /* Should be default anyway */ qDebug() << "Setting verifypeer failed"; @@ -40,6 +43,11 @@ return; } + if (curl_easy_setopt(mCurl, CURLOPT_ERRORBUFFER, mErrBuf) != CURLE_OK) { + qDebug() << "Setting errorbuf failed"; + return; + } + mCertFile.open(); if (mCertFile.write(mPinnedCert) != mPinnedCert.size()) { qDebug() << "Failed to write temporary certificate"; @@ -70,12 +78,25 @@ } int SSLConnectionCurl::connect() { + CURLcode retval; + + if (curl_easy_setopt(mCurl, CURLOPT_URL, mUrl.toEncoded().constData()) != CURLE_OK) { + qDebug() << "Failed to set URL"; + return -1; + } + if (curl_easy_setopt(mCurl, CURLOPT_CONNECT_ONLY, 1L) != CURLE_OK) { qDebug() << "Failed to set connect only option"; return -1; } - if (curl_easy_perform (mCurl) != CURLE_OK) { - qDebug() << "Failed to connect"; + retval = curl_easy_perform(mCurl); + if (retval != CURLE_OK) { + qDebug() << "Failed to connect: " << mErrBuf << " retval: " << retval; + if (retval == CURLE_PEER_FAILED_VERIFICATION) { + mErrorState = InvalidCertificate; + return -1; + } + mErrorState = NoConnection; return -1; } @@ -83,51 +104,128 @@ return 0; } -int SSLConnectionCurl::write(const QByteArray& request) { - size_t written = 0; +/* Globally do this as we can't pass this to the c function */ +size_t ssl_curl_max_write, ssl_curl_written; - if (curl_easy_send (mCurl, request.constData(), request.size(), &written) != CURLE_OK) { - qDebug() << "Failed to send request"; - return -1; +size_t write_data(void *ptr, size_t size, size_t nmemb, + QSaveFile *fp) +{ + qDebug() << "Writing size: " << size << " * " << nmemb; + if (ssl_curl_max_write < ssl_curl_written) { + qDebug() << "Aborting write. Too much data."; + return 0; } - if (written != (size_t)request.size()) { - qDebug() << "Failed to write everything"; - return -1; + size_t written = fp->write((const char *)ptr, size * nmemb); + if (written != size * nmemb) { + qDebug() << "Failed to write data. Written: " << written + << " requested: " << size * nmemb; + return 0; } - return 0; + ssl_curl_written += written; + return written; } -QByteArray SSLConnectionCurl::read(size_t len) +bool SSLConnectionCurl::downloadFile(const QString &resource, + const QString &fileName, + size_t maxSize) { - unsigned char buf[len]; - QByteArray retval(""); - CURLcode ret; - size_t read = 0; - unsigned int tries = 0; + QSaveFile outputFile(fileName); + ssl_curl_written = 0; + ssl_curl_max_write = maxSize; + // Open / Create the file to write to. + if (!outputFile.open(QIODevice::WriteOnly)) { + qDebug() << "Failed to open file"; + return false; + } + QUrl urlCopy = mUrl; + urlCopy.setPath(resource); - do { - memset (buf, 0, sizeof(buf)); - ret = curl_easy_recv (mCurl, buf, len, &read); - if (ret == CURLE_OK && read == 0) { - return retval; - } - if (ret == CURLE_AGAIN) { - tries++; - continue; - } - if (ret != CURLE_OK) { - qDebug() << "Read failed."; - return QByteArray(); - } - if (len < (len - read)) { - /* Should never happen if ssl_read behaves */ - qDebug() << "integer overflow in polarSSLRead"; - return QByteArray(); - } + if (curl_easy_setopt(mCurl, CURLOPT_URL, urlCopy.toEncoded().constData()) != CURLE_OK) { + qDebug() << "Failed to set URL"; + return false; + } - len -= read; - retval.append((const char *)buf, read); - } while (len > 0 && tries < 10); + if (curl_easy_setopt(mCurl, CURLOPT_CONNECT_ONLY, 0L) != CURLE_OK) { + qDebug() << "Failed to set connect"; + return false; + } - return retval; + if (curl_easy_setopt(mCurl, CURLOPT_HEADER, 0L) != CURLE_OK) { + qDebug() << "Failed to set header"; + return false; + } + + if (curl_easy_setopt(mCurl, CURLOPT_NOBODY, 0L) != CURLE_OK) { + qDebug() << "Failed to set no body"; + return false; + } + + if (curl_easy_setopt(mCurl, CURLOPT_WRITEFUNCTION, write_data) != CURLE_OK) { + qDebug() << "Failed to set write function"; + return false; + } + + if (curl_easy_setopt(mCurl, CURLOPT_WRITEDATA, &outputFile) != CURLE_OK) { + qDebug() << "Failed to set write function"; + return false; + } + + if (curl_easy_perform (mCurl) != CURLE_OK) { + qDebug() << "Failed to perform download."; + return false; + } + + if (!outputFile.commit()) { + qDebug() << "Failed to commit data to filesystem."; + return false; + } + + return true; } + +QDateTime SSLConnectionCurl::getLastModifiedHeader(const QString &resource) { + QUrl urlCopy = mUrl; + urlCopy.setPath(resource); + + if (curl_easy_setopt(mCurl, CURLOPT_URL, urlCopy.toEncoded().constData()) != CURLE_OK) { + qDebug() << "Failed to set URL"; + return QDateTime(); + } + + if (curl_easy_setopt(mCurl, CURLOPT_CONNECT_ONLY, 0L) != CURLE_OK) { + qDebug() << "Failed to set connect"; + return QDateTime(); + } + + if (curl_easy_setopt(mCurl, CURLOPT_HEADER, 1L) != CURLE_OK) { + qDebug() << "Failed to set header"; + return QDateTime(); + } + + if (curl_easy_setopt(mCurl, CURLOPT_NOBODY, 1L) != CURLE_OK) { + qDebug() << "Failed to set no body"; + return QDateTime(); + } + + if (curl_easy_setopt(mCurl, CURLOPT_FILETIME, 1L) != CURLE_OK) { + qDebug() << "Failed to set filetime"; + return QDateTime(); + } + + if (curl_easy_perform (mCurl) != CURLE_OK) { + qDebug() << "Failed to perform last modified check."; + return QDateTime(); + } + long filetime = 0; + + if (curl_easy_getinfo (mCurl, CURLINFO_FILETIME, &filetime) != CURLE_OK) { + qDebug() << "Failed to get filetime"; + return QDateTime(); + } + + if (filetime == -1) { + qDebug() << "Invalid Time"; + return QDateTime(); + } + return QDateTime::fromTime_t(filetime); +}