Mercurial > trustbridge
view 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 source
/* Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik * Software engineering by Intevation GmbH * * This file is Free Software under the GNU GPL (v>=2) * and comes with ABSOLUTELY NO WARRANTY! * See LICENSE.txt for details. */ #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), mCurl (NULL) { curl_global_init(CURL_GLOBAL_DEFAULT); mCurl = curl_easy_init(); if (!mCurl) { qDebug() << "Failed to initialize curl"; return; } if (curl_easy_setopt(mCurl, CURLOPT_SSL_VERIFYPEER, 1L) != CURLE_OK) { /* Should be default anyway */ qDebug() << "Setting verifypeer failed"; return; } if (curl_easy_setopt(mCurl, CURLOPT_SSL_VERIFYHOST, 0L) != CURLE_OK) { /* There are no limitiations for the pinned certificate */ qDebug() << "Setting verifyhost failed"; 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"; return; } mCertFile.close(); if (curl_easy_setopt(mCurl, CURLOPT_CAINFO, mCertFile.fileName().toUtf8().constData()) != CURLE_OK) { qDebug() << "Failed to write temporary certificate"; return; } mInitialized = true; #ifdef CONNECTION_DEBUG curl_easy_setopt(mCurl, CURLOPT_VERBOSE, 1L); #endif } SSLConnectionCurl::~SSLConnectionCurl() { if (mCurl) { curl_easy_cleanup (mCurl); } if (mInitialized) { mCertFile.close(); } curl_global_cleanup(); } 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; } 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; } mConnected = true; return 0; } /* Globally do this as we can't pass this to the c function */ size_t ssl_curl_max_write, ssl_curl_written; 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; } 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; } ssl_curl_written += written; return written; } bool SSLConnectionCurl::downloadFile(const QString &resource, const QString &fileName, size_t maxSize) { 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); if (curl_easy_setopt(mCurl, CURLOPT_URL, urlCopy.toEncoded().constData()) != CURLE_OK) { qDebug() << "Failed to set URL"; return false; } if (curl_easy_setopt(mCurl, CURLOPT_CONNECT_ONLY, 0L) != CURLE_OK) { qDebug() << "Failed to set connect"; return false; } 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); }