Fix 'occurred' typo
[bpdyndnsd] / src / httphelper.cpp
CommitLineData
efbde536
BS
1/** @file
2 * @brief HTTPHelper class implementation. This class represents a Helper to perform HTTP operations easily.
3 *
4 *
5 *
6 * @copyright Intra2net AG
7 * @license GPLv2
8*/
9
4de6a9b8 10#include "httphelper.hpp"
f04a7cb4 11#include "version_info.h"
efbde536 12
ca5d6889 13using namespace std;
d5a516ba 14
31af6a2e
BS
15
16/**
17 * Default Constructor.
18 */
19HTTPHelper::HTTPHelper()
20 : Log(new Logger)
21 , ProxyPort(0)
22 , CurlError(CURLE_OK)
e417b034 23 , CurlInitError(CURLE_OK)
31af6a2e 24{
c730deea 25 CurlEasyHandle = init_curl(CurlWritedataBuff, CurlErrBuff);
31af6a2e
BS
26}
27
28
d5a516ba 29/**
7de01277 30 * Constructor. Use this constructor if HTTP AUTH should be used. Username and password will then be set as HTTP auth options.
4de6a9b8 31 * @param _log Logger Object
d5a516ba
BS
32 * @param _proxy Proxy to use
33 * @param _proxy_port Proxy Port
34 * @param _username Username
35 * @param _password Password
36 */
2dd2db3e 37HTTPHelper::HTTPHelper(Logger::Ptr _log, const string& _proxy, const int _proxy_port, const string& _username, const string& _password)
6ec86aff
TJ
38 : Log(_log)
39 , Proxy(_proxy)
40 , ProxyPort(_proxy_port)
31af6a2e 41 , CurlError(CURLE_OK)
e417b034
BS
42 , CurlInitError(CURLE_OK)
43 , Username(_username)
44 , Password(_password)
efbde536 45{
efbde536 46 CurlEasyHandle = init_curl(CurlWritedataBuff, CurlErrBuff);
31af6a2e
BS
47 if ( CurlEasyHandle != NULL )
48 {
e417b034 49 if ( (CurlInitError = set_curl_auth(Username,Password)) != CURLE_OK )
c730deea
BS
50 {
51 curl_easy_cleanup(CurlEasyHandle);
52 CurlEasyHandle = NULL;
53 }
31af6a2e 54 }
efbde536
BS
55}
56
57
d5a516ba 58/**
7de01277 59 * Constructor. Use this constructor if you have to encode the username and password into the url
4de6a9b8 60 * @param _log Logger Object
7de01277
BS
61 * @param _proxy Proxy to use
62 * @param _proxy_port Proxy Port
63 */
64HTTPHelper::HTTPHelper(Logger::Ptr _log, const string& _proxy, const int _proxy_port)
6ec86aff
TJ
65 : Log(_log)
66 , Proxy(_proxy)
67 , ProxyPort(_proxy_port)
31af6a2e 68 , CurlError(CURLE_OK)
e417b034 69 , CurlInitError(CURLE_OK)
7de01277 70{
7de01277
BS
71 CurlEasyHandle = init_curl(CurlWritedataBuff, CurlErrBuff);
72}
73
74
75/**
d5a516ba
BS
76 * Destructor
77 */
efbde536
BS
78HTTPHelper::~HTTPHelper()
79{
891ae3b9 80 // Free memory
31af6a2e
BS
81 if ( CurlEasyHandle != NULL )
82 {
83 curl_easy_cleanup(CurlEasyHandle);
84 CurlEasyHandle = NULL;
85 }
efbde536
BS
86}
87
e417b034
BS
88/**
89 * Re-Init curl
90 */
91void HTTPHelper::re_initialize()
92{
93 CurlEasyHandle = init_curl(CurlWritedataBuff, CurlErrBuff);
94 if ( (CurlEasyHandle != NULL) && !(Username.empty()) && !(Password.empty()) )
95 {
96 if ( (CurlInitError = set_curl_auth(Username,Password)) != CURLE_OK )
97 {
98 curl_easy_cleanup(CurlEasyHandle);
99 CurlEasyHandle = NULL;
100 }
101 }
102}
103
efbde536 104
efbde536
BS
105/**
106 * Perform a HTTP GET operation
107 * @param url URL for HTTP GET operation
d5a516ba 108 * @return The status code from the http operation or -1 if an curl error occurs
efbde536 109 */
d5a516ba 110long HTTPHelper::http_get(const string& url)
efbde536 111{
d5a516ba 112 long curl_info;
e417b034 113 CurlError = CURLE_OK;
efbde536 114
31af6a2e 115 if ( CurlEasyHandle != NULL )
efbde536 116 {
e417b034 117 if ( (CurlInitError = set_curl_url(url)) != CURLE_OK )
c730deea 118 {
e417b034 119 Log->print_curl_error(url,CurlInitError,CurlErrBuff);
c730deea
BS
120 CurlWritedataBuff.clear();
121 return -1;
122 }
123 if ( (CurlError = curl_easy_perform(CurlEasyHandle) ) != CURLE_OK )
31af6a2e 124 {
c730deea 125 Log->print_curl_error(url,CurlError,CurlErrBuff);
31af6a2e
BS
126 CurlWritedataBuff.clear();
127 return -1;
128 }
c730deea 129 if ( (CurlError = curl_easy_getinfo(CurlEasyHandle,CURLINFO_RESPONSE_CODE,&curl_info)) != CURLE_OK )
31af6a2e 130 {
c730deea 131 Log->print_curl_error(url,CurlError);
31af6a2e
BS
132 CurlWritedataBuff.clear();
133 return -1;
134 }
135
136 Log->print_curl_data(CurlWritedataBuff);
137
138 // Copy the received data received via curl from the curl data buffer member to the received data member. This is needed because curl appends data to the buffer rather than overrites it.
139 ReceivedCurlData = CurlWritedataBuff;
1fda5599 140 CurlWritedataBuff.clear();
1fda5599 141
31af6a2e
BS
142 // Operation performed without any problems so we can return the curl_info
143 return curl_info;
144 }
145 return -1;
efbde536
BS
146}
147
148
149/**
b6228761
BS
150 * Getter for member CurlWritedataBuff
151 * @return CurlWritedataBuff
152 */
153string HTTPHelper::get_curl_data() const
154{
1fda5599 155 return ReceivedCurlData;
b6228761
BS
156}
157
158
159/**
efbde536
BS
160 * Initialized curl easy handle with a few options.
161 * @param curl_writedata_buff Reference to a string wich will be filled with the curl result
162 * @param curl_err_buff A pointer to an char array which will be filled with error message.
c730deea 163 * @return A pointer to the easy curl handle or NULL if something went wrong.
efbde536 164 */
31af6a2e 165CURL* HTTPHelper::init_curl(string& curl_writedata_buff,char* curl_err_buff)
efbde536 166{
e417b034 167 CurlInitError = CURLE_OK;
f04a7cb4 168 ostringstream user_agent_stream;
1dc0bc9b 169 user_agent_stream << "Intra2net AG - Bullet Proof DYNDNS Daemon - " << MAJOR_VERSION << "." << MINOR_VERSION;
f04a7cb4 170 string user_agent = user_agent_stream.str();
b6228761 171
efbde536 172 CURL *curl_easy_handle = curl_easy_init();
31af6a2e
BS
173 if ( curl_easy_handle == NULL )
174 {
175 // something went wrong.
e417b034 176 CurlInitError = CURLE_FAILED_INIT;
31af6a2e
BS
177 Log->print_curl_error_init("Could not initialize CURL object.",CURLE_FAILED_INIT);
178 return NULL;
179 }
efbde536 180
e417b034
BS
181 CurlInitError = curl_easy_setopt(curl_easy_handle,CURLOPT_NOPROGRESS,1);
182 if ( CurlInitError == CURLE_OK)
183 CurlInitError = curl_easy_setopt(curl_easy_handle,CURLOPT_CONNECTTIMEOUT,5);
184 if ( CurlInitError == CURLE_OK)
185 CurlInitError = curl_easy_setopt(curl_easy_handle,CURLOPT_TIMEOUT,10);
186 if ( CurlInitError == CURLE_OK)
187 CurlInitError = curl_easy_setopt(curl_easy_handle,CURLOPT_BUFFERSIZE,1024);
188 if ( CurlInitError == CURLE_OK)
189 CurlInitError = curl_easy_setopt(curl_easy_handle,CURLOPT_ERRORBUFFER,curl_err_buff);
190 if ( CurlInitError == CURLE_OK)
191 CurlInitError = curl_easy_setopt(curl_easy_handle,CURLOPT_WRITEFUNCTION,http_receive);
192 if ( CurlInitError == CURLE_OK)
193 CurlInitError = curl_easy_setopt(curl_easy_handle,CURLOPT_WRITEDATA,&curl_writedata_buff);
194 if ( CurlInitError == CURLE_OK)
b2e85bb4 195 CurlInitError = curl_easy_setopt(curl_easy_handle,CURLOPT_USERAGENT,user_agent.c_str());
b38006d2
TJ
196 if ( CurlInitError == CURLE_OK)
197 CurlInitError = curl_easy_setopt(curl_easy_handle,CURLOPT_SSL_VERIFYHOST,0);
198 if ( CurlInitError == CURLE_OK)
199 CurlInitError = curl_easy_setopt(curl_easy_handle,CURLOPT_SSL_VERIFYPEER,0);
efbde536
BS
200
201 if ( !Proxy.empty() )
202 {
e417b034
BS
203 if ( CurlInitError == CURLE_OK)
204 CurlInitError = curl_easy_setopt(curl_easy_handle,CURLOPT_PROXY,Proxy.c_str());
205 if ( CurlInitError == CURLE_OK)
206 CurlInitError = curl_easy_setopt(curl_easy_handle,CURLOPT_PROXYPORT,ProxyPort);
31af6a2e
BS
207 }
208
e417b034 209 if ( CurlInitError != CURLE_OK )
31af6a2e
BS
210 {
211 // Some options could not be set, so destroy the CURL handle.
e417b034 212 Log->print_curl_error_init("Could not set CURL options properly.",CurlInitError);
ce70569b 213 curl_easy_cleanup(curl_easy_handle);
31af6a2e 214 curl_easy_handle = NULL;
efbde536
BS
215 }
216
217 return curl_easy_handle;
218}
219
220
221/**
31af6a2e
BS
222 * Test if the curl handle is initialized correctly.
223 * @return True if correctly initialized, false if something went wrong during initialization.
224 */
08a5a621 225bool HTTPHelper::is_initialized() const
31af6a2e 226{
e417b034 227 if ( (CurlInitError == CURLE_OK) && (CurlEasyHandle != NULL) )
31af6a2e
BS
228 {
229 return true;
230 }
231 return false;
232}
233
234
235/**
efbde536
BS
236 * Sets a url to the easy curl handle
237 * @param url The url to set.
c730deea 238 * @return CURLcode CURLE_OK if everything is right.
efbde536 239 */
c730deea 240CURLcode HTTPHelper::set_curl_url(const string& url)
efbde536 241{
e417b034
BS
242 CURLcode curlError = CURLE_OK;
243 if ( (CurlEasyHandle != NULL) && (CurlInitError == CURLE_OK) )
31af6a2e 244 {
e417b034
BS
245 curlError = curl_easy_setopt(CurlEasyHandle,CURLOPT_URL,url.c_str());
246 if ( curlError != CURLE_OK )
c730deea
BS
247 {
248 // Some options could not be set, so destroy the CURL handle.
e417b034 249 Log->print_curl_error_init("Could not set CURL URL properly.",curlError);
c730deea
BS
250 curl_easy_cleanup(CurlEasyHandle);
251 CurlEasyHandle = NULL;
252 }
31af6a2e 253 }
e417b034
BS
254 else
255 {
256 return CURLE_FAILED_INIT;
257 }
258 return curlError;
efbde536
BS
259}
260
261
262/**
2dd2db3e
BS
263 * Sets HTTP AUTH parameters
264 * @param username The username for HTTP AUTH
265 * @param password The password for HTTP AUTH
c730deea 266 * @return CURLcode CURLE_OK if everything is right.
2dd2db3e 267 */
c730deea 268CURLcode HTTPHelper::set_curl_auth(const string& username, const string& password)
2dd2db3e 269{
e417b034
BS
270 CURLcode curlError = CURLE_OK;
271 if ( (CurlEasyHandle != NULL) && (CurlInitError == CURLE_OK) )
272 {
273 curlError = curl_easy_setopt(CurlEasyHandle,CURLOPT_USERNAME,username.c_str());
274 if ( curlError != CURLE_OK )
275 Log->print_curl_error_init("Could not set CURL username properly.",curlError);
276 curlError = curl_easy_setopt(CurlEasyHandle,CURLOPT_PASSWORD,password.c_str());
277 if ( curlError != CURLE_OK )
278 Log->print_curl_error_init("Could not set CURL password properly.",curlError);
279 }
280 else
31af6a2e 281 {
e417b034 282 return CURLE_FAILED_INIT;
31af6a2e 283 }
e417b034 284 return curlError;
2dd2db3e
BS
285}
286
287
288/**
efbde536
BS
289 * Callback Function is called every time CURL is receiving data from HTTPS-Server and will copy all received Data to the given stream pointer
290 * @param inBuffer Pointer to input.
291 * @param size How many mem blocks are received
292 * @param nmemb size of each memblock
293 * @param outBuffer Pointer to output stream.
294 * @return The size received.
295 */
0955e6a2 296size_t HTTPHelper::http_receive( void *inBuffer, size_t size, size_t nmemb, string *outBuffer )
efbde536 297{
0955e6a2 298 outBuffer->append(static_cast<char *>(inBuffer), size*nmemb);
efbde536 299 return (size*nmemb);
0955e6a2 300} //lint !e818