Home | News | Projects | Releases
Bugs | RFE | Repositories | Help
CardDAV: Set CURLOPT_SSL_VERIFYSTATUS to 0 when using certificate file
[xestiaab/.git] / source / carddav2 / carddav2.cpp
index 9d42c04..dd70bab 100644 (file)
 
 #include "carddav2.h"
 
-#include <iostream>
-
 using namespace std;
 
+CardDAV2::CardDAV2(string ServerAddress, int ServerPort, string ServerUser, string ServerPass, bool ServerSSL){
+
+       this->ServerAddress = ServerAddress;
+       this->ServerPort = ServerPort;
+       this->ServerUser = ServerUser;
+       this->ServerPass = ServerPass;
+       this->ServerSSL = ServerSSL;
+
+       TestMode = true;
+       this->SetupConnectionObject();
+
+}
+
+CardDAV2::CardDAV2(string ServerAddress, int ServerPort, string ServerUser, string ServerPass, bool ServerSSL, string ServerPrefix, string ServerAccount){
+
+       this->ServerAddress = ServerAddress;
+       this->ServerPort = ServerPort;
+       this->ServerUser = ServerUser;
+       this->ServerPass = ServerPass;
+       this->ServerSSL = ServerSSL;
+       this->ServerPrefix = ServerPrefix;
+       this->ServerAccount = ServerAccount;
+
+
+       TestMode = false;
+       this->SetupConnectionObject();
+
+}
+
 size_t CardDAV2::WritebackFunc(char *ptr, size_t size, size_t nmemb, void *stream){
-       
-       return static_cast<CardDAV2*>(stream)->WritebackFuncImplementation(ptr, size, nmemb, stream);
+
+       return static_cast<CardDAV2PassObject*>(stream)->CardDAV2Object->WritebackFuncImplementation(ptr, size, nmemb, stream);
        
 }
