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