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