PageRenderTime 31ms CodeModel.GetById 13ms app.highlight 15ms RepoModel.GetById 1ms app.codeStats 0ms

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