1 // CardDAV2.cpp - CardDAV v2 class
3 // (c) 2012-2016 Xestia Software Development.
5 // This file is part of Xestia Address Book.
7 // Xestia Address Book is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License as published by the
9 // Free Software Foundation, version 3 of the license.
11 // Xestia Address Book is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License along
17 // with Xestia Address Book. If not, see <http://www.gnu.org/licenses/>
25 size_t CardDAV2::WritebackFunc(char *ptr, size_t size, size_t nmemb, void *stream){
27 return static_cast<CardDAV2*>(stream)->WritebackFuncImplementation(ptr, size, nmemb, stream);
31 size_t CardDAV2::WritebackFuncImplementation(char *ptr, size_t size, size_t nmemb, void *stream){
33 // Writeback function for the CardDAV object.
35 string *data = static_cast<string*>(stream);
38 // Get the SSL engine pointer and trust if required on certain operating systems.
42 #if defined(__APPLE__)
44 const struct curl_tlssessioninfo *TLSInfo;
46 CURL *Connection = GetConnectionObject();
47 TLSCode = curl_easy_getinfo(Connection, CURLINFO_TLS_SSL_PTR, &TLSInfo);
49 if (TLSInfo->internals != nullptr && TLSCode == CURLE_OK){
50 SSLCopyPeerTrust((SSLContext*)TLSInfo->internals, &SecTrustObject);
53 #elif defined(__WIN32__)
55 const struct curl_tlssessioninfo *TLSInfo;
57 CURL *Connection = GetConnectionObject();
58 TLSCode = curl_easy_getinfo(Connection, CURLINFO_TLS_SSL_PTR, &TLSInfo);
60 if (TLSInfo->internals != nullptr && TLSCode == CURLE_OK){
62 // Free the previous certificate data.
64 CertFreeCertificateContext(CertificateData);
66 PCtxtHandle SSLHandle = (PCtxtHandle)TLSInfo->internals;
67 SECURITY_STATUS GetData = QueryContextAttributes(SSLHandle, SECPKG_ATTR_REMOTE_CERT_CONTEXT, &CertificateData);
79 CardDAV2::~CardDAV2(){
80 curl_easy_cleanup(ConnectionSession);
81 ConnectionSession = nullptr;
84 #if defined(__APPLE__)
86 #elif defined(__WIN32__)
90 SSLCertCollectionString CardDAV2::BuildSSLCollection(){
92 // Build and return the SSL collection.
94 SSLCertCollectionString SSLCertInfo;
96 // Grab the certificate data.
99 struct curl_slist *certdata;
100 struct curl_certinfo *certinfo;
103 certptr.certdata = NULL;
105 curl_easy_getinfo(ConnectionSession, CURLINFO_CERTINFO, &certptr.certinfo);
107 std::string CertPropName;
108 std::string CertPropValue;
110 for (int i = 0; i < certptr.certinfo->num_of_certs; i++){
112 struct curl_slist *slist;
113 SSLCertDataString SSLCertDataInc;
115 for (slist = certptr.certinfo->certinfo[i]; slist; slist = slist->next){
117 // Using wxStringTokenizer from wxWidgets.
119 wxStringTokenizer CertDataInc(wxString::FromUTF8(slist->data), ":");
121 // Get first token as the property name.
123 CertPropName = CertDataInc.GetNextToken().ToStdString();
125 // Get remaining tokens as the property value.
127 while(CertDataInc.HasMoreTokens()){
129 CertPropValue.append(CertDataInc.GetNextToken());
133 SSLCertDataInc.CertData.insert(std::make_pair(CertPropName, CertPropValue));
134 CertPropName.clear();
135 CertPropValue.clear();
139 SSLCertInfo.SSLCollection.insert(std::make_pair(i, SSLCertDataInc));
147 void CardDAV2::BypassSSLVerification(bool EnableBypass){
148 EnableSSLBypass = EnableBypass;
149 SSLSelfSigned = EnableBypass;
154 void CardDAV2::SetupConnectionObject(){
155 ConnectionSession = curl_easy_init();
158 bool CardDAV2::IsTaskCompleted(){
162 COConnectResult CardDAV2::Connect(bool DoAuthentication){
164 ServerSSL ? SetupDefaultParametersSSL(DoAuthentication) : SetupDefaultParametersNonSSL(DoAuthentication);
167 COConnectResult ConnectResult = COCONNECT_UNITTESTFAIL;
168 string ServerAddressURL = BuildURL("/principals/");
170 curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str());
172 if (TestMode == true){
173 SessionResult = curl_easy_perform(ConnectionSession);
178 switch(SessionResult){
181 SSLVerified = COSSL_VERIFIED;
182 ConnectResult = COCONNECT_OK;
184 case CURLE_SSL_CACERT:
185 case CURLE_SSL_CONNECT_ERROR:
187 ConnectResult = COCONNECT_OK;
188 SSLVerified = COSSL_UNABLETOVERIFY;
191 ConnectResult = COCONNECT_INVALID;
195 // Check if an error occured before continuing.
197 // Check if authentication was successful.
199 long SessionResponseCode = 0;
201 curl_easy_getinfo(ConnectionSession, CURLINFO_RESPONSE_CODE, &SessionResponseCode);
203 if (DoAuthentication == true){
205 // Get the HTTP status code (Should be 200 and not 403).
206 // Return error otherwise.
208 if (SessionResponseCode == 200){
209 ConnectResult = COCONNECT_OK;
211 ValidResponse = true;
212 } else if (SessionResponseCode == 403){
213 ConnectResult = COCONNECT_AUTHFAIL;
215 ValidResponse = true;
216 } else if (SessionResponseCode >= 200) {
217 ConnectResult = COCONNECT_INVALID;
219 ValidResponse = true;
221 ConnectResult = COCONNECT_INVALID;
223 ValidResponse = false;
228 ValidResponse = true;
232 // Check the header to see if CardDAV is supported.
234 vector<string> DAVHeaderValues = GetDAVHeader();
236 for (vector<string>::iterator DAVHeaderValuesIter = DAVHeaderValues.begin();
237 DAVHeaderValuesIter != DAVHeaderValues.end(); DAVHeaderValuesIter++){
239 if ((*DAVHeaderValuesIter) == "addressbook"){
246 return ConnectResult;
250 COServerResponse CardDAV2::GetDefaultPrefix(string *ServerPrefix){
252 // Check if authentication was successful, otherwise don't do anything.
254 COServerResponse ServerResponse;
256 if (AuthPassed == false){
257 ServerResponse.RequestResult = COREQUEST_ERROR_NOTCONNECTED;
258 ServerResponse.EntityTag = "";
259 ServerResponse.SessionCode = 0;
260 ServerResponse.ResultCode = 0;
261 ServerResponse.ResultMessage = "";
262 return ServerResponse;
265 ServerSSL ? SetupDefaultParametersSSL(true) : SetupDefaultParametersNonSSL(true);
268 // Need to do three requests:
270 // 1. Get the current user principal URI.
271 // 2. Get the address book home URI.
272 // 3. Get the default address book URI.
274 // Setup the first query finding out where the principal URL is.
276 const char* CurrentUserPrincipalXMLQuery = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
277 "<D:propfind xmlns:D=\"DAV:\">\n"
279 " <D:current-user-principal/>\n"
283 // Setup the second query finding out where the address book home URL is.
285 const char* AddressBookHomeXMLQuery = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
286 "<D:propfind xmlns:D=\"DAV:\""
287 " xmlns:C=\"urn:ietf:params:xml:ns:carddav\">\n"
289 " <C:addressbook-home-set/>\n"
293 // Setup the third query finding out where the default address book URL is.
295 const char* DefaultAddressBookXMLQuery = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
296 "<D:propfind xmlns:D=\"DAV:\""
297 " xmlns:C=\"urn:ietf:params:xml:ns:carddav\">\n"
299 " <C:default-addressbook-URL/>\n"
303 string ServerAddressURL = BuildURL("/principals/");
304 curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str());
305 curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "PROPFIND");
306 curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDS, CurrentUserPrincipalXMLQuery);
307 curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDSIZE, strlen(CurrentUserPrincipalXMLQuery));
309 if (TestMode == true){
310 SessionResult = curl_easy_perform(ConnectionSession);
315 switch(SessionResult){
318 SSLVerified = COSSL_VERIFIED;
320 case CURLE_SSL_CACERT:
321 case CURLE_SSL_CONNECT_ERROR:
323 SSLVerified = COSSL_UNABLETOVERIFY;
329 long SessionResponseCode = 0;
331 curl_easy_getinfo(ConnectionSession, CURLINFO_RESPONSE_CODE, &SessionResponseCode);
333 if (SessionResponseCode == 200 || SessionResponseCode == 207){
335 ValidResponse = true;
336 } else if (SessionResponseCode == 403){
338 ValidResponse = true;
339 } else if (SessionResponseCode >= 200) {
341 ValidResponse = true;
344 ValidResponse = false;
347 if (ValidResponse == false && AuthPassed == false){
348 ServerResponse.RequestResult = COREQUEST_ERROR_SERVER;
349 ServerResponse.EntityTag = "";
350 ServerResponse.SessionCode = SessionResult;
351 ServerResponse.ResultCode = SessionResponseCode;
352 ServerResponse.ResultMessage = "";
353 return ServerResponse;
356 // Process the first response.
358 string UserPrincipalURI = GetUserPrincipalURI();
360 // Cleanup and reset for the second connection.
362 ServerSSL ? SetupDefaultParametersSSL(true) : SetupDefaultParametersNonSSL(true);
365 ServerAddressURL = BuildURL(UserPrincipalURI);
366 curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str());
367 curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "PROPFIND");
368 curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDS, AddressBookHomeXMLQuery);
369 curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDSIZE, strlen(AddressBookHomeXMLQuery));
371 if (TestMode == true){
372 SessionResult = curl_easy_perform(ConnectionSession);
377 switch(SessionResult){
380 SSLVerified = COSSL_VERIFIED;
382 case CURLE_SSL_CACERT:
383 case CURLE_SSL_CONNECT_ERROR:
385 SSLVerified = COSSL_UNABLETOVERIFY;
391 SessionResponseCode = 0;
393 curl_easy_getinfo(ConnectionSession, CURLINFO_RESPONSE_CODE, &SessionResponseCode);
395 if (SessionResponseCode == 200 || SessionResponseCode == 207){
396 //ConnectResult = COCONNECT_OK;
398 ValidResponse = true;
399 } else if (SessionResponseCode == 403){
400 //ConnectResult = COCONNECT_AUTHFAIL;
402 ValidResponse = true;
403 } else if (SessionResponseCode >= 200) {
404 //ConnectResult = COCONNECT_INVALID;
406 ValidResponse = true;
408 //ConnectResult = COCONNECT_INVALID;
410 ValidResponse = false;
413 if (ValidResponse == false && AuthPassed == false){
414 ServerResponse.RequestResult = COREQUEST_ERROR_SERVER;
415 ServerResponse.EntityTag = "";
416 ServerResponse.SessionCode = SessionResult;
417 ServerResponse.ResultCode = SessionResponseCode;
418 ServerResponse.ResultMessage = "";
419 return ServerResponse;
422 // Process the second response.
424 string AddressBookHomeURI = GetAddressBookHomeURI();
426 // Cleanup and reset for the second connection.
428 ServerSSL ? SetupDefaultParametersSSL(true) : SetupDefaultParametersNonSSL(true);
431 ServerAddressURL = BuildURL(AddressBookHomeURI);
432 curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str());
433 curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "PROPFIND");
434 curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDS, DefaultAddressBookXMLQuery);
435 curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDSIZE, strlen(DefaultAddressBookXMLQuery));
437 if (TestMode == true){
438 SessionResult = curl_easy_perform(ConnectionSession);
443 switch(SessionResult){
446 SSLVerified = COSSL_VERIFIED;
448 case CURLE_SSL_CACERT:
449 case CURLE_SSL_CONNECT_ERROR:
451 SSLVerified = COSSL_UNABLETOVERIFY;
457 SessionResponseCode = 0;
459 curl_easy_getinfo(ConnectionSession, CURLINFO_RESPONSE_CODE, &SessionResponseCode);
461 if (SessionResponseCode == 200 || SessionResponseCode == 207){
463 ValidResponse = true;
464 } else if (SessionResponseCode == 403){
466 ValidResponse = true;
467 } else if (SessionResponseCode >= 200) {
469 ValidResponse = true;
472 ValidResponse = false;
475 if (ValidResponse == false && AuthPassed == false){
476 ServerResponse.RequestResult = COREQUEST_ERROR_SERVER;
477 ServerResponse.EntityTag = "";
478 ServerResponse.SessionCode = SessionResult;
479 ServerResponse.ResultCode = SessionResponseCode;
480 ServerResponse.ResultMessage = "";
481 return ServerResponse;
484 // Process the second response.
486 (*ServerPrefix) = GetDefaultAddressBookURI();
490 ServerResponse.RequestResult = COREQUEST_OK;
491 ServerResponse.EntityTag = "";
492 ServerResponse.SessionCode = SessionResult;
493 ServerResponse.ResultCode = SessionResponseCode;
494 ServerResponse.ResultMessage = SessionErrorBuffer;
495 return ServerResponse;
499 std::string CardDAV2::GetUserPrincipalURI(){
501 xmlDocPtr xmlCardDAVDoc;
502 xmlCardDAVDoc = xmlReadMemory(PageData.c_str(), (int)PageData.size(), "noname.xml", NULL, 0);
503 string UserPrincipalURI = "";
505 xmlNodePtr nodeLevel1;
506 xmlNodePtr nodeLevel2;
507 xmlNodePtr nodeLevel3;
508 xmlNodePtr nodeLevel4;
509 xmlNodePtr nodeLevel5;
510 xmlNodePtr nodeLevel6;
511 xmlNodePtr nodeLevel7;
513 for (nodeLevel1 = xmlCardDAVDoc->children;
515 nodeLevel1 = nodeLevel1->next)
518 for (nodeLevel2 = nodeLevel1->children;
520 nodeLevel2 = nodeLevel2->next)
524 for (nodeLevel3 = nodeLevel2->children;
526 nodeLevel3 = nodeLevel3->next)
529 for (nodeLevel4 = nodeLevel3->children;
531 nodeLevel4 = nodeLevel4->next)
534 for (nodeLevel5 = nodeLevel4->children;
536 nodeLevel5 = nodeLevel5->next)
539 for (nodeLevel6 = nodeLevel5->children;
541 nodeLevel6 = nodeLevel6->next)
544 if (!xmlStrcmp(nodeLevel6->name, (const xmlChar *)"href") ||
545 !xmlStrcmp(nodeLevel6->name, (const xmlChar *)"d:href") ||
546 !xmlStrcmp(nodeLevel6->name, (const xmlChar *)"D:href")
549 // Found the <href> part so extract the principal URL address.
551 for (nodeLevel7 = nodeLevel6->children;
553 nodeLevel7 = nodeLevel7->next)
556 UserPrincipalURI = ((const char*)nodeLevel7->content);
574 xmlFreeDoc(xmlCardDAVDoc);
576 return UserPrincipalURI;
580 std::string CardDAV2::GetAddressBookHomeURI(){
582 xmlDocPtr xmlCardDAVDoc;
583 xmlCardDAVDoc = xmlReadMemory(PageData.c_str(), (int)PageData.size(), "noname.xml", NULL, 0);
584 string AddressBookHomeURI = "";
586 xmlNodePtr nodeLevel1;
587 xmlNodePtr nodeLevel2;
588 xmlNodePtr nodeLevel3;
589 xmlNodePtr nodeLevel4;
590 xmlNodePtr nodeLevel5;
591 xmlNodePtr nodeLevel6;
592 xmlNodePtr nodeLevel7;
594 for (nodeLevel1 = xmlCardDAVDoc->children;
596 nodeLevel1 = nodeLevel1->next)
599 for (nodeLevel2 = nodeLevel1->children;
601 nodeLevel2 = nodeLevel2->next)
605 for (nodeLevel3 = nodeLevel2->children;
607 nodeLevel3 = nodeLevel3->next)
610 for (nodeLevel4 = nodeLevel3->children;
612 nodeLevel4 = nodeLevel4->next)
615 for (nodeLevel5 = nodeLevel4->children;
617 nodeLevel5 = nodeLevel5->next)
620 for (nodeLevel6 = nodeLevel5->children;
622 nodeLevel6 = nodeLevel6->next)
625 if (!xmlStrcmp(nodeLevel6->name, (const xmlChar *)"href") ||
626 !xmlStrcmp(nodeLevel6->name, (const xmlChar *)"d:href") ||
627 !xmlStrcmp(nodeLevel6->name, (const xmlChar *)"D:href")
630 // Found the <href> part so extract the principal URL address.
632 for (nodeLevel7 = nodeLevel6->children;
634 nodeLevel7 = nodeLevel7->next)
637 AddressBookHomeURI = ((const char*)nodeLevel7->content);
655 xmlFreeDoc(xmlCardDAVDoc);
657 return AddressBookHomeURI;
661 std::string CardDAV2::GetDefaultAddressBookURI(){
663 xmlDocPtr xmlCardDAVDoc;
664 xmlCardDAVDoc = xmlReadMemory(PageData.c_str(), (int)PageData.size(), "noname.xml", NULL, 0);
665 string DefaultAddressBookURI = "";
667 xmlNodePtr nodeLevel1;
668 xmlNodePtr nodeLevel2;
669 xmlNodePtr nodeLevel3;
670 xmlNodePtr nodeLevel4;
671 xmlNodePtr nodeLevel5;
672 xmlNodePtr nodeLevel6;
673 xmlNodePtr nodeLevel7;
675 for (nodeLevel1 = xmlCardDAVDoc->children;
677 nodeLevel1 = nodeLevel1->next)
680 for (nodeLevel2 = nodeLevel1->children;
682 nodeLevel2 = nodeLevel2->next)
686 for (nodeLevel3 = nodeLevel2->children;
688 nodeLevel3 = nodeLevel3->next)
691 for (nodeLevel4 = nodeLevel3->children;
693 nodeLevel4 = nodeLevel4->next)
696 for (nodeLevel5 = nodeLevel4->children;
698 nodeLevel5 = nodeLevel5->next)
701 for (nodeLevel6 = nodeLevel5->children;
703 nodeLevel6 = nodeLevel6->next)
706 if (!xmlStrcmp(nodeLevel6->name, (const xmlChar *)"href") ||
707 !xmlStrcmp(nodeLevel6->name, (const xmlChar *)"d:href") ||
708 !xmlStrcmp(nodeLevel6->name, (const xmlChar *)"D:href")
711 // Found the <href> part so extract the principal URL address.
713 for (nodeLevel7 = nodeLevel6->children;
715 nodeLevel7 = nodeLevel7->next)
718 DefaultAddressBookURI = ((const char*)nodeLevel7->content);
736 xmlFreeDoc(xmlCardDAVDoc);
738 return DefaultAddressBookURI;
742 COServerResponse CardDAV2::AddContact(std::string Location, std::string Data){
746 COServerResponse CardDAV2::EditContact(std::string Location, std::string Data){
750 COServerResponse CardDAV2::DeleteContact(std::string Location, std::string EntityTag){
754 COServerResponse CardDAV2::GetServerEntityTagValue(std::string Location){
758 COServerResponse CardDAV2::GetContact(std::string Location){
762 COContactList CardDAV2::GetContactList(std::string SyncToken){
766 bool CardDAV2::CanDoProcessing(){
770 bool CardDAV2::CanDoSSL(){
774 COSSLVerified CardDAV2::SSLVerify(){
778 bool CardDAV2::AbleToLogin(){
782 bool CardDAV2::HasValidResponse(){
783 return ValidResponse;
786 bool CardDAV2::IsSelfSigned(){
787 return SSLSelfSigned;
790 void CardDAV2::SetupDefaultParametersNonSSL(bool DoAuthentication){
792 std::string ServerAddress = "";
794 string ServerAddressURL = "http://" + ServerAddress + ":" + to_string(ServerPort) + "/";
795 string UsernamePassword = ServerUser + ":" + ServerPass;
797 curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddress.c_str());
798 curl_easy_setopt(ConnectionSession, CURLOPT_NOPROGRESS, 1L);
799 curl_easy_setopt(ConnectionSession, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
800 curl_easy_setopt(ConnectionSession, CURLOPT_TIMEOUT, 60);
801 curl_easy_setopt(ConnectionSession, CURLOPT_FAILONERROR, true);
802 curl_easy_setopt(ConnectionSession, CURLOPT_USERAGENT, XSDAB_USERAGENT);
803 curl_easy_setopt(ConnectionSession, CURLOPT_WRITEFUNCTION, CardDAV2::WritebackFunc);
804 curl_easy_setopt(ConnectionSession, CURLOPT_WRITEDATA, &PageData);
805 curl_easy_setopt(ConnectionSession, CURLOPT_WRITEHEADER, &PageHeader);
806 curl_easy_setopt(ConnectionSession, CURLOPT_NOSIGNAL, 1);
807 curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "GET");
809 if (DoAuthentication == true){
810 curl_easy_setopt(ConnectionSession, CURLOPT_USERPWD, UsernamePassword.c_str());
812 curl_easy_setopt(ConnectionSession, CURLOPT_USERPWD, ":");
817 void CardDAV2::SetupDefaultParametersSSL(bool DoAuthentication){
819 // Setup the default parameters.
821 string ServerAddressURL = "https://" + ServerAddress + ":" + to_string(ServerPort) + "/";
822 string UsernamePassword = ServerUser + ":" + ServerPass;
824 curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str());
825 curl_easy_setopt(ConnectionSession, CURLOPT_NOPROGRESS, 1L);
826 curl_easy_setopt(ConnectionSession, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
827 curl_easy_setopt(ConnectionSession, CURLOPT_TIMEOUT, 60);
828 curl_easy_setopt(ConnectionSession, CURLOPT_FAILONERROR, true);
829 curl_easy_setopt(ConnectionSession, CURLOPT_USERAGENT, XSDAB_USERAGENT);
830 curl_easy_setopt(ConnectionSession, CURLOPT_WRITEFUNCTION, CardDAV2::WritebackFunc);
831 curl_easy_setopt(ConnectionSession, CURLOPT_WRITEDATA, &PageData);
832 curl_easy_setopt(ConnectionSession, CURLOPT_WRITEHEADER, &PageHeader);
833 curl_easy_setopt(ConnectionSession, CURLOPT_ERRORBUFFER, SessionErrorBuffer);
834 curl_easy_setopt(ConnectionSession, CURLOPT_NOSIGNAL, 1);
835 curl_easy_setopt(ConnectionSession, CURLOPT_CERTINFO, 1);
836 curl_easy_setopt(ConnectionSession, CURLOPT_VERBOSE, 1);
837 curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "GET");
839 if (DoAuthentication == true){
840 curl_easy_setopt(ConnectionSession, CURLOPT_USERPWD, UsernamePassword.c_str());
842 curl_easy_setopt(ConnectionSession, CURLOPT_USERPWD, ":");
845 if (EnableSSLBypass == true){
846 curl_easy_setopt(ConnectionSession, CURLOPT_SSL_VERIFYHOST, 0);
847 curl_easy_setopt(ConnectionSession, CURLOPT_SSL_VERIFYPEER, 0);
849 curl_easy_setopt(ConnectionSession, CURLOPT_SSL_VERIFYHOST, 2);
850 curl_easy_setopt(ConnectionSession, CURLOPT_SSL_VERIFYPEER, 1);
855 string CardDAV2::BuildURL(string URI){
857 string ServerAddressURL;
859 if (SSLStatus == true){
860 ServerAddressURL = "https://" + ServerAddress + ":" + to_string(ServerPort) + URI;
862 ServerAddressURL = "https://" + ServerAddress + ":" + to_string(ServerPort) + URI;
865 return ServerAddressURL;
869 string CardDAV2::GetErrorMessage(){
871 ErrorMessage = SessionErrorBuffer;
876 void CardDAV2::ResetResults(){
879 COSSLVerified SSLVerified = COSSL_NORESULT;
880 ValidResponse = false;
883 SSLSelfSigned = false;
884 TaskCompleted = false;
886 SessionErrorBuffer[0] = '\0';
892 vector<string> CardDAV2::GetDAVHeader(){
894 // Go through each of the lines looking for the
900 bool DAVFound = false;
901 bool FastForward = false;
902 vector<string> DAVHeaderList;
904 for (int HeaderSeek = 0; HeaderSeek < PageHeader.size(); HeaderSeek++){
906 if (FastForward == true){
908 if (PageHeader[HeaderSeek] == '\n'){
917 PageHeader.substr(HeaderSeek, 4) == "DAV:";
920 catch (const out_of_range &oor){
924 if (PageHeader.substr(HeaderSeek, 4) == "DAV:"){
926 int CharacterSeek = 5;
928 while ((HeaderSeek + CharacterSeek) < PageHeader.size()){
930 if (PageHeader.substr((HeaderSeek + CharacterSeek), 2) == "\r\n"){
934 HeaderValue += PageHeader.substr((HeaderSeek + CharacterSeek), 1);
947 if (PageHeader[HeaderSeek] == '\n'){
951 //HeaderName += PageHeader.substr(HeaderSeek, 1);
955 // Split the header data.
957 std::string DAVHeaderValue;
959 for (int HeaderSeek = 0; HeaderSeek < HeaderValue.size(); HeaderSeek++){
961 if (HeaderValue.substr(HeaderSeek, 1) == ","){
962 DAVHeaderList.push_back(DAVHeaderValue);
968 DAVHeaderValue += HeaderValue[HeaderSeek];
972 if (DAVHeaderValue.size() > 0){
974 DAVHeaderList.push_back(DAVHeaderValue);
978 return DAVHeaderList;