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