-       
+
 size_t CardDAV2::WritebackFuncImplementation(char *ptr, size_t size, size_t nmemb, void *stream){
        
        // Writeback function for the CardDAV object.
                
-       string *data = static_cast<string*>(stream);
-       data->append(ptr);
+       CardDAV2PassObject *data = static_cast<CardDAV2PassObject*>(stream);
+       data->DataSetting->append(ptr);
        
        // Get the SSL engine pointer and trust if required on certain operating systems.
-       
-       if (ServerSSL){
-       
+
+       if (data->ServerUsingSSL == true) {
+
 #if defined(__APPLE__)
-       
+
                const struct curl_tlssessioninfo *TLSInfo;
                CURLcode TLSCode;
-               CURL *Connection = GetConnectionObject();
-               TLSCode = curl_easy_getinfo(Connection, CURLINFO_TLS_SSL_PTR, &TLSInfo);
-       
-               if (TLSInfo->internals != nullptr && TLSCode == CURLE_OK){
-                       SSLCopyPeerTrust((SSLContext*)TLSInfo->internals, &SecTrustObject);
+               TLSCode = curl_easy_getinfo(data->ConnectionSessionObject, CURLINFO_TLS_SSL_PTR, &TLSInfo);
+
+               SecTrustRef CertificateData;
+               
+               if (TLSInfo->internals != nullptr && TLSCode == CURLE_OK) {
+                       SSLCopyPeerTrust((SSLContext*)TLSInfo->internals, &CertificateData);
+                       data->SSLContext = CertificateData;
                }
-       
+
 #elif defined(__WIN32__)
 
                const struct curl_tlssessioninfo *TLSInfo;
                CURLcode TLSCode;
-               CURL *Connection = GetConnectionObject();
-               TLSCode = curl_easy_getinfo(Connection, CURLINFO_TLS_SSL_PTR, &TLSInfo);
+               TLSCode = curl_easy_getinfo(data->ConnectionSessionObject, CURLINFO_TLS_SSL_PTR, &TLSInfo);
 
-               if (TLSInfo->internals != nullptr && TLSCode == CURLE_OK){
+               if (TLSInfo->internals != nullptr && TLSCode == CURLE_OK) {
 
                        // Free the previous certificate data.
 
-                       CertFreeCertificateContext(CertificateData);
+                       //CertFreeCertificateContext(CertificateData);
+
+                       PCCERT_CONTEXT CertificateData;
 
                        PCtxtHandle SSLHandle = (PCtxtHandle)TLSInfo->internals;
                        SECURITY_STATUS GetData = QueryContextAttributes(SSLHandle, SECPKG_ATTR_REMOTE_CERT_CONTEXT, &CertificateData);
 
+                       data->SSLContext = CertificateData;
+
                }
 
 #endif
 
        }
-       
+
        return size * nmemb;
 
 }
 
+void CardDAV2::SetCertificateData() {
+
+}
+
 CardDAV2::~CardDAV2(){
        
        curl_easy_cleanup(ConnectionSession);
@@ -85,13 +121,35 @@ CardDAV2::~CardDAV2(){
                curl_slist_free_all(HeaderList);
                HeaderList = nullptr;
        }
+
+#if defined(__WIN32__)
+
+       if (CertificateData != nullptr) {
+
+               CertFreeCertificateContext(CertificateData);
+
+       }
+
+#endif
        
 }
 
 #if defined(__APPLE__)
 
+SecTrustRef CardDAV2::BuildSSLCollection(){
+       
+       return CertificateData;
+       
+}
+
 #elif defined(__WIN32__)
 
+PCCERT_CONTEXT CardDAV2::BuildSSLCollection(){
+
+       return CertificateData;
+
+}
+
 #else
 
 SSLCertCollectionString CardDAV2::BuildSSLCollection(){
@@ -109,13 +167,13 @@ SSLCertCollectionString CardDAV2::BuildSSLCollection(){
 
        certptr.certdata = NULL;
        
-       curl_easy_getinfo(ConnectionSession, CURLINFO_CERTINFO, &certptr.certinfo);
-
+       CURLcode result = curl_easy_getinfo(ConnectionSession, CURLINFO_CERTINFO, &certptr.certinfo);
+       
        std::string CertPropName;
        std::string CertPropValue;
-
+       
        for (int i = 0; i < certptr.certinfo->num_of_certs; i++){
-
+               
                struct curl_slist *slist;
                SSLCertDataString SSLCertDataInc;
                
@@ -151,13 +209,13 @@ SSLCertCollectionString CardDAV2::BuildSSLCollection(){
 
 }
 
-void CardDAV2::BypassSSLVerification(bool EnableBypass){
+#endif
+
+void CardDAV2::BypassSSLVerification(bool EnableBypass) {
        EnableSSLBypass = EnableBypass;
        SSLSelfSigned = EnableBypass;
 }
 
-#endif
-
 void CardDAV2::SetupConnectionObject(){
        ConnectionSession = curl_easy_init();
 }
@@ -173,7 +231,7 @@ COConnectResult CardDAV2::Connect(bool DoAuthentication){
        
        COConnectResult ConnectResult = COCONNECT_UNITTESTFAIL;
        string ServerAddressURL = BuildURL("/principals/");
-
+       
        curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str());
        
        if (TestMode == true){
@@ -189,6 +247,7 @@ COConnectResult CardDAV2::Connect(bool DoAuthentication){
                        SSLVerified = COSSL_VERIFIED;
                        ConnectResult = COCONNECT_OK;
                        break;
+               case CURLE_SSL_INVALIDCERTSTATUS:
                case CURLE_SSL_CACERT:
                case CURLE_SSL_CONNECT_ERROR:
                        SSLStatus = true;
@@ -200,6 +259,26 @@ COConnectResult CardDAV2::Connect(bool DoAuthentication){
                        break;
        };
        
+       // Set the certificate data (if required).
+
+#if defined(__APPLE__)
+       
+       if (ServerSSL) {
+               
+               CertificateData = PageHeaderObject.SSLContext;
+               
+       }
+       
+#elif defined(__WIN32__)
+
+       if (ServerSSL) {
+
+               CertificateData = PageHeaderObject.SSLContext;
+
+       }
+
+#endif
+
        // Check if an error occured before continuing.
        
        // Check if authentication was successful.
@@ -915,7 +994,83 @@ COServerResponse CardDAV2::EditContact(std::string Location, std::string Data){
        
 }
 
-COServerResponse CardDAV2::DeleteContact(std::string Location, std::string EntityTag){
+COServerResponse CardDAV2::DeleteContact(std::string Location){
+       
+       // Check if authentication was successful, otherwise don't do anything.
+
+       COServerResponse ServerResponse;
+       
+       if (AuthPassed == false){
+               ServerResponse.RequestResult = COREQUEST_ERROR_NOTCONNECTED;
+               ServerResponse.EntityTag = "";
+               ServerResponse.SessionCode = 0;
+               ServerResponse.ResultCode = 0;
+               ServerResponse.ResultMessage = "";
+               return ServerResponse;
+       }
+
+       ServerSSL ? SetupDefaultParametersSSL(true) : SetupDefaultParametersNonSSL(true);
+       ResetResults();
+       
+       string ServerAddressURL = BuildURL(ServerPrefix + Location);
+       curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str());
+       curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "DELETE");
+       
+       if (TestMode == true){
+               SessionResult = curl_easy_perform(ConnectionSession);
+       } else {
+               SessionResult = curl_easy_perform(ConnectionSession);
+       }
+       
+       switch(SessionResult){
+               case CURLE_OK:
+                       SSLStatus = true;
+                       SSLVerified = COSSL_VERIFIED;
+                       break;
+               case CURLE_SSL_CACERT:
+               case CURLE_SSL_CONNECT_ERROR:
+                       SSLStatus = true;
+                       SSLVerified = COSSL_UNABLETOVERIFY;
+                       break;
+               default:
+                       break;
+       };
+       
+       long SessionResponseCode = 0;
+       
+       curl_easy_getinfo(ConnectionSession, CURLINFO_RESPONSE_CODE, &SessionResponseCode);
+       
+       if (SessionResponseCode == 200 || SessionResponseCode == 202 || SessionResponseCode == 204){
+               AuthPassed = true;
+               ValidResponse = true;
+       } else if (SessionResponseCode == 403){
+               AuthPassed = false;
+               ValidResponse = true;
+       } else if (SessionResponseCode >= 400){
+               AuthPassed = false;
+               ValidResponse = true;
+       } else {
+               AuthPassed = false;
+               ValidResponse = false;                  
+       }
+       
+       if (ValidResponse == false || AuthPassed == false){
+               ServerResponse.RequestResult = COREQUEST_ERROR_SERVER;
+               ServerResponse.EntityTag = "";
+               ServerResponse.SessionCode = SessionResult;
+               ServerResponse.ResultCode = SessionResponseCode;
+               ServerResponse.ResultMessage = "";
+               return ServerResponse;
+       }
+       
+       CanProcess = true;
+       
+       ServerResponse.RequestResult = COREQUEST_OK;
+       ServerResponse.EntityTag = "";
+       ServerResponse.SessionCode = SessionResult;
+       ServerResponse.ResultCode = SessionResponseCode;
+       ServerResponse.ResultMessage = SessionErrorBuffer;
+       return ServerResponse;
        
 }
 
@@ -1096,6 +1251,122 @@ COServerResponse CardDAV2::GetContact(std::string Location, std::string *Contact
 
 COContactList CardDAV2::GetContactList(std::string SyncToken){
        
+       COContactList ServerContactList;
+       
+       // Check if authentication was successful, otherwise don't do anything.
+       
+       if (AuthPassed == false){
+               ServerContactList.ServerResponse.RequestResult = COREQUEST_ERROR_NOTCONNECTED;
+               ServerContactList.ServerResponse.EntityTag = "";
+               ServerContactList.ServerResponse.SessionCode = 0;
+               ServerContactList.ServerResponse.ResultCode = 0;
+               ServerContactList.ServerResponse.ResultMessage = "";
+               return ServerContactList;
+       }
+
+       ServerSSL ? SetupDefaultParametersSSL(true) : SetupDefaultParametersNonSSL(true);
+       ResetResults();
+       
+       std::string SyncData;
+       
+       if (SyncToken.size() > 0){
+               
+               SyncData = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
+               "<D:sync-collection xmlns:D=\"DAV:\"\n"
+               " xmlns:C=\"urn:ietf:params:xml:ns:carddav\">\n"
+               "<D:sync-token>";
+               SyncData.append(SyncToken);
+               SyncData.append("</D:sync-token>\n"
+               "<D:sync-level>1</D:sync-level>\n"
+               "<D:prop>\n"
+               "       <D:getetag/>\n"
+               "</D:prop>\n"
+               "</D:sync-collection>");
+       
+       } else {
+               
+               SyncData = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
+               "<D:sync-collection xmlns:D=\"DAV:\"\n"
+               " xmlns:C=\"urn:ietf:params:xml:ns:carddav\">\n"
+               "<D:sync-level>1</D:sync-level>\n"
+               "<D:prop>\n"
+               "       <D:getetag/>\n"
+               "</D:prop>\n"
+               "</D:sync-collection>";
+
+       }
+       
+       string ServerAddressURL = BuildURL(ServerPrefix);
+       
+       curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str());
+       curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDS, SyncData.c_str());
+       curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDSIZE, strlen(SyncData.c_str()));
+       curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "REPORT");
+       
+       HeaderList = curl_slist_append(HeaderList, "Content-Type: application/xml; charset=utf-8");
+       HeaderList = curl_slist_append(HeaderList, "Depth: 1");
+
+       curl_easy_setopt(ConnectionSession, CURLOPT_HTTPHEADER, HeaderList);
+       
+       if (TestMode == true){
+               SessionResult = curl_easy_perform(ConnectionSession);
+       } else {
+               SessionResult = curl_easy_perform(ConnectionSession);
+       }
+       
+       switch(SessionResult){
+               case CURLE_OK:
+                       SSLStatus = true;
+                       SSLVerified = COSSL_VERIFIED;
+                       break;
+               case CURLE_SSL_CACERT:
+               case CURLE_SSL_CONNECT_ERROR:
+                       SSLStatus = true;
+                       SSLVerified = COSSL_UNABLETOVERIFY;
+                       break;
+               default:
+                       break;
+       };
+       
+       long SessionResponseCode = 0;
+       
+       curl_easy_getinfo(ConnectionSession, CURLINFO_RESPONSE_CODE, &SessionResponseCode);
+       
+       if (SessionResponseCode == 207){
+               AuthPassed = true;
+               ValidResponse = true;
+       } else if (SessionResponseCode == 403){
+               AuthPassed = false;
+               ValidResponse = true;
+       } else if (SessionResponseCode >= 400){
+               AuthPassed = false;
+               ValidResponse = true;
+       } else {
+               AuthPassed = false;
+               ValidResponse = false;                  
+       }
+       
+       if (ValidResponse == false || AuthPassed == false){
+               ServerContactList.ServerResponse.RequestResult = COREQUEST_ERROR_SERVER;
+               ServerContactList.ServerResponse.EntityTag = "";
+               ServerContactList.ServerResponse.SessionCode = SessionResult;
+               ServerContactList.ServerResponse.ResultCode = SessionResponseCode;
+               ServerContactList.ServerResponse.ResultMessage = "";
+               return ServerContactList;
+       }
+       
+       CanProcess = true;
+       
+       ProcessContactData(&ServerContactList);
+       
+       ServerContactList.ServerResponse.RequestResult = COREQUEST_OK;
+       ServerContactList.ServerResponse.EntityTag = "";
+       ServerContactList.ServerResponse.SessionCode = SessionResult;
+       ServerContactList.ServerResponse.ResultCode = SessionResponseCode;
+       ServerContactList.ServerResponse.ResultMessage = SessionErrorBuffer;
+       
+       return ServerContactList;
+       
 }
        
 bool CardDAV2::CanDoProcessing(){
@@ -1128,26 +1399,36 @@ void CardDAV2::SetupDefaultParametersNonSSL(bool DoAuthentication){
 
        string ServerAddressURL = "http://" + ServerAddress + ":" + to_string(ServerPort) + "/";
        string UsernamePassword = ServerUser + ":" + ServerPass;
+
+       PageDataObject.CardDAV2Object = this;
+       PageDataObject.ConnectionSessionObject = ConnectionSession;
+       PageDataObject.DataSetting = &PageData;
+       PageDataObject.ServerUsingSSL = false;
+
+       PageHeaderObject.CardDAV2Object = this;
+       PageHeaderObject.ConnectionSessionObject = ConnectionSession;
+       PageHeaderObject.DataSetting = &PageHeader;
+       PageHeaderObject.ServerUsingSSL = false;
        
        curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddress.c_str());
        curl_easy_setopt(ConnectionSession, CURLOPT_NOPROGRESS, 1L);
-       curl_easy_setopt(ConnectionSession, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
+       curl_easy_setopt(ConnectionSession, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST|CURLAUTH_BASIC);
        curl_easy_setopt(ConnectionSession, CURLOPT_TIMEOUT, 60);
        curl_easy_setopt(ConnectionSession, CURLOPT_FAILONERROR, true);
        curl_easy_setopt(ConnectionSession, CURLOPT_USERAGENT, XSDAB_USERAGENT);
        curl_easy_setopt(ConnectionSession, CURLOPT_WRITEFUNCTION, CardDAV2::WritebackFunc);
-       curl_easy_setopt(ConnectionSession, CURLOPT_WRITEDATA, &PageData);
-       curl_easy_setopt(ConnectionSession, CURLOPT_WRITEHEADER, &PageHeader);
-       curl_easy_setopt(ConnectionSession, CURLOPT_NOSIGNAL, 1);
+       curl_easy_setopt(ConnectionSession, CURLOPT_WRITEDATA, &PageDataObject);
+       curl_easy_setopt(ConnectionSession, CURLOPT_WRITEHEADER, &PageHeaderObject);
+       curl_easy_setopt(ConnectionSession, CURLOPT_NOSIGNAL, 1L);
        curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "GET");
        curl_easy_setopt(ConnectionSession, CURLOPT_HTTPHEADER, nullptr);
        curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDS, nullptr);
        curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDSIZE, 0L);
-       
+
        if (DoAuthentication == true){
                curl_easy_setopt(ConnectionSession, CURLOPT_USERPWD, UsernamePassword.c_str());
        } else {
-               curl_easy_setopt(ConnectionSession, CURLOPT_USERPWD, ":");              
+               curl_easy_setopt(ConnectionSession, CURLOPT_USERPWD, NULL);             
        }
        
 }
@@ -1158,39 +1439,51 @@ void CardDAV2::SetupDefaultParametersSSL(bool DoAuthentication){
        
        string ServerAddressURL = "https://" + ServerAddress + ":" + to_string(ServerPort) + "/";
        string UsernamePassword = ServerUser + ":" + ServerPass;
+
+       PageDataObject.CardDAV2Object = this;
+       PageDataObject.ConnectionSessionObject = ConnectionSession;
+       PageDataObject.DataSetting = &PageData;
+       PageDataObject.ServerUsingSSL = true;
+
+       PageHeaderObject.CardDAV2Object = this;
+       PageHeaderObject.ConnectionSessionObject = ConnectionSession;
+       PageHeaderObject.DataSetting = &PageHeader;
+       PageHeaderObject.ServerUsingSSL = true;
        
        curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str());
        curl_easy_setopt(ConnectionSession, CURLOPT_NOPROGRESS, 1L);
-       curl_easy_setopt(ConnectionSession, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
+       curl_easy_setopt(ConnectionSession, CURLOPT_CERTINFO, 1L);
+       curl_easy_setopt(ConnectionSession, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST|CURLAUTH_BASIC);
        curl_easy_setopt(ConnectionSession, CURLOPT_TIMEOUT, 60);
-       curl_easy_setopt(ConnectionSession, CURLOPT_FAILONERROR, true);
+       curl_easy_setopt(ConnectionSession, CURLOPT_FAILONERROR, 0L);
        curl_easy_setopt(ConnectionSession, CURLOPT_USERAGENT, XSDAB_USERAGENT);
        curl_easy_setopt(ConnectionSession, CURLOPT_WRITEFUNCTION, CardDAV2::WritebackFunc);
-       curl_easy_setopt(ConnectionSession, CURLOPT_WRITEDATA, &PageData);
-       curl_easy_setopt(ConnectionSession, CURLOPT_WRITEHEADER, &PageHeader);
+       curl_easy_setopt(ConnectionSession, CURLOPT_WRITEDATA, &PageDataObject);
+       curl_easy_setopt(ConnectionSession, CURLOPT_WRITEHEADER, &PageHeaderObject);
        curl_easy_setopt(ConnectionSession, CURLOPT_ERRORBUFFER, SessionErrorBuffer);
-       curl_easy_setopt(ConnectionSession, CURLOPT_NOSIGNAL, 1);
-       curl_easy_setopt(ConnectionSession, CURLOPT_CERTINFO, 1);
-       curl_easy_setopt(ConnectionSession, CURLOPT_VERBOSE, 1);
        curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "GET");
        curl_easy_setopt(ConnectionSession, CURLOPT_HTTPHEADER, nullptr);
        curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDS, nullptr);
        curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDSIZE, 0L);
-       
+
        if (DoAuthentication == true){
                curl_easy_setopt(ConnectionSession, CURLOPT_USERPWD, UsernamePassword.c_str());
        } else {
-               curl_easy_setopt(ConnectionSession, CURLOPT_USERPWD, ":");              
+               curl_easy_setopt(ConnectionSession, CURLOPT_USERPWD, NULL);             
        }
        
        if (EnableSSLBypass == true){
-               curl_easy_setopt(ConnectionSession, CURLOPT_SSL_VERIFYHOST, 0);
-               curl_easy_setopt(ConnectionSession, CURLOPT_SSL_VERIFYPEER, 0);
+               curl_easy_setopt(ConnectionSession, CURLOPT_SSL_VERIFYHOST, 0L);
+               curl_easy_setopt(ConnectionSession, CURLOPT_SSL_VERIFYPEER, 0L);
+               curl_easy_setopt(ConnectionSession, CURLOPT_SSL_VERIFYSTATUS, 0L);
        } else {
-               curl_easy_setopt(ConnectionSession, CURLOPT_SSL_VERIFYHOST, 2);
-               curl_easy_setopt(ConnectionSession, CURLOPT_SSL_VERIFYPEER, 1);         
+               curl_easy_setopt(ConnectionSession, CURLOPT_SSL_VERIFYHOST, 2L);
+               curl_easy_setopt(ConnectionSession, CURLOPT_SSL_VERIFYPEER, 1L);
+               curl_easy_setopt(ConnectionSession, CURLOPT_SSL_VERIFYSTATUS, 1L);
        }
        
+#if !defined(__APPLE__) || defined(__WIN32__)
+       
        if (TestMode == false && ServerAccount.size() > 0){
                
                // Check if the server certificate file exists.
@@ -1198,12 +1491,17 @@ void CardDAV2::SetupDefaultParametersSSL(bool DoAuthentication){
                string CertificateFilename = GetAccountDir(ServerAccount, true);
                
                if (wxFile::Exists(CertificateFilename)){
-                       
+               
                        curl_easy_setopt(ConnectionSession, CURLOPT_CAINFO, CertificateFilename.c_str());
                        
+                       // Force CURLOPT_SSL_VERIFYSTATUS to 0.
+                       curl_easy_setopt(ConnectionSession, CURLOPT_SSL_VERIFYSTATUS, 0L);
+                       
                }
                
        }
+
+#endif
        
 }
 
@@ -1211,10 +1509,10 @@ string CardDAV2::BuildURL(string URI){
        
        string ServerAddressURL;
        
-       if (SSLStatus == true){
+       if (ServerSSL == true){
                ServerAddressURL = "https://" + ServerAddress + ":" + to_string(ServerPort) + URI;      
        } else {
-               ServerAddressURL = "https://" + ServerAddress + ":" + to_string(ServerPort) + URI;
+               ServerAddressURL = "http://" + ServerAddress + ":" + to_string(ServerPort) + URI;
        }
        
        return ServerAddressURL;
@@ -1239,6 +1537,7 @@ void CardDAV2::ResetResults(){
        TaskCompleted = false;
        ErrorMessage = "";
        SessionErrorBuffer[0] = '\0';
+       SessionResult = CURLE_OK;
        PageData = "";
        PageHeader = "";
        if (HeaderList != nullptr){
@@ -1554,4 +1853,163 @@ vector<string> CardDAV2::GetDAVHeader(){
        
        return DAVHeaderList;
        
-}
\ No newline at end of file
+}
+
+void CardDAV2::ProcessContactData(COContactList *ContactList){
+       
+       xmlDocPtr xmlCardDAVDoc;
+       xmlCardDAVDoc = xmlReadMemory(PageData.c_str(), (int)PageData.size(), "noname.xml", NULL, 0);
+
+       xmlNodePtr MultiStatusNode;
+       xmlNodePtr ResponseNode;
+       xmlNodePtr ResponseDataNode;
+       xmlNodePtr PropStatNode;
+       xmlNodePtr ValueNode;
+       xmlNodePtr ETagNode;
+       xmlNodePtr StatusNode;
+
+       std::string HREFValue;
+       std::string ETagValue;
+       std::string StatusValue;
+       std::string SyncValue;
+
+       // Go through the document!
+
+       MultiStatusNode = xmlCardDAVDoc->children;
+
+       if (MultiStatusNode == nullptr){
+               return;
+       }
+
+       bool SyncTokenFound = false;
+
+       // Tranverse through the catacombs of the response to get our ETag for the file and
+       // the server syncronisation token.
+       
+       for (ResponseNode = MultiStatusNode->children;
+               ResponseNode != nullptr;
+               ResponseNode = ResponseNode->next){
+
+               // Check if tag is response or sync-token.
+
+               if (!xmlStrcmp(ResponseNode->name, (const xmlChar *)"response") ||
+               !xmlStrcmp(ResponseNode->name, (const xmlChar *)"d:response") ||
+               !xmlStrcmp(ResponseNode->name, (const xmlChar *)"D:response")){
+
+                       COContactStatus ContactStatus = COCS_UNKNOWN;
+                       
+                       for (ResponseDataNode = ResponseNode->children;
+                               ResponseDataNode != nullptr;
+                               ResponseDataNode = ResponseDataNode->next){
+
+                               if (!xmlStrcmp(ResponseDataNode->name, (const xmlChar *)"href") ||
+                               !xmlStrcmp(ResponseDataNode->name, (const xmlChar *)"d:href") ||
+                               !xmlStrcmp(ResponseDataNode->name, (const xmlChar *)"D:href")){
+                               
+                                       HREFValue = (const char*)ResponseDataNode->children->content;
+
+                                       // Get the filename after the last forward slash.
+                                       
+                                       int LastSlash = 0;
+                                       
+                                       for (int HREFValueSeek = 0; HREFValueSeek < HREFValue.size(); HREFValueSeek++){
+                                               
+                                               if (HREFValue[HREFValueSeek] == '/'){
+                                               
+                                                       LastSlash = HREFValueSeek;
+                                                       
+                                               }
+                                               
+                                       }
+                                       
+                                       HREFValue = HREFValue.substr((LastSlash + 1));
+                                       
+                               } else if (!xmlStrcmp(ResponseDataNode->name, (const xmlChar *)"propstat") ||
+                               !xmlStrcmp(ResponseDataNode->name, (const xmlChar *)"d:propstat") ||
+                               !xmlStrcmp(ResponseDataNode->name, (const xmlChar *)"D:propstat")){
+
+                                       for (PropStatNode = ResponseDataNode->children;
+                                               PropStatNode != nullptr;
+                                               PropStatNode = PropStatNode->next){
+
+                                               if (!xmlStrcmp(PropStatNode->name, (const xmlChar *)"prop") ||
+                                                       !xmlStrcmp(PropStatNode->name, (const xmlChar *)"d:prop") ||
+                                                       !xmlStrcmp(PropStatNode->name, (const xmlChar *)"D:prop")){
+
+                                                       for (ETagNode = PropStatNode->children;
+                                                               ETagNode != nullptr;
+                                                               ETagNode = ETagNode->next){
+
+                                                                       if (!xmlStrcmp(ETagNode->name, (const xmlChar *)"getetag") ||
+                                                                       !xmlStrcmp(ETagNode->name, (const xmlChar *)"getetag") ||
+                                                                       !xmlStrcmp(ETagNode->name, (const xmlChar *)"getetag")){
+
+                                                                               ETagValue = (const char*)ETagNode->children->content;
+
+                                                                               if (ETagValue.size() > 2 && ETagValue.substr(0,1) == "\""){
+                                                                                       ETagValue.erase((ETagValue.size() - 1),1);
+                                                                                       ETagValue.erase(0,1);
+                                                                               }
+
+                                                                       }
+                                                       
+
+                                                       }
+
+                                               } else if (!xmlStrcmp(PropStatNode->name, (const xmlChar *)"status") ||
+                                                       !xmlStrcmp(PropStatNode->name, (const xmlChar *)"d:status") ||
+                                                       !xmlStrcmp(PropStatNode->name, (const xmlChar *)"D:status")){
+
+                                                       StatusValue = (const char*)PropStatNode->children->content;
+
+                                                       if (StatusValue == "HTTP/1.1 200 OK"){
+
+                                                               ContactStatus = COCS_UPDATED;
+
+                                                       } else if (StatusValue == "HTTP/1.1 404 Not Found"){
+
+                                                               ContactStatus = COCS_DELETED;
+
+                                                       } else {
+
+                                                               ContactStatus = COCS_UNKNOWN;
+
+                                                       }
+
+                                               }
+
+                                       }
+
+                               }
+
+                       }
+
+                       COContactData ContactInformation;
+                       
+                       ContactInformation.Location = HREFValue;
+                       ContactInformation.Data = ETagValue;
+                       ContactInformation.Status = ContactStatus;
+
+                       HREFValue.clear();
+                       ETagValue.clear();
+                       StatusValue.clear();
+                       
+                       ContactList->ListData.push_back(ContactInformation);
+
+               } else if (!xmlStrcmp(ResponseNode->name, (const xmlChar *)"sync-token") ||
+                       !xmlStrcmp(ResponseNode->name, (const xmlChar *)"d:sync-token") ||
+                       !xmlStrcmp(ResponseNode->name, (const xmlChar *)"D:sync-token")){
+
+                       SyncValue = (const char*)ResponseNode->children->content;
+
+               }
+
+       }
+
+       ContactList->SyncToken = SyncValue;
+
+       xmlFreeDoc(xmlCardDAVDoc);
+
+       return;
+       
+}
Xestia Software Development
Yn Maystri
© 2006 - 2019 Xestia Software Development
Software

Xestia Address Book
Xestia Calendar
Development

Xestia Gelforn
Everything else

About
News
Privacy Policy