diff options
author | Robin Gareus <robin@gareus.org> | 2016-07-18 16:45:45 +0200 |
---|---|---|
committer | Robin Gareus <robin@gareus.org> | 2016-07-18 16:46:59 +0200 |
commit | 004b57e9f67c6b818357759005c8e53b041dead4 (patch) | |
tree | 59f6b6309d18bc62bd3a3fa2c455574259e5b80e /gtk2_ardour | |
parent | 1dcb54ba22fc84883512ac332cd45e14b5bf9e1b (diff) |
ArdourCurl: prepare to unify various curl calls
mainly motivated by a central location to setup SSL.
Diffstat (limited to 'gtk2_ardour')
-rw-r--r-- | gtk2_ardour/ardour_http.cc | 197 | ||||
-rw-r--r-- | gtk2_ardour/ardour_http.h | 90 | ||||
-rw-r--r-- | gtk2_ardour/bundle_env_linux.cc | 10 | ||||
-rw-r--r-- | gtk2_ardour/wscript | 1 |
4 files changed, 294 insertions, 4 deletions
diff --git a/gtk2_ardour/ardour_http.cc b/gtk2_ardour/ardour_http.cc new file mode 100644 index 0000000000..569c0e2197 --- /dev/null +++ b/gtk2_ardour/ardour_http.cc @@ -0,0 +1,197 @@ +/* + * Copyright (C) 2016 Robin Gareus <robin@gareus.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include <assert.h> +#include <stdlib.h> +#include <unistd.h> +#include <cstring> + +#include <glibmm.h> + +#include "pbd/compose.h" +#include "pbd/i18n.h" +#include "pbd/error.h" + +#include "ardour_http.h" + +#ifdef WAF_BUILD +#include "gtk2ardour-version.h" +#endif + +#ifndef ARDOUR_CURL_TIMEOUT +#define ARDOUR_CURL_TIMEOUT (60) +#endif + +using namespace ArdourCurl; + +const char* HttpGet::ca_path = NULL; +const char* HttpGet::ca_info = NULL; + +void +HttpGet::setup_certificate_paths () +{ + /* this is only needed for Linux Bundles. + * (on OSX, Windows, we use system-wide ssl (darwinssl, winssl) + * Gnu/Linux distro will link against system-wide libcurl. + * + * but for linux-bundles we get to enjoy: + * https://www.happyassassin.net/2015/01/12/a-note-about-ssltls-trusted-certificate-stores-and-platforms/ + * + * (we do ship curl + nss + nss-pem) + * + * Short of this mess: we could simply bundle a .crt of + * COMODO (ardour) and ghandi (freesound) and be done with it. + */ + assert (!ca_path && !ca_info); // call once + + curl_global_init (CURL_GLOBAL_DEFAULT); + + if (Glib::file_test ("/etc/pki/tls/certs/ca-bundle.crt", Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) { + // Fedora / RHEL, Arch + ca_info = "/etc/pki/tls/certs/ca-bundle.crt"; + } + else if (Glib::file_test ("/etc/ssl/certs/ca-certificates.crt", Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) { + // Debian and derivatives + ca_info = "/etc/ssl/certs/ca-certificates.crt"; + } + else if (Glib::file_test ("/etc/pki/tls/cert.pem", Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) { + // GNU/TLS can keep extra stuff here + ca_info = "/etc/pki/tls/cert.pem"; + } + // else NULL: use default (currently) "/etc/ssl/certs/ca-certificates.crt" if it exists + + if (Glib::file_test ("/etc/pki/tls/certs/ca-bundle.crt", Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) { + // we're on RHEL // https://bugzilla.redhat.com/show_bug.cgi?id=1053882 + ca_path = "/nonexistent_path"; // don't try "/etc/ssl/certs" in case it's curl's default + } + else if (Glib::file_test ("/etc/ssl/certs", Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) { + // Debian and derivs + OpenSuSe + ca_path = "/etc/ssl/certs"; + } else { + ca_path = "/nonexistent_path"; // don't try -- just in case: + } + + /* If we don't set anything defaults are used. at the time of writing we compile bundled curl on debian + * and it'll default to /etc/ssl/certs and /etc/ssl/certs/ca-certificates.crt + */ +} + +static size_t +WriteMemoryCallback (void *ptr, size_t size, size_t nmemb, void *data) { + size_t realsize = size * nmemb; + struct HttpGet::MemStruct *mem = (struct HttpGet::MemStruct*)data; + + mem->data = (char *)realloc (mem->data, mem->size + realsize + 1); + if (mem->data) { + memcpy (&(mem->data[mem->size]), ptr, realsize); + mem->size += realsize; + mem->data[mem->size] = 0; + } + return realsize; +} + + +HttpGet::HttpGet (bool p, bool ssl) + : persist (p) + , _status (-1) + , _result (-1) +{ + error_buffer[0] = '\0'; + _curl = curl_easy_init (); + + curl_easy_setopt (_curl, CURLOPT_WRITEDATA, (void *)&mem); + curl_easy_setopt (_curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback); + curl_easy_setopt (_curl, CURLOPT_USERAGENT, PROGRAM_NAME VERSIONSTRING); + curl_easy_setopt (_curl, CURLOPT_TIMEOUT, ARDOUR_CURL_TIMEOUT); + curl_easy_setopt (_curl, CURLOPT_NOSIGNAL, 1); + curl_easy_setopt (_curl, CURLOPT_ERRORBUFFER, error_buffer); + + // by default use curl's default. + if (ssl && ca_info) { + curl_easy_setopt (_curl, CURLOPT_CAINFO, ca_info); + } + if (ssl && ca_path) { + curl_easy_setopt (_curl, CURLOPT_CAPATH, ca_path); + } +} + +HttpGet::~HttpGet () +{ + curl_easy_cleanup (_curl); + if (!persist) { + free (mem.data); + } +} + +char* +HttpGet::get (const char* url) +{ + if (!_curl) { + return NULL; + } + + if (strncmp ("http://", url, 7) && strncmp ("https://", url, 8)) { + return NULL; + } + + if (!persist) { + free (mem.data); + } + mem.size = 0; + + curl_easy_setopt (_curl, CURLOPT_URL, url); + _result = curl_easy_perform (_curl); + curl_easy_getinfo (_curl, CURLINFO_RESPONSE_CODE, &_status); + + if (_result) { + PBD::error << string_compose (_("HTTP request failed: (%1) %2"), _result, error_buffer); + return NULL; + } + if (_status != 200) { + PBD::error << string_compose (_("HTTP request status: %1"), _status); + return NULL; + } + + return mem.data; +} + +std::string +HttpGet::error () const { + if (_result != 0) { + return string_compose (_("HTTP request failed: (%1) %2"), _result, error_buffer); + } + if (_status != 200) { + return string_compose (_("HTTP request status: %1"), _status); + } + return "No Error"; +} + +char* +ArdourCurl::http_get (const char* url, int* status) { + HttpGet h (true); + char* rv = h.get (url); + if (status) { + *status = h.status (); + } + return rv; +} + +std::string +ArdourCurl::http_get (const std::string& url) { + return HttpGet (false).get (url); +} diff --git a/gtk2_ardour/ardour_http.h b/gtk2_ardour/ardour_http.h new file mode 100644 index 0000000000..cabcb3d5bc --- /dev/null +++ b/gtk2_ardour/ardour_http.h @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2016 Robin Gareus <robin@gareus.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __gtk_ardour_http_h__ +#define __gtk_ardour_http_h__ + +#include <curl/curl.h> +#include <string> + +namespace ArdourCurl { + +class HttpGet { + public: + HttpGet (bool persist = false, bool ssl = true); + ~HttpGet (); + + struct MemStruct { + MemStruct () : data (0), size (0) {} + char* data; + size_t size; + }; + + char* get (const char* url); + + std::string get (const std::string& url) { + char *rv = get (url.c_str ()); + return rv ? std::string (rv) : std::string (); + } + + char* data () const { return mem.data; } + size_t data_size () const { return mem.size; } + + long int status () const { return _status; } + + char* escape (const char* s, int l) const { + return curl_easy_escape (_curl, s, l); + } + + char* unescape (const char* s, int l, int *o) const { + return curl_easy_unescape (_curl, s, l, o); + } + + void free (void *p) const { + curl_free (p); + } + + std::string error () const; + + CURL* curl () const { return _curl; } + + // called from fixup_bundle_environment + static void setup_certificate_paths (); + + private: + CURL* _curl; + bool persist; + + long int _status; + long int _result; + + char error_buffer[CURL_ERROR_SIZE]; + + struct MemStruct mem; + + static const char* ca_path; + static const char* ca_info; +}; + +char* http_get (const char* url, int* status); + +std::string http_get (const std::string& url); + +} // namespace + +#endif /* __gtk_ardour_http_h__ */ diff --git a/gtk2_ardour/bundle_env_linux.cc b/gtk2_ardour/bundle_env_linux.cc index e553213ec0..80830964b4 100644 --- a/gtk2_ardour/bundle_env_linux.cc +++ b/gtk2_ardour/bundle_env_linux.cc @@ -36,6 +36,7 @@ #include "pbd/pathexpand.h" #include "pbd/file_utils.h" +#include "ardour_http.h" #include "bundle_env.h" #include "pbd/i18n.h" @@ -110,11 +111,12 @@ fixup_bundle_environment (int /*argc*/, char* argv[], string & localedir) error << _("No fontconfig file found on your system. Things may looked very odd or ugly") << endmsg; } - /* this doesn't do much but setting it should prevent various parts of the GTK/GNU stack - from looking outside the bundle to find the charset.alias file. - */ - g_setenv ("CHARSETALIASDIR", dir_path.c_str(), 1); + /* this doesn't do much but setting it should prevent various parts of the GTK/GNU stack + from looking outside the bundle to find the charset.alias file. + */ + g_setenv ("CHARSETALIASDIR", dir_path.c_str(), 1); + ArdourCurl::HttpGet::setup_certificate_paths (); } void diff --git a/gtk2_ardour/wscript b/gtk2_ardour/wscript index d9e6b2efcd..4597ecefb2 100644 --- a/gtk2_ardour/wscript +++ b/gtk2_ardour/wscript @@ -35,6 +35,7 @@ gtk2_ardour_sources = [ 'ardour_dialog.cc', 'ardour_display.cc', 'ardour_dropdown.cc', + 'ardour_http.cc', 'ardour_knob.cc', 'ardour_spinner.cc', 'ardour_ui.cc', |