2 // Copyright (C) 2007 Christoph Sommer <christoph.sommer@2007.expires.deltadevelopment.de>
3 // 2014 Ingo Ruhnke <grumbel@gmail.com>
5 // This program is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program. If not, see <http://www.gnu.org/licenses/>.
18 #include "addon/downloader.hpp"
20 #include <curl/curl.h>
21 #include <curl/easy.h>
26 #include "util/log.hpp"
31 size_t my_curl_string_append(void* ptr, size_t size, size_t nmemb, void* userdata)
33 std::string& s = *static_cast<std::string*>(userdata);
34 std::string buf(static_cast<char*>(ptr), size * nmemb);
36 log_debug << "read " << size * nmemb << " bytes of data..." << std::endl;
40 size_t my_curl_physfs_write(void* ptr, size_t size, size_t nmemb, void* userdata)
42 PHYSFS_file* f = static_cast<PHYSFS_file*>(userdata);
43 PHYSFS_sint64 written = PHYSFS_write(f, ptr, size, nmemb);
44 log_debug << "read " << size * nmemb << " bytes of data..." << std::endl;
45 return size * written;
50 Downloader::Downloader()
52 curl_global_init(CURL_GLOBAL_ALL);
55 Downloader::~Downloader()
57 curl_global_cleanup();
61 Downloader::download(const std::string& url,
62 size_t (*write_func)(void* ptr, size_t size, size_t nmemb, void* userdata),
65 log_info << "Downloading " << url << std::endl;
67 char error_buffer[CURL_ERROR_SIZE+1];
69 CURL* curl_handle = curl_easy_init();
70 curl_easy_setopt(curl_handle, CURLOPT_URL, url.c_str());
71 curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "SuperTux/" PACKAGE_VERSION " libcURL");
72 curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_func);
73 curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, userdata);
74 curl_easy_setopt(curl_handle, CURLOPT_ERRORBUFFER, error_buffer);
75 curl_easy_setopt(curl_handle, CURLOPT_NOPROGRESS, 1);
76 curl_easy_setopt(curl_handle, CURLOPT_NOSIGNAL, 1);
77 curl_easy_setopt(curl_handle, CURLOPT_FAILONERROR, 1);
78 curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1);
79 CURLcode result = curl_easy_perform(curl_handle);
80 curl_easy_cleanup(curl_handle);
82 if (result != CURLE_OK)
84 std::string why = error_buffer[0] ? error_buffer : "unhandled error";
85 throw std::runtime_error(url + ": download failed: " + why);
90 Downloader::download(const std::string& url)
93 download(url, my_curl_string_append, &result);
98 Downloader::download(const std::string& url, const std::string& filename)
100 std::unique_ptr<PHYSFS_file, int(*)(PHYSFS_File*)> fout(PHYSFS_openWrite(filename.c_str()),
102 download(url, my_curl_physfs_write, fout.get());