xref: /aosp_15_r20/external/google-breakpad/src/common/linux/libcurl_wrapper.cc (revision 9712c20fc9bbfbac4935993a2ca0b3958c5adad2)
1*9712c20fSFrederick Mayle // Copyright 2009 Google LLC
2*9712c20fSFrederick Mayle //
3*9712c20fSFrederick Mayle // Redistribution and use in source and binary forms, with or without
4*9712c20fSFrederick Mayle // modification, are permitted provided that the following conditions are
5*9712c20fSFrederick Mayle // met:
6*9712c20fSFrederick Mayle //
7*9712c20fSFrederick Mayle //     * Redistributions of source code must retain the above copyright
8*9712c20fSFrederick Mayle // notice, this list of conditions and the following disclaimer.
9*9712c20fSFrederick Mayle //     * Redistributions in binary form must reproduce the above
10*9712c20fSFrederick Mayle // copyright notice, this list of conditions and the following disclaimer
11*9712c20fSFrederick Mayle // in the documentation and/or other materials provided with the
12*9712c20fSFrederick Mayle // distribution.
13*9712c20fSFrederick Mayle //     * Neither the name of Google LLC nor the names of its
14*9712c20fSFrederick Mayle // contributors may be used to endorse or promote products derived from
15*9712c20fSFrederick Mayle // this software without specific prior written permission.
16*9712c20fSFrederick Mayle //
17*9712c20fSFrederick Mayle // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18*9712c20fSFrederick Mayle // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19*9712c20fSFrederick Mayle // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20*9712c20fSFrederick Mayle // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21*9712c20fSFrederick Mayle // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22*9712c20fSFrederick Mayle // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23*9712c20fSFrederick Mayle // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24*9712c20fSFrederick Mayle // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25*9712c20fSFrederick Mayle // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26*9712c20fSFrederick Mayle // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27*9712c20fSFrederick Mayle // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*9712c20fSFrederick Mayle 
29*9712c20fSFrederick Mayle #ifdef HAVE_CONFIG_H
30*9712c20fSFrederick Mayle #include <config.h>  // Must come first
31*9712c20fSFrederick Mayle #endif
32*9712c20fSFrederick Mayle 
33*9712c20fSFrederick Mayle #include <dlfcn.h>
34*9712c20fSFrederick Mayle 
35*9712c20fSFrederick Mayle #include <iostream>
36*9712c20fSFrederick Mayle #include <string>
37*9712c20fSFrederick Mayle 
38*9712c20fSFrederick Mayle #include "common/linux/libcurl_wrapper.h"
39*9712c20fSFrederick Mayle #include "common/using_std_string.h"
40*9712c20fSFrederick Mayle 
41*9712c20fSFrederick Mayle namespace google_breakpad {
LibcurlWrapper()42*9712c20fSFrederick Mayle LibcurlWrapper::LibcurlWrapper()
43*9712c20fSFrederick Mayle     : init_ok_(false),
44*9712c20fSFrederick Mayle       curl_lib_(nullptr),
45*9712c20fSFrederick Mayle       last_curl_error_(""),
46*9712c20fSFrederick Mayle       curl_(nullptr),
47*9712c20fSFrederick Mayle       formpost_(nullptr),
48*9712c20fSFrederick Mayle       lastptr_(nullptr),
49*9712c20fSFrederick Mayle       headerlist_(nullptr) {}
50*9712c20fSFrederick Mayle 
~LibcurlWrapper()51*9712c20fSFrederick Mayle LibcurlWrapper::~LibcurlWrapper() {
52*9712c20fSFrederick Mayle   if (init_ok_) {
53*9712c20fSFrederick Mayle     (*easy_cleanup_)(curl_);
54*9712c20fSFrederick Mayle     (*global_cleanup_)();
55*9712c20fSFrederick Mayle     dlclose(curl_lib_);
56*9712c20fSFrederick Mayle   }
57*9712c20fSFrederick Mayle }
58*9712c20fSFrederick Mayle 
SetProxy(const string & proxy_host,const string & proxy_userpwd)59*9712c20fSFrederick Mayle bool LibcurlWrapper::SetProxy(const string& proxy_host,
60*9712c20fSFrederick Mayle                               const string& proxy_userpwd) {
61*9712c20fSFrederick Mayle   if (!CheckInit()) return false;
62*9712c20fSFrederick Mayle 
63*9712c20fSFrederick Mayle   // Set proxy information if necessary.
64*9712c20fSFrederick Mayle   if (!proxy_host.empty()) {
65*9712c20fSFrederick Mayle     (*easy_setopt_)(curl_, CURLOPT_PROXY, proxy_host.c_str());
66*9712c20fSFrederick Mayle   } else {
67*9712c20fSFrederick Mayle     std::cout << "SetProxy called with empty proxy host.";
68*9712c20fSFrederick Mayle     return false;
69*9712c20fSFrederick Mayle   }
70*9712c20fSFrederick Mayle   if (!proxy_userpwd.empty()) {
71*9712c20fSFrederick Mayle     (*easy_setopt_)(curl_, CURLOPT_PROXYUSERPWD, proxy_userpwd.c_str());
72*9712c20fSFrederick Mayle   } else {
73*9712c20fSFrederick Mayle     std::cout << "SetProxy called with empty proxy username/password.";
74*9712c20fSFrederick Mayle     return false;
75*9712c20fSFrederick Mayle   }
76*9712c20fSFrederick Mayle   std::cout << "Set proxy host to " << proxy_host;
77*9712c20fSFrederick Mayle   return true;
78*9712c20fSFrederick Mayle }
79*9712c20fSFrederick Mayle 
AddFile(const string & upload_file_path,const string & basename)80*9712c20fSFrederick Mayle bool LibcurlWrapper::AddFile(const string& upload_file_path,
81*9712c20fSFrederick Mayle                              const string& basename) {
82*9712c20fSFrederick Mayle   if (!CheckInit()) return false;
83*9712c20fSFrederick Mayle 
84*9712c20fSFrederick Mayle   std::cout << "Adding " << upload_file_path << " to form upload.";
85*9712c20fSFrederick Mayle   // Add form file.
86*9712c20fSFrederick Mayle   (*formadd_)(&formpost_, &lastptr_,
87*9712c20fSFrederick Mayle               CURLFORM_COPYNAME, basename.c_str(),
88*9712c20fSFrederick Mayle               CURLFORM_FILE, upload_file_path.c_str(),
89*9712c20fSFrederick Mayle               CURLFORM_END);
90*9712c20fSFrederick Mayle 
91*9712c20fSFrederick Mayle   return true;
92*9712c20fSFrederick Mayle }
93*9712c20fSFrederick Mayle 
94*9712c20fSFrederick Mayle // Callback to get the response data from server.
WriteCallback(void * ptr,size_t size,size_t nmemb,void * userp)95*9712c20fSFrederick Mayle static size_t WriteCallback(void* ptr, size_t size,
96*9712c20fSFrederick Mayle                             size_t nmemb, void* userp) {
97*9712c20fSFrederick Mayle   if (!userp)
98*9712c20fSFrederick Mayle     return 0;
99*9712c20fSFrederick Mayle 
100*9712c20fSFrederick Mayle   string* response = reinterpret_cast<string*>(userp);
101*9712c20fSFrederick Mayle   size_t real_size = size * nmemb;
102*9712c20fSFrederick Mayle   response->append(reinterpret_cast<char*>(ptr), real_size);
103*9712c20fSFrederick Mayle   return real_size;
104*9712c20fSFrederick Mayle }
105*9712c20fSFrederick Mayle 
SendRequest(const string & url,const std::map<string,string> & parameters,long * http_status_code,string * http_header_data,string * http_response_data)106*9712c20fSFrederick Mayle bool LibcurlWrapper::SendRequest(const string& url,
107*9712c20fSFrederick Mayle                                  const std::map<string, string>& parameters,
108*9712c20fSFrederick Mayle                                  long* http_status_code,
109*9712c20fSFrederick Mayle                                  string* http_header_data,
110*9712c20fSFrederick Mayle                                  string* http_response_data) {
111*9712c20fSFrederick Mayle   if (!CheckInit()) return false;
112*9712c20fSFrederick Mayle 
113*9712c20fSFrederick Mayle   std::map<string, string>::const_iterator iter = parameters.begin();
114*9712c20fSFrederick Mayle   for (; iter != parameters.end(); ++iter)
115*9712c20fSFrederick Mayle     (*formadd_)(&formpost_, &lastptr_,
116*9712c20fSFrederick Mayle                 CURLFORM_COPYNAME, iter->first.c_str(),
117*9712c20fSFrederick Mayle                 CURLFORM_COPYCONTENTS, iter->second.c_str(),
118*9712c20fSFrederick Mayle                 CURLFORM_END);
119*9712c20fSFrederick Mayle 
120*9712c20fSFrederick Mayle   (*easy_setopt_)(curl_, CURLOPT_HTTPPOST, formpost_);
121*9712c20fSFrederick Mayle 
122*9712c20fSFrederick Mayle   return SendRequestInner(url, http_status_code, http_header_data,
123*9712c20fSFrederick Mayle                           http_response_data);
124*9712c20fSFrederick Mayle }
125*9712c20fSFrederick Mayle 
SendGetRequest(const string & url,long * http_status_code,string * http_header_data,string * http_response_data)126*9712c20fSFrederick Mayle bool LibcurlWrapper::SendGetRequest(const string& url,
127*9712c20fSFrederick Mayle                                     long* http_status_code,
128*9712c20fSFrederick Mayle                                     string* http_header_data,
129*9712c20fSFrederick Mayle                                     string* http_response_data) {
130*9712c20fSFrederick Mayle   if (!CheckInit()) return false;
131*9712c20fSFrederick Mayle 
132*9712c20fSFrederick Mayle   (*easy_setopt_)(curl_, CURLOPT_HTTPGET, 1L);
133*9712c20fSFrederick Mayle 
134*9712c20fSFrederick Mayle   return SendRequestInner(url, http_status_code, http_header_data,
135*9712c20fSFrederick Mayle                           http_response_data);
136*9712c20fSFrederick Mayle }
137*9712c20fSFrederick Mayle 
SendPutRequest(const string & url,const string & path,long * http_status_code,string * http_header_data,string * http_response_data)138*9712c20fSFrederick Mayle bool LibcurlWrapper::SendPutRequest(const string& url,
139*9712c20fSFrederick Mayle                                     const string& path,
140*9712c20fSFrederick Mayle                                     long* http_status_code,
141*9712c20fSFrederick Mayle                                     string* http_header_data,
142*9712c20fSFrederick Mayle                                     string* http_response_data) {
143*9712c20fSFrederick Mayle   if (!CheckInit()) return false;
144*9712c20fSFrederick Mayle 
145*9712c20fSFrederick Mayle   FILE* file = fopen(path.c_str(), "rb");
146*9712c20fSFrederick Mayle   (*easy_setopt_)(curl_, CURLOPT_UPLOAD, 1L);
147*9712c20fSFrederick Mayle   (*easy_setopt_)(curl_, CURLOPT_PUT, 1L);
148*9712c20fSFrederick Mayle   (*easy_setopt_)(curl_, CURLOPT_READDATA, file);
149*9712c20fSFrederick Mayle 
150*9712c20fSFrederick Mayle   bool success = SendRequestInner(url, http_status_code, http_header_data,
151*9712c20fSFrederick Mayle                                   http_response_data);
152*9712c20fSFrederick Mayle 
153*9712c20fSFrederick Mayle   fclose(file);
154*9712c20fSFrederick Mayle   return success;
155*9712c20fSFrederick Mayle }
156*9712c20fSFrederick Mayle 
SendSimplePostRequest(const string & url,const string & body,const string & content_type,long * http_status_code,string * http_header_data,string * http_response_data)157*9712c20fSFrederick Mayle bool LibcurlWrapper::SendSimplePostRequest(const string& url,
158*9712c20fSFrederick Mayle                                            const string& body,
159*9712c20fSFrederick Mayle                                            const string& content_type,
160*9712c20fSFrederick Mayle                                            long* http_status_code,
161*9712c20fSFrederick Mayle                                            string* http_header_data,
162*9712c20fSFrederick Mayle                                            string* http_response_data) {
163*9712c20fSFrederick Mayle   if (!CheckInit()) return false;
164*9712c20fSFrederick Mayle 
165*9712c20fSFrederick Mayle   (*easy_setopt_)(curl_, CURLOPT_POSTFIELDSIZE, body.size());
166*9712c20fSFrederick Mayle   (*easy_setopt_)(curl_, CURLOPT_COPYPOSTFIELDS, body.c_str());
167*9712c20fSFrederick Mayle 
168*9712c20fSFrederick Mayle   if (!content_type.empty()) {
169*9712c20fSFrederick Mayle     string content_type_header = "Content-Type: " + content_type;
170*9712c20fSFrederick Mayle     headerlist_ = (*slist_append_)(
171*9712c20fSFrederick Mayle         headerlist_,
172*9712c20fSFrederick Mayle         content_type_header.c_str());
173*9712c20fSFrederick Mayle   }
174*9712c20fSFrederick Mayle 
175*9712c20fSFrederick Mayle   return SendRequestInner(url, http_status_code, http_header_data,
176*9712c20fSFrederick Mayle                           http_response_data);
177*9712c20fSFrederick Mayle }
178*9712c20fSFrederick Mayle 
Init()179*9712c20fSFrederick Mayle bool LibcurlWrapper::Init() {
180*9712c20fSFrederick Mayle   // First check to see if libcurl was statically linked:
181*9712c20fSFrederick Mayle   curl_lib_ = dlopen(nullptr, RTLD_NOW);
182*9712c20fSFrederick Mayle   if (curl_lib_ &&
183*9712c20fSFrederick Mayle       (!dlsym(curl_lib_, "curl_easy_init") ||
184*9712c20fSFrederick Mayle       !dlsym(curl_lib_, "curl_easy_setopt"))) {
185*9712c20fSFrederick Mayle     // Not statically linked, try again below.
186*9712c20fSFrederick Mayle     dlerror();  // Clear dlerror before attempting to open libraries.
187*9712c20fSFrederick Mayle     dlclose(curl_lib_);
188*9712c20fSFrederick Mayle     curl_lib_ = nullptr;
189*9712c20fSFrederick Mayle   }
190*9712c20fSFrederick Mayle   if (!curl_lib_) {
191*9712c20fSFrederick Mayle     curl_lib_ = dlopen("libcurl.so", RTLD_NOW);
192*9712c20fSFrederick Mayle   }
193*9712c20fSFrederick Mayle   if (!curl_lib_) {
194*9712c20fSFrederick Mayle     curl_lib_ = dlopen("libcurl.so.4", RTLD_NOW);
195*9712c20fSFrederick Mayle   }
196*9712c20fSFrederick Mayle   if (!curl_lib_) {
197*9712c20fSFrederick Mayle     curl_lib_ = dlopen("libcurl.so.3", RTLD_NOW);
198*9712c20fSFrederick Mayle   }
199*9712c20fSFrederick Mayle   if (!curl_lib_) {
200*9712c20fSFrederick Mayle     std::cout << "Could not find libcurl via dlopen";
201*9712c20fSFrederick Mayle     return false;
202*9712c20fSFrederick Mayle   }
203*9712c20fSFrederick Mayle 
204*9712c20fSFrederick Mayle   if (!SetFunctionPointers()) {
205*9712c20fSFrederick Mayle     std::cout << "Could not find function pointers";
206*9712c20fSFrederick Mayle     return false;
207*9712c20fSFrederick Mayle   }
208*9712c20fSFrederick Mayle 
209*9712c20fSFrederick Mayle   curl_ = (*easy_init_)();
210*9712c20fSFrederick Mayle 
211*9712c20fSFrederick Mayle   last_curl_error_ = "No Error";
212*9712c20fSFrederick Mayle 
213*9712c20fSFrederick Mayle   if (!curl_) {
214*9712c20fSFrederick Mayle     dlclose(curl_lib_);
215*9712c20fSFrederick Mayle     std::cout << "Curl initialization failed";
216*9712c20fSFrederick Mayle     return false;
217*9712c20fSFrederick Mayle   }
218*9712c20fSFrederick Mayle 
219*9712c20fSFrederick Mayle   init_ok_ = true;
220*9712c20fSFrederick Mayle   return true;
221*9712c20fSFrederick Mayle }
222*9712c20fSFrederick Mayle 
223*9712c20fSFrederick Mayle #define SET_AND_CHECK_FUNCTION_POINTER(var, function_name, type) \
224*9712c20fSFrederick Mayle   var = reinterpret_cast<type>(dlsym(curl_lib_, function_name)); \
225*9712c20fSFrederick Mayle   if (!var) { \
226*9712c20fSFrederick Mayle     std::cout << "Could not find libcurl function " << function_name; \
227*9712c20fSFrederick Mayle     init_ok_ = false; \
228*9712c20fSFrederick Mayle     return false; \
229*9712c20fSFrederick Mayle   }
230*9712c20fSFrederick Mayle 
SetFunctionPointers()231*9712c20fSFrederick Mayle bool LibcurlWrapper::SetFunctionPointers() {
232*9712c20fSFrederick Mayle 
233*9712c20fSFrederick Mayle   SET_AND_CHECK_FUNCTION_POINTER(easy_init_,
234*9712c20fSFrederick Mayle                                  "curl_easy_init",
235*9712c20fSFrederick Mayle                                  CURL*(*)());
236*9712c20fSFrederick Mayle 
237*9712c20fSFrederick Mayle   SET_AND_CHECK_FUNCTION_POINTER(easy_setopt_,
238*9712c20fSFrederick Mayle                                  "curl_easy_setopt",
239*9712c20fSFrederick Mayle                                  CURLcode(*)(CURL*, CURLoption, ...));
240*9712c20fSFrederick Mayle 
241*9712c20fSFrederick Mayle   SET_AND_CHECK_FUNCTION_POINTER(formadd_, "curl_formadd",
242*9712c20fSFrederick Mayle       CURLFORMcode(*)(curl_httppost**, curl_httppost**, ...));
243*9712c20fSFrederick Mayle 
244*9712c20fSFrederick Mayle   SET_AND_CHECK_FUNCTION_POINTER(slist_append_, "curl_slist_append",
245*9712c20fSFrederick Mayle       curl_slist*(*)(curl_slist*, const char*));
246*9712c20fSFrederick Mayle 
247*9712c20fSFrederick Mayle   SET_AND_CHECK_FUNCTION_POINTER(easy_perform_,
248*9712c20fSFrederick Mayle                                  "curl_easy_perform",
249*9712c20fSFrederick Mayle                                  CURLcode(*)(CURL*));
250*9712c20fSFrederick Mayle 
251*9712c20fSFrederick Mayle   SET_AND_CHECK_FUNCTION_POINTER(easy_cleanup_,
252*9712c20fSFrederick Mayle                                  "curl_easy_cleanup",
253*9712c20fSFrederick Mayle                                  void(*)(CURL*));
254*9712c20fSFrederick Mayle 
255*9712c20fSFrederick Mayle   SET_AND_CHECK_FUNCTION_POINTER(easy_getinfo_,
256*9712c20fSFrederick Mayle                                  "curl_easy_getinfo",
257*9712c20fSFrederick Mayle                                  CURLcode(*)(CURL*, CURLINFO info, ...));
258*9712c20fSFrederick Mayle 
259*9712c20fSFrederick Mayle   SET_AND_CHECK_FUNCTION_POINTER(easy_reset_,
260*9712c20fSFrederick Mayle                                  "curl_easy_reset",
261*9712c20fSFrederick Mayle                                  void(*)(CURL*));
262*9712c20fSFrederick Mayle 
263*9712c20fSFrederick Mayle   SET_AND_CHECK_FUNCTION_POINTER(slist_free_all_,
264*9712c20fSFrederick Mayle                                  "curl_slist_free_all",
265*9712c20fSFrederick Mayle                                  void(*)(curl_slist*));
266*9712c20fSFrederick Mayle 
267*9712c20fSFrederick Mayle   SET_AND_CHECK_FUNCTION_POINTER(formfree_,
268*9712c20fSFrederick Mayle                                  "curl_formfree",
269*9712c20fSFrederick Mayle                                  void(*)(curl_httppost*));
270*9712c20fSFrederick Mayle 
271*9712c20fSFrederick Mayle   SET_AND_CHECK_FUNCTION_POINTER(global_cleanup_,
272*9712c20fSFrederick Mayle                                  "curl_global_cleanup",
273*9712c20fSFrederick Mayle                                  void(*)(void));
274*9712c20fSFrederick Mayle   return true;
275*9712c20fSFrederick Mayle }
276*9712c20fSFrederick Mayle 
SendRequestInner(const string & url,long * http_status_code,string * http_header_data,string * http_response_data)277*9712c20fSFrederick Mayle bool LibcurlWrapper::SendRequestInner(const string& url,
278*9712c20fSFrederick Mayle                                       long* http_status_code,
279*9712c20fSFrederick Mayle                                       string* http_header_data,
280*9712c20fSFrederick Mayle                                       string* http_response_data) {
281*9712c20fSFrederick Mayle   string url_copy(url);
282*9712c20fSFrederick Mayle   (*easy_setopt_)(curl_, CURLOPT_URL, url_copy.c_str());
283*9712c20fSFrederick Mayle 
284*9712c20fSFrederick Mayle   // Disable 100-continue header.
285*9712c20fSFrederick Mayle   char buf[] = "Expect:";
286*9712c20fSFrederick Mayle   headerlist_ = (*slist_append_)(headerlist_, buf);
287*9712c20fSFrederick Mayle   (*easy_setopt_)(curl_, CURLOPT_HTTPHEADER, headerlist_);
288*9712c20fSFrederick Mayle 
289*9712c20fSFrederick Mayle   if (http_response_data != nullptr) {
290*9712c20fSFrederick Mayle     http_response_data->clear();
291*9712c20fSFrederick Mayle     (*easy_setopt_)(curl_, CURLOPT_WRITEFUNCTION, WriteCallback);
292*9712c20fSFrederick Mayle     (*easy_setopt_)(curl_, CURLOPT_WRITEDATA,
293*9712c20fSFrederick Mayle                     reinterpret_cast<void*>(http_response_data));
294*9712c20fSFrederick Mayle   }
295*9712c20fSFrederick Mayle   if (http_header_data != nullptr) {
296*9712c20fSFrederick Mayle     http_header_data->clear();
297*9712c20fSFrederick Mayle     (*easy_setopt_)(curl_, CURLOPT_HEADERFUNCTION, WriteCallback);
298*9712c20fSFrederick Mayle     (*easy_setopt_)(curl_, CURLOPT_HEADERDATA,
299*9712c20fSFrederick Mayle                     reinterpret_cast<void*>(http_header_data));
300*9712c20fSFrederick Mayle   }
301*9712c20fSFrederick Mayle   CURLcode err_code = CURLE_OK;
302*9712c20fSFrederick Mayle   err_code = (*easy_perform_)(curl_);
303*9712c20fSFrederick Mayle   easy_strerror_ = reinterpret_cast<const char* (*)(CURLcode)>
304*9712c20fSFrederick Mayle       (dlsym(curl_lib_, "curl_easy_strerror"));
305*9712c20fSFrederick Mayle 
306*9712c20fSFrederick Mayle   if (http_status_code != nullptr) {
307*9712c20fSFrederick Mayle     (*easy_getinfo_)(curl_, CURLINFO_RESPONSE_CODE, http_status_code);
308*9712c20fSFrederick Mayle   }
309*9712c20fSFrederick Mayle 
310*9712c20fSFrederick Mayle   if (err_code != CURLE_OK)
311*9712c20fSFrederick Mayle     fprintf(stderr, "Failed to send http request to %s, error: %s\n",
312*9712c20fSFrederick Mayle             url.c_str(),
313*9712c20fSFrederick Mayle             (*easy_strerror_)(err_code));
314*9712c20fSFrederick Mayle 
315*9712c20fSFrederick Mayle   Reset();
316*9712c20fSFrederick Mayle 
317*9712c20fSFrederick Mayle   return err_code == CURLE_OK;
318*9712c20fSFrederick Mayle }
319*9712c20fSFrederick Mayle 
Reset()320*9712c20fSFrederick Mayle void LibcurlWrapper::Reset() {
321*9712c20fSFrederick Mayle   if (headerlist_ != nullptr) {
322*9712c20fSFrederick Mayle     (*slist_free_all_)(headerlist_);
323*9712c20fSFrederick Mayle     headerlist_ = nullptr;
324*9712c20fSFrederick Mayle   }
325*9712c20fSFrederick Mayle 
326*9712c20fSFrederick Mayle   if (formpost_ != nullptr) {
327*9712c20fSFrederick Mayle     (*formfree_)(formpost_);
328*9712c20fSFrederick Mayle     formpost_ = nullptr;
329*9712c20fSFrederick Mayle   }
330*9712c20fSFrederick Mayle 
331*9712c20fSFrederick Mayle   (*easy_reset_)(curl_);
332*9712c20fSFrederick Mayle }
333*9712c20fSFrederick Mayle 
CheckInit()334*9712c20fSFrederick Mayle bool LibcurlWrapper::CheckInit() {
335*9712c20fSFrederick Mayle   if (!init_ok_) {
336*9712c20fSFrederick Mayle     std::cout << "LibcurlWrapper: You must call Init(), and have it return "
337*9712c20fSFrederick Mayle                  "'true' before invoking any other methods.\n";
338*9712c20fSFrederick Mayle     return false;
339*9712c20fSFrederick Mayle   }
340*9712c20fSFrederick Mayle 
341*9712c20fSFrederick Mayle   return true;
342*9712c20fSFrederick Mayle }
343*9712c20fSFrederick Mayle 
344*9712c20fSFrederick Mayle }  // namespace google_breakpad
345