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