/thirdparty/breakpad/common/linux/libcurl_wrapper.cc

http://github.com/tomahawk-player/tomahawk · C++ · 223 lines · 157 code · 34 blank · 32 comment · 25 complexity · dd80a0b02c7805eec36c9574101ebe83 MD5 · raw file

  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. #include <dlfcn.h>
  30. #include <iostream>
  31. #include <string>
  32. #include "common/linux/libcurl_wrapper.h"
  33. using std::string;
  34. namespace google_breakpad {
  35. LibcurlWrapper::LibcurlWrapper()
  36. : init_ok_(false),
  37. formpost_(NULL),
  38. lastptr_(NULL),
  39. headerlist_(NULL) {
  40. curl_lib_ = dlopen("libcurl.so", RTLD_NOW);
  41. if (!curl_lib_) {
  42. curl_lib_ = dlopen("libcurl.so.4", RTLD_NOW);
  43. }
  44. if (!curl_lib_) {
  45. curl_lib_ = dlopen("libcurl.so.3", RTLD_NOW);
  46. }
  47. if (!curl_lib_) {
  48. std::cout << "Could not find libcurl via dlopen";
  49. return;
  50. }
  51. std::cout << "LibcurlWrapper init succeeded";
  52. init_ok_ = true;
  53. return;
  54. }
  55. bool LibcurlWrapper::SetProxy(const std::string& proxy_host,
  56. const std::string& proxy_userpwd) {
  57. if (!init_ok_) {
  58. return false;
  59. }
  60. // Set proxy information if necessary.
  61. if (!proxy_host.empty()) {
  62. (*easy_setopt_)(curl_, CURLOPT_PROXY, proxy_host.c_str());
  63. } else {
  64. std::cout << "SetProxy called with empty proxy host.";
  65. return false;
  66. }
  67. if (!proxy_userpwd.empty()) {
  68. (*easy_setopt_)(curl_, CURLOPT_PROXYUSERPWD, proxy_userpwd.c_str());
  69. } else {
  70. std::cout << "SetProxy called with empty proxy username/password.";
  71. return false;
  72. }
  73. std::cout << "Set proxy host to " << proxy_host;
  74. return true;
  75. }
  76. bool LibcurlWrapper::AddFile(const std::string& upload_file_path,
  77. const std::string& basename) {
  78. if (!init_ok_) {
  79. return false;
  80. }
  81. std::cout << "Adding " << upload_file_path << " to form upload.";
  82. // Add form file.
  83. (*formadd_)(&formpost_, &lastptr_,
  84. CURLFORM_COPYNAME, basename.c_str(),
  85. CURLFORM_FILE, upload_file_path.c_str(),
  86. CURLFORM_END);
  87. return true;
  88. }
  89. // Callback to get the response data from server.
  90. static size_t WriteCallback(void *ptr, size_t size,
  91. size_t nmemb, void *userp) {
  92. if (!userp)
  93. return 0;
  94. std::string *response = reinterpret_cast<std::string *>(userp);
  95. size_t real_size = size * nmemb;
  96. response->append(reinterpret_cast<char *>(ptr), real_size);
  97. return real_size;
  98. }
  99. bool LibcurlWrapper::SendRequest(const std::string& url,
  100. const std::map<std::string, std::string>& parameters,
  101. std::string* server_response) {
  102. (*easy_setopt_)(curl_, CURLOPT_URL, url.c_str());
  103. std::map<std::string, std::string>::const_iterator iter = parameters.begin();
  104. for (; iter != parameters.end(); ++iter)
  105. (*formadd_)(&formpost_, &lastptr_,
  106. CURLFORM_COPYNAME, iter->first.c_str(),
  107. CURLFORM_COPYCONTENTS, iter->second.c_str(),
  108. CURLFORM_END);
  109. (*easy_setopt_)(curl_, CURLOPT_HTTPPOST, formpost_);
  110. if (server_response != NULL) {
  111. (*easy_setopt_)(curl_, CURLOPT_WRITEFUNCTION, WriteCallback);
  112. (*easy_setopt_)(curl_, CURLOPT_WRITEDATA,
  113. reinterpret_cast<void *>(server_response));
  114. }
  115. CURLcode err_code = CURLE_OK;
  116. err_code = (*easy_perform_)(curl_);
  117. easy_strerror_ = reinterpret_cast<const char* (*)(CURLcode)>
  118. (dlsym(curl_lib_, "curl_easy_strerror"));
  119. #ifndef NDEBUG
  120. if (err_code != CURLE_OK)
  121. fprintf(stderr, "Failed to send http request to %s, error: %s\n",
  122. url.c_str(),
  123. (*easy_strerror_)(err_code));
  124. #endif
  125. if (headerlist_ != NULL) {
  126. (*slist_free_all_)(headerlist_);
  127. }
  128. (*easy_cleanup_)(curl_);
  129. if (formpost_ != NULL) {
  130. (*formfree_)(formpost_);
  131. }
  132. return err_code == CURLE_OK;
  133. }
  134. bool LibcurlWrapper::Init() {
  135. if (!init_ok_) {
  136. std::cout << "Init_OK was not true in LibcurlWrapper::Init(), check earlier log messages";
  137. return false;
  138. }
  139. if (!SetFunctionPointers()) {
  140. std::cout << "Could not find function pointers";
  141. init_ok_ = false;
  142. return false;
  143. }
  144. curl_ = (*easy_init_)();
  145. last_curl_error_ = "No Error";
  146. if (!curl_) {
  147. dlclose(curl_lib_);
  148. std::cout << "Curl initialization failed";
  149. return false;
  150. }
  151. // Disable 100-continue header.
  152. char buf[] = "Expect:";
  153. headerlist_ = (*slist_append_)(headerlist_, buf);
  154. (*easy_setopt_)(curl_, CURLOPT_HTTPHEADER, headerlist_);
  155. return true;
  156. }
  157. #define SET_AND_CHECK_FUNCTION_POINTER(var, function_name, type) \
  158. var = reinterpret_cast<type>(dlsym(curl_lib_, function_name)); \
  159. if (!var) { \
  160. std::cout << "Could not find libcurl function " << function_name; \
  161. init_ok_ = false; \
  162. return false; \
  163. }
  164. bool LibcurlWrapper::SetFunctionPointers() {
  165. SET_AND_CHECK_FUNCTION_POINTER(easy_init_,
  166. "curl_easy_init",
  167. CURL*(*)());
  168. SET_AND_CHECK_FUNCTION_POINTER(easy_setopt_,
  169. "curl_easy_setopt",
  170. CURLcode(*)(CURL*, CURLoption, ...));
  171. SET_AND_CHECK_FUNCTION_POINTER(formadd_, "curl_formadd",
  172. CURLFORMcode(*)(curl_httppost**, curl_httppost**, ...));
  173. SET_AND_CHECK_FUNCTION_POINTER(slist_append_, "curl_slist_append",
  174. curl_slist*(*)(curl_slist*, const char*));
  175. SET_AND_CHECK_FUNCTION_POINTER(easy_perform_,
  176. "curl_easy_perform",
  177. CURLcode(*)(CURL*));
  178. SET_AND_CHECK_FUNCTION_POINTER(easy_cleanup_,
  179. "curl_easy_cleanup",
  180. void(*)(CURL*));
  181. SET_AND_CHECK_FUNCTION_POINTER(slist_free_all_,
  182. "curl_slist_free_all",
  183. void(*)(curl_slist*));
  184. SET_AND_CHECK_FUNCTION_POINTER(formfree_,
  185. "curl_formfree",
  186. void(*)(curl_httppost*));
  187. return true;
  188. }
  189. }