1 /*
2
3 Copyright (C) 2011 Gregory Smith
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 This license is contained in the file "COPYING",
16 which is included with this source code; it is available online at
17 http://www.gnu.org/licenses/gpl.html
18
19 HTTP utilities
20 */
21
22 #include "HTTP.h"
23
24 #include "cseries.h"
25 #include "Logging.h"
26 #include "preferences.h"
27
28 #ifdef HAVE_CURL
29 #include "curl/curl.h"
30 #include "curl/easy.h"
31
32 #include <boost/shared_ptr.hpp>
33
Init()34 void HTTPClient::Init()
35 {
36 curl_global_init(CURL_GLOBAL_ALL);
37 }
38
WriteCallback(void * buffer,size_t size,size_t nmemb,void * p)39 size_t HTTPClient::WriteCallback(void* buffer, size_t size, size_t nmemb, void* p)
40 {
41 HTTPClient* client = reinterpret_cast<HTTPClient*>(p);
42 client->response_.append(reinterpret_cast<char*>(buffer), size * nmemb);
43 return size * nmemb;
44 }
45
Get(const std::string & url)46 bool HTTPClient::Get(const std::string& url)
47 {
48 response_.clear();
49
50 boost::shared_ptr<CURL> handle(curl_easy_init(), curl_easy_cleanup);
51 if (!handle)
52 {
53 logError("CURL init failed");
54 return false;
55 }
56
57 curl_easy_setopt(handle.get(), CURLOPT_URL, url.c_str());
58 curl_easy_setopt(handle.get(), CURLOPT_WRITEFUNCTION, WriteCallback);
59 curl_easy_setopt(handle.get(), CURLOPT_WRITEDATA, this);
60 curl_easy_setopt(handle.get(), CURLOPT_SSL_VERIFYPEER, network_preferences->verify_https);
61 curl_easy_setopt(handle.get(), CURLOPT_FOLLOWLOCATION, 1);
62
63 CURLcode ret = curl_easy_perform(handle.get());
64 if (ret == CURLE_OK)
65 {
66 return true;
67 }
68 else
69 {
70 logError("HTTP(s) GET from %s failed: %s", url.c_str(), curl_easy_strerror(ret));
71 return false;
72 }
73 }
74
75 #if LIBCURL_VERSION_NUM >= 0x071504
escape(CURL * handle,const std::string & s)76 static std::string escape(CURL* handle, const std::string& s)
77 #else
78 static std::string escape(CURL*, const std::string& s)
79 #endif
80 {
81 #if LIBCURL_VERSION_NUM >= 0x071504
82 boost::shared_ptr<char> dst(curl_easy_escape(handle, s.c_str(), s.size()), curl_free);
83 #else
84 boost::shared_ptr<char> dst(curl_escape(s.c_str(), s.size()), curl_free);
85 #endif
86 return std::string(dst.get());
87 }
88
Post(const std::string & url,const parameter_map & parameters)89 bool HTTPClient::Post(const std::string& url, const parameter_map& parameters)
90 {
91 response_.clear();
92
93 boost::shared_ptr<CURL> handle(curl_easy_init(), curl_easy_cleanup);
94 if (!handle)
95 {
96 logError("CURL init failed");
97 return false;
98 }
99
100
101 std::string parameter_string;
102 for (parameter_map::const_iterator it = parameters.begin(); it != parameters.end(); ++it)
103 {
104 if (parameter_string.size())
105 {
106 parameter_string.append("&");
107 }
108 parameter_string.append(escape(handle.get(), it->first));
109 parameter_string.append("=");
110 parameter_string.append(escape(handle.get(), it->second));
111 }
112
113 curl_easy_setopt(handle.get(), CURLOPT_URL, url.c_str());
114 curl_easy_setopt(handle.get(), CURLOPT_WRITEFUNCTION, WriteCallback);
115 curl_easy_setopt(handle.get(), CURLOPT_WRITEDATA, this);
116 curl_easy_setopt(handle.get(), CURLOPT_POST, 1L);
117 curl_easy_setopt(handle.get(), CURLOPT_SSL_VERIFYPEER, network_preferences->verify_https);
118 curl_easy_setopt(handle.get(), CURLOPT_POSTFIELDS, parameter_string.c_str());
119
120 CURLcode ret = curl_easy_perform(handle.get());
121 if (ret == CURLE_OK)
122 {
123 return true;
124 }
125 else
126 {
127 logError("HTTP(s) POST to %s failed: %s", url.c_str(), curl_easy_strerror(ret));
128 return false;
129 }
130 }
131 #else // we do not HAVE_CURL
Init()132 void HTTPClient::Init()
133 {
134
135 }
136
Get(const std::string &)137 bool HTTPClient::Get(const std::string&)
138 {
139 return false;
140 }
141
Post(const std::string &,const std::map<std::string,std::string> &)142 bool HTTPClient::Post(const std::string&, const std::map<std::string, std::string>&)
143 {
144 return false;
145 }
146
147 #endif
148
149