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