Bugfix: Avoid curl from segfaulting when CurlErrBuff is filled. Allocate CurlErrBuff...
[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.h"
11
12
13 /**
14  * Constructor. Use this constructor if HTTP AUTH should be used. Username and password will then be set as HTTP auth options.
15  * @param _log Logger Object 
16  * @param _proxy Proxy to use
17  * @param _proxy_port Proxy Port
18  * @param _username Username
19  * @param _password Password
20  */
21 HTTPHelper::HTTPHelper(Logger::Ptr _log, const string& _proxy, const int _proxy_port, const string& _username, const string& _password)
22     : Log(_log)
23     , Proxy(_proxy)
24     , ProxyPort(_proxy_port)
25 {
26     CurlEasyHandle = init_curl(CurlWritedataBuff, CurlErrBuff);
27     set_curl_auth(_username,_password);
28 }
29
30
31 /**
32  * Constructor. Use this constructor if you have to encode the username and password into the url
33  * @param _log Logger Object 
34  * @param _proxy Proxy to use
35  * @param _proxy_port Proxy Port
36  */
37 HTTPHelper::HTTPHelper(Logger::Ptr _log, const string& _proxy, const int _proxy_port)
38     : Log(_log)
39     , Proxy(_proxy)
40     , ProxyPort(_proxy_port)
41 {
42     CurlEasyHandle = init_curl(CurlWritedataBuff, CurlErrBuff);
43 }
44
45
46 /**
47  * Destructor
48  */
49 HTTPHelper::~HTTPHelper()
50 {
51     // Free memory
52     curl_easy_cleanup(CurlEasyHandle);
53 }
54
55
56 /**
57  * Perform a HTTP GET operation
58  * @param url URL for HTTP GET operation
59  * @return The status code from the http operation or -1 if an curl error occurs
60  */
61 long HTTPHelper::http_get(const string& url)
62 {
63     int curl_err_code;
64     long curl_info;
65
66     set_curl_url(url);
67
68     if ( (curl_err_code = curl_easy_perform(CurlEasyHandle) ) != 0 )
69     {
70         Log->print_curl_error(url,curl_err_code,CurlErrBuff);
71         return -1;
72     }
73     if ( (curl_err_code = curl_easy_getinfo(CurlEasyHandle,CURLINFO_RESPONSE_CODE,&curl_info)) != 0 )
74     {
75         Log->print_curl_error(url,curl_err_code);
76         return -1;
77     }
78
79     Log->print_curl_data(CurlWritedataBuff);
80
81     // Operation performed without any problems so we can return the curl_info
82     return curl_info;
83 }
84
85
86 /**
87  * Getter for member CurlWritedataBuff
88  * @return CurlWritedataBuff
89  */
90 string HTTPHelper::get_curl_data() const
91 {
92     return CurlWritedataBuff;
93 }
94
95
96 /**
97  * Initialized curl easy handle with a few options.
98  * @param curl_writedata_buff Reference to a string wich will be filled with the curl result
99  * @param curl_err_buff A pointer to an char array which will be filled with error message.
100  * @return A pointer to the easy curl handle.
101  */
102 CURL* HTTPHelper::init_curl(string& curl_writedata_buff,char* curl_err_buff) const
103 {
104     string user_agent = "Bullet Proof DYNDNS Daemon - Intra2net AG 2009";
105
106     CURL *curl_easy_handle = curl_easy_init();
107
108     curl_easy_setopt(curl_easy_handle,CURLOPT_NOPROGRESS,1);
109     curl_easy_setopt(curl_easy_handle,CURLOPT_CONNECTTIMEOUT,5);
110     curl_easy_setopt(curl_easy_handle,CURLOPT_TIMEOUT,10);
111     curl_easy_setopt(curl_easy_handle,CURLOPT_BUFFERSIZE,1024);
112     curl_easy_setopt(curl_easy_handle,CURLOPT_ERRORBUFFER,curl_err_buff);
113     curl_easy_setopt(curl_easy_handle,CURLOPT_WRITEFUNCTION,http_receive);
114     curl_easy_setopt(curl_easy_handle,CURLOPT_WRITEDATA,&curl_writedata_buff);
115     curl_easy_setopt(curl_easy_handle,CURLOPT_USERAGENT,&user_agent);
116
117     if ( !Proxy.empty() )
118     {
119         curl_easy_setopt(curl_easy_handle,CURLOPT_PROXY,Proxy.c_str());
120         curl_easy_setopt(curl_easy_handle,CURLOPT_PROXYPORT,ProxyPort);
121     }
122
123     return curl_easy_handle;
124 }
125
126
127 /**
128  * Sets a url to the easy curl handle
129  * @param url The url to set.
130  */
131 void HTTPHelper::set_curl_url(const string& url)
132 {
133     curl_easy_setopt(CurlEasyHandle,CURLOPT_URL,url.c_str());
134 }
135
136
137 /**
138  * Sets HTTP AUTH parameters
139  * @param username The username for HTTP AUTH
140  * @param password The password for HTTP AUTH
141  */
142 void HTTPHelper::set_curl_auth(const string& username, const string& password)
143 {
144     curl_easy_setopt(CurlEasyHandle,CURLOPT_USERNAME,username.c_str());
145     curl_easy_setopt(CurlEasyHandle,CURLOPT_PASSWORD,password.c_str());
146 }
147
148
149 /**
150  * Callback Function is called every time CURL is receiving data from HTTPS-Server and will copy all received Data to the given stream pointer
151  * @param inBuffer Pointer to input.
152  * @param size How many mem blocks are received
153  * @param nmemb size of each memblock
154  * @param outBuffer Pointer to output stream.
155  * @return The size received.
156  */
157 int HTTPHelper::http_receive( char *inBuffer, size_t size, size_t nmemb, string *outBuffer )
158 {
159     outBuffer->append(inBuffer);
160     return (size*nmemb);
161 }
162