2 // Copyright (C) 2014 Ingo Ruhnke <grumbel@gmail.com>
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #include "addon/downloader.hpp"
19 #include <curl/curl.h>
20 #include <curl/easy.h>
25 #include "util/log.hpp"
30 size_t my_curl_string_append(void* ptr, size_t size, size_t nmemb, void* userdata)
32 std::string& s = *static_cast<std::string*>(userdata);
33 std::string buf(static_cast<char*>(ptr), size * nmemb);
35 log_debug << "read " << size * nmemb << " bytes of data..." << std::endl;
39 size_t my_curl_physfs_write(void* ptr, size_t size, size_t nmemb, void* userdata)
41 PHYSFS_file* f = static_cast<PHYSFS_file*>(userdata);
42 PHYSFS_sint64 written = PHYSFS_write(f, ptr, size, nmemb);
43 log_debug << "read " << size * nmemb << " bytes of data..." << std::endl;
44 return size * written;
49 Downloader::Downloader()
51 curl_global_init(CURL_GLOBAL_ALL);
54 Downloader::~Downloader()
56 curl_global_cleanup();
60 Downloader::download(const std::string& url,
61 size_t (*write_func)(void* ptr, size_t size, size_t nmemb, void* userdata),
64 log_info << "Downloading " << url << std::endl;
66 char error_buffer[CURL_ERROR_SIZE+1];
68 CURL* curl_handle = curl_easy_init();
69 curl_easy_setopt(curl_handle, CURLOPT_URL, url.c_str());
70 curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "SuperTux/" PACKAGE_VERSION " libcURL");
71 curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_func);
72 curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, userdata);
73 curl_easy_setopt(curl_handle, CURLOPT_ERRORBUFFER, error_buffer);
74 curl_easy_setopt(curl_handle, CURLOPT_NOPROGRESS, 1);
75 curl_easy_setopt(curl_handle, CURLOPT_NOSIGNAL, 1);
76 curl_easy_setopt(curl_handle, CURLOPT_FAILONERROR, 1);
77 curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1);
78 CURLcode result = curl_easy_perform(curl_handle);
79 curl_easy_cleanup(curl_handle);
81 if (result != CURLE_OK)
83 std::string why = error_buffer[0] ? error_buffer : "unhandled error";
84 throw std::runtime_error(url + ": download failed: " + why);
89 Downloader::download(const std::string& url)
92 download(url, my_curl_string_append, &result);
97 Downloader::download(const std::string& url, const std::string& filename)
99 std::unique_ptr<PHYSFS_file, int(*)(PHYSFS_File*)> fout(PHYSFS_openWrite(filename.c_str()),
101 download(url, my_curl_physfs_write, fout.get());