Home | News | Projects | Releases
Bugs | RFE | Repositories | Help
Initial version of CardDAV2 class
authorSteve Brokenshire <sbrokenshire@xestia.co.uk>
Fri, 19 Aug 2016 23:13:49 +0000 (00:13 +0100)
committerSteve Brokenshire <sbrokenshire@xestia.co.uk>
Fri, 19 Aug 2016 23:13:49 +0000 (00:13 +0100)
Inherits from the ConnectionObject interface.

source/carddav2/carddav2.cpp [new file with mode: 0644]
source/carddav2/carddav2.h [new file with mode: 0644]

diff --git a/source/carddav2/carddav2.cpp b/source/carddav2/carddav2.cpp
new file mode 100644 (file)
index 0000000..f5bc2a3
--- /dev/null
@@ -0,0 +1,980 @@
+// CardDAV2.cpp - CardDAV v2 class
+//
+// (c) 2012-2016 Xestia Software Development.
+//
+// This file is part of Xestia Address Book.
+//
+// Xestia Address Book is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by the
+// Free Software Foundation, version 3 of the license.
+//
+// Xestia Address Book is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with Xestia Address Book. If not, see <http://www.gnu.org/licenses/> 
+
+#include "carddav2.h"
+
+#include <iostream>
+
+using namespace std;
+
+size_t CardDAV2::WritebackFunc(char *ptr, size_t size, size_t nmemb, void *stream){
+       
+       return static_cast<CardDAV2*>(stream)->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);
+       
+       // Get the SSL engine pointer and trust if required on certain operating systems.
+       
+       if (ServerSSL){
+       
+#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);
+               }
+       
+#elif defined(__WIN32__)
+
+               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){
+
+                       // Free the previous certificate data.
+
+                       CertFreeCertificateContext(CertificateData);
+
+                       PCtxtHandle SSLHandle = (PCtxtHandle)TLSInfo->internals;
+                       SECURITY_STATUS GetData = QueryContextAttributes(SSLHandle, SECPKG_ATTR_REMOTE_CERT_CONTEXT, &CertificateData);
+
+               }
+
+#endif
+
+       }
+       
+       return size * nmemb;
+
+}
+
+CardDAV2::~CardDAV2(){
+       curl_easy_cleanup(ConnectionSession);
+       ConnectionSession = nullptr;
+}
+
+#if defined(__APPLE__)
+
+#elif defined(__WIN32__)
+
+#else
+
+SSLCertCollectionString CardDAV2::BuildSSLCollection(){
+
+       // Build and return the SSL collection.
+       
+       SSLCertCollectionString SSLCertInfo;
+
+       // Grab the certificate data.
+
+       union {
+               struct curl_slist *certdata;
+               struct curl_certinfo *certinfo;
+       } certptr;
+
+       certptr.certdata = NULL;
+       
+       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;
+               
+               for (slist = certptr.certinfo->certinfo[i]; slist; slist = slist->next){
+                       
+                       // Using wxStringTokenizer from wxWidgets.
+                       
+                       wxStringTokenizer CertDataInc(wxString::FromUTF8(slist->data), ":");
+                       
+                       // Get first token as the property name.
+                       
+                       CertPropName = CertDataInc.GetNextToken().ToStdString();
+                       
+                       // Get remaining tokens as the property value.
+                       
+                       while(CertDataInc.HasMoreTokens()){
+                       
+                               CertPropValue.append(CertDataInc.GetNextToken());
+                       
+                       }
+                       
+                       SSLCertDataInc.CertData.insert(std::make_pair(CertPropName, CertPropValue));
+                       CertPropName.clear();
+                       CertPropValue.clear();
+                       
+               }
+       
+               SSLCertInfo.SSLCollection.insert(std::make_pair(i, SSLCertDataInc));
+       
+       }
+       
+       return SSLCertInfo;
+
+}
+
+void CardDAV2::BypassSSLVerification(bool EnableBypass){
+       EnableSSLBypass = EnableBypass;
+       SSLSelfSigned = EnableBypass;
+}
+
+#endif
+
+void CardDAV2::SetupConnectionObject(){
+       ConnectionSession = curl_easy_init();
+}
+
+bool CardDAV2::IsTaskCompleted(){
+       return false;
+}
+
+COConnectResult CardDAV2::Connect(bool DoAuthentication){
+       
+       ServerSSL ? SetupDefaultParametersSSL(DoAuthentication) : SetupDefaultParametersNonSSL(DoAuthentication);
+       ResetResults();
+       
+       COConnectResult ConnectResult = COCONNECT_UNITTESTFAIL;
+       string ServerAddressURL = BuildURL("/principals/");
+
+       curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str());
+       
+       if (TestMode == true){
+               SessionResult = curl_easy_perform(ConnectionSession);
+       } else {
+               
+       }
+       
+       switch(SessionResult){
+               case CURLE_OK:
+                       SSLStatus = true;
+                       SSLVerified = COSSL_VERIFIED;
+                       ConnectResult = COCONNECT_OK;
+                       break;
+               case CURLE_SSL_CACERT:
+               case CURLE_SSL_CONNECT_ERROR:
+                       SSLStatus = true;
+                       ConnectResult = COCONNECT_OK;
+                       SSLVerified = COSSL_UNABLETOVERIFY;
+                       break;
+               default:
+                       ConnectResult = COCONNECT_INVALID;
+                       break;
+       };
+       
+       // Check if an error occured before continuing.
+       
+       // Check if authentication was successful.
+       
+       long SessionResponseCode = 0;
+       
+       curl_easy_getinfo(ConnectionSession, CURLINFO_RESPONSE_CODE, &SessionResponseCode);
+       
+       if (DoAuthentication == true){
+               
+               // Get the HTTP status code (Should be 200 and not 403).
+               // Return error otherwise.
+               
+               if (SessionResponseCode == 200){
+                       ConnectResult = COCONNECT_OK;
+                       AuthPassed = true;
+                       ValidResponse = true;
+               } else if (SessionResponseCode == 403){
+                       ConnectResult = COCONNECT_AUTHFAIL;
+                       AuthPassed = false;
+                       ValidResponse = true;
+               } else if (SessionResponseCode >= 200) {
+                       ConnectResult = COCONNECT_INVALID;
+                       AuthPassed = false;
+                       ValidResponse = true;
+               } else {
+                       ConnectResult = COCONNECT_INVALID;
+                       AuthPassed = false;
+                       ValidResponse = false;                  
+               }
+               
+       } else {
+               
+               ValidResponse = true;
+               
+       }
+       
+       // Check the header to see if CardDAV is supported.
+       
+       vector<string> DAVHeaderValues = GetDAVHeader();
+       
+       for (vector<string>::iterator DAVHeaderValuesIter = DAVHeaderValues.begin();
+               DAVHeaderValuesIter != DAVHeaderValues.end(); DAVHeaderValuesIter++){
+               
+               if ((*DAVHeaderValuesIter) == "addressbook"){
+                       CanProcess = true;
+                       break;
+               }
+                       
+       }
+       
+       return ConnectResult;
+       
+}
+
+COServerResponse CardDAV2::GetDefaultPrefix(string *ServerPrefix){
+
+       // 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();
+       
+       // Need to do three requests:
+       
+       // 1. Get the current user principal URI.
+       // 2. Get the address book home URI.
+       // 3. Get the default address book URI.
+       
+       // Setup the first query finding out where the principal URL is.
+       
+       const char* CurrentUserPrincipalXMLQuery = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
+               "<D:propfind xmlns:D=\"DAV:\">\n"
+               " <D:prop>"
+               "  <D:current-user-principal/>\n"
+               " </D:prop>"
+               "</D:propfind>";
+
+       // Setup the second query finding out where the address book home URL is.
+       
+       const char* AddressBookHomeXMLQuery = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
+       "<D:propfind xmlns:D=\"DAV:\""
+       "  xmlns:C=\"urn:ietf:params:xml:ns:carddav\">\n"
+       "  <D:prop>\n"
+       "    <C:addressbook-home-set/>\n"
+       "  </D:prop>\n"
+       "</D:propfind>";
+       
+       // Setup the third query finding out where the default address book URL is.
+       
+       const char* DefaultAddressBookXMLQuery = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
+       "<D:propfind xmlns:D=\"DAV:\""
+       "  xmlns:C=\"urn:ietf:params:xml:ns:carddav\">\n"
+       "  <D:prop>\n"
+       "    <C:default-addressbook-URL/>\n"    
+       "  </D:prop>\n"
+       "</D:propfind>";
+       
+       string ServerAddressURL = BuildURL("/principals/");
+       curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str());
+       curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "PROPFIND");
+       curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDS, CurrentUserPrincipalXMLQuery);
+       curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDSIZE, strlen(CurrentUserPrincipalXMLQuery));
+       
+       if (TestMode == true){
+               SessionResult = curl_easy_perform(ConnectionSession);
+       } else {
+               
+       }
+       
+       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 == 207){
+               AuthPassed = true;
+               ValidResponse = true;
+       } else if (SessionResponseCode == 403){
+               AuthPassed = false;
+               ValidResponse = true;
+       } else if (SessionResponseCode >= 200) {
+               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;
+       }
+       
+       // Process the first response.
+       
+       string UserPrincipalURI = GetUserPrincipalURI();
+       
+       // Cleanup and reset for the second connection.
+       
+       ServerSSL ? SetupDefaultParametersSSL(true) : SetupDefaultParametersNonSSL(true);
+       ResetResults();
+
+       ServerAddressURL = BuildURL(UserPrincipalURI);
+       curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str());
+       curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "PROPFIND");
+       curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDS, AddressBookHomeXMLQuery);
+       curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDSIZE, strlen(AddressBookHomeXMLQuery));
+       
+       if (TestMode == true){
+               SessionResult = curl_easy_perform(ConnectionSession);
+       } else {
+               
+       }
+       
+       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;
+       };
+       
+       SessionResponseCode = 0;
+       
+       curl_easy_getinfo(ConnectionSession, CURLINFO_RESPONSE_CODE, &SessionResponseCode);
+       
+       if (SessionResponseCode == 200 || SessionResponseCode == 207){
+               //ConnectResult = COCONNECT_OK;
+               AuthPassed = true;
+               ValidResponse = true;
+       } else if (SessionResponseCode == 403){
+               //ConnectResult = COCONNECT_AUTHFAIL;
+               AuthPassed = false;
+               ValidResponse = true;
+       } else if (SessionResponseCode >= 200) {
+               //ConnectResult = COCONNECT_INVALID;
+               AuthPassed = false;
+               ValidResponse = true;
+       } else {
+               //ConnectResult = COCONNECT_INVALID;
+               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;
+       }
+       
+       // Process the second response.
+       
+       string AddressBookHomeURI = GetAddressBookHomeURI();
+       
+       // Cleanup and reset for the second connection.
+       
+       ServerSSL ? SetupDefaultParametersSSL(true) : SetupDefaultParametersNonSSL(true);
+       ResetResults();
+       
+       ServerAddressURL = BuildURL(AddressBookHomeURI);
+       curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str());
+       curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "PROPFIND");
+       curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDS, DefaultAddressBookXMLQuery);
+       curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDSIZE, strlen(DefaultAddressBookXMLQuery));
+       
+       if (TestMode == true){
+               SessionResult = curl_easy_perform(ConnectionSession);
+       } else {
+               
+       }
+       
+       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;
+       };
+       
+       SessionResponseCode = 0;
+       
+       curl_easy_getinfo(ConnectionSession, CURLINFO_RESPONSE_CODE, &SessionResponseCode);
+       
+       if (SessionResponseCode == 200 || SessionResponseCode == 207){
+               AuthPassed = true;
+               ValidResponse = true;
+       } else if (SessionResponseCode == 403){
+               AuthPassed = false;
+               ValidResponse = true;
+       } else if (SessionResponseCode >= 200) {
+               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;
+       }
+       
+       // Process the second response.
+       
+       (*ServerPrefix) = GetDefaultAddressBookURI();
+       
+       CanProcess = true;
+       
+       ServerResponse.RequestResult = COREQUEST_OK;
+       ServerResponse.EntityTag = "";
+       ServerResponse.SessionCode = SessionResult;
+       ServerResponse.ResultCode = SessionResponseCode;
+       ServerResponse.ResultMessage = SessionErrorBuffer;
+       return ServerResponse;
+       
+}
+
+std::string CardDAV2::GetUserPrincipalURI(){
+       
+       xmlDocPtr xmlCardDAVDoc;
+       xmlCardDAVDoc = xmlReadMemory(PageData.c_str(), (int)PageData.size(), "noname.xml", NULL, 0);
+       string UserPrincipalURI = "";
+       
+       xmlNodePtr nodeLevel1;
+       xmlNodePtr nodeLevel2;
+       xmlNodePtr nodeLevel3;
+       xmlNodePtr nodeLevel4;
+       xmlNodePtr nodeLevel5;
+       xmlNodePtr nodeLevel6;
+       xmlNodePtr nodeLevel7;
+               
+       for (nodeLevel1 = xmlCardDAVDoc->children;
+               nodeLevel1 != NULL;
+               nodeLevel1 = nodeLevel1->next)
+       {
+
+               for (nodeLevel2 = nodeLevel1->children;
+                       nodeLevel2 != NULL;
+                       nodeLevel2 = nodeLevel2->next)
+               {
+
+
+                       for (nodeLevel3 = nodeLevel2->children;
+                       nodeLevel3 != NULL;
+                       nodeLevel3 = nodeLevel3->next)
+                       {
+                       
+                               for (nodeLevel4 = nodeLevel3->children;
+                               nodeLevel4 != NULL;
+                               nodeLevel4 = nodeLevel4->next)
+                               {
+                       
+                                       for (nodeLevel5 = nodeLevel4->children;
+                                       nodeLevel5 != NULL;
+                                       nodeLevel5 = nodeLevel5->next)
+                                       {
+                       
+                                               for (nodeLevel6 = nodeLevel5->children;
+                                               nodeLevel6 != NULL;
+                                               nodeLevel6 = nodeLevel6->next)
+                                               {
+                       
+                                                       if (!xmlStrcmp(nodeLevel6->name, (const xmlChar *)"href") ||
+                                                       !xmlStrcmp(nodeLevel6->name, (const xmlChar *)"d:href") ||
+                                                       !xmlStrcmp(nodeLevel6->name, (const xmlChar *)"D:href")
+                                                       ){
+                       
+                                                               // Found the <href> part so extract the principal URL address.
+                                                               
+                                                               for (nodeLevel7 = nodeLevel6->children;
+                                                               nodeLevel7 != NULL;
+                                                               nodeLevel7 = nodeLevel7->next)
+                                                               {
+                                                               
+                                                                       UserPrincipalURI = ((const char*)nodeLevel7->content);
+
+                                                               }
+                       
+                                                       }
+                       
+                                               }
+                       
+                                       }
+                       
+                               }
+                       
+                       }
+               
+               }
+               
+       }
+       
+       xmlFreeDoc(xmlCardDAVDoc);
+       
+       return UserPrincipalURI;
+       
+}
+
+std::string CardDAV2::GetAddressBookHomeURI(){
+       
+       xmlDocPtr xmlCardDAVDoc;
+       xmlCardDAVDoc = xmlReadMemory(PageData.c_str(), (int)PageData.size(), "noname.xml", NULL, 0);
+       string AddressBookHomeURI = "";
+       
+       xmlNodePtr nodeLevel1;
+       xmlNodePtr nodeLevel2;
+       xmlNodePtr nodeLevel3;
+       xmlNodePtr nodeLevel4;
+       xmlNodePtr nodeLevel5;
+       xmlNodePtr nodeLevel6;
+       xmlNodePtr nodeLevel7;
+               
+       for (nodeLevel1 = xmlCardDAVDoc->children;
+               nodeLevel1 != NULL;
+               nodeLevel1 = nodeLevel1->next)
+       {
+
+               for (nodeLevel2 = nodeLevel1->children;
+                       nodeLevel2 != NULL;
+                       nodeLevel2 = nodeLevel2->next)
+               {
+
+
+                       for (nodeLevel3 = nodeLevel2->children;
+                       nodeLevel3 != NULL;
+                       nodeLevel3 = nodeLevel3->next)
+                       {
+                       
+                               for (nodeLevel4 = nodeLevel3->children;
+                               nodeLevel4 != NULL;
+                               nodeLevel4 = nodeLevel4->next)
+                               {
+                       
+                                       for (nodeLevel5 = nodeLevel4->children;
+                                       nodeLevel5 != NULL;
+                                       nodeLevel5 = nodeLevel5->next)
+                                       {
+                       
+                                               for (nodeLevel6 = nodeLevel5->children;
+                                               nodeLevel6 != NULL;
+                                               nodeLevel6 = nodeLevel6->next)
+                                               {
+                       
+                                                       if (!xmlStrcmp(nodeLevel6->name, (const xmlChar *)"href") ||
+                                                       !xmlStrcmp(nodeLevel6->name, (const xmlChar *)"d:href") ||
+                                                       !xmlStrcmp(nodeLevel6->name, (const xmlChar *)"D:href")
+                                                       ){
+                       
+                                                               // Found the <href> part so extract the principal URL address.
+                                                               
+                                                               for (nodeLevel7 = nodeLevel6->children;
+                                                               nodeLevel7 != NULL;
+                                                               nodeLevel7 = nodeLevel7->next)
+                                                               {
+                                                               
+                                                                       AddressBookHomeURI = ((const char*)nodeLevel7->content);
+
+                                                               }
+                       
+                                                       }
+                       
+                                               }
+                       
+                                       }
+                       
+                               }
+                       
+                       }
+               
+               }
+               
+       }
+       
+       xmlFreeDoc(xmlCardDAVDoc);
+       
+       return AddressBookHomeURI;
+       
+}
+
+std::string CardDAV2::GetDefaultAddressBookURI(){
+       
+       xmlDocPtr xmlCardDAVDoc;
+       xmlCardDAVDoc = xmlReadMemory(PageData.c_str(), (int)PageData.size(), "noname.xml", NULL, 0);
+       string DefaultAddressBookURI = "";
+       
+       xmlNodePtr nodeLevel1;
+       xmlNodePtr nodeLevel2;
+       xmlNodePtr nodeLevel3;
+       xmlNodePtr nodeLevel4;
+       xmlNodePtr nodeLevel5;
+       xmlNodePtr nodeLevel6;
+       xmlNodePtr nodeLevel7;
+               
+       for (nodeLevel1 = xmlCardDAVDoc->children;
+               nodeLevel1 != NULL;
+               nodeLevel1 = nodeLevel1->next)
+       {
+
+               for (nodeLevel2 = nodeLevel1->children;
+                       nodeLevel2 != NULL;
+                       nodeLevel2 = nodeLevel2->next)
+               {
+
+
+                       for (nodeLevel3 = nodeLevel2->children;
+                       nodeLevel3 != NULL;
+                       nodeLevel3 = nodeLevel3->next)
+                       {
+                       
+                               for (nodeLevel4 = nodeLevel3->children;
+                               nodeLevel4 != NULL;
+                               nodeLevel4 = nodeLevel4->next)
+                               {
+                       
+                                       for (nodeLevel5 = nodeLevel4->children;
+                                       nodeLevel5 != NULL;
+                                       nodeLevel5 = nodeLevel5->next)
+                                       {
+                       
+                                               for (nodeLevel6 = nodeLevel5->children;
+                                               nodeLevel6 != NULL;
+                                               nodeLevel6 = nodeLevel6->next)
+                                               {
+                       
+                                                       if (!xmlStrcmp(nodeLevel6->name, (const xmlChar *)"href") ||
+                                                       !xmlStrcmp(nodeLevel6->name, (const xmlChar *)"d:href") ||
+                                                       !xmlStrcmp(nodeLevel6->name, (const xmlChar *)"D:href")
+                                                       ){
+                       
+                                                               // Found the <href> part so extract the principal URL address.
+                                                               
+                                                               for (nodeLevel7 = nodeLevel6->children;
+                                                               nodeLevel7 != NULL;
+                                                               nodeLevel7 = nodeLevel7->next)
+                                                               {
+                                                               
+                                                                       DefaultAddressBookURI = ((const char*)nodeLevel7->content);
+
+                                                               }
+                       
+                                                       }
+                       
+                                               }
+                       
+                                       }
+                       
+                               }
+                       
+                       }
+               
+               }
+               
+       }
+       
+       xmlFreeDoc(xmlCardDAVDoc);
+       
+       return DefaultAddressBookURI;
+       
+}
+
+COServerResponse CardDAV2::AddContact(std::string Location, std::string Data){
+       
+}
+
+COServerResponse CardDAV2::EditContact(std::string Location, std::string Data){
+       
+}
+
+COServerResponse CardDAV2::DeleteContact(std::string Location, std::string EntityTag){
+       
+}
+
+COServerResponse CardDAV2::GetServerEntityTagValue(std::string Location){
+       
+}
+
+COServerResponse CardDAV2::GetContact(std::string Location){
+       
+}
+
+COContactList CardDAV2::GetContactList(std::string SyncToken){
+       
+}
+       
+bool CardDAV2::CanDoProcessing(){
+       return CanProcess;
+}
+
+bool CardDAV2::CanDoSSL(){
+       return SSLStatus;
+}
+
+COSSLVerified CardDAV2::SSLVerify(){
+       return SSLVerified;
+}
+
+bool CardDAV2::AbleToLogin(){
+       return AuthPassed;
+}
+
+bool CardDAV2::HasValidResponse(){
+       return ValidResponse;
+}
+
+bool CardDAV2::IsSelfSigned(){
+       return SSLSelfSigned;
+}
+
+void CardDAV2::SetupDefaultParametersNonSSL(bool DoAuthentication){
+       
+       std::string ServerAddress = "";
+
+       string ServerAddressURL = "http://" + ServerAddress + ":" + to_string(ServerPort) + "/";
+       string UsernamePassword = ServerUser + ":" + ServerPass;
+       
+       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_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_CUSTOMREQUEST, "GET");
+       
+       if (DoAuthentication == true){
+               curl_easy_setopt(ConnectionSession, CURLOPT_USERPWD, UsernamePassword.c_str());
+       } else {
+               curl_easy_setopt(ConnectionSession, CURLOPT_USERPWD, ":");              
+       }
+       
+}
+
+void CardDAV2::SetupDefaultParametersSSL(bool DoAuthentication){
+       
+       // Setup the default parameters.
+       
+       string ServerAddressURL = "https://" + ServerAddress + ":" + to_string(ServerPort) + "/";
+       string UsernamePassword = ServerUser + ":" + ServerPass;
+       
+       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_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_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");
+       
+       if (DoAuthentication == true){
+               curl_easy_setopt(ConnectionSession, CURLOPT_USERPWD, UsernamePassword.c_str());
+       } else {
+               curl_easy_setopt(ConnectionSession, CURLOPT_USERPWD, ":");              
+       }
+       
+       if (EnableSSLBypass == true){
+               curl_easy_setopt(ConnectionSession, CURLOPT_SSL_VERIFYHOST, 0);
+               curl_easy_setopt(ConnectionSession, CURLOPT_SSL_VERIFYPEER, 0);
+       } else {
+               curl_easy_setopt(ConnectionSession, CURLOPT_SSL_VERIFYHOST, 2);
+               curl_easy_setopt(ConnectionSession, CURLOPT_SSL_VERIFYPEER, 1);         
+       }
+       
+}
+
+string CardDAV2::BuildURL(string URI){
+       
+       string ServerAddressURL;
+       
+       if (SSLStatus == true){
+               ServerAddressURL = "https://" + ServerAddress + ":" + to_string(ServerPort) + URI;      
+       } else {
+               ServerAddressURL = "https://" + ServerAddress + ":" + to_string(ServerPort) + URI;
+       }
+       
+       return ServerAddressURL;
+       
+}
+
+string CardDAV2::GetErrorMessage(){
+       
+       ErrorMessage = SessionErrorBuffer;      
+       return ErrorMessage;
+       
+}
+
+void CardDAV2::ResetResults(){
+       
+       SSLStatus = false;
+       COSSLVerified SSLVerified = COSSL_NORESULT;
+       ValidResponse = false;
+       AuthPassed = false;
+       CanProcess = false;
+       SSLSelfSigned = false;
+       TaskCompleted = false;
+       ErrorMessage = "";
+       SessionErrorBuffer[0] = '\0';
+       PageData = "";
+       PageHeader = "";
+       
+}
+
+vector<string> CardDAV2::GetDAVHeader(){
+       
+       // Go through each of the lines looking for the
+       // 'DAV:' section.
+       
+       
+       string HeaderName;
+       string HeaderValue;
+       bool DAVFound = false;
+       bool FastForward = false;
+       vector<string> DAVHeaderList;
+       
+       for (int HeaderSeek = 0; HeaderSeek < PageHeader.size(); HeaderSeek++){
+               
+               if (FastForward == true){
+                       
+                       if (PageHeader[HeaderSeek] == '\n'){
+                               FastForward = false;
+                       }
+                       
+                       continue;
+                       
+               }
+               
+               try {
+                       PageHeader.substr(HeaderSeek, 4) == "DAV:";
+               }
+               
+               catch (const out_of_range &oor){
+                       break;
+               }
+               
+               if (PageHeader.substr(HeaderSeek, 4) == "DAV:"){
+                       
+                       int CharacterSeek = 5;
+                       
+                       while ((HeaderSeek + CharacterSeek) < PageHeader.size()){
+                               
+                               if (PageHeader.substr((HeaderSeek + CharacterSeek), 2) == "\r\n"){
+                                       break;
+                               }
+                               
+                               HeaderValue += PageHeader.substr((HeaderSeek + CharacterSeek), 1);
+                               CharacterSeek++;
+                       }
+                       
+                       break;
+                       
+               } else {
+                       
+                       FastForward = true;
+                       continue;
+                       
+               }
+               
+               if (PageHeader[HeaderSeek] == '\n'){
+                       HeaderName = "";
+               }
+               
+               //HeaderName += PageHeader.substr(HeaderSeek, 1);
+               
+       }
+       
+       // Split the header data.
+       
+       std::string DAVHeaderValue;
+       
+       for (int HeaderSeek = 0; HeaderSeek < HeaderValue.size(); HeaderSeek++){
+               
+               if (HeaderValue.substr(HeaderSeek, 1) == ","){
+                       DAVHeaderList.push_back(DAVHeaderValue);
+                       DAVHeaderValue = "";
+                       HeaderSeek++;
+                       continue;
+               }
+               
+               DAVHeaderValue += HeaderValue[HeaderSeek];
+               
+       }
+       
+       if (DAVHeaderValue.size() > 0){
+               
+               DAVHeaderList.push_back(DAVHeaderValue);
+               
+       }
+       
+       return DAVHeaderList;
+       
+}
\ No newline at end of file
diff --git a/source/carddav2/carddav2.h b/source/carddav2/carddav2.h
new file mode 100644 (file)
index 0000000..0c41fdb
--- /dev/null
@@ -0,0 +1,111 @@
+// CardDAV2.h - CardDAV v2 class header
+//
+// (c) 2012-2016 Xestia Software Development.
+//
+// This file is part of Xestia Address Book.
+//
+// Xestia Address Book is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by the
+// Free Software Foundation, version 3 of the license.
+//
+// Xestia Address Book is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with Xestia Address Book. If not, see <http://www.gnu.org/licenses/> 
+
+#ifndef __CARDDAV2_CARDDAV2_H__
+#define __CARDDAV2_CARDDAV2_H__
+
+#include "../connobject/ConnectionObject.h"
+#include "../version.h"
+#include "../common/sslcertstructs.h"
+
+#include <curl/curl.h>
+#include <wx/tokenzr.h>
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+
+#include <string>
+#include <vector>
+
+class CardDAV2 : public ConnectionObject {
+       
+       public:
+       
+               using ConnectionObject::ConnectionObject;
+       
+               // Destructor.
+       
+               ~CardDAV2();
+       
+               // Functions from the ConnectionObject interface.
+       
+               void SetupConnectionObject();
+               
+               bool IsTaskCompleted();
+               
+               COConnectResult Connect(bool DoAuthentication);
+               
+               COServerResponse GetDefaultPrefix(std::string *ServerPrefix);
+               COServerResponse AddContact(std::string Location, std::string Data);
+               COServerResponse EditContact(std::string Location, std::string Data);
+               COServerResponse DeleteContact(std::string Location, std::string EntityTag);
+               COServerResponse GetServerEntityTagValue(std::string Location);
+               COServerResponse GetContact(std::string Location);
+               COContactList GetContactList(std::string SyncToken);
+       
+               bool CanDoProcessing();
+               bool CanDoSSL();
+               COSSLVerified SSLVerify();
+               bool AbleToLogin();
+               bool HasValidResponse();
+               bool IsSelfSigned();
+               std::string GetErrorMessage();
+
+               void BypassSSLVerification(bool EnableBypass);
+
+#if defined(__APPLE__)
+#elif defined(__WIN32__)
+#else
+               SSLCertCollectionString BuildSSLCollection();
+
+#endif
+       
+       protected:
+       private:
+               
+               // Variables to set for the CardDAV2 class.
+               
+               CURL *ConnectionSession = nullptr;
+               CURLcode SessionResult = CURLE_OK;
+       
+               void SetupDefaultParametersNonSSL(bool DoAuthentication);
+               void SetupDefaultParametersSSL(bool DoAuthentication);
+       
+               std::string PageData;
+               std::string PageHeader;
+               char SessionErrorBuffer[CURL_ERROR_SIZE];
+       
+               static size_t WritebackFunc(char *ptr, size_t size, size_t nmemb, void *stream);
+               size_t WritebackFuncImplementation(char *ptr, size_t size, size_t nmemb, void *stream);
+       
+               std::string BuildURL(std::string URI);
+               void ResetResults();
+               std::vector<std::string> GetDAVHeader();
+       
+               std::string GetUserPrincipalURI();
+               std::string GetAddressBookHomeURI();
+               std::string GetDefaultAddressBookURI();
+       
+#if defined(__APPLE__)
+#elif defined(__WIN32__)
+#else
+               bool EnableSSLBypass = false;
+#endif
+       
+};
+
+#endif
\ No newline at end of file
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