Home | News | Projects | Releases
Bugs | RFE | Repositories | Help
2159b989702346034936db97dde64f2aa04c2ebc
[xestiaab/.git] / source / carddav2 / carddav2.cpp
1 // CardDAV2.cpp - CardDAV v2 class
2 //
3 // (c) 2012-2016 Xestia Software Development.
4 //
5 // This file is part of Xestia Address Book.
6 //
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.
10 //
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.
15 //
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/> 
19 #include "carddav2.h"
21 #include <iostream>
23 using namespace std;
25 size_t CardDAV2::WritebackFunc(char *ptr, size_t size, size_t nmemb, void *stream){
26         
27         return static_cast<CardDAV2*>(stream)->WritebackFuncImplementation(ptr, size, nmemb, stream);
28         
29 }
30         
31 size_t CardDAV2::WritebackFuncImplementation(char *ptr, size_t size, size_t nmemb, void *stream){
32         
33         // Writeback function for the CardDAV object.
34                 
35         string *data = static_cast<string*>(stream);
36         data->append(ptr);
37         
38         // Get the SSL engine pointer and trust if required on certain operating systems.
39         
40         if (ServerSSL){
41         
42 #if defined(__APPLE__)
43         
44                 const struct curl_tlssessioninfo *TLSInfo;
45                 CURLcode TLSCode;
46                 CURL *Connection = GetConnectionObject();
47                 TLSCode = curl_easy_getinfo(Connection, CURLINFO_TLS_SSL_PTR, &TLSInfo);
48         
49                 if (TLSInfo->internals != nullptr && TLSCode == CURLE_OK){
50                         SSLCopyPeerTrust((SSLContext*)TLSInfo->internals, &SecTrustObject);
51                 }
52         
53 #elif defined(__WIN32__)
55                 const struct curl_tlssessioninfo *TLSInfo;
56                 CURLcode TLSCode;
57                 TLSCode = curl_easy_getinfo(ConnectionSession, CURLINFO_TLS_SSL_PTR, &TLSInfo);
59                 if (TLSInfo->internals != nullptr && TLSCode == CURLE_OK){
61                         // Free the previous certificate data.
63                         CertFreeCertificateContext(CertificateData);
65                         PCtxtHandle SSLHandle = (PCtxtHandle)TLSInfo->internals;
66                         SECURITY_STATUS GetData = QueryContextAttributes(SSLHandle, SECPKG_ATTR_REMOTE_CERT_CONTEXT, &CertificateData);
68                 }
70 #endif
72         }
73         
74         return size * nmemb;
76 }
78 CardDAV2::~CardDAV2(){
79         
80         curl_easy_cleanup(ConnectionSession);
81         ConnectionSession = nullptr;
82         
83         if (HeaderList != nullptr){
84                 curl_slist_free_all(HeaderList);
85                 HeaderList = nullptr;
86         }
88 #if defined(__WIN32__)
90         CertFreeCertificateContext(CertificateData);
92 #endif
93         
94 }
96 #if defined(__APPLE__)
98 #elif defined(__WIN32__)
100 PCCERT_CONTEXT CardDAV2::BuildSSLCollection(){
102         return CertificateData;
106 #else
108 SSLCertCollectionString CardDAV2::BuildSSLCollection(){
110         // Build and return the SSL collection.
111         
112         SSLCertCollectionString SSLCertInfo;
114         // Grab the certificate data.
116         union {
117                 struct curl_slist *certdata;
118                 struct curl_certinfo *certinfo;
119         } certptr;
121         certptr.certdata = NULL;
122         
123         curl_easy_getinfo(ConnectionSession, CURLINFO_CERTINFO, &certptr.certinfo);
125         std::string CertPropName;
126         std::string CertPropValue;
128         for (int i = 0; i < certptr.certinfo->num_of_certs; i++){
130                 struct curl_slist *slist;
131                 SSLCertDataString SSLCertDataInc;
132                 
133                 for (slist = certptr.certinfo->certinfo[i]; slist; slist = slist->next){
134                         
135                         // Using wxStringTokenizer from wxWidgets.
136                         
137                         wxStringTokenizer CertDataInc(wxString::FromUTF8(slist->data), ":");
138                         
139                         // Get first token as the property name.
140                         
141                         CertPropName = CertDataInc.GetNextToken().ToStdString();
142                         
143                         // Get remaining tokens as the property value.
144                         
145                         while(CertDataInc.HasMoreTokens()){
146                         
147                                 CertPropValue.append(CertDataInc.GetNextToken());
148                         
149                         }
150                         
151                         SSLCertDataInc.CertData.insert(std::make_pair(CertPropName, CertPropValue));
152                         CertPropName.clear();
153                         CertPropValue.clear();
154                         
155                 }
156         
157                 SSLCertInfo.SSLCollection.insert(std::make_pair(i, SSLCertDataInc));
158         
159         }
160         
161         return SSLCertInfo;
165 void CardDAV2::BypassSSLVerification(bool EnableBypass){
166         EnableSSLBypass = EnableBypass;
167         SSLSelfSigned = EnableBypass;
170 #endif
172 void CardDAV2::SetupConnectionObject(){
173         ConnectionSession = curl_easy_init();
176 bool CardDAV2::IsTaskCompleted(){
177         return false;
180 COConnectResult CardDAV2::Connect(bool DoAuthentication){
181         
182         ServerSSL ? SetupDefaultParametersSSL(DoAuthentication) : SetupDefaultParametersNonSSL(DoAuthentication);
183         ResetResults();
184         
185         COConnectResult ConnectResult = COCONNECT_UNITTESTFAIL;
186         string ServerAddressURL = BuildURL("/principals/");
188         curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str());
189         
190         if (TestMode == true){
191                 SessionResult = curl_easy_perform(ConnectionSession);
192         } else {
193                 SessionResult = curl_easy_perform(ConnectionSession);           
194         }
195         
196         switch(SessionResult){
197                 case CURLE_OK:
198                 case CURLE_HTTP_RETURNED_ERROR:
199                         SSLStatus = true;
200                         SSLVerified = COSSL_VERIFIED;
201                         ConnectResult = COCONNECT_OK;
202                         break;
203                 case CURLE_SSL_CACERT:
204                 case CURLE_SSL_CONNECT_ERROR:
205                         SSLStatus = true;
206                         ConnectResult = COCONNECT_OK;
207                         SSLVerified = COSSL_UNABLETOVERIFY;
208                         break;
209                 default:
210                         ConnectResult = COCONNECT_INVALID;
211                         break;
212         };
213         
214         // Check if an error occured before continuing.
215         
216         // Check if authentication was successful.
217         
218         long SessionResponseCode = 0;
219         
220         curl_easy_getinfo(ConnectionSession, CURLINFO_RESPONSE_CODE, &SessionResponseCode);
221         
222         if (DoAuthentication == true){
223                 
224                 // Get the HTTP status code (Should be 200 and not 403).
225                 // Return error otherwise.
226                 
227                 if (SessionResponseCode == 200){
228                         ConnectResult = COCONNECT_OK;
229                         AuthPassed = true;
230                         ValidResponse = true;
231                 } else if (SessionResponseCode == 401){
232                         ConnectResult = COCONNECT_AUTHFAIL;
233                         AuthPassed = false;
234                         ValidResponse = true;
235                 } else if (SessionResponseCode >= 200) {
236                         ConnectResult = COCONNECT_INVALID;
237                         AuthPassed = false;
238                         ValidResponse = true;
239                 } else {
240                         ConnectResult = COCONNECT_INVALID;
241                         AuthPassed = false;
242                         ValidResponse = false;                  
243                 }
244                 
245         } else {
246                 
247                 ValidResponse = true;
248                 
249         }
250         
251         // Check the header to see if CardDAV is supported.
252         
253         vector<string> DAVHeaderValues = GetDAVHeader();
254         
255         for (vector<string>::iterator DAVHeaderValuesIter = DAVHeaderValues.begin();
256                 DAVHeaderValuesIter != DAVHeaderValues.end(); DAVHeaderValuesIter++){
257                 
258                 if ((*DAVHeaderValuesIter) == "addressbook"){
259                         CanProcess = true;
260                         break;
261                 }
262                         
263         }
264         
265         return ConnectResult;
266         
269 COServerResponse CardDAV2::GetDefaultPrefix(string *ServerPrefix){
271         // Check if authentication was successful, otherwise don't do anything.
273         COServerResponse ServerResponse;
274         
275         if (AuthPassed == false){
276                 ServerResponse.RequestResult = COREQUEST_ERROR_NOTCONNECTED;
277                 ServerResponse.EntityTag = "";
278                 ServerResponse.SessionCode = 0;
279                 ServerResponse.ResultCode = 0;
280                 ServerResponse.ResultMessage = "";
281                 return ServerResponse;
282         }
284         ServerSSL ? SetupDefaultParametersSSL(true) : SetupDefaultParametersNonSSL(true);
285         ResetResults();
286         
287         // Need to do three requests:
288         
289         // 1. Get the current user principal URI.
290         // 2. Get the address book home URI.
291         // 3. Get the default address book URI.
292         
293         // Setup the first query finding out where the principal URL is.
294         
295         const char* CurrentUserPrincipalXMLQuery = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
296                 "<D:propfind xmlns:D=\"DAV:\">\n"
297                 " <D:prop>"
298                 "  <D:current-user-principal/>\n"
299                 " </D:prop>"
300                 "</D:propfind>";
302         // Setup the second query finding out where the address book home URL is.
303         
304         const char* AddressBookHomeXMLQuery = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
305         "<D:propfind xmlns:D=\"DAV:\""
306         "  xmlns:C=\"urn:ietf:params:xml:ns:carddav\">\n"
307         "  <D:prop>\n"
308         "    <C:addressbook-home-set/>\n"
309         "  </D:prop>\n"
310         "</D:propfind>";
311         
312         // Setup the third query finding out where the default address book URL is.
313         
314         const char* DefaultAddressBookXMLQuery = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
315         "<D:propfind xmlns:D=\"DAV:\""
316         "  xmlns:C=\"urn:ietf:params:xml:ns:carddav\">\n"
317         "  <D:prop>\n"
318         "    <C:default-addressbook-URL/>\n"    
319         "  </D:prop>\n"
320         "</D:propfind>";
321         
322         string ServerAddressURL = BuildURL("/principals/");
323         curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str());
324         curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "PROPFIND");
325         curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDS, CurrentUserPrincipalXMLQuery);
326         curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDSIZE, strlen(CurrentUserPrincipalXMLQuery));
327         
328         if (TestMode == true){
329                 SessionResult = curl_easy_perform(ConnectionSession);
330         } else {
331                 
332         }
333         
334         switch(SessionResult){
335                 case CURLE_OK:
336                         SSLStatus = true;
337                         SSLVerified = COSSL_VERIFIED;
338                         break;
339                 case CURLE_SSL_CACERT:
340                 case CURLE_SSL_CONNECT_ERROR:
341                         SSLStatus = true;
342                         SSLVerified = COSSL_UNABLETOVERIFY;
343                         break;
344                 default:
345                         break;
346         };
347         
348         long SessionResponseCode = 0;
349         
350         curl_easy_getinfo(ConnectionSession, CURLINFO_RESPONSE_CODE, &SessionResponseCode);
351         
352         if (SessionResponseCode == 200 || SessionResponseCode == 207){
353                 AuthPassed = true;
354                 ValidResponse = true;
355         } else if (SessionResponseCode == 403){
356                 AuthPassed = false;
357                 ValidResponse = true;
358         } else if (SessionResponseCode >= 400) {
359                 AuthPassed = false;
360                 ValidResponse = true;
361         } else {
362                 AuthPassed = false;
363                 ValidResponse = false;                  
364         }
365         
366         if (ValidResponse == false && AuthPassed == false){
367                 ServerResponse.RequestResult = COREQUEST_ERROR_SERVER;
368                 ServerResponse.EntityTag = "";
369                 ServerResponse.SessionCode = SessionResult;
370                 ServerResponse.ResultCode = SessionResponseCode;
371                 ServerResponse.ResultMessage = "";
372                 return ServerResponse;
373         }
374         
375         // Process the first response.
376         
377         string UserPrincipalURI = GetUserPrincipalURI();
378         
379         // Cleanup and reset for the second connection.
380         
381         ServerSSL ? SetupDefaultParametersSSL(true) : SetupDefaultParametersNonSSL(true);
382         ResetResults();
384         ServerAddressURL = BuildURL(UserPrincipalURI);
385         curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str());
386         curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "PROPFIND");
387         curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDS, AddressBookHomeXMLQuery);
388         curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDSIZE, strlen(AddressBookHomeXMLQuery));
389         
390         if (TestMode == true){
391                 SessionResult = curl_easy_perform(ConnectionSession);
392         } else {
393                 
394         }
395         
396         switch(SessionResult){
397                 case CURLE_OK:
398                         SSLStatus = true;
399                         SSLVerified = COSSL_VERIFIED;
400                         break;
401                 case CURLE_SSL_CACERT:
402                 case CURLE_SSL_CONNECT_ERROR:
403                         SSLStatus = true;
404                         SSLVerified = COSSL_UNABLETOVERIFY;
405                         break;
406                 default:
407                         break;
408         };
409         
410         SessionResponseCode = 0;
411         
412         curl_easy_getinfo(ConnectionSession, CURLINFO_RESPONSE_CODE, &SessionResponseCode);
413         
414         if (SessionResponseCode == 200 || SessionResponseCode == 207){
415                 AuthPassed = true;
416                 ValidResponse = true;
417         } else if (SessionResponseCode == 403){
418                 AuthPassed = false;
419                 ValidResponse = true;
420         } else if (SessionResponseCode >= 400) {
421                 AuthPassed = false;
422                 ValidResponse = true;
423         } else {
424                 AuthPassed = false;
425                 ValidResponse = false;                  
426         }
427         
428         if (ValidResponse == false && AuthPassed == false){
429                 ServerResponse.RequestResult = COREQUEST_ERROR_SERVER;
430                 ServerResponse.EntityTag = "";
431                 ServerResponse.SessionCode = SessionResult;
432                 ServerResponse.ResultCode = SessionResponseCode;
433                 ServerResponse.ResultMessage = "";
434                 return ServerResponse;
435         }
436         
437         // Process the second response.
438         
439         string AddressBookHomeURI = GetAddressBookHomeURI();
440         
441         // Cleanup and reset for the second connection.
442         
443         ServerSSL ? SetupDefaultParametersSSL(true) : SetupDefaultParametersNonSSL(true);
444         ResetResults();
445         
446         ServerAddressURL = BuildURL(AddressBookHomeURI);
447         curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str());
448         curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "PROPFIND");
449         curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDS, DefaultAddressBookXMLQuery);
450         curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDSIZE, strlen(DefaultAddressBookXMLQuery));
451         
452         if (TestMode == true){
453                 SessionResult = curl_easy_perform(ConnectionSession);
454         } else {
455                 
456         }
457         
458         switch(SessionResult){
459                 case CURLE_OK:
460                         SSLStatus = true;
461                         SSLVerified = COSSL_VERIFIED;
462                         break;
463                 case CURLE_SSL_CACERT:
464                 case CURLE_SSL_CONNECT_ERROR:
465                         SSLStatus = true;
466                         SSLVerified = COSSL_UNABLETOVERIFY;
467                         break;
468                 default:
469                         break;
470         };
471         
472         SessionResponseCode = 0;
473         
474         curl_easy_getinfo(ConnectionSession, CURLINFO_RESPONSE_CODE, &SessionResponseCode);
475         
476         if (SessionResponseCode == 200 || SessionResponseCode == 207){
477                 AuthPassed = true;
478                 ValidResponse = true;
479         } else if (SessionResponseCode == 403){
480                 AuthPassed = false;
481                 ValidResponse = true;
482         } else if (SessionResponseCode >= 200) {
483                 AuthPassed = false;
484                 ValidResponse = true;
485         } else {
486                 AuthPassed = false;
487                 ValidResponse = false;                  
488         }
489         
490         if (ValidResponse == false || AuthPassed == false){
491                 ServerResponse.RequestResult = COREQUEST_ERROR_SERVER;
492                 ServerResponse.EntityTag = "";
493                 ServerResponse.SessionCode = SessionResult;
494                 ServerResponse.ResultCode = SessionResponseCode;
495                 ServerResponse.ResultMessage = "";
496                 return ServerResponse;
497         }
498         
499         // Process the second response.
500         
501         (*ServerPrefix) = GetDefaultAddressBookURI();
502         
503         CanProcess = true;
504         
505         ServerResponse.RequestResult = COREQUEST_OK;
506         ServerResponse.EntityTag = "";
507         ServerResponse.SessionCode = SessionResult;
508         ServerResponse.ResultCode = SessionResponseCode;
509         ServerResponse.ResultMessage = SessionErrorBuffer;
510         return ServerResponse;
511         
514 std::string CardDAV2::GetUserPrincipalURI(){
515         
516         xmlDocPtr xmlCardDAVDoc;
517         xmlCardDAVDoc = xmlReadMemory(PageData.c_str(), (int)PageData.size(), "noname.xml", NULL, 0);
518         string UserPrincipalURI = "";
519         
520         xmlNodePtr nodeLevel1;
521         xmlNodePtr nodeLevel2;
522         xmlNodePtr nodeLevel3;
523         xmlNodePtr nodeLevel4;
524         xmlNodePtr nodeLevel5;
525         xmlNodePtr nodeLevel6;
526         xmlNodePtr nodeLevel7;
527                 
528         for (nodeLevel1 = xmlCardDAVDoc->children;
529                 nodeLevel1 != NULL;
530                 nodeLevel1 = nodeLevel1->next)
531         {
533                 for (nodeLevel2 = nodeLevel1->children;
534                         nodeLevel2 != NULL;
535                         nodeLevel2 = nodeLevel2->next)
536                 {
539                         for (nodeLevel3 = nodeLevel2->children;
540                         nodeLevel3 != NULL;
541                         nodeLevel3 = nodeLevel3->next)
542                         {
543                         
544                                 for (nodeLevel4 = nodeLevel3->children;
545                                 nodeLevel4 != NULL;
546                                 nodeLevel4 = nodeLevel4->next)
547                                 {
548                         
549                                         for (nodeLevel5 = nodeLevel4->children;
550                                         nodeLevel5 != NULL;
551                                         nodeLevel5 = nodeLevel5->next)
552                                         {
553                         
554                                                 for (nodeLevel6 = nodeLevel5->children;
555                                                 nodeLevel6 != NULL;
556                                                 nodeLevel6 = nodeLevel6->next)
557                                                 {
558                         
559                                                         if (!xmlStrcmp(nodeLevel6->name, (const xmlChar *)"href") ||
560                                                         !xmlStrcmp(nodeLevel6->name, (const xmlChar *)"d:href") ||
561                                                         !xmlStrcmp(nodeLevel6->name, (const xmlChar *)"D:href")
562                                                         ){
563                         
564                                                                 // Found the <href> part so extract the principal URL address.
565                                                                 
566                                                                 for (nodeLevel7 = nodeLevel6->children;
567                                                                 nodeLevel7 != NULL;
568                                                                 nodeLevel7 = nodeLevel7->next)
569                                                                 {
570                                                                 
571                                                                         UserPrincipalURI = ((const char*)nodeLevel7->content);
573                                                                 }
574                         
575                                                         }
576                         
577                                                 }
578                         
579                                         }
580                         
581                                 }
582                         
583                         }
584                 
585                 }
586                 
587         }
588         
589         xmlFreeDoc(xmlCardDAVDoc);
590         
591         return UserPrincipalURI;
592         
595 std::string CardDAV2::GetAddressBookHomeURI(){
596         
597         xmlDocPtr xmlCardDAVDoc;
598         xmlCardDAVDoc = xmlReadMemory(PageData.c_str(), (int)PageData.size(), "noname.xml", NULL, 0);
599         string AddressBookHomeURI = "";
600         
601         xmlNodePtr nodeLevel1;
602         xmlNodePtr nodeLevel2;
603         xmlNodePtr nodeLevel3;
604         xmlNodePtr nodeLevel4;
605         xmlNodePtr nodeLevel5;
606         xmlNodePtr nodeLevel6;
607         xmlNodePtr nodeLevel7;
608                 
609         for (nodeLevel1 = xmlCardDAVDoc->children;
610                 nodeLevel1 != NULL;
611                 nodeLevel1 = nodeLevel1->next)
612         {
614                 for (nodeLevel2 = nodeLevel1->children;
615                         nodeLevel2 != NULL;
616                         nodeLevel2 = nodeLevel2->next)
617                 {
620                         for (nodeLevel3 = nodeLevel2->children;
621                         nodeLevel3 != NULL;
622                         nodeLevel3 = nodeLevel3->next)
623                         {
624                         
625                                 for (nodeLevel4 = nodeLevel3->children;
626                                 nodeLevel4 != NULL;
627                                 nodeLevel4 = nodeLevel4->next)
628                                 {
629                         
630                                         for (nodeLevel5 = nodeLevel4->children;
631                                         nodeLevel5 != NULL;
632                                         nodeLevel5 = nodeLevel5->next)
633                                         {
634                         
635                                                 for (nodeLevel6 = nodeLevel5->children;
636                                                 nodeLevel6 != NULL;
637                                                 nodeLevel6 = nodeLevel6->next)
638                                                 {
639                         
640                                                         if (!xmlStrcmp(nodeLevel6->name, (const xmlChar *)"href") ||
641                                                         !xmlStrcmp(nodeLevel6->name, (const xmlChar *)"d:href") ||
642                                                         !xmlStrcmp(nodeLevel6->name, (const xmlChar *)"D:href")
643                                                         ){
644                         
645                                                                 // Found the <href> part so extract the principal URL address.
646                                                                 
647                                                                 for (nodeLevel7 = nodeLevel6->children;
648                                                                 nodeLevel7 != NULL;
649                                                                 nodeLevel7 = nodeLevel7->next)
650                                                                 {
651                                                                 
652                                                                         AddressBookHomeURI = ((const char*)nodeLevel7->content);
654                                                                 }
655                         
656                                                         }
657                         
658                                                 }
659                         
660                                         }
661                         
662                                 }
663                         
664                         }
665                 
666                 }
667                 
668         }
669         
670         xmlFreeDoc(xmlCardDAVDoc);
671         
672         return AddressBookHomeURI;
673         
676 std::string CardDAV2::GetDefaultAddressBookURI(){
677         
678         xmlDocPtr xmlCardDAVDoc;
679         xmlCardDAVDoc = xmlReadMemory(PageData.c_str(), (int)PageData.size(), "noname.xml", NULL, 0);
680         string DefaultAddressBookURI = "";
681         
682         xmlNodePtr nodeLevel1;
683         xmlNodePtr nodeLevel2;
684         xmlNodePtr nodeLevel3;
685         xmlNodePtr nodeLevel4;
686         xmlNodePtr nodeLevel5;
687         xmlNodePtr nodeLevel6;
688         xmlNodePtr nodeLevel7;
689                 
690         for (nodeLevel1 = xmlCardDAVDoc->children;
691                 nodeLevel1 != NULL;
692                 nodeLevel1 = nodeLevel1->next)
693         {
695                 for (nodeLevel2 = nodeLevel1->children;
696                         nodeLevel2 != NULL;
697                         nodeLevel2 = nodeLevel2->next)
698                 {
701                         for (nodeLevel3 = nodeLevel2->children;
702                         nodeLevel3 != NULL;
703                         nodeLevel3 = nodeLevel3->next)
704                         {
705                         
706                                 for (nodeLevel4 = nodeLevel3->children;
707                                 nodeLevel4 != NULL;
708                                 nodeLevel4 = nodeLevel4->next)
709                                 {
710                         
711                                         for (nodeLevel5 = nodeLevel4->children;
712                                         nodeLevel5 != NULL;
713                                         nodeLevel5 = nodeLevel5->next)
714                                         {
715                         
716                                                 for (nodeLevel6 = nodeLevel5->children;
717                                                 nodeLevel6 != NULL;
718                                                 nodeLevel6 = nodeLevel6->next)
719                                                 {
720                         
721                                                         if (!xmlStrcmp(nodeLevel6->name, (const xmlChar *)"href") ||
722                                                         !xmlStrcmp(nodeLevel6->name, (const xmlChar *)"d:href") ||
723                                                         !xmlStrcmp(nodeLevel6->name, (const xmlChar *)"D:href")
724                                                         ){
725                         
726                                                                 // Found the <href> part so extract the principal URL address.
727                                                                 
728                                                                 for (nodeLevel7 = nodeLevel6->children;
729                                                                 nodeLevel7 != NULL;
730                                                                 nodeLevel7 = nodeLevel7->next)
731                                                                 {
732                                                                 
733                                                                         DefaultAddressBookURI = ((const char*)nodeLevel7->content);
735                                                                 }
736                         
737                                                         }
738                         
739                                                 }
740                         
741                                         }
742                         
743                                 }
744                         
745                         }
746                 
747                 }
748                 
749         }
750         
751         xmlFreeDoc(xmlCardDAVDoc);
752         
753         return DefaultAddressBookURI;
754         
757 COServerResponse CardDAV2::AddContact(std::string Location, std::string Data){
758         
759         // Check if authentication was successful, otherwise don't do anything.
761         COServerResponse ServerResponse;
762         
763         if (AuthPassed == false){
764                 ServerResponse.RequestResult = COREQUEST_ERROR_NOTCONNECTED;
765                 ServerResponse.EntityTag = "";
766                 ServerResponse.SessionCode = 0;
767                 ServerResponse.ResultCode = 0;
768                 ServerResponse.ResultMessage = "";
769                 return ServerResponse;
770         }
772         ServerSSL ? SetupDefaultParametersSSL(true) : SetupDefaultParametersNonSSL(true);
773         ResetResults();
774         
775         string ServerAddressURL = BuildURL(ServerPrefix + Location);
776         curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str());
777         curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "PUT");
778         curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDS, Data.c_str());
779         curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDSIZE, strlen(Data.c_str()));
780         
781         HeaderList = curl_slist_append(HeaderList, "Content-Type: text/vcard; charset=utf-8");
783         curl_easy_setopt(ConnectionSession, CURLOPT_HTTPHEADER, HeaderList);
784         
785         if (TestMode == true){
786                 SessionResult = curl_easy_perform(ConnectionSession);
787         } else {
788                 SessionResult = curl_easy_perform(ConnectionSession);
789         }
790         
791         switch(SessionResult){
792                 case CURLE_OK:
793                         SSLStatus = true;
794                         SSLVerified = COSSL_VERIFIED;
795                         break;
796                 case CURLE_SSL_CACERT:
797                 case CURLE_SSL_CONNECT_ERROR:
798                         SSLStatus = true;
799                         SSLVerified = COSSL_UNABLETOVERIFY;
800                         break;
801                 default:
802                         break;
803         };
804         
805         long SessionResponseCode = 0;
806         
807         curl_easy_getinfo(ConnectionSession, CURLINFO_RESPONSE_CODE, &SessionResponseCode);
808         
809         if (SessionResponseCode == 200 || SessionResponseCode == 201 || SessionResponseCode == 204){
810                 AuthPassed = true;
811                 ValidResponse = true;
812         } else if (SessionResponseCode == 403){
813                 AuthPassed = false;
814                 ValidResponse = true;
815         } else if (SessionResponseCode >= 400){
816                 AuthPassed = false;
817                 ValidResponse = true;
818         } else {
819                 AuthPassed = false;
820                 ValidResponse = false;                  
821         }
822         
823         if (ValidResponse == false || AuthPassed == false){
824                 ServerResponse.RequestResult = COREQUEST_ERROR_SERVER;
825                 ServerResponse.EntityTag = "";
826                 ServerResponse.SessionCode = SessionResult;
827                 ServerResponse.ResultCode = SessionResponseCode;
828                 ServerResponse.ResultMessage = "";
829                 return ServerResponse;
830         }
831         
832         CanProcess = true;
833         
834         ServerResponse.RequestResult = COREQUEST_OK;
835         ServerResponse.EntityTag = "";
836         ServerResponse.SessionCode = SessionResult;
837         ServerResponse.ResultCode = SessionResponseCode;
838         ServerResponse.ResultMessage = SessionErrorBuffer;
839         return ServerResponse;
840         
843 COServerResponse CardDAV2::EditContact(std::string Location, std::string Data){
845         // Check if authentication was successful, otherwise don't do anything.
847         COServerResponse ServerResponse;
848         
849         if (AuthPassed == false){
850                 ServerResponse.RequestResult = COREQUEST_ERROR_NOTCONNECTED;
851                 ServerResponse.EntityTag = "";
852                 ServerResponse.SessionCode = 0;
853                 ServerResponse.ResultCode = 0;
854                 ServerResponse.ResultMessage = "";
855                 return ServerResponse;
856         }
858         ServerSSL ? SetupDefaultParametersSSL(true) : SetupDefaultParametersNonSSL(true);
859         ResetResults();
860         
861         string ServerAddressURL = BuildURL(ServerPrefix + Location);
862         curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str());
863         curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "PUT");
864         curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDS, Data.c_str());
865         curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDSIZE, strlen(Data.c_str()));
866         
867         HeaderList = curl_slist_append(HeaderList, "Content-Type: text/vcard; charset=utf-8");
869         curl_easy_setopt(ConnectionSession, CURLOPT_HTTPHEADER, HeaderList);
870         
871         if (TestMode == true){
872                 SessionResult = curl_easy_perform(ConnectionSession);
873         } else {
874                 SessionResult = curl_easy_perform(ConnectionSession);
875         }
876         
877         switch(SessionResult){
878                 case CURLE_OK:
879                         SSLStatus = true;
880                         SSLVerified = COSSL_VERIFIED;
881                         break;
882                 case CURLE_SSL_CACERT:
883                 case CURLE_SSL_CONNECT_ERROR:
884                         SSLStatus = true;
885                         SSLVerified = COSSL_UNABLETOVERIFY;
886                         break;
887                 default:
888                         break;
889         };
890         
891         long SessionResponseCode = 0;
892         
893         curl_easy_getinfo(ConnectionSession, CURLINFO_RESPONSE_CODE, &SessionResponseCode);
894         
895         if (SessionResponseCode == 200 || SessionResponseCode == 201 || SessionResponseCode == 204){
896                 AuthPassed = true;
897                 ValidResponse = true;
898         } else if (SessionResponseCode == 403){
899                 AuthPassed = false;
900                 ValidResponse = true;
901         } else if (SessionResponseCode >= 400){
902                 AuthPassed = false;
903                 ValidResponse = true;
904         } else {
905                 AuthPassed = false;
906                 ValidResponse = false;                  
907         }
908         
909         if (ValidResponse == false || AuthPassed == false){
910                 ServerResponse.RequestResult = COREQUEST_ERROR_SERVER;
911                 ServerResponse.EntityTag = "";
912                 ServerResponse.SessionCode = SessionResult;
913                 ServerResponse.ResultCode = SessionResponseCode;
914                 ServerResponse.ResultMessage = "";
915                 return ServerResponse;
916         }
917         
918         CanProcess = true;
919         
920         ServerResponse.RequestResult = COREQUEST_OK;
921         ServerResponse.EntityTag = "";
922         ServerResponse.SessionCode = SessionResult;
923         ServerResponse.ResultCode = SessionResponseCode;
924         ServerResponse.ResultMessage = SessionErrorBuffer;
925         return ServerResponse;
926         
929 COServerResponse CardDAV2::DeleteContact(std::string Location){
930         
931         // Check if authentication was successful, otherwise don't do anything.
933         COServerResponse ServerResponse;
934         
935         if (AuthPassed == false){
936                 ServerResponse.RequestResult = COREQUEST_ERROR_NOTCONNECTED;
937                 ServerResponse.EntityTag = "";
938                 ServerResponse.SessionCode = 0;
939                 ServerResponse.ResultCode = 0;
940                 ServerResponse.ResultMessage = "";
941                 return ServerResponse;
942         }
944         ServerSSL ? SetupDefaultParametersSSL(true) : SetupDefaultParametersNonSSL(true);
945         ResetResults();
946         
947         string ServerAddressURL = BuildURL(ServerPrefix + Location);
948         curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str());
949         curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "DELETE");
950         
951         if (TestMode == true){
952                 SessionResult = curl_easy_perform(ConnectionSession);
953         } else {
954                 SessionResult = curl_easy_perform(ConnectionSession);
955         }
956         
957         switch(SessionResult){
958                 case CURLE_OK:
959                         SSLStatus = true;
960                         SSLVerified = COSSL_VERIFIED;
961                         break;
962                 case CURLE_SSL_CACERT:
963                 case CURLE_SSL_CONNECT_ERROR:
964                         SSLStatus = true;
965                         SSLVerified = COSSL_UNABLETOVERIFY;
966                         break;
967                 default:
968                         break;
969         };
970         
971         long SessionResponseCode = 0;
972         
973         curl_easy_getinfo(ConnectionSession, CURLINFO_RESPONSE_CODE, &SessionResponseCode);
974         
975         if (SessionResponseCode == 200 || SessionResponseCode == 202 || SessionResponseCode == 204){
976                 AuthPassed = true;
977                 ValidResponse = true;
978         } else if (SessionResponseCode == 403){
979                 AuthPassed = false;
980                 ValidResponse = true;
981         } else if (SessionResponseCode >= 400){
982                 AuthPassed = false;
983                 ValidResponse = true;
984         } else {
985                 AuthPassed = false;
986                 ValidResponse = false;                  
987         }
988         
989         if (ValidResponse == false || AuthPassed == false){
990                 ServerResponse.RequestResult = COREQUEST_ERROR_SERVER;
991                 ServerResponse.EntityTag = "";
992                 ServerResponse.SessionCode = SessionResult;
993                 ServerResponse.ResultCode = SessionResponseCode;
994                 ServerResponse.ResultMessage = "";
995                 return ServerResponse;
996         }
997         
998         CanProcess = true;
999         
1000         ServerResponse.RequestResult = COREQUEST_OK;
1001         ServerResponse.EntityTag = "";
1002         ServerResponse.SessionCode = SessionResult;
1003         ServerResponse.ResultCode = SessionResponseCode;
1004         ServerResponse.ResultMessage = SessionErrorBuffer;
1005         return ServerResponse;
1006         
1009 COServerResponse CardDAV2::GetServerEntityTagValue(std::string Location){
1010         
1011         // Check if authentication was successful, otherwise don't do anything.
1013         COServerResponse ServerResponse;
1014         
1015         if (AuthPassed == false){
1016                 ServerResponse.RequestResult = COREQUEST_ERROR_NOTCONNECTED;
1017                 ServerResponse.EntityTag = "";
1018                 ServerResponse.SessionCode = 0;
1019                 ServerResponse.ResultCode = 0;
1020                 ServerResponse.ResultMessage = "";
1021                 return ServerResponse;
1022         }
1024         ServerSSL ? SetupDefaultParametersSSL(true) : SetupDefaultParametersNonSSL(true);
1025         ResetResults();
1026         
1027         static const char* GetETagQuery =
1028         "<?xml version=\"1.0\" encoding=\"utf-8\" ?>"
1029         "<C:addressbook-query xmlns:D=\"DAV:\""
1030         "       xmlns:C=\"urn:ietf:params:xml:ns:carddav\">"
1031         "<D:prop><D:getetag/>"
1032         "</D:prop>"
1033         "<C:filter/>"
1034         "</C:addressbook-query>";
1035         
1036         string ServerAddressURL = BuildURL(ServerPrefix + Location);
1037         curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str());
1038         curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "REPORT");
1039         curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDS, GetETagQuery);
1040         curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDSIZE, strlen(GetETagQuery));
1041         
1042         if (TestMode == true){
1043                 SessionResult = curl_easy_perform(ConnectionSession);
1044         } else {
1045                 SessionResult = curl_easy_perform(ConnectionSession);
1046         }
1047         
1048         switch(SessionResult){
1049                 case CURLE_OK:
1050                         SSLStatus = true;
1051                         SSLVerified = COSSL_VERIFIED;
1052                         break;
1053                 case CURLE_SSL_CACERT:
1054                 case CURLE_SSL_CONNECT_ERROR:
1055                         SSLStatus = true;
1056                         SSLVerified = COSSL_UNABLETOVERIFY;
1057                         break;
1058                 default:
1059                         break;
1060         };
1061         
1062         long SessionResponseCode = 0;
1063         
1064         curl_easy_getinfo(ConnectionSession, CURLINFO_RESPONSE_CODE, &SessionResponseCode);
1065         
1066         if (SessionResponseCode == 207){
1067                 AuthPassed = true;
1068                 ValidResponse = true;
1069         } else if (SessionResponseCode == 403){
1070                 AuthPassed = false;
1071                 ValidResponse = true;
1072         } else if (SessionResponseCode >= 400){
1073                 AuthPassed = false;
1074                 ValidResponse = true;
1075         } else {
1076                 AuthPassed = false;
1077                 ValidResponse = false;                  
1078         }
1079         
1080         if (ValidResponse == false || AuthPassed == false){
1081                 ServerResponse.RequestResult = COREQUEST_ERROR_SERVER;
1082                 ServerResponse.EntityTag = "";
1083                 ServerResponse.SessionCode = SessionResult;
1084                 ServerResponse.ResultCode = SessionResponseCode;
1085                 ServerResponse.ResultMessage = "";
1086                 return ServerResponse;
1087         }
1088         
1089         CanProcess = true;
1090         
1091         ServerResponse.RequestResult = COREQUEST_OK;
1092         ServerResponse.EntityTag = GetETagValue();
1093         ServerResponse.SessionCode = SessionResult;
1094         ServerResponse.ResultCode = SessionResponseCode;
1095         ServerResponse.ResultMessage = SessionErrorBuffer;
1096         
1097         return ServerResponse;
1098         
1101 COServerResponse CardDAV2::GetContact(std::string Location, std::string *ContactData){
1102         
1103         // Check if authentication was successful, otherwise don't do anything.
1105         COServerResponse ServerResponse;
1106         
1107         if (AuthPassed == false){
1108                 ServerResponse.RequestResult = COREQUEST_ERROR_NOTCONNECTED;
1109                 ServerResponse.EntityTag = "";
1110                 ServerResponse.SessionCode = 0;
1111                 ServerResponse.ResultCode = 0;
1112                 ServerResponse.ResultMessage = "";
1113                 return ServerResponse;
1114         }
1116         ServerSSL ? SetupDefaultParametersSSL(true) : SetupDefaultParametersNonSSL(true);
1117         ResetResults();
1118         
1119         string ServerAddressURL = BuildURL(ServerPrefix + Location);
1120         curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str());
1121         curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "GET");
1122         
1123         if (TestMode == true){
1124                 SessionResult = curl_easy_perform(ConnectionSession);
1125         } else {
1126                 SessionResult = curl_easy_perform(ConnectionSession);
1127         }
1128         
1129         switch(SessionResult){
1130                 case CURLE_OK:
1131                         SSLStatus = true;
1132                         SSLVerified = COSSL_VERIFIED;
1133                         break;
1134                 case CURLE_SSL_CACERT:
1135                 case CURLE_SSL_CONNECT_ERROR:
1136                         SSLStatus = true;
1137                         SSLVerified = COSSL_UNABLETOVERIFY;
1138                         break;
1139                 default:
1140                         break;
1141         };
1142         
1143         long SessionResponseCode = 0;
1144         
1145         curl_easy_getinfo(ConnectionSession, CURLINFO_RESPONSE_CODE, &SessionResponseCode);
1146         
1147         if (SessionResponseCode == 200){
1148                 AuthPassed = true;
1149                 ValidResponse = true;
1150         } else if (SessionResponseCode == 403){
1151                 AuthPassed = false;
1152                 ValidResponse = true;
1153         } else if (SessionResponseCode >= 400){
1154                 AuthPassed = false;
1155                 ValidResponse = true;
1156         } else {
1157                 AuthPassed = false;
1158                 ValidResponse = false;                  
1159         }
1160         
1161         if (ValidResponse == false && AuthPassed == false){
1162                 ServerResponse.RequestResult = COREQUEST_ERROR_SERVER;
1163                 ServerResponse.EntityTag = "";
1164                 ServerResponse.SessionCode = SessionResult;
1165                 ServerResponse.ResultCode = SessionResponseCode;
1166                 ServerResponse.ResultMessage = "";
1167                 return ServerResponse;
1168         }
1169         
1170         CanProcess = true;
1171         
1172         ServerResponse.RequestResult = COREQUEST_OK;
1173         ServerResponse.EntityTag = "";
1174         ServerResponse.SessionCode = SessionResult;
1175         ServerResponse.ResultCode = SessionResponseCode;
1176         ServerResponse.ResultMessage = SessionErrorBuffer;
1177         
1178         (*ContactData) = PageData;
1179         
1180         return ServerResponse;
1181         
1184 COContactList CardDAV2::GetContactList(std::string SyncToken){
1185         
1186         COContactList ServerContactList;
1187         
1188         // Check if authentication was successful, otherwise don't do anything.
1189         
1190         if (AuthPassed == false){
1191                 ServerContactList.ServerResponse.RequestResult = COREQUEST_ERROR_NOTCONNECTED;
1192                 ServerContactList.ServerResponse.EntityTag = "";
1193                 ServerContactList.ServerResponse.SessionCode = 0;
1194                 ServerContactList.ServerResponse.ResultCode = 0;
1195                 ServerContactList.ServerResponse.ResultMessage = "";
1196                 return ServerContactList;
1197         }
1199         ServerSSL ? SetupDefaultParametersSSL(true) : SetupDefaultParametersNonSSL(true);
1200         ResetResults();
1201         
1202         std::string SyncData;
1203         
1204         // TODO: Copy old code from CardDAV class as needed.
1205         
1206         if (SyncToken.size() > 0){
1207                 
1208                 SyncData = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
1209                 "<D:sync-collection xmlns:D=\"DAV:\"\n"
1210                 " xmlns:C=\"urn:ietf:params:xml:ns:carddav\">\n"
1211                 "<D:sync-token>";
1212                 SyncData.append(SyncToken);
1213                 SyncData.append("</D:sync-token>\n"
1214                 "<D:sync-level>1</D:sync-level>\n"
1215                 "<D:prop>\n"
1216                 "       <D:getetag/>\n"
1217                 "</D:prop>\n"
1218                 "</D:sync-collection>");
1219         
1220         } else {
1221                 
1222                 SyncData = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
1223                 "<D:sync-collection xmlns:D=\"DAV:\"\n"
1224                 " xmlns:C=\"urn:ietf:params:xml:ns:carddav\">\n"
1225                 "<D:sync-level>1</D:sync-level>\n"
1226                 "<D:prop>\n"
1227                 "       <D:getetag/>\n"
1228                 "</D:prop>\n"
1229                 "</D:sync-collection>";
1231         }
1232         
1233         string ServerAddressURL = BuildURL(ServerPrefix);
1234         
1235         std::cout << SyncData << std::endl;
1236         
1237         curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str());
1238         curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDS, SyncData.c_str());
1239         curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDSIZE, strlen(SyncData.c_str()));
1240         curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "REPORT");
1241         
1242         HeaderList = curl_slist_append(HeaderList, "Content-Type: application/xml; charset=utf-8");
1243         HeaderList = curl_slist_append(HeaderList, "Depth: 1");
1245         curl_easy_setopt(ConnectionSession, CURLOPT_HTTPHEADER, HeaderList);
1246         
1247         if (TestMode == true){
1248                 SessionResult = curl_easy_perform(ConnectionSession);
1249         } else {
1250                 SessionResult = curl_easy_perform(ConnectionSession);
1251         }
1252         
1253         switch(SessionResult){
1254                 case CURLE_OK:
1255                         SSLStatus = true;
1256                         SSLVerified = COSSL_VERIFIED;
1257                         break;
1258                 case CURLE_SSL_CACERT:
1259                 case CURLE_SSL_CONNECT_ERROR:
1260                         SSLStatus = true;
1261                         SSLVerified = COSSL_UNABLETOVERIFY;
1262                         break;
1263                 default:
1264                         break;
1265         };
1266         
1267         long SessionResponseCode = 0;
1268         
1269         curl_easy_getinfo(ConnectionSession, CURLINFO_RESPONSE_CODE, &SessionResponseCode);
1270         
1271         if (SessionResponseCode == 207){
1272                 AuthPassed = true;
1273                 ValidResponse = true;
1274         } else if (SessionResponseCode == 403){
1275                 AuthPassed = false;
1276                 ValidResponse = true;
1277         } else if (SessionResponseCode >= 400){
1278                 AuthPassed = false;
1279                 ValidResponse = true;
1280         } else {
1281                 AuthPassed = false;
1282                 ValidResponse = false;                  
1283         }
1284         
1285         if (ValidResponse == false || AuthPassed == false){
1286                 ServerContactList.ServerResponse.RequestResult = COREQUEST_ERROR_SERVER;
1287                 ServerContactList.ServerResponse.EntityTag = "";
1288                 ServerContactList.ServerResponse.SessionCode = SessionResult;
1289                 ServerContactList.ServerResponse.ResultCode = SessionResponseCode;
1290                 ServerContactList.ServerResponse.ResultMessage = "";
1291                 return ServerContactList;
1292         }
1293         
1294         CanProcess = true;
1295         
1296         ProcessContactData(&ServerContactList);
1297         
1298         ServerContactList.ServerResponse.RequestResult = COREQUEST_OK;
1299         ServerContactList.ServerResponse.EntityTag = "";
1300         ServerContactList.ServerResponse.SessionCode = SessionResult;
1301         ServerContactList.ServerResponse.ResultCode = SessionResponseCode;
1302         ServerContactList.ServerResponse.ResultMessage = SessionErrorBuffer;
1303         
1304         return ServerContactList;
1305         
1307         
1308 bool CardDAV2::CanDoProcessing(){
1309         return CanProcess;
1312 bool CardDAV2::CanDoSSL(){
1313         return SSLStatus;
1316 COSSLVerified CardDAV2::SSLVerify(){
1317         return SSLVerified;
1320 bool CardDAV2::AbleToLogin(){
1321         return AuthPassed;
1324 bool CardDAV2::HasValidResponse(){
1325         return ValidResponse;
1328 bool CardDAV2::IsSelfSigned(){
1329         return SSLSelfSigned;
1332 void CardDAV2::SetupDefaultParametersNonSSL(bool DoAuthentication){
1333         
1334         std::string ServerAddress = "";
1336         string ServerAddressURL = "http://" + ServerAddress + ":" + to_string(ServerPort) + "/";
1337         string UsernamePassword = ServerUser + ":" + ServerPass;
1338         
1339         curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddress.c_str());
1340         curl_easy_setopt(ConnectionSession, CURLOPT_NOPROGRESS, 1L);
1341         curl_easy_setopt(ConnectionSession, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
1342         curl_easy_setopt(ConnectionSession, CURLOPT_TIMEOUT, 60);
1343         curl_easy_setopt(ConnectionSession, CURLOPT_FAILONERROR, true);
1344         curl_easy_setopt(ConnectionSession, CURLOPT_USERAGENT, XSDAB_USERAGENT);
1345         curl_easy_setopt(ConnectionSession, CURLOPT_WRITEFUNCTION, CardDAV2::WritebackFunc);
1346         curl_easy_setopt(ConnectionSession, CURLOPT_WRITEDATA, &PageData);
1347         curl_easy_setopt(ConnectionSession, CURLOPT_WRITEHEADER, &PageHeader);
1348         curl_easy_setopt(ConnectionSession, CURLOPT_NOSIGNAL, 1);
1349         curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "GET");
1350         curl_easy_setopt(ConnectionSession, CURLOPT_HTTPHEADER, nullptr);
1351         curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDS, nullptr);
1352         curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDSIZE, 0L);
1353         
1354         if (DoAuthentication == true){
1355                 curl_easy_setopt(ConnectionSession, CURLOPT_USERPWD, UsernamePassword.c_str());
1356         } else {
1357                 curl_easy_setopt(ConnectionSession, CURLOPT_USERPWD, ":");              
1358         }
1359         
1362 void CardDAV2::SetupDefaultParametersSSL(bool DoAuthentication){
1363         
1364         // Setup the default parameters.
1365         
1366         string ServerAddressURL = "https://" + ServerAddress + ":" + to_string(ServerPort) + "/";
1367         string UsernamePassword = ServerUser + ":" + ServerPass;
1368         
1369         curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str());
1370         curl_easy_setopt(ConnectionSession, CURLOPT_NOPROGRESS, 1L);
1371         curl_easy_setopt(ConnectionSession, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
1372         curl_easy_setopt(ConnectionSession, CURLOPT_TIMEOUT, 60);
1373         curl_easy_setopt(ConnectionSession, CURLOPT_FAILONERROR, true);
1374         curl_easy_setopt(ConnectionSession, CURLOPT_USERAGENT, XSDAB_USERAGENT);
1375         curl_easy_setopt(ConnectionSession, CURLOPT_WRITEFUNCTION, CardDAV2::WritebackFunc);
1376         curl_easy_setopt(ConnectionSession, CURLOPT_WRITEDATA, &PageData);
1377         curl_easy_setopt(ConnectionSession, CURLOPT_WRITEHEADER, &PageHeader);
1378         curl_easy_setopt(ConnectionSession, CURLOPT_ERRORBUFFER, SessionErrorBuffer);
1379         curl_easy_setopt(ConnectionSession, CURLOPT_NOSIGNAL, 1);
1380         curl_easy_setopt(ConnectionSession, CURLOPT_CERTINFO, 1);
1381         curl_easy_setopt(ConnectionSession, CURLOPT_VERBOSE, 1);
1382         curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "GET");
1383         curl_easy_setopt(ConnectionSession, CURLOPT_HTTPHEADER, nullptr);
1384         curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDS, nullptr);
1385         curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDSIZE, 0L);
1386         
1387         if (DoAuthentication == true){
1388                 curl_easy_setopt(ConnectionSession, CURLOPT_USERPWD, UsernamePassword.c_str());
1389         } else {
1390                 curl_easy_setopt(ConnectionSession, CURLOPT_USERPWD, ":");              
1391         }
1392         
1393 #if !defined(__WIN32__)
1395         if (EnableSSLBypass == true){
1396                 curl_easy_setopt(ConnectionSession, CURLOPT_SSL_VERIFYHOST, 0);
1397                 curl_easy_setopt(ConnectionSession, CURLOPT_SSL_VERIFYPEER, 0);
1398         } else {
1399                 curl_easy_setopt(ConnectionSession, CURLOPT_SSL_VERIFYHOST, 2);
1400                 curl_easy_setopt(ConnectionSession, CURLOPT_SSL_VERIFYPEER, 1);         
1401         }
1403 #endif
1404         
1405         if (TestMode == false && ServerAccount.size() > 0){
1406                 
1407                 // Check if the server certificate file exists.
1408                 
1409                 string CertificateFilename = GetAccountDir(ServerAccount, true);
1410                 
1411                 if (wxFile::Exists(CertificateFilename)){
1412                         
1413                         curl_easy_setopt(ConnectionSession, CURLOPT_CAINFO, CertificateFilename.c_str());
1414                         
1415                 }
1416                 
1417         }
1418         
1421 string CardDAV2::BuildURL(string URI){
1422         
1423         string ServerAddressURL;
1424         
1425         if (SSLStatus == true){
1426                 ServerAddressURL = "https://" + ServerAddress + ":" + to_string(ServerPort) + URI;      
1427         } else {
1428                 ServerAddressURL = "https://" + ServerAddress + ":" + to_string(ServerPort) + URI;
1429         }
1430         
1431         return ServerAddressURL;
1432         
1435 string CardDAV2::GetErrorMessage(){
1436         
1437         ErrorMessage = SessionErrorBuffer;      
1438         return ErrorMessage;
1439         
1442 void CardDAV2::ResetResults(){
1443         
1444         SSLStatus = false;
1445         COSSLVerified SSLVerified = COSSL_NORESULT;
1446         ValidResponse = false;
1447         AuthPassed = false;
1448         CanProcess = false;
1449         SSLSelfSigned = false;
1450         TaskCompleted = false;
1451         ErrorMessage = "";
1452         SessionErrorBuffer[0] = '\0';
1453         PageData = "";
1454         PageHeader = "";
1455         if (HeaderList != nullptr){
1456                 curl_slist_free_all(HeaderList);
1457                 HeaderList = nullptr;
1458         }
1459         
1462 string CardDAV2::GetETagValue(){
1463         
1464         xmlDocPtr xmlCardDAVDoc;
1466         xmlCardDAVDoc = xmlReadMemory(PageData.c_str(), (int)PageData.size(), "noname.xml", NULL, 0);
1468         xmlNodePtr nodeLevel1;
1469         xmlNodePtr nodeLevel2;
1470         xmlNodePtr nodeLevel3;
1471         xmlNodePtr nodeLevel4;
1472         xmlNodePtr nodeLevel5;
1473         xmlNodePtr nodeLevel6;
1475         //std::map<wxString,wxString> xmlDataMap;
1477         std::string DataFilename;
1478         std::string ETagData;
1480         std::string xmlStringSafe;
1481         std::string ETagValue;
1483         // Tranverse through the catacombs of the response to get our ETag for the file.
1485         for (nodeLevel1 = xmlCardDAVDoc->children;
1486                 nodeLevel1 != NULL;
1487                 nodeLevel1 = nodeLevel1->next)
1488         {
1490                 bool HREFFound = FALSE;
1491                 bool ETagFound = FALSE;
1493                 for (nodeLevel2 = nodeLevel1->children;
1494                         nodeLevel2 != NULL;
1495                         nodeLevel2 = nodeLevel2->next)
1496                 {
1498                         for (nodeLevel3 = nodeLevel2->children;
1499                         nodeLevel3 != NULL;
1500                         nodeLevel3 = nodeLevel3->next)
1501                         {
1503                                 if (!xmlStrcmp(nodeLevel3->name, (const xmlChar *)"href") ||
1504                                 !xmlStrcmp(nodeLevel3->name, (const xmlChar *)"d:href") ||
1505                                 !xmlStrcmp(nodeLevel3->name, (const xmlChar *)"D:href")
1506                                 ){
1508                                         // Get the filename.
1509                                         
1510                                         for (nodeLevel4 = nodeLevel3->children;
1511                                         nodeLevel4 != NULL;
1512                                         nodeLevel4 = nodeLevel4->next)
1513                                         {
1514                                         
1515                                                 if (!xmlStrcmp(nodeLevel4->name, (const xmlChar *)"text") ||
1516                                                 !xmlStrcmp(nodeLevel4->name, (const xmlChar *)"d:text") ||
1517                                                 !xmlStrcmp(nodeLevel4->name, (const xmlChar *)"D:text")
1518                                                 ){
1520                                                         DataFilename = wxString::FromUTF8((const char*)nodeLevel4->content);
1521                                                         wxStringTokenizer wSTDFilename(DataFilename, wxT("/"));
1522                                                 
1523                                                         while (wSTDFilename.HasMoreTokens()){
1524                                                         
1525                                                                 DataFilename = wSTDFilename.GetNextToken().ToStdString();
1526                                                         
1527                                                         }
1528                                                         
1529                                                         HREFFound = TRUE;
1530                                                 
1531                                                 }
1532                                                 
1533         
1534                                         
1535                                         }
1537                                 } else {
1539                                         for (nodeLevel4 = nodeLevel3->children;
1540                                         nodeLevel4 != NULL;
1541                                         nodeLevel4 = nodeLevel4->next)
1542                                         {
1543                                                         
1544                                                         for (nodeLevel5 = nodeLevel4->children;
1545                                                         nodeLevel5 != NULL;
1546                                                         nodeLevel5 = nodeLevel5->next)
1547                                                         {
1549                                                                 if (!xmlStrcmp(nodeLevel5->name, (const xmlChar *)"getetag") ||
1550                                                                 !xmlStrcmp(nodeLevel5->name, (const xmlChar *)"d:getetag") ||
1551                                                                 !xmlStrcmp(nodeLevel5->name, (const xmlChar *)"D:getetag")
1552                                                                 ){
1554                                                                         for (nodeLevel6 = nodeLevel5->children;
1555                                                                         nodeLevel6 != NULL;
1556                                                                         nodeLevel6 = nodeLevel6->next)
1557                                                                         {
1558                                                         
1559                                                                                 // Strip the quotes from the ETag.
1560                                                         
1561                                                                                 ETagData = (const char*)nodeLevel6->content;
1562                                                                                 if (ETagData[0] == '"' && ETagData[(ETagData.size() - 1)] == '"'){
1563                                                         
1564                                                                                         ETagData.erase(0, 1);
1565                                                                                         ETagData.erase((ETagData.size() - 1));
1566                                                         
1567                                                                                 }
1568                                                                         
1569                                                                                 ETagFound = TRUE;
1571                                                                         }
1572                                                                         
1573                                                                 }
1575                                                         }       
1577                                         }
1579                                 }
1581                         }
1583                 }
1584                 
1585                 if (HREFFound == TRUE && ETagFound == TRUE){
1586                                 
1587                         // Add to the map data.
1588                                 
1589                         ETagValue = ETagData;
1590                         
1591                         HREFFound = FALSE;
1592                         ETagFound = FALSE;
1593                         break;
1594                                 
1595                 }
1598         }
1600         xmlFreeDoc(xmlCardDAVDoc);
1601         
1602         return ETagValue;
1603         
1606 string CardDAV2::GetETagHeader(){
1607         
1608         // Go through each of the lines looking for the
1609         // 'DAV:' section.
1610         
1611         string HeaderName;
1612         string HeaderValue;
1613         bool FastForward = false;
1614         
1615         for (int HeaderSeek = 0; HeaderSeek < PageHeader.size(); HeaderSeek++){
1616                 
1617                 if (FastForward == true){
1618                         
1619                         if (PageHeader[HeaderSeek] == '\n'){
1620                                 FastForward = false;
1621                         }
1622                         
1623                         continue;
1624                         
1625                 }
1626                 
1627                 try {
1628                         PageHeader.substr(HeaderSeek, 5) == "ETag:";
1629                 }
1630                 
1631                 catch (const out_of_range &oor){
1632                         break;
1633                 }
1634                 
1635                 if (PageHeader.substr(HeaderSeek, 5) == "ETag:"){
1636                         
1637                         int CharacterSeek = 5;
1638                         
1639                         while ((HeaderSeek + CharacterSeek) < PageHeader.size()){
1640                                 
1641                                 if (PageHeader.substr((HeaderSeek + CharacterSeek), 2) == "\r\n"){
1642                                         break;
1643                                 }
1644                                 
1645                                 HeaderValue += PageHeader.substr((HeaderSeek + CharacterSeek), 1);
1646                                 CharacterSeek++;
1647                         }
1648                         
1649                         break;
1650                         
1651                 } else {
1652                         
1653                         FastForward = true;
1654                         continue;
1655                         
1656                 }
1657                 
1658                 if (PageHeader[HeaderSeek] == '\n'){
1659                         HeaderName = "";
1660                 }
1661                 
1662                 //HeaderName += PageHeader.substr(HeaderSeek, 1);
1663                 
1664         }
1665         
1666         // Check for quotation marks at the start and end and strip
1667         // them out.
1668         
1669         if (HeaderValue.size() >= 2){
1670                 
1671                 if (HeaderValue[0] == '"'){
1672                         HeaderValue.erase((HeaderValue.size() - 1));
1673                         HeaderValue.erase(0);
1674                 }
1675                 
1676         }
1677         
1678         return HeaderValue;
1679         
1682 vector<string> CardDAV2::GetDAVHeader(){
1683         
1684         // Go through each of the lines looking for the
1685         // 'DAV:' section.
1686         
1687         string HeaderName;
1688         string HeaderValue;
1689         bool FastForward = false;
1690         vector<string> DAVHeaderList;
1691         
1692         for (int HeaderSeek = 0; HeaderSeek < PageHeader.size(); HeaderSeek++){
1693                 
1694                 if (FastForward == true){
1695                         
1696                         if (PageHeader[HeaderSeek] == '\n'){
1697                                 FastForward = false;
1698                         }
1699                         
1700                         continue;
1701                         
1702                 }
1703                 
1704                 try {
1705                         PageHeader.substr(HeaderSeek, 4) == "DAV:";
1706                 }
1707                 
1708                 catch (const out_of_range &oor){
1709                         break;
1710                 }
1711                 
1712                 if (PageHeader.substr(HeaderSeek, 4) == "DAV:"){
1713                         
1714                         int CharacterSeek = 5;
1715                         
1716                         while ((HeaderSeek + CharacterSeek) < PageHeader.size()){
1717                                 
1718                                 if (PageHeader.substr((HeaderSeek + CharacterSeek), 2) == "\r\n"){
1719                                         break;
1720                                 }
1721                                 
1722                                 HeaderValue += PageHeader.substr((HeaderSeek + CharacterSeek), 1);
1723                                 CharacterSeek++;
1724                         }
1725                         
1726                         break;
1727                         
1728                 } else {
1729                         
1730                         FastForward = true;
1731                         continue;
1732                         
1733                 }
1734                 
1735                 if (PageHeader[HeaderSeek] == '\n'){
1736                         HeaderName = "";
1737                 }
1738                 
1739                 //HeaderName += PageHeader.substr(HeaderSeek, 1);
1740                 
1741         }
1742         
1743         // Split the header data.
1744         
1745         std::string DAVHeaderValue;
1746         
1747         for (int HeaderSeek = 0; HeaderSeek < HeaderValue.size(); HeaderSeek++){
1748                 
1749                 if (HeaderValue.substr(HeaderSeek, 1) == ","){
1750                         DAVHeaderList.push_back(DAVHeaderValue);
1751                         DAVHeaderValue = "";
1752                         HeaderSeek++;
1753                         continue;
1754                 }
1755                 
1756                 DAVHeaderValue += HeaderValue[HeaderSeek];
1757                 
1758         }
1759         
1760         if (DAVHeaderValue.size() > 0){
1761                 
1762                 DAVHeaderList.push_back(DAVHeaderValue);
1763                 
1764         }
1765         
1766         return DAVHeaderList;
1767         
1770 void CardDAV2::ProcessContactData(COContactList *ContactList){
1771         
1772         xmlDocPtr xmlCardDAVDoc;
1773         xmlCardDAVDoc = xmlReadMemory(PageData.c_str(), (int)PageData.size(), "noname.xml", NULL, 0);
1775         xmlNodePtr MultiStatusNode;
1776         xmlNodePtr ResponseNode;
1777         xmlNodePtr ResponseDataNode;
1778         xmlNodePtr PropStatNode;
1779         xmlNodePtr ValueNode;
1780         xmlNodePtr ETagNode;
1781         xmlNodePtr StatusNode;
1783         std::string HREFValue;
1784         std::string ETagValue;
1785         std::string StatusValue;
1786         std::string SyncValue;
1788         // Go through the document!
1790         MultiStatusNode = xmlCardDAVDoc->children;
1792         if (MultiStatusNode == nullptr){
1793                 return;
1794         }
1796         bool SyncTokenFound = false;
1798         // Tranverse through the catacombs of the response to get our ETag for the file and
1799         // the server syncronisation token.
1800         
1801         for (ResponseNode = MultiStatusNode->children;
1802                 ResponseNode != nullptr;
1803                 ResponseNode = ResponseNode->next){
1805                 // Check if tag is response or sync-token.
1807                 if (!xmlStrcmp(ResponseNode->name, (const xmlChar *)"response") ||
1808                 !xmlStrcmp(ResponseNode->name, (const xmlChar *)"d:response") ||
1809                 !xmlStrcmp(ResponseNode->name, (const xmlChar *)"D:response")){
1811                         COContactStatus ContactStatus = COCS_UNKNOWN;
1812                         
1813                         for (ResponseDataNode = ResponseNode->children;
1814                                 ResponseDataNode != nullptr;
1815                                 ResponseDataNode = ResponseDataNode->next){
1817                                 if (!xmlStrcmp(ResponseDataNode->name, (const xmlChar *)"href") ||
1818                                 !xmlStrcmp(ResponseDataNode->name, (const xmlChar *)"d:href") ||
1819                                 !xmlStrcmp(ResponseDataNode->name, (const xmlChar *)"D:href")){
1820                                 
1821                                         HREFValue = (const char*)ResponseDataNode->children->content;
1823                                         // Get the filename after the last forward slash.
1824                                         
1825                                         int LastSlash = 0;
1826                                         
1827                                         for (int HREFValueSeek = 0; HREFValueSeek < HREFValue.size(); HREFValueSeek++){
1828                                                 
1829                                                 if (HREFValue[HREFValueSeek] == '/'){
1830                                                 
1831                                                         LastSlash = HREFValueSeek;
1832                                                         
1833                                                 }
1834                                                 
1835                                         }
1836                                         
1837                                         HREFValue = HREFValue.substr((LastSlash + 1));
1838                                         
1839                                 } else if (!xmlStrcmp(ResponseDataNode->name, (const xmlChar *)"propstat") ||
1840                                 !xmlStrcmp(ResponseDataNode->name, (const xmlChar *)"d:propstat") ||
1841                                 !xmlStrcmp(ResponseDataNode->name, (const xmlChar *)"D:propstat")){
1843                                         for (PropStatNode = ResponseDataNode->children;
1844                                                 PropStatNode != nullptr;
1845                                                 PropStatNode = PropStatNode->next){
1847                                                 if (!xmlStrcmp(PropStatNode->name, (const xmlChar *)"prop") ||
1848                                                         !xmlStrcmp(PropStatNode->name, (const xmlChar *)"d:prop") ||
1849                                                         !xmlStrcmp(PropStatNode->name, (const xmlChar *)"D:prop")){
1851                                                         for (ETagNode = PropStatNode->children;
1852                                                                 ETagNode != nullptr;
1853                                                                 ETagNode = ETagNode->next){
1855                                                                         if (!xmlStrcmp(ETagNode->name, (const xmlChar *)"getetag") ||
1856                                                                         !xmlStrcmp(ETagNode->name, (const xmlChar *)"getetag") ||
1857                                                                         !xmlStrcmp(ETagNode->name, (const xmlChar *)"getetag")){
1859                                                                                 ETagValue = (const char*)ETagNode->children->content;
1861                                                                                 if (ETagValue.size() > 2 && ETagValue.substr(0,1) == "\""){
1862                                                                                         ETagValue.erase((ETagValue.size() - 1),1);
1863                                                                                         ETagValue.erase(0,1);
1864                                                                                 }
1866                                                                         }
1867                                                         
1869                                                         }
1871                                                 } else if (!xmlStrcmp(PropStatNode->name, (const xmlChar *)"status") ||
1872                                                         !xmlStrcmp(PropStatNode->name, (const xmlChar *)"d:status") ||
1873                                                         !xmlStrcmp(PropStatNode->name, (const xmlChar *)"D:status")){
1875                                                         StatusValue = (const char*)PropStatNode->children->content;
1877                                                         if (StatusValue == "HTTP/1.1 200 OK"){
1879                                                                 ContactStatus = COCS_UPDATED;
1881                                                         } else if (StatusValue == "HTTP/1.1 404 Not Found"){
1883                                                                 ContactStatus = COCS_DELETED;
1885                                                         } else {
1887                                                                 ContactStatus = COCS_UNKNOWN;
1889                                                         }
1891                                                 }
1893                                         }
1895                                 }
1897                         }
1899                         COContactData ContactInformation;
1900                         
1901                         ContactInformation.Location = HREFValue;
1902                         ContactInformation.Data = ETagValue;
1903                         ContactInformation.Status = ContactStatus;
1905                         HREFValue.clear();
1906                         ETagValue.clear();
1907                         StatusValue.clear();
1908                         
1909                         ContactList->ListData.push_back(ContactInformation);
1911                 } else if (!xmlStrcmp(ResponseNode->name, (const xmlChar *)"sync-token") ||
1912                         !xmlStrcmp(ResponseNode->name, (const xmlChar *)"d:sync-token") ||
1913                         !xmlStrcmp(ResponseNode->name, (const xmlChar *)"D:sync-token")){
1915                         SyncValue = (const char*)ResponseNode->children->content;
1917                 }
1919         }
1921         ContactList->SyncToken = SyncValue;
1923         xmlFreeDoc(xmlCardDAVDoc);
1925         return;
1926         
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