Home | News | Projects | Releases
Bugs | RFE | Repositories | Help
Added AddContact for CardDAV2 and frmActivityMgr
[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){
833         
836 COServerResponse CardDAV2::DeleteContact(std::string Location, std::string EntityTag){
837         
840 COServerResponse CardDAV2::GetServerEntityTagValue(std::string Location){
841         
844 COServerResponse CardDAV2::GetContact(std::string Location){
845         
848 COContactList CardDAV2::GetContactList(std::string SyncToken){
849         
851         
852 bool CardDAV2::CanDoProcessing(){
853         return CanProcess;
856 bool CardDAV2::CanDoSSL(){
857         return SSLStatus;
860 COSSLVerified CardDAV2::SSLVerify(){
861         return SSLVerified;
864 bool CardDAV2::AbleToLogin(){
865         return AuthPassed;
868 bool CardDAV2::HasValidResponse(){
869         return ValidResponse;
872 bool CardDAV2::IsSelfSigned(){
873         return SSLSelfSigned;
876 void CardDAV2::SetupDefaultParametersNonSSL(bool DoAuthentication){
877         
878         std::string ServerAddress = "";
880         string ServerAddressURL = "http://" + ServerAddress + ":" + to_string(ServerPort) + "/";
881         string UsernamePassword = ServerUser + ":" + ServerPass;
882         
883         curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddress.c_str());
884         curl_easy_setopt(ConnectionSession, CURLOPT_NOPROGRESS, 1L);
885         curl_easy_setopt(ConnectionSession, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
886         curl_easy_setopt(ConnectionSession, CURLOPT_TIMEOUT, 60);
887         curl_easy_setopt(ConnectionSession, CURLOPT_FAILONERROR, true);
888         curl_easy_setopt(ConnectionSession, CURLOPT_USERAGENT, XSDAB_USERAGENT);
889         curl_easy_setopt(ConnectionSession, CURLOPT_WRITEFUNCTION, CardDAV2::WritebackFunc);
890         curl_easy_setopt(ConnectionSession, CURLOPT_WRITEDATA, &PageData);
891         curl_easy_setopt(ConnectionSession, CURLOPT_WRITEHEADER, &PageHeader);
892         curl_easy_setopt(ConnectionSession, CURLOPT_NOSIGNAL, 1);
893         curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "GET");
894         curl_easy_setopt(ConnectionSession, CURLOPT_HTTPHEADER, nullptr);
895         
896         if (DoAuthentication == true){
897                 curl_easy_setopt(ConnectionSession, CURLOPT_USERPWD, UsernamePassword.c_str());
898         } else {
899                 curl_easy_setopt(ConnectionSession, CURLOPT_USERPWD, ":");              
900         }
901         
904 void CardDAV2::SetupDefaultParametersSSL(bool DoAuthentication){
905         
906         // Setup the default parameters.
907         
908         string ServerAddressURL = "https://" + ServerAddress + ":" + to_string(ServerPort) + "/";
909         string UsernamePassword = ServerUser + ":" + ServerPass;
910         
911         curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str());
912         curl_easy_setopt(ConnectionSession, CURLOPT_NOPROGRESS, 1L);
913         curl_easy_setopt(ConnectionSession, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
914         curl_easy_setopt(ConnectionSession, CURLOPT_TIMEOUT, 60);
915         curl_easy_setopt(ConnectionSession, CURLOPT_FAILONERROR, true);
916         curl_easy_setopt(ConnectionSession, CURLOPT_USERAGENT, XSDAB_USERAGENT);
917         curl_easy_setopt(ConnectionSession, CURLOPT_WRITEFUNCTION, CardDAV2::WritebackFunc);
918         curl_easy_setopt(ConnectionSession, CURLOPT_WRITEDATA, &PageData);
919         curl_easy_setopt(ConnectionSession, CURLOPT_WRITEHEADER, &PageHeader);
920         curl_easy_setopt(ConnectionSession, CURLOPT_ERRORBUFFER, SessionErrorBuffer);
921         curl_easy_setopt(ConnectionSession, CURLOPT_NOSIGNAL, 1);
922         curl_easy_setopt(ConnectionSession, CURLOPT_CERTINFO, 1);
923         curl_easy_setopt(ConnectionSession, CURLOPT_VERBOSE, 1);
924         curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "GET");
925         curl_easy_setopt(ConnectionSession, CURLOPT_HTTPHEADER, nullptr);
926         
927         if (DoAuthentication == true){
928                 curl_easy_setopt(ConnectionSession, CURLOPT_USERPWD, UsernamePassword.c_str());
929         } else {
930                 curl_easy_setopt(ConnectionSession, CURLOPT_USERPWD, ":");              
931         }
932         
933         if (EnableSSLBypass == true){
934                 curl_easy_setopt(ConnectionSession, CURLOPT_SSL_VERIFYHOST, 0);
935                 curl_easy_setopt(ConnectionSession, CURLOPT_SSL_VERIFYPEER, 0);
936         } else {
937                 curl_easy_setopt(ConnectionSession, CURLOPT_SSL_VERIFYHOST, 2);
938                 curl_easy_setopt(ConnectionSession, CURLOPT_SSL_VERIFYPEER, 1);         
939         }
940         
941         if (TestMode == false && ServerAccount.size() > 0){
942                 
943                 // Check if the server certificate file exists.
944                 
945                 string CertificateFilename = GetAccountDir(ServerAccount, true);
946                 
947                 if (wxFile::Exists(CertificateFilename)){
948                         
949                         curl_easy_setopt(ConnectionSession, CURLOPT_CAINFO, CertificateFilename.c_str());
950                         
951                 }
952                 
953         }
954         
957 string CardDAV2::BuildURL(string URI){
958         
959         string ServerAddressURL;
960         
961         if (SSLStatus == true){
962                 ServerAddressURL = "https://" + ServerAddress + ":" + to_string(ServerPort) + URI;      
963         } else {
964                 ServerAddressURL = "https://" + ServerAddress + ":" + to_string(ServerPort) + URI;
965         }
966         
967         return ServerAddressURL;
968         
971 string CardDAV2::GetErrorMessage(){
972         
973         ErrorMessage = SessionErrorBuffer;      
974         return ErrorMessage;
975         
978 void CardDAV2::ResetResults(){
979         
980         SSLStatus = false;
981         COSSLVerified SSLVerified = COSSL_NORESULT;
982         ValidResponse = false;
983         AuthPassed = false;
984         CanProcess = false;
985         SSLSelfSigned = false;
986         TaskCompleted = false;
987         ErrorMessage = "";
988         SessionErrorBuffer[0] = '\0';
989         PageData = "";
990         PageHeader = "";
991         if (HeaderList != nullptr){
992                 curl_slist_free_all(HeaderList);
993                 HeaderList = nullptr;
994         }
995         
998 string CardDAV2::GetETagHeader(){
999         
1000         // Go through each of the lines looking for the
1001         // 'DAV:' section.
1002         
1003         string HeaderName;
1004         string HeaderValue;
1005         bool FastForward = false;
1006         
1007         for (int HeaderSeek = 0; HeaderSeek < PageHeader.size(); HeaderSeek++){
1008                 
1009                 if (FastForward == true){
1010                         
1011                         if (PageHeader[HeaderSeek] == '\n'){
1012                                 FastForward = false;
1013                         }
1014                         
1015                         continue;
1016                         
1017                 }
1018                 
1019                 try {
1020                         PageHeader.substr(HeaderSeek, 5) == "ETag:";
1021                 }
1022                 
1023                 catch (const out_of_range &oor){
1024                         break;
1025                 }
1026                 
1027                 if (PageHeader.substr(HeaderSeek, 5) == "ETag:"){
1028                         
1029                         int CharacterSeek = 5;
1030                         
1031                         while ((HeaderSeek + CharacterSeek) < PageHeader.size()){
1032                                 
1033                                 if (PageHeader.substr((HeaderSeek + CharacterSeek), 2) == "\r\n"){
1034                                         break;
1035                                 }
1036                                 
1037                                 HeaderValue += PageHeader.substr((HeaderSeek + CharacterSeek), 1);
1038                                 CharacterSeek++;
1039                         }
1040                         
1041                         break;
1042                         
1043                 } else {
1044                         
1045                         FastForward = true;
1046                         continue;
1047                         
1048                 }
1049                 
1050                 if (PageHeader[HeaderSeek] == '\n'){
1051                         HeaderName = "";
1052                 }
1053                 
1054                 //HeaderName += PageHeader.substr(HeaderSeek, 1);
1055                 
1056         }
1057         
1058         // Check for quotation marks at the start and end and strip
1059         // them out.
1060         
1061         if (HeaderValue.size() >= 2){
1062                 
1063                 if (HeaderValue[0] == '"'){
1064                         HeaderValue.erase((HeaderValue.size() - 1));
1065                         HeaderValue.erase(0);
1066                 }
1067                 
1068         }
1069         
1070         return HeaderValue;
1071         
1074 vector<string> CardDAV2::GetDAVHeader(){
1075         
1076         // Go through each of the lines looking for the
1077         // 'DAV:' section.
1078         
1079         string HeaderName;
1080         string HeaderValue;
1081         bool FastForward = false;
1082         vector<string> DAVHeaderList;
1083         
1084         for (int HeaderSeek = 0; HeaderSeek < PageHeader.size(); HeaderSeek++){
1085                 
1086                 if (FastForward == true){
1087                         
1088                         if (PageHeader[HeaderSeek] == '\n'){
1089                                 FastForward = false;
1090                         }
1091                         
1092                         continue;
1093                         
1094                 }
1095                 
1096                 try {
1097                         PageHeader.substr(HeaderSeek, 4) == "DAV:";
1098                 }
1099                 
1100                 catch (const out_of_range &oor){
1101                         break;
1102                 }
1103                 
1104                 if (PageHeader.substr(HeaderSeek, 4) == "DAV:"){
1105                         
1106                         int CharacterSeek = 5;
1107                         
1108                         while ((HeaderSeek + CharacterSeek) < PageHeader.size()){
1109                                 
1110                                 if (PageHeader.substr((HeaderSeek + CharacterSeek), 2) == "\r\n"){
1111                                         break;
1112                                 }
1113                                 
1114                                 HeaderValue += PageHeader.substr((HeaderSeek + CharacterSeek), 1);
1115                                 CharacterSeek++;
1116                         }
1117                         
1118                         break;
1119                         
1120                 } else {
1121                         
1122                         FastForward = true;
1123                         continue;
1124                         
1125                 }
1126                 
1127                 if (PageHeader[HeaderSeek] == '\n'){
1128                         HeaderName = "";
1129                 }
1130                 
1131                 //HeaderName += PageHeader.substr(HeaderSeek, 1);
1132                 
1133         }
1134         
1135         // Split the header data.
1136         
1137         std::string DAVHeaderValue;
1138         
1139         for (int HeaderSeek = 0; HeaderSeek < HeaderValue.size(); HeaderSeek++){
1140                 
1141                 if (HeaderValue.substr(HeaderSeek, 1) == ","){
1142                         DAVHeaderList.push_back(DAVHeaderValue);
1143                         DAVHeaderValue = "";
1144                         HeaderSeek++;
1145                         continue;
1146                 }
1147                 
1148                 DAVHeaderValue += HeaderValue[HeaderSeek];
1149                 
1150         }
1151         
1152         if (DAVHeaderValue.size() > 0){
1153                 
1154                 DAVHeaderList.push_back(DAVHeaderValue);
1155                 
1156         }
1157         
1158         return DAVHeaderList;
1159         
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