OpenCPN Partial API docs
Loading...
Searching...
No Matches
downloader.cpp
1/******************************************************************************
2 *
3 * Project: OpenCPN
4 *
5 ***************************************************************************
6 * Copyright (C) 2019 Alec Leamas *
7 * *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
12 * *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program; if not, write to the *
20 * Free Software Foundation, Inc., *
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
22 ***************************************************************************
23 */
24
25#include <fstream>
26
27#include <curl/curl.h>
28
29#include <wx/filename.h>
30#include <wx/log.h>
31
32#include "downloader.h"
33
35static size_t throw_cb(void* ptr, size_t size, size_t nmemb, void* data) {
36 (void)ptr;
37 (void)data;
38 return (size_t)(size * nmemb);
39}
40
41static unsigned write_cb(char* in, unsigned size, unsigned nmemb, void* data);
42// Forward
43
44Downloader::Downloader(std::string url_)
45 : url(url_), stream(), error_msg(""), errorcode(0){};
46
47int Downloader::last_errorcode() { return errorcode; }
48
49std::string Downloader::last_error() { return error_msg; }
50
51void Downloader::on_chunk(const char* buff, unsigned bytes) {
52 stream->write(buff, bytes);
53}
54
55bool Downloader::download(std::ostream* stream) {
56 CURL* curl;
57 char curl_errbuf[CURL_ERROR_SIZE];
58
59 this->stream = stream;
60 curl = curl_easy_init();
61 curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
62 curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, curl_errbuf);
63 curl_easy_setopt(curl, CURLOPT_USERAGENT, "Mozilla/5.0");
64 curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1L);
65 curl_easy_setopt(curl, CURLOPT_VERBOSE, 0L);
66 // FIXME -- Add correct certificates on host.
67 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
68 curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
69 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb);
70 curl_easy_setopt(curl, CURLOPT_WRITEDATA, this);
71 curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L);
72 int code = curl_easy_perform(curl);
73 curl_easy_cleanup(curl);
74 if (code != CURLE_OK) {
75 wxLogWarning("Failed to get '%s' [%s]\n", url, curl_errbuf);
76 errorcode = code;
77 error_msg = std::string(curl_errbuf);
78 return false;
79 }
80 return true;
81}
82
83bool Downloader::download(std::string& path) {
84 if (path == "") {
85 path = wxFileName::CreateTempFileName("ocpn_dl").ToStdString();
86 }
87 std::ofstream stream;
88 stream.open(path.c_str(), std::ios::out | std::ios::binary | std::ios::trunc);
89 if (!stream.is_open()) {
90 errorcode = CURLE_WRITE_ERROR;
91 error_msg = std::string("Cannot open temporary file ") + path;
92 return false;
93 }
94 bool ok = download(&stream);
95 stream.close();
96 return ok;
97}
98
100 CURL* curl;
101 char curl_errbuf[CURL_ERROR_SIZE] = {0};
102 double filesize = 0.0;
103
104 curl = curl_easy_init();
105 curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
106 curl_easy_setopt(curl, CURLOPT_NOBODY, 1L);
107 curl_easy_setopt(curl, CURLOPT_FILETIME, 1L);
108 curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, throw_cb);
109 curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
110 curl_easy_setopt(curl, CURLOPT_HEADER, 0L);
111 // FIXME -- Add correct certificates on host.
112 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
113
114 int r = curl_easy_perform(curl);
115 if (r == CURLE_OK) {
116 r = curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &filesize);
117 }
118 curl_easy_cleanup(curl);
119 wxLogMessage("filesize %s: %d bytes\n", url.c_str(), (int)filesize);
120 if (r != CURLE_OK) {
121 errorcode = r;
122 error_msg = std::string(curl_errbuf);
123 return 0;
124 }
125 return (long)filesize;
126}
127
129static unsigned write_cb(char* in, unsigned size, unsigned nmemb, void* data) {
130 auto downloader = static_cast<Downloader*>(data);
131 if (data == 0) {
132 return 0;
133 }
134 downloader->on_chunk(in, size * nmemb);
135 return in == NULL ? 0 : size * nmemb;
136}
Handle downloading of files from remote urls.
Definition: downloader.h:34
bool download(std::ostream *stream)
Download url into stream, return false on errors.
Definition: downloader.cpp:55
long get_filesize()
Try to get remote filesize, return 0 on failure.
Definition: downloader.cpp:99
std::string last_error()
Last Curl error message.
Definition: downloader.cpp:49
virtual void on_chunk(const char *buff, unsigned bytes)
Called when given bytes has been transferred from remote.
Definition: downloader.cpp:51
int last_errorcode()
Last error code, a CURLE return code.
Definition: downloader.cpp:47