Fix 'occurred' typo
[bpdyndnsd] / src / httphelper.cpp
index f402d4c..eb35fd9 100644 (file)
@@ -7,21 +7,28 @@
  * @license GPLv2
 */
 
-#include "httphelper.h"
+#include "httphelper.hpp"
+#include "version_info.h"
+
+using namespace std;
+
 
 /**
- * Default Constructor
+ * Default Constructor.
  */
 HTTPHelper::HTTPHelper()
-    : ProxyPort(0)
-    , Log(new Logger)
+    : Log(new Logger)
+    , ProxyPort(0)
+    , CurlError(CURLE_OK)
+    , CurlInitError(CURLE_OK)
 {
+    CurlEasyHandle = init_curl(CurlWritedataBuff, CurlErrBuff);
 }
 
 
 /**
  * Constructor. Use this constructor if HTTP AUTH should be used. Username and password will then be set as HTTP auth options.
- * @param _log Logger Object 
+ * @param _log Logger Object
  * @param _proxy Proxy to use
  * @param _proxy_port Proxy Port
  * @param _username Username
@@ -31,16 +38,26 @@ HTTPHelper::HTTPHelper(Logger::Ptr _log, const string& _proxy, const int _proxy_
     : Log(_log)
     , Proxy(_proxy)
     , ProxyPort(_proxy_port)
+    , CurlError(CURLE_OK)
+    , CurlInitError(CURLE_OK)
+    , Username(_username)
+    , Password(_password)
 {
     CurlEasyHandle = init_curl(CurlWritedataBuff, CurlErrBuff);
-
-    set_curl_auth(_username,_password);
+    if ( CurlEasyHandle != NULL )
+    {
+        if ( (CurlInitError = set_curl_auth(Username,Password)) != CURLE_OK )
+        {
+            curl_easy_cleanup(CurlEasyHandle);
+            CurlEasyHandle = NULL;
+        }
+    }
 }
 
 
 /**
  * Constructor. Use this constructor if you have to encode the username and password into the url
- * @param _log Logger Object 
+ * @param _log Logger Object
  * @param _proxy Proxy to use
  * @param _proxy_port Proxy Port
  */
@@ -48,6 +65,8 @@ HTTPHelper::HTTPHelper(Logger::Ptr _log, const string& _proxy, const int _proxy_
     : Log(_log)
     , Proxy(_proxy)
     , ProxyPort(_proxy_port)
+    , CurlError(CURLE_OK)
+    , CurlInitError(CURLE_OK)
 {
     CurlEasyHandle = init_curl(CurlWritedataBuff, CurlErrBuff);
 }
@@ -58,6 +77,28 @@ HTTPHelper::HTTPHelper(Logger::Ptr _log, const string& _proxy, const int _proxy_
  */
 HTTPHelper::~HTTPHelper()
 {
+    // Free memory
+    if ( CurlEasyHandle != NULL )
+    {
+        curl_easy_cleanup(CurlEasyHandle);
+        CurlEasyHandle = NULL;
+    }
+}
+
+/**
+ * Re-Init curl
+ */
+void HTTPHelper::re_initialize()
+{
+    CurlEasyHandle = init_curl(CurlWritedataBuff, CurlErrBuff);
+    if ( (CurlEasyHandle != NULL) && !(Username.empty()) && !(Password.empty()) )
+    {
+        if ( (CurlInitError = set_curl_auth(Username,Password)) != CURLE_OK )
+        {
+            curl_easy_cleanup(CurlEasyHandle);
+            CurlEasyHandle = NULL;
+        }
+    }
 }
 
 
@@ -68,26 +109,40 @@ HTTPHelper::~HTTPHelper()
  */
 long HTTPHelper::http_get(const string& url)
 {
-    int curl_err_code;
     long curl_info;
+    CurlError = CURLE_OK;
 
-    set_curl_url(url);
-
-    if ( (curl_err_code = curl_easy_perform(CurlEasyHandle) ) != 0 )
+    if ( CurlEasyHandle != NULL )
     {
-        Log->print_curl_error(url,curl_err_code,CurlErrBuff);
-        return -1;
-    }
-    if ( (curl_err_code = curl_easy_getinfo(CurlEasyHandle,CURLINFO_RESPONSE_CODE,&curl_info)) != 0 )
-    {
-         Log->print_curl_error(url,curl_err_code);
-        return -1;
-    }
+        if ( (CurlInitError = set_curl_url(url)) != CURLE_OK )
+        {
+            Log->print_curl_error(url,CurlInitError,CurlErrBuff);
+            CurlWritedataBuff.clear();
+            return -1;
+        }
+        if ( (CurlError = curl_easy_perform(CurlEasyHandle) ) != CURLE_OK )
+        {
+            Log->print_curl_error(url,CurlError,CurlErrBuff);
+            CurlWritedataBuff.clear();
+            return -1;
+        }
+        if ( (CurlError = curl_easy_getinfo(CurlEasyHandle,CURLINFO_RESPONSE_CODE,&curl_info)) != CURLE_OK )
+        {
+            Log->print_curl_error(url,CurlError);
+            CurlWritedataBuff.clear();
+            return -1;
+        }
+
+        Log->print_curl_data(CurlWritedataBuff);
 
-    Log->print_curl_data(CurlWritedataBuff);
+        // 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.
+        ReceivedCurlData = CurlWritedataBuff;
+        CurlWritedataBuff.clear();
 
-    // Operation performed without any problems so we can return the curl_info
-    return curl_info;
+        // Operation performed without any problems so we can return the curl_info
+        return curl_info;
+    }
+    return -1;
 }
 
 
@@ -97,7 +152,7 @@ long HTTPHelper::http_get(const string& url)
  */
 string HTTPHelper::get_curl_data() const
 {
-    return CurlWritedataBuff;
+    return ReceivedCurlData;
 }
 
 
@@ -105,27 +160,58 @@ string HTTPHelper::get_curl_data() const
  * Initialized curl easy handle with a few options.
  * @param curl_writedata_buff Reference to a string wich will be filled with the curl result
  * @param curl_err_buff A pointer to an char array which will be filled with error message.
- * @return A pointer to the easy curl handle.
+ * @return A pointer to the easy curl handle or NULL if something went wrong.
  */
-CURL* HTTPHelper::init_curl(string& curl_writedata_buff,char* curl_err_buff) const
+CURL* HTTPHelper::init_curl(string& curl_writedata_buff,char* curl_err_buff)
 {
-    string user_agent = "bpdyndnsd Intra2net AG 2009";
+    CurlInitError = CURLE_OK;
+    ostringstream user_agent_stream;
+    user_agent_stream << "Intra2net AG - Bullet Proof DYNDNS Daemon - " << MAJOR_VERSION << "." << MINOR_VERSION;
+    string user_agent = user_agent_stream.str();
 
     CURL *curl_easy_handle = curl_easy_init();
+    if ( curl_easy_handle == NULL )
+    {
+        // something went wrong.
+        CurlInitError = CURLE_FAILED_INIT;
+        Log->print_curl_error_init("Could not initialize CURL object.",CURLE_FAILED_INIT);
+        return NULL;
+    }
 
-    curl_easy_setopt(curl_easy_handle,CURLOPT_NOPROGRESS,1);
-    curl_easy_setopt(curl_easy_handle,CURLOPT_CONNECTTIMEOUT,5);
-    curl_easy_setopt(curl_easy_handle,CURLOPT_TIMEOUT,10);
-    curl_easy_setopt(curl_easy_handle,CURLOPT_BUFFERSIZE,1024);
-    curl_easy_setopt(curl_easy_handle,CURLOPT_ERRORBUFFER,curl_err_buff);
-    curl_easy_setopt(curl_easy_handle,CURLOPT_WRITEFUNCTION,http_receive);
-    curl_easy_setopt(curl_easy_handle,CURLOPT_WRITEDATA,&curl_writedata_buff);
-    curl_easy_setopt(curl_easy_handle,CURLOPT_USERAGENT,&user_agent);
+    CurlInitError = curl_easy_setopt(curl_easy_handle,CURLOPT_NOPROGRESS,1);
+    if ( CurlInitError == CURLE_OK)
+        CurlInitError = curl_easy_setopt(curl_easy_handle,CURLOPT_CONNECTTIMEOUT,5);
+    if ( CurlInitError == CURLE_OK)
+        CurlInitError = curl_easy_setopt(curl_easy_handle,CURLOPT_TIMEOUT,10);
+    if ( CurlInitError == CURLE_OK)
+        CurlInitError = curl_easy_setopt(curl_easy_handle,CURLOPT_BUFFERSIZE,1024);
+    if ( CurlInitError == CURLE_OK)
+        CurlInitError = curl_easy_setopt(curl_easy_handle,CURLOPT_ERRORBUFFER,curl_err_buff);
+    if ( CurlInitError == CURLE_OK)
+        CurlInitError = curl_easy_setopt(curl_easy_handle,CURLOPT_WRITEFUNCTION,http_receive);
+    if ( CurlInitError == CURLE_OK)
+        CurlInitError = curl_easy_setopt(curl_easy_handle,CURLOPT_WRITEDATA,&curl_writedata_buff);
+    if ( CurlInitError == CURLE_OK)
+        CurlInitError = curl_easy_setopt(curl_easy_handle,CURLOPT_USERAGENT,user_agent.c_str());
+    if ( CurlInitError == CURLE_OK)
+        CurlInitError = curl_easy_setopt(curl_easy_handle,CURLOPT_SSL_VERIFYHOST,0);
+    if ( CurlInitError == CURLE_OK)
+        CurlInitError = curl_easy_setopt(curl_easy_handle,CURLOPT_SSL_VERIFYPEER,0);
 
     if ( !Proxy.empty() )
     {
-        curl_easy_setopt(curl_easy_handle,CURLOPT_PROXY,Proxy.c_str());
-        curl_easy_setopt(curl_easy_handle,CURLOPT_PROXYPORT,ProxyPort);
+        if ( CurlInitError == CURLE_OK)
+            CurlInitError = curl_easy_setopt(curl_easy_handle,CURLOPT_PROXY,Proxy.c_str());
+        if ( CurlInitError == CURLE_OK)
+            CurlInitError = curl_easy_setopt(curl_easy_handle,CURLOPT_PROXYPORT,ProxyPort);
+    }
+
+    if ( CurlInitError != CURLE_OK )
+    {
+        // Some options could not be set, so destroy the CURL handle.
+        Log->print_curl_error_init("Could not set CURL options properly.",CurlInitError);
+        curl_easy_cleanup(curl_easy_handle);
+        curl_easy_handle = NULL;
     }
 
     return curl_easy_handle;
@@ -133,12 +219,43 @@ CURL* HTTPHelper::init_curl(string& curl_writedata_buff,char* curl_err_buff) con
 
 
 /**
+ * Test if the curl handle is initialized correctly.
+ * @return True if correctly initialized, false if something went wrong during initialization.
+ */
+bool HTTPHelper::is_initialized() const
+{
+    if ( (CurlInitError == CURLE_OK) && (CurlEasyHandle != NULL) )
+    {
+        return true;
+    }
+    return false;
+}
+
+
+/**
  * Sets a url to the easy curl handle
  * @param url The url to set.
+ * @return CURLcode CURLE_OK if everything is right.
  */
-void HTTPHelper::set_curl_url(const string& url)
+CURLcode HTTPHelper::set_curl_url(const string& url)
 {
-    curl_easy_setopt(CurlEasyHandle,CURLOPT_URL,url.c_str());
+    CURLcode curlError = CURLE_OK;
+    if ( (CurlEasyHandle != NULL) && (CurlInitError == CURLE_OK) )
+    {
+        curlError = curl_easy_setopt(CurlEasyHandle,CURLOPT_URL,url.c_str());
+        if ( curlError != CURLE_OK )
+        {
+            // Some options could not be set, so destroy the CURL handle.
+            Log->print_curl_error_init("Could not set CURL URL properly.",curlError);
+            curl_easy_cleanup(CurlEasyHandle);
+            CurlEasyHandle = NULL;
+        }
+    }
+    else
+    {
+        return CURLE_FAILED_INIT;
+    }
+    return curlError;
 }
 
 
@@ -146,11 +263,25 @@ void HTTPHelper::set_curl_url(const string& url)
  * Sets HTTP AUTH parameters
  * @param username The username for HTTP AUTH
  * @param password The password for HTTP AUTH
+ * @return CURLcode CURLE_OK if everything is right.
  */
-void HTTPHelper::set_curl_auth(const string& username, const string& password)
+CURLcode HTTPHelper::set_curl_auth(const string& username, const string& password)
 {
-    curl_easy_setopt(CurlEasyHandle,CURLOPT_USERNAME,username.c_str());
-    curl_easy_setopt(CurlEasyHandle,CURLOPT_PASSWORD,password.c_str());
+    CURLcode curlError = CURLE_OK;
+    if ( (CurlEasyHandle != NULL) && (CurlInitError == CURLE_OK) )
+    {
+        curlError = curl_easy_setopt(CurlEasyHandle,CURLOPT_USERNAME,username.c_str());
+        if ( curlError != CURLE_OK )
+            Log->print_curl_error_init("Could not set CURL username properly.",curlError);
+        curlError = curl_easy_setopt(CurlEasyHandle,CURLOPT_PASSWORD,password.c_str());
+        if ( curlError != CURLE_OK )
+            Log->print_curl_error_init("Could not set CURL password properly.",curlError);
+    }
+    else
+    {
+        return CURLE_FAILED_INIT;
+    }
+    return curlError;
 }
 
 
@@ -162,9 +293,8 @@ void HTTPHelper::set_curl_auth(const string& username, const string& password)
  * @param outBuffer Pointer to output stream.
  * @return The size received.
  */
-int HTTPHelper::http_receive( char *inBuffer, size_t size, size_t nmemb, string *outBuffer )
+size_t HTTPHelper::http_receive( void *inBuffer, size_t size, size_t nmemb, string *outBuffer )
 {
-    outBuffer->append(inBuffer);
+    outBuffer->append(static_cast<char *>(inBuffer), size*nmemb);
     return (size*nmemb);
-}
-
+} //lint !e818