OLD | NEW |
| (Empty) |
1 // Copyright (c) 2009, Google Inc. | |
2 // All rights reserved. | |
3 // | |
4 // Redistribution and use in source and binary forms, with or without | |
5 // modification, are permitted provided that the following conditions are | |
6 // met: | |
7 // | |
8 // * Redistributions of source code must retain the above copyright | |
9 // notice, this list of conditions and the following disclaimer. | |
10 // * Redistributions in binary form must reproduce the above | |
11 // copyright notice, this list of conditions and the following disclaimer | |
12 // in the documentation and/or other materials provided with the | |
13 // distribution. | |
14 // * Neither the name of Google Inc. nor the names of its | |
15 // contributors may be used to endorse or promote products derived from | |
16 // this software without specific prior written permission. | |
17 // | |
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
29 | |
30 #include <curl/curl.h> | |
31 #include <curl/easy.h> | |
32 #include <curl/types.h> | |
33 #include <dlfcn.h> | |
34 | |
35 #include <string> | |
36 | |
37 #include "common/linux/libcurl_wrapper.h" | |
38 #include "third_party/linux/include/glog/logging.h" | |
39 | |
40 namespace google_breakpad { | |
41 LibcurlWrapper::LibcurlWrapper() | |
42 : init_ok_(false), | |
43 formpost_(NULL), | |
44 lastptr_(NULL), | |
45 headerlist_(NULL) { | |
46 curl_lib_ = dlopen("libcurl.so", RTLD_NOW); | |
47 if (!curl_lib_) { | |
48 curl_lib_ = dlopen("libcurl.so.4", RTLD_NOW); | |
49 } | |
50 if (!curl_lib_) { | |
51 curl_lib_ = dlopen("libcurl.so.3", RTLD_NOW); | |
52 } | |
53 if (!curl_lib_) { | |
54 LOG(WARNING) << "Could not find libcurl via dlopen"; | |
55 return; | |
56 } | |
57 LOG(INFO) << "LibcurlWrapper init succeeded"; | |
58 init_ok_ = true; | |
59 return; | |
60 } | |
61 | |
62 bool LibcurlWrapper::SetProxy(const std::string& proxy_host, | |
63 const std::string& proxy_userpwd) { | |
64 if (!init_ok_) { | |
65 return false; | |
66 } | |
67 // Set proxy information if necessary. | |
68 if (!proxy_host.empty()) { | |
69 (*easy_setopt_)(curl_, CURLOPT_PROXY, proxy_host.c_str()); | |
70 } else { | |
71 LOG(WARNING) << "SetProxy called with empty proxy host."; | |
72 return false; | |
73 } | |
74 if (!proxy_userpwd.empty()) { | |
75 (*easy_setopt_)(curl_, CURLOPT_PROXYUSERPWD, proxy_userpwd.c_str()); | |
76 } else { | |
77 LOG(WARNING) << "SetProxy called with empty proxy username/password."; | |
78 return false; | |
79 } | |
80 LOG(INFO) << "Set proxy host to " << proxy_host; | |
81 return true; | |
82 } | |
83 | |
84 bool LibcurlWrapper::AddFile(const std::string& upload_file_path, | |
85 const std::string& basename) { | |
86 if (!init_ok_) { | |
87 return false; | |
88 } | |
89 LOG(INFO) << "Adding " << upload_file_path << " to form upload."; | |
90 // Add form file. | |
91 (*formadd_)(&formpost_, &lastptr_, | |
92 CURLFORM_COPYNAME, basename.c_str(), | |
93 CURLFORM_FILE, upload_file_path.c_str(), | |
94 CURLFORM_END); | |
95 | |
96 return true; | |
97 } | |
98 | |
99 // Callback to get the response data from server. | |
100 static size_t WriteCallback(void *ptr, size_t size, | |
101 size_t nmemb, void *userp) { | |
102 if (!userp) | |
103 return 0; | |
104 | |
105 std::string *response = reinterpret_cast<std::string *>(userp); | |
106 size_t real_size = size * nmemb; | |
107 response->append(reinterpret_cast<char *>(ptr), real_size); | |
108 return real_size; | |
109 } | |
110 | |
111 bool LibcurlWrapper::SendRequest(const std::string& url, | |
112 const std::map<std::string, std::string>& param
eters, | |
113 std::string* server_response) { | |
114 (*easy_setopt_)(curl_, CURLOPT_URL, url.c_str()); | |
115 std::map<std::string, std::string>::const_iterator iter = parameters.begin(); | |
116 for (; iter != parameters.end(); ++iter) | |
117 (*formadd_)(&formpost_, &lastptr_, | |
118 CURLFORM_COPYNAME, iter->first.c_str(), | |
119 CURLFORM_COPYCONTENTS, iter->second.c_str(), | |
120 CURLFORM_END); | |
121 | |
122 (*easy_setopt_)(curl_, CURLOPT_HTTPPOST, formpost_); | |
123 if (server_response != NULL) { | |
124 (*easy_setopt_)(curl_, CURLOPT_WRITEFUNCTION, WriteCallback); | |
125 (*easy_setopt_)(curl_, CURLOPT_WRITEDATA, | |
126 reinterpret_cast<void *>(server_response)); | |
127 } | |
128 | |
129 CURLcode err_code = CURLE_OK; | |
130 err_code = (*easy_perform_)(curl_); | |
131 *(void**) (&easy_strerror_) = dlsym(curl_lib_, "curl_easy_strerror"); | |
132 #ifndef NDEBUG | |
133 if (err_code != CURLE_OK) | |
134 fprintf(stderr, "Failed to send http request to %s, error: %s\n", | |
135 url.c_str(), | |
136 (*easy_strerror_)(err_code)); | |
137 #endif | |
138 if (headerlist_ != NULL) { | |
139 (*slist_free_all_)(headerlist_); | |
140 } | |
141 | |
142 (*easy_cleanup_)(curl_); | |
143 if (formpost_ != NULL) { | |
144 (*formfree_)(formpost_); | |
145 } | |
146 | |
147 return err_code == CURLE_OK; | |
148 } | |
149 | |
150 bool LibcurlWrapper::Init() { | |
151 if (!init_ok_) { | |
152 LOG(WARNING) << "Init_OK was not true in LibcurlWrapper::Init(), check earli
er log messages"; | |
153 return false; | |
154 } | |
155 | |
156 if (!SetFunctionPointers()) { | |
157 LOG(WARNING) << "Could not find function pointers"; | |
158 init_ok_ = false; | |
159 return false; | |
160 } | |
161 | |
162 curl_ = (*easy_init_)(); | |
163 | |
164 last_curl_error_ = "No Error"; | |
165 | |
166 if (!curl_) { | |
167 dlclose(curl_lib_); | |
168 LOG(WARNING) << "Curl initialization failed"; | |
169 return false; | |
170 } | |
171 | |
172 // Disable 100-continue header. | |
173 char buf[] = "Expect:"; | |
174 | |
175 headerlist_ = (*slist_append_)(headerlist_, buf); | |
176 (*easy_setopt_)(curl_, CURLOPT_HTTPHEADER, headerlist_); | |
177 return true; | |
178 } | |
179 | |
180 #define SET_AND_CHECK_FUNCTION_POINTER(var, function_name) \ | |
181 *(void**) (&var) = dlsym(curl_lib_, function_name); \ | |
182 if (!var) { \ | |
183 LOG(WARNING) << "Could not find libcurl function " << function_name; \ | |
184 init_ok_ = false; \ | |
185 return false; \ | |
186 } | |
187 | |
188 bool LibcurlWrapper::SetFunctionPointers() { | |
189 | |
190 SET_AND_CHECK_FUNCTION_POINTER(easy_init_, | |
191 "curl_easy_init"); | |
192 SET_AND_CHECK_FUNCTION_POINTER(easy_setopt_, | |
193 "curl_easy_setopt"); | |
194 SET_AND_CHECK_FUNCTION_POINTER(formadd_, | |
195 "curl_formadd"); | |
196 SET_AND_CHECK_FUNCTION_POINTER(slist_append_, | |
197 "curl_slist_append"); | |
198 SET_AND_CHECK_FUNCTION_POINTER(easy_perform_, | |
199 "curl_easy_perform"); | |
200 SET_AND_CHECK_FUNCTION_POINTER(easy_cleanup_, | |
201 "curl_easy_cleanup"); | |
202 SET_AND_CHECK_FUNCTION_POINTER(slist_free_all_, | |
203 "curl_slist_free_all"); | |
204 SET_AND_CHECK_FUNCTION_POINTER(formfree_, | |
205 "curl_formfree"); | |
206 return true; | |
207 } | |
208 | |
209 } | |
OLD | NEW |