1 // CardDAV2.cpp - CardDAV v2 class
3 // (c) 2012-2016 Xestia Software Development.
5 // This file is part of Xestia Address Book.
7 // Xestia Address Book is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License as published by the
9 // Free Software Foundation, version 3 of the license.
11 // Xestia Address Book is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License along
17 // with Xestia Address Book. If not, see <http://www.gnu.org/licenses/>
25 CardDAV2::CardDAV2(string ServerAddress, int ServerPort, string ServerUser, string ServerPass, bool ServerSSL){
27 this->ServerAddress = ServerAddress;
28 this->ServerPort = ServerPort;
29 this->ServerUser = ServerUser;
30 this->ServerPass = ServerPass;
31 this->ServerSSL = ServerSSL;
34 this->SetupConnectionObject();
38 CardDAV2::CardDAV2(string ServerAddress, int ServerPort, string ServerUser, string ServerPass, bool ServerSSL, string ServerPrefix, string ServerAccount){
40 this->ServerAddress = ServerAddress;
41 this->ServerPort = ServerPort;
42 this->ServerUser = ServerUser;
43 this->ServerPass = ServerPass;
44 this->ServerSSL = ServerSSL;
45 this->ServerPrefix = ServerPrefix;
46 this->ServerAccount = ServerAccount;
50 this->SetupConnectionObject();
54 size_t CardDAV2::WritebackFunc(char *ptr, size_t size, size_t nmemb, void *stream){
56 return static_cast<CardDAV2PassObject*>(stream)->CardDAV2Object->WritebackFuncImplementation(ptr, size, nmemb, stream);
60 size_t CardDAV2::WritebackFuncImplementation(char *ptr, size_t size, size_t nmemb, void *stream){
62 // Writeback function for the CardDAV object.
64 CardDAV2PassObject *data = static_cast<CardDAV2PassObject*>(stream);
65 data->DataSetting->append(ptr);
67 // Get the SSL engine pointer and trust if required on certain operating systems.
69 if (data->ServerUsingSSL == true) {
71 #if defined(__APPLE__)
73 const struct curl_tlssessioninfo *TLSInfo;
75 TLSCode = curl_easy_getinfo(data->ConnectionSessionObject, CURLINFO_TLS_SSL_PTR, &TLSInfo);
77 SecTrustRef CertificateData;
79 if (TLSInfo->internals != nullptr && TLSCode == CURLE_OK) {
80 SSLCopyPeerTrust((SSLContext*)TLSInfo->internals, &CertificateData);
81 data->SSLContext = CertificateData;
84 #elif defined(__WIN32__)
86 const struct curl_tlssessioninfo *TLSInfo;
88 TLSCode = curl_easy_getinfo(data->ConnectionSessionObject, CURLINFO_TLS_SSL_PTR, &TLSInfo);
90 if (TLSInfo->internals != nullptr && TLSCode == CURLE_OK) {
92 // Free the previous certificate data.
94 //CertFreeCertificateContext(CertificateData);
96 PCCERT_CONTEXT CertificateData;
98 PCtxtHandle SSLHandle = (PCtxtHandle)TLSInfo->internals;
99 SECURITY_STATUS GetData = QueryContextAttributes(SSLHandle, SECPKG_ATTR_REMOTE_CERT_CONTEXT, &CertificateData);
101 data->SSLContext = CertificateData;
113 void CardDAV2::SetCertificateData() {
117 CardDAV2::~CardDAV2(){
119 curl_easy_cleanup(ConnectionSession);
120 ConnectionSession = nullptr;
122 if (HeaderList != nullptr){
123 curl_slist_free_all(HeaderList);
124 HeaderList = nullptr;
127 #if defined(__WIN32__)
129 if (CertificateData != nullptr) {
131 CertFreeCertificateContext(CertificateData);
139 #if defined(__APPLE__)
141 SecTrustRef CardDAV2::BuildSSLCollection(){
143 return CertificateData;
147 #elif defined(__WIN32__)
149 PCCERT_CONTEXT CardDAV2::BuildSSLCollection(){
151 return CertificateData;
157 SSLCertCollectionString CardDAV2::BuildSSLCollection(){
159 // Build and return the SSL collection.
161 SSLCertCollectionString SSLCertInfo;
163 // Grab the certificate data.
166 struct curl_slist *certdata;
167 struct curl_certinfo *certinfo;
170 certptr.certdata = NULL;
172 curl_easy_getinfo(ConnectionSession, CURLINFO_CERTINFO, &certptr.certinfo);
174 std::string CertPropName;
175 std::string CertPropValue;
177 for (int i = 0; i < certptr.certinfo->num_of_certs; i++){
179 struct curl_slist *slist;
180 SSLCertDataString SSLCertDataInc;
182 for (slist = certptr.certinfo->certinfo[i]; slist; slist = slist->next){
184 // Using wxStringTokenizer from wxWidgets.
186 wxStringTokenizer CertDataInc(wxString::FromUTF8(slist->data), ":");
188 // Get first token as the property name.
190 CertPropName = CertDataInc.GetNextToken().ToStdString();
192 // Get remaining tokens as the property value.
194 while(CertDataInc.HasMoreTokens()){
196 CertPropValue.append(CertDataInc.GetNextToken());
200 SSLCertDataInc.CertData.insert(std::make_pair(CertPropName, CertPropValue));
201 CertPropName.clear();
202 CertPropValue.clear();
206 SSLCertInfo.SSLCollection.insert(std::make_pair(i, SSLCertDataInc));
216 void CardDAV2::BypassSSLVerification(bool EnableBypass) {
217 EnableSSLBypass = EnableBypass;
218 SSLSelfSigned = EnableBypass;
221 void CardDAV2::SetupConnectionObject(){
222 ConnectionSession = curl_easy_init();
225 bool CardDAV2::IsTaskCompleted(){
229 COConnectResult CardDAV2::Connect(bool DoAuthentication){
231 ServerSSL ? SetupDefaultParametersSSL(DoAuthentication) : SetupDefaultParametersNonSSL(DoAuthentication);
234 COConnectResult ConnectResult = COCONNECT_UNITTESTFAIL;
235 string ServerAddressURL = BuildURL("/principals/");
237 curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str());
239 if (TestMode == true){
240 SessionResult = curl_easy_perform(ConnectionSession);
242 SessionResult = curl_easy_perform(ConnectionSession);
245 switch(SessionResult){
247 case CURLE_HTTP_RETURNED_ERROR:
249 SSLVerified = COSSL_VERIFIED;
250 ConnectResult = COCONNECT_OK;
252 case CURLE_SSL_CACERT:
253 case CURLE_SSL_CONNECT_ERROR:
255 ConnectResult = COCONNECT_OK;
256 SSLVerified = COSSL_UNABLETOVERIFY;
259 ConnectResult = COCONNECT_INVALID;
263 // Set the certificate data (if required).
265 #if defined(__APPLE__)
269 CertificateData = PageHeaderObject.SSLContext;
273 #elif defined(__WIN32__)
277 CertificateData = PageHeaderObject.SSLContext;
283 // Check if an error occured before continuing.
285 // Check if authentication was successful.
287 long SessionResponseCode = 0;
289 curl_easy_getinfo(ConnectionSession, CURLINFO_RESPONSE_CODE, &SessionResponseCode);
291 if (DoAuthentication == true){
293 // Get the HTTP status code (Should be 200 and not 403).
294 // Return error otherwise.
296 if (SessionResponseCode == 200){
297 ConnectResult = COCONNECT_OK;
299 ValidResponse = true;
300 } else if (SessionResponseCode == 401){
301 ConnectResult = COCONNECT_AUTHFAIL;
303 ValidResponse = true;
304 } else if (SessionResponseCode >= 200) {
305 ConnectResult = COCONNECT_INVALID;
307 ValidResponse = true;
309 ConnectResult = COCONNECT_INVALID;
311 ValidResponse = false;
316 ValidResponse = true;
320 // Check the header to see if CardDAV is supported.
322 vector<string> DAVHeaderValues = GetDAVHeader();
324 for (vector<string>::iterator DAVHeaderValuesIter = DAVHeaderValues.begin();
325 DAVHeaderValuesIter != DAVHeaderValues.end(); DAVHeaderValuesIter++){
327 if ((*DAVHeaderValuesIter) == "addressbook"){
334 return ConnectResult;
338 COServerResponse CardDAV2::GetDefaultPrefix(string *ServerPrefix){
340 // Check if authentication was successful, otherwise don't do anything.
342 COServerResponse ServerResponse;
344 if (AuthPassed == false){
345 ServerResponse.RequestResult = COREQUEST_ERROR_NOTCONNECTED;
346 ServerResponse.EntityTag = "";
347 ServerResponse.SessionCode = 0;
348 ServerResponse.ResultCode = 0;
349 ServerResponse.ResultMessage = "";
350 return ServerResponse;
353 ServerSSL ? SetupDefaultParametersSSL(true) : SetupDefaultParametersNonSSL(true);
356 // Need to do three requests:
358 // 1. Get the current user principal URI.
359 // 2. Get the address book home URI.
360 // 3. Get the default address book URI.
362 // Setup the first query finding out where the principal URL is.
364 const char* CurrentUserPrincipalXMLQuery = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
365 "<D:propfind xmlns:D=\"DAV:\">\n"
367 " <D:current-user-principal/>\n"
371 // Setup the second query finding out where the address book home URL is.
373 const char* AddressBookHomeXMLQuery = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
374 "<D:propfind xmlns:D=\"DAV:\""
375 " xmlns:C=\"urn:ietf:params:xml:ns:carddav\">\n"
377 " <C:addressbook-home-set/>\n"
381 // Setup the third query finding out where the default address book URL is.
383 const char* DefaultAddressBookXMLQuery = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
384 "<D:propfind xmlns:D=\"DAV:\""
385 " xmlns:C=\"urn:ietf:params:xml:ns:carddav\">\n"
387 " <C:default-addressbook-URL/>\n"
391 string ServerAddressURL = BuildURL("/principals/");
392 curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str());
393 curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "PROPFIND");
394 curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDS, CurrentUserPrincipalXMLQuery);
395 curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDSIZE, strlen(CurrentUserPrincipalXMLQuery));
397 if (TestMode == true){
398 SessionResult = curl_easy_perform(ConnectionSession);
403 switch(SessionResult){
406 SSLVerified = COSSL_VERIFIED;
408 case CURLE_SSL_CACERT:
409 case CURLE_SSL_CONNECT_ERROR:
411 SSLVerified = COSSL_UNABLETOVERIFY;
417 long SessionResponseCode = 0;
419 curl_easy_getinfo(ConnectionSession, CURLINFO_RESPONSE_CODE, &SessionResponseCode);
421 if (SessionResponseCode == 200 || SessionResponseCode == 207){
423 ValidResponse = true;
424 } else if (SessionResponseCode == 403){
426 ValidResponse = true;
427 } else if (SessionResponseCode >= 400) {
429 ValidResponse = true;
432 ValidResponse = false;
435 if (ValidResponse == false && AuthPassed == false){
436 ServerResponse.RequestResult = COREQUEST_ERROR_SERVER;
437 ServerResponse.EntityTag = "";
438 ServerResponse.SessionCode = SessionResult;
439 ServerResponse.ResultCode = SessionResponseCode;
440 ServerResponse.ResultMessage = "";
441 return ServerResponse;
444 // Process the first response.
446 string UserPrincipalURI = GetUserPrincipalURI();
448 // Cleanup and reset for the second connection.
450 ServerSSL ? SetupDefaultParametersSSL(true) : SetupDefaultParametersNonSSL(true);
453 ServerAddressURL = BuildURL(UserPrincipalURI);
454 curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str());
455 curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "PROPFIND");
456 curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDS, AddressBookHomeXMLQuery);
457 curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDSIZE, strlen(AddressBookHomeXMLQuery));
459 if (TestMode == true){
460 SessionResult = curl_easy_perform(ConnectionSession);
465 switch(SessionResult){
468 SSLVerified = COSSL_VERIFIED;
470 case CURLE_SSL_CACERT:
471 case CURLE_SSL_CONNECT_ERROR:
473 SSLVerified = COSSL_UNABLETOVERIFY;
479 SessionResponseCode = 0;
481 curl_easy_getinfo(ConnectionSession, CURLINFO_RESPONSE_CODE, &SessionResponseCode);
483 if (SessionResponseCode == 200 || SessionResponseCode == 207){
485 ValidResponse = true;
486 } else if (SessionResponseCode == 403){
488 ValidResponse = true;
489 } else if (SessionResponseCode >= 400) {
491 ValidResponse = true;
494 ValidResponse = false;
497 if (ValidResponse == false && AuthPassed == false){
498 ServerResponse.RequestResult = COREQUEST_ERROR_SERVER;
499 ServerResponse.EntityTag = "";
500 ServerResponse.SessionCode = SessionResult;
501 ServerResponse.ResultCode = SessionResponseCode;
502 ServerResponse.ResultMessage = "";
503 return ServerResponse;
506 // Process the second response.
508 string AddressBookHomeURI = GetAddressBookHomeURI();
510 // Cleanup and reset for the second connection.
512 ServerSSL ? SetupDefaultParametersSSL(true) : SetupDefaultParametersNonSSL(true);
515 ServerAddressURL = BuildURL(AddressBookHomeURI);
516 curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str());
517 curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "PROPFIND");
518 curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDS, DefaultAddressBookXMLQuery);
519 curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDSIZE, strlen(DefaultAddressBookXMLQuery));
521 if (TestMode == true){
522 SessionResult = curl_easy_perform(ConnectionSession);
527 switch(SessionResult){
530 SSLVerified = COSSL_VERIFIED;
532 case CURLE_SSL_CACERT:
533 case CURLE_SSL_CONNECT_ERROR:
535 SSLVerified = COSSL_UNABLETOVERIFY;
541 SessionResponseCode = 0;
543 curl_easy_getinfo(ConnectionSession, CURLINFO_RESPONSE_CODE, &SessionResponseCode);
545 if (SessionResponseCode == 200 || SessionResponseCode == 207){
547 ValidResponse = true;
548 } else if (SessionResponseCode == 403){
550 ValidResponse = true;
551 } else if (SessionResponseCode >= 200) {
553 ValidResponse = true;
556 ValidResponse = false;
559 if (ValidResponse == false || AuthPassed == false){
560 ServerResponse.RequestResult = COREQUEST_ERROR_SERVER;
561 ServerResponse.EntityTag = "";
562 ServerResponse.SessionCode = SessionResult;
563 ServerResponse.ResultCode = SessionResponseCode;
564 ServerResponse.ResultMessage = "";
565 return ServerResponse;
568 // Process the second response.
570 (*ServerPrefix) = GetDefaultAddressBookURI();
574 ServerResponse.RequestResult = COREQUEST_OK;
575 ServerResponse.EntityTag = "";
576 ServerResponse.SessionCode = SessionResult;
577 ServerResponse.ResultCode = SessionResponseCode;
578 ServerResponse.ResultMessage = SessionErrorBuffer;
579 return ServerResponse;
583 std::string CardDAV2::GetUserPrincipalURI(){
585 xmlDocPtr xmlCardDAVDoc;
586 xmlCardDAVDoc = xmlReadMemory(PageData.c_str(), (int)PageData.size(), "noname.xml", NULL, 0);
587 string UserPrincipalURI = "";
589 xmlNodePtr nodeLevel1;
590 xmlNodePtr nodeLevel2;
591 xmlNodePtr nodeLevel3;
592 xmlNodePtr nodeLevel4;
593 xmlNodePtr nodeLevel5;
594 xmlNodePtr nodeLevel6;
595 xmlNodePtr nodeLevel7;
597 for (nodeLevel1 = xmlCardDAVDoc->children;
599 nodeLevel1 = nodeLevel1->next)
602 for (nodeLevel2 = nodeLevel1->children;
604 nodeLevel2 = nodeLevel2->next)
608 for (nodeLevel3 = nodeLevel2->children;
610 nodeLevel3 = nodeLevel3->next)
613 for (nodeLevel4 = nodeLevel3->children;
615 nodeLevel4 = nodeLevel4->next)
618 for (nodeLevel5 = nodeLevel4->children;
620 nodeLevel5 = nodeLevel5->next)
623 for (nodeLevel6 = nodeLevel5->children;
625 nodeLevel6 = nodeLevel6->next)
628 if (!xmlStrcmp(nodeLevel6->name, (const xmlChar *)"href") ||
629 !xmlStrcmp(nodeLevel6->name, (const xmlChar *)"d:href") ||
630 !xmlStrcmp(nodeLevel6->name, (const xmlChar *)"D:href")
633 // Found the <href> part so extract the principal URL address.
635 for (nodeLevel7 = nodeLevel6->children;
637 nodeLevel7 = nodeLevel7->next)
640 UserPrincipalURI = ((const char*)nodeLevel7->content);
658 xmlFreeDoc(xmlCardDAVDoc);
660 return UserPrincipalURI;
664 std::string CardDAV2::GetAddressBookHomeURI(){
666 xmlDocPtr xmlCardDAVDoc;
667 xmlCardDAVDoc = xmlReadMemory(PageData.c_str(), (int)PageData.size(), "noname.xml", NULL, 0);
668 string AddressBookHomeURI = "";
670 xmlNodePtr nodeLevel1;
671 xmlNodePtr nodeLevel2;
672 xmlNodePtr nodeLevel3;
673 xmlNodePtr nodeLevel4;
674 xmlNodePtr nodeLevel5;
675 xmlNodePtr nodeLevel6;
676 xmlNodePtr nodeLevel7;
678 for (nodeLevel1 = xmlCardDAVDoc->children;
680 nodeLevel1 = nodeLevel1->next)
683 for (nodeLevel2 = nodeLevel1->children;
685 nodeLevel2 = nodeLevel2->next)
689 for (nodeLevel3 = nodeLevel2->children;
691 nodeLevel3 = nodeLevel3->next)
694 for (nodeLevel4 = nodeLevel3->children;
696 nodeLevel4 = nodeLevel4->next)
699 for (nodeLevel5 = nodeLevel4->children;
701 nodeLevel5 = nodeLevel5->next)
704 for (nodeLevel6 = nodeLevel5->children;
706 nodeLevel6 = nodeLevel6->next)
709 if (!xmlStrcmp(nodeLevel6->name, (const xmlChar *)"href") ||
710 !xmlStrcmp(nodeLevel6->name, (const xmlChar *)"d:href") ||
711 !xmlStrcmp(nodeLevel6->name, (const xmlChar *)"D:href")
714 // Found the <href> part so extract the principal URL address.
716 for (nodeLevel7 = nodeLevel6->children;
718 nodeLevel7 = nodeLevel7->next)
721 AddressBookHomeURI = ((const char*)nodeLevel7->content);
739 xmlFreeDoc(xmlCardDAVDoc);
741 return AddressBookHomeURI;
745 std::string CardDAV2::GetDefaultAddressBookURI(){
747 xmlDocPtr xmlCardDAVDoc;
748 xmlCardDAVDoc = xmlReadMemory(PageData.c_str(), (int)PageData.size(), "noname.xml", NULL, 0);
749 string DefaultAddressBookURI = "";
751 xmlNodePtr nodeLevel1;
752 xmlNodePtr nodeLevel2;
753 xmlNodePtr nodeLevel3;
754 xmlNodePtr nodeLevel4;
755 xmlNodePtr nodeLevel5;
756 xmlNodePtr nodeLevel6;
757 xmlNodePtr nodeLevel7;
759 for (nodeLevel1 = xmlCardDAVDoc->children;
761 nodeLevel1 = nodeLevel1->next)
764 for (nodeLevel2 = nodeLevel1->children;
766 nodeLevel2 = nodeLevel2->next)
770 for (nodeLevel3 = nodeLevel2->children;
772 nodeLevel3 = nodeLevel3->next)
775 for (nodeLevel4 = nodeLevel3->children;
777 nodeLevel4 = nodeLevel4->next)
780 for (nodeLevel5 = nodeLevel4->children;
782 nodeLevel5 = nodeLevel5->next)
785 for (nodeLevel6 = nodeLevel5->children;
787 nodeLevel6 = nodeLevel6->next)
790 if (!xmlStrcmp(nodeLevel6->name, (const xmlChar *)"href") ||
791 !xmlStrcmp(nodeLevel6->name, (const xmlChar *)"d:href") ||
792 !xmlStrcmp(nodeLevel6->name, (const xmlChar *)"D:href")
795 // Found the <href> part so extract the principal URL address.
797 for (nodeLevel7 = nodeLevel6->children;
799 nodeLevel7 = nodeLevel7->next)
802 DefaultAddressBookURI = ((const char*)nodeLevel7->content);
820 xmlFreeDoc(xmlCardDAVDoc);
822 return DefaultAddressBookURI;
826 COServerResponse CardDAV2::AddContact(std::string Location, std::string Data){
828 // Check if authentication was successful, otherwise don't do anything.
830 COServerResponse ServerResponse;
832 if (AuthPassed == false){
833 ServerResponse.RequestResult = COREQUEST_ERROR_NOTCONNECTED;
834 ServerResponse.EntityTag = "";
835 ServerResponse.SessionCode = 0;
836 ServerResponse.ResultCode = 0;
837 ServerResponse.ResultMessage = "";
838 return ServerResponse;
841 ServerSSL ? SetupDefaultParametersSSL(true) : SetupDefaultParametersNonSSL(true);
844 string ServerAddressURL = BuildURL(ServerPrefix + Location);
845 curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str());
846 curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "PUT");
847 curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDS, Data.c_str());
848 curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDSIZE, strlen(Data.c_str()));
850 HeaderList = curl_slist_append(HeaderList, "Content-Type: text/vcard; charset=utf-8");
852 curl_easy_setopt(ConnectionSession, CURLOPT_HTTPHEADER, HeaderList);
854 if (TestMode == true){
855 SessionResult = curl_easy_perform(ConnectionSession);
857 SessionResult = curl_easy_perform(ConnectionSession);
860 switch(SessionResult){
863 SSLVerified = COSSL_VERIFIED;
865 case CURLE_SSL_CACERT:
866 case CURLE_SSL_CONNECT_ERROR:
868 SSLVerified = COSSL_UNABLETOVERIFY;
874 long SessionResponseCode = 0;
876 curl_easy_getinfo(ConnectionSession, CURLINFO_RESPONSE_CODE, &SessionResponseCode);
878 if (SessionResponseCode == 200 || SessionResponseCode == 201 || SessionResponseCode == 204){
880 ValidResponse = true;
881 } else if (SessionResponseCode == 403){
883 ValidResponse = true;
884 } else if (SessionResponseCode >= 400){
886 ValidResponse = true;
889 ValidResponse = false;
892 if (ValidResponse == false || AuthPassed == false){
893 ServerResponse.RequestResult = COREQUEST_ERROR_SERVER;
894 ServerResponse.EntityTag = "";
895 ServerResponse.SessionCode = SessionResult;
896 ServerResponse.ResultCode = SessionResponseCode;
897 ServerResponse.ResultMessage = "";
898 return ServerResponse;
903 ServerResponse.RequestResult = COREQUEST_OK;
904 ServerResponse.EntityTag = "";
905 ServerResponse.SessionCode = SessionResult;
906 ServerResponse.ResultCode = SessionResponseCode;
907 ServerResponse.ResultMessage = SessionErrorBuffer;
908 return ServerResponse;
912 COServerResponse CardDAV2::EditContact(std::string Location, std::string Data){
914 // Check if authentication was successful, otherwise don't do anything.
916 COServerResponse ServerResponse;
918 if (AuthPassed == false){
919 ServerResponse.RequestResult = COREQUEST_ERROR_NOTCONNECTED;
920 ServerResponse.EntityTag = "";
921 ServerResponse.SessionCode = 0;
922 ServerResponse.ResultCode = 0;
923 ServerResponse.ResultMessage = "";
924 return ServerResponse;
927 ServerSSL ? SetupDefaultParametersSSL(true) : SetupDefaultParametersNonSSL(true);
930 string ServerAddressURL = BuildURL(ServerPrefix + Location);
931 curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str());
932 curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "PUT");
933 curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDS, Data.c_str());
934 curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDSIZE, strlen(Data.c_str()));
936 HeaderList = curl_slist_append(HeaderList, "Content-Type: text/vcard; charset=utf-8");
938 curl_easy_setopt(ConnectionSession, CURLOPT_HTTPHEADER, HeaderList);
940 if (TestMode == true){
941 SessionResult = curl_easy_perform(ConnectionSession);
943 SessionResult = curl_easy_perform(ConnectionSession);
946 switch(SessionResult){
949 SSLVerified = COSSL_VERIFIED;
951 case CURLE_SSL_CACERT:
952 case CURLE_SSL_CONNECT_ERROR:
954 SSLVerified = COSSL_UNABLETOVERIFY;
960 long SessionResponseCode = 0;
962 curl_easy_getinfo(ConnectionSession, CURLINFO_RESPONSE_CODE, &SessionResponseCode);
964 if (SessionResponseCode == 200 || SessionResponseCode == 201 || SessionResponseCode == 204){
966 ValidResponse = true;
967 } else if (SessionResponseCode == 403){
969 ValidResponse = true;
970 } else if (SessionResponseCode >= 400){
972 ValidResponse = true;
975 ValidResponse = false;
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;
989 ServerResponse.RequestResult = COREQUEST_OK;
990 ServerResponse.EntityTag = "";
991 ServerResponse.SessionCode = SessionResult;
992 ServerResponse.ResultCode = SessionResponseCode;
993 ServerResponse.ResultMessage = SessionErrorBuffer;
994 return ServerResponse;
998 COServerResponse CardDAV2::DeleteContact(std::string Location){
1000 // Check if authentication was successful, otherwise don't do anything.
1002 COServerResponse ServerResponse;
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;
1013 ServerSSL ? SetupDefaultParametersSSL(true) : SetupDefaultParametersNonSSL(true);
1016 string ServerAddressURL = BuildURL(ServerPrefix + Location);
1017 curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str());
1018 curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "DELETE");
1020 if (TestMode == true){
1021 SessionResult = curl_easy_perform(ConnectionSession);
1023 SessionResult = curl_easy_perform(ConnectionSession);
1026 switch(SessionResult){
1029 SSLVerified = COSSL_VERIFIED;
1031 case CURLE_SSL_CACERT:
1032 case CURLE_SSL_CONNECT_ERROR:
1034 SSLVerified = COSSL_UNABLETOVERIFY;
1040 long SessionResponseCode = 0;
1042 curl_easy_getinfo(ConnectionSession, CURLINFO_RESPONSE_CODE, &SessionResponseCode);
1044 if (SessionResponseCode == 200 || SessionResponseCode == 202 || SessionResponseCode == 204){
1046 ValidResponse = true;
1047 } else if (SessionResponseCode == 403){
1049 ValidResponse = true;
1050 } else if (SessionResponseCode >= 400){
1052 ValidResponse = true;
1055 ValidResponse = false;
1058 if (ValidResponse == false || AuthPassed == false){
1059 ServerResponse.RequestResult = COREQUEST_ERROR_SERVER;
1060 ServerResponse.EntityTag = "";
1061 ServerResponse.SessionCode = SessionResult;
1062 ServerResponse.ResultCode = SessionResponseCode;
1063 ServerResponse.ResultMessage = "";
1064 return ServerResponse;
1069 ServerResponse.RequestResult = COREQUEST_OK;
1070 ServerResponse.EntityTag = "";
1071 ServerResponse.SessionCode = SessionResult;
1072 ServerResponse.ResultCode = SessionResponseCode;
1073 ServerResponse.ResultMessage = SessionErrorBuffer;
1074 return ServerResponse;
1078 COServerResponse CardDAV2::GetServerEntityTagValue(std::string Location){
1080 // Check if authentication was successful, otherwise don't do anything.
1082 COServerResponse ServerResponse;
1084 if (AuthPassed == false){
1085 ServerResponse.RequestResult = COREQUEST_ERROR_NOTCONNECTED;
1086 ServerResponse.EntityTag = "";
1087 ServerResponse.SessionCode = 0;
1088 ServerResponse.ResultCode = 0;
1089 ServerResponse.ResultMessage = "";
1090 return ServerResponse;
1093 ServerSSL ? SetupDefaultParametersSSL(true) : SetupDefaultParametersNonSSL(true);
1096 static const char* GetETagQuery =
1097 "<?xml version=\"1.0\" encoding=\"utf-8\" ?>"
1098 "<C:addressbook-query xmlns:D=\"DAV:\""
1099 " xmlns:C=\"urn:ietf:params:xml:ns:carddav\">"
1100 "<D:prop><D:getetag/>"
1103 "</C:addressbook-query>";
1105 string ServerAddressURL = BuildURL(ServerPrefix + Location);
1106 curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str());
1107 curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "REPORT");
1108 curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDS, GetETagQuery);
1109 curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDSIZE, strlen(GetETagQuery));
1111 if (TestMode == true){
1112 SessionResult = curl_easy_perform(ConnectionSession);
1114 SessionResult = curl_easy_perform(ConnectionSession);
1117 switch(SessionResult){
1120 SSLVerified = COSSL_VERIFIED;
1122 case CURLE_SSL_CACERT:
1123 case CURLE_SSL_CONNECT_ERROR:
1125 SSLVerified = COSSL_UNABLETOVERIFY;
1131 long SessionResponseCode = 0;
1133 curl_easy_getinfo(ConnectionSession, CURLINFO_RESPONSE_CODE, &SessionResponseCode);
1135 if (SessionResponseCode == 207){
1137 ValidResponse = true;
1138 } else if (SessionResponseCode == 403){
1140 ValidResponse = true;
1141 } else if (SessionResponseCode >= 400){
1143 ValidResponse = true;
1146 ValidResponse = false;
1149 if (ValidResponse == false || AuthPassed == false){
1150 ServerResponse.RequestResult = COREQUEST_ERROR_SERVER;
1151 ServerResponse.EntityTag = "";
1152 ServerResponse.SessionCode = SessionResult;
1153 ServerResponse.ResultCode = SessionResponseCode;
1154 ServerResponse.ResultMessage = "";
1155 return ServerResponse;
1160 ServerResponse.RequestResult = COREQUEST_OK;
1161 ServerResponse.EntityTag = GetETagValue();
1162 ServerResponse.SessionCode = SessionResult;
1163 ServerResponse.ResultCode = SessionResponseCode;
1164 ServerResponse.ResultMessage = SessionErrorBuffer;
1166 return ServerResponse;
1170 COServerResponse CardDAV2::GetContact(std::string Location, std::string *ContactData){
1172 // Check if authentication was successful, otherwise don't do anything.
1174 COServerResponse ServerResponse;
1176 if (AuthPassed == false){
1177 ServerResponse.RequestResult = COREQUEST_ERROR_NOTCONNECTED;
1178 ServerResponse.EntityTag = "";
1179 ServerResponse.SessionCode = 0;
1180 ServerResponse.ResultCode = 0;
1181 ServerResponse.ResultMessage = "";
1182 return ServerResponse;
1185 ServerSSL ? SetupDefaultParametersSSL(true) : SetupDefaultParametersNonSSL(true);
1188 string ServerAddressURL = BuildURL(ServerPrefix + Location);
1189 curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str());
1190 curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "GET");
1192 if (TestMode == true){
1193 SessionResult = curl_easy_perform(ConnectionSession);
1195 SessionResult = curl_easy_perform(ConnectionSession);
1198 switch(SessionResult){
1201 SSLVerified = COSSL_VERIFIED;
1203 case CURLE_SSL_CACERT:
1204 case CURLE_SSL_CONNECT_ERROR:
1206 SSLVerified = COSSL_UNABLETOVERIFY;
1212 long SessionResponseCode = 0;
1214 curl_easy_getinfo(ConnectionSession, CURLINFO_RESPONSE_CODE, &SessionResponseCode);
1216 if (SessionResponseCode == 200){
1218 ValidResponse = true;
1219 } else if (SessionResponseCode == 403){
1221 ValidResponse = true;
1222 } else if (SessionResponseCode >= 400){
1224 ValidResponse = true;
1227 ValidResponse = false;
1230 if (ValidResponse == false && AuthPassed == false){
1231 ServerResponse.RequestResult = COREQUEST_ERROR_SERVER;
1232 ServerResponse.EntityTag = "";
1233 ServerResponse.SessionCode = SessionResult;
1234 ServerResponse.ResultCode = SessionResponseCode;
1235 ServerResponse.ResultMessage = "";
1236 return ServerResponse;
1241 ServerResponse.RequestResult = COREQUEST_OK;
1242 ServerResponse.EntityTag = "";
1243 ServerResponse.SessionCode = SessionResult;
1244 ServerResponse.ResultCode = SessionResponseCode;
1245 ServerResponse.ResultMessage = SessionErrorBuffer;
1247 (*ContactData) = PageData;
1249 return ServerResponse;
1253 COContactList CardDAV2::GetContactList(std::string SyncToken){
1255 COContactList ServerContactList;
1257 // Check if authentication was successful, otherwise don't do anything.
1259 if (AuthPassed == false){
1260 ServerContactList.ServerResponse.RequestResult = COREQUEST_ERROR_NOTCONNECTED;
1261 ServerContactList.ServerResponse.EntityTag = "";
1262 ServerContactList.ServerResponse.SessionCode = 0;
1263 ServerContactList.ServerResponse.ResultCode = 0;
1264 ServerContactList.ServerResponse.ResultMessage = "";
1265 return ServerContactList;
1268 ServerSSL ? SetupDefaultParametersSSL(true) : SetupDefaultParametersNonSSL(true);
1271 std::string SyncData;
1273 // TODO: Copy old code from CardDAV class as needed.
1275 if (SyncToken.size() > 0){
1277 SyncData = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
1278 "<D:sync-collection xmlns:D=\"DAV:\"\n"
1279 " xmlns:C=\"urn:ietf:params:xml:ns:carddav\">\n"
1281 SyncData.append(SyncToken);
1282 SyncData.append("</D:sync-token>\n"
1283 "<D:sync-level>1</D:sync-level>\n"
1287 "</D:sync-collection>");
1291 SyncData = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
1292 "<D:sync-collection xmlns:D=\"DAV:\"\n"
1293 " xmlns:C=\"urn:ietf:params:xml:ns:carddav\">\n"
1294 "<D:sync-level>1</D:sync-level>\n"
1298 "</D:sync-collection>";
1302 string ServerAddressURL = BuildURL(ServerPrefix);
1304 curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str());
1305 curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDS, SyncData.c_str());
1306 curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDSIZE, strlen(SyncData.c_str()));
1307 curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "REPORT");
1309 HeaderList = curl_slist_append(HeaderList, "Content-Type: application/xml; charset=utf-8");
1310 HeaderList = curl_slist_append(HeaderList, "Depth: 1");
1312 curl_easy_setopt(ConnectionSession, CURLOPT_HTTPHEADER, HeaderList);
1314 if (TestMode == true){
1315 SessionResult = curl_easy_perform(ConnectionSession);
1317 SessionResult = curl_easy_perform(ConnectionSession);
1320 switch(SessionResult){
1323 SSLVerified = COSSL_VERIFIED;
1325 case CURLE_SSL_CACERT:
1326 case CURLE_SSL_CONNECT_ERROR:
1328 SSLVerified = COSSL_UNABLETOVERIFY;
1334 long SessionResponseCode = 0;
1336 curl_easy_getinfo(ConnectionSession, CURLINFO_RESPONSE_CODE, &SessionResponseCode);
1338 if (SessionResponseCode == 207){
1340 ValidResponse = true;
1341 } else if (SessionResponseCode == 403){
1343 ValidResponse = true;
1344 } else if (SessionResponseCode >= 400){
1346 ValidResponse = true;
1349 ValidResponse = false;
1352 if (ValidResponse == false || AuthPassed == false){
1353 ServerContactList.ServerResponse.RequestResult = COREQUEST_ERROR_SERVER;
1354 ServerContactList.ServerResponse.EntityTag = "";
1355 ServerContactList.ServerResponse.SessionCode = SessionResult;
1356 ServerContactList.ServerResponse.ResultCode = SessionResponseCode;
1357 ServerContactList.ServerResponse.ResultMessage = "";
1358 return ServerContactList;
1363 ProcessContactData(&ServerContactList);
1365 ServerContactList.ServerResponse.RequestResult = COREQUEST_OK;
1366 ServerContactList.ServerResponse.EntityTag = "";
1367 ServerContactList.ServerResponse.SessionCode = SessionResult;
1368 ServerContactList.ServerResponse.ResultCode = SessionResponseCode;
1369 ServerContactList.ServerResponse.ResultMessage = SessionErrorBuffer;
1371 return ServerContactList;
1375 bool CardDAV2::CanDoProcessing(){
1379 bool CardDAV2::CanDoSSL(){
1383 COSSLVerified CardDAV2::SSLVerify(){
1387 bool CardDAV2::AbleToLogin(){
1391 bool CardDAV2::HasValidResponse(){
1392 return ValidResponse;
1395 bool CardDAV2::IsSelfSigned(){
1396 return SSLSelfSigned;
1399 void CardDAV2::SetupDefaultParametersNonSSL(bool DoAuthentication){
1401 std::string ServerAddress = "";
1403 string ServerAddressURL = "http://" + ServerAddress + ":" + to_string(ServerPort) + "/";
1404 string UsernamePassword = ServerUser + ":" + ServerPass;
1406 PageDataObject.CardDAV2Object = this;
1407 PageDataObject.ConnectionSessionObject = ConnectionSession;
1408 PageDataObject.DataSetting = &PageData;
1409 PageDataObject.ServerUsingSSL = false;
1411 PageHeaderObject.CardDAV2Object = this;
1412 PageHeaderObject.ConnectionSessionObject = ConnectionSession;
1413 PageHeaderObject.DataSetting = &PageHeader;
1414 PageHeaderObject.ServerUsingSSL = false;
1416 curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddress.c_str());
1417 curl_easy_setopt(ConnectionSession, CURLOPT_NOPROGRESS, 1L);
1418 curl_easy_setopt(ConnectionSession, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST|CURLAUTH_BASIC);
1419 curl_easy_setopt(ConnectionSession, CURLOPT_TIMEOUT, 60);
1420 curl_easy_setopt(ConnectionSession, CURLOPT_FAILONERROR, true);
1421 curl_easy_setopt(ConnectionSession, CURLOPT_USERAGENT, XSDAB_USERAGENT);
1422 curl_easy_setopt(ConnectionSession, CURLOPT_WRITEFUNCTION, CardDAV2::WritebackFunc);
1423 curl_easy_setopt(ConnectionSession, CURLOPT_WRITEDATA, &PageDataObject);
1424 curl_easy_setopt(ConnectionSession, CURLOPT_WRITEHEADER, &PageHeaderObject);
1425 curl_easy_setopt(ConnectionSession, CURLOPT_NOSIGNAL, 1L);
1426 curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "GET");
1427 curl_easy_setopt(ConnectionSession, CURLOPT_HTTPHEADER, nullptr);
1428 curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDS, nullptr);
1429 curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDSIZE, 0L);
1431 if (DoAuthentication == true){
1432 curl_easy_setopt(ConnectionSession, CURLOPT_USERPWD, UsernamePassword.c_str());
1434 curl_easy_setopt(ConnectionSession, CURLOPT_USERPWD, NULL);
1439 void CardDAV2::SetupDefaultParametersSSL(bool DoAuthentication){
1441 // Setup the default parameters.
1443 string ServerAddressURL = "https://" + ServerAddress + ":" + to_string(ServerPort) + "/";
1444 string UsernamePassword = ServerUser + ":" + ServerPass;
1446 PageDataObject.CardDAV2Object = this;
1447 PageDataObject.ConnectionSessionObject = ConnectionSession;
1448 PageDataObject.DataSetting = &PageData;
1449 PageDataObject.ServerUsingSSL = true;
1451 PageHeaderObject.CardDAV2Object = this;
1452 PageHeaderObject.ConnectionSessionObject = ConnectionSession;
1453 PageHeaderObject.DataSetting = &PageHeader;
1454 PageHeaderObject.ServerUsingSSL = true;
1456 curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str());
1457 curl_easy_setopt(ConnectionSession, CURLOPT_NOPROGRESS, 1L);
1458 curl_easy_setopt(ConnectionSession, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST|CURLAUTH_BASIC);
1459 curl_easy_setopt(ConnectionSession, CURLOPT_TIMEOUT, 60);
1460 curl_easy_setopt(ConnectionSession, CURLOPT_FAILONERROR, 0L);
1461 curl_easy_setopt(ConnectionSession, CURLOPT_USERAGENT, XSDAB_USERAGENT);
1462 curl_easy_setopt(ConnectionSession, CURLOPT_WRITEFUNCTION, CardDAV2::WritebackFunc);
1463 curl_easy_setopt(ConnectionSession, CURLOPT_WRITEDATA, &PageDataObject);
1464 curl_easy_setopt(ConnectionSession, CURLOPT_WRITEHEADER, &PageHeaderObject);
1465 curl_easy_setopt(ConnectionSession, CURLOPT_ERRORBUFFER, SessionErrorBuffer);
1466 //curl_easy_setopt(ConnectionSession, CURLOPT_NOSIGNAL, 1L);
1467 curl_easy_setopt(ConnectionSession, CURLOPT_CERTINFO, 1L);
1468 //curl_easy_setopt(ConnectionSession, CURLOPT_VERBOSE, 2L);
1469 curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "GET");
1470 curl_easy_setopt(ConnectionSession, CURLOPT_HTTPHEADER, nullptr);
1471 curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDS, nullptr);
1472 curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDSIZE, 0L);
1474 if (DoAuthentication == true){
1475 curl_easy_setopt(ConnectionSession, CURLOPT_USERPWD, UsernamePassword.c_str());
1477 curl_easy_setopt(ConnectionSession, CURLOPT_USERPWD, NULL);
1480 if (EnableSSLBypass == true){
1481 curl_easy_setopt(ConnectionSession, CURLOPT_SSL_VERIFYHOST, 0L);
1482 curl_easy_setopt(ConnectionSession, CURLOPT_SSL_VERIFYPEER, 0L);
1483 curl_easy_setopt(ConnectionSession, CURLOPT_SSL_VERIFYSTATUS, 0L);
1485 curl_easy_setopt(ConnectionSession, CURLOPT_SSL_VERIFYHOST, 2L);
1486 curl_easy_setopt(ConnectionSession, CURLOPT_SSL_VERIFYPEER, 1L);
1487 curl_easy_setopt(ConnectionSession, CURLOPT_SSL_VERIFYSTATUS, 1L);
1490 #if !defined(__APPLE__) || defined(__WIN32__)
1492 if (TestMode == false && ServerAccount.size() > 0){
1494 // Check if the server certificate file exists.
1496 string CertificateFilename = GetAccountDir(ServerAccount, true);
1498 if (wxFile::Exists(CertificateFilename)){
1500 curl_easy_setopt(ConnectionSession, CURLOPT_CAINFO, CertificateFilename.c_str());
1510 string CardDAV2::BuildURL(string URI){
1512 string ServerAddressURL;
1514 if (SSLStatus == true){
1515 ServerAddressURL = "https://" + ServerAddress + ":" + to_string(ServerPort) + URI;
1517 ServerAddressURL = "http://" + ServerAddress + ":" + to_string(ServerPort) + URI;
1520 return ServerAddressURL;
1524 string CardDAV2::GetErrorMessage(){
1526 ErrorMessage = SessionErrorBuffer;
1527 return ErrorMessage;
1531 void CardDAV2::ResetResults(){
1534 COSSLVerified SSLVerified = COSSL_NORESULT;
1535 ValidResponse = false;
1538 SSLSelfSigned = false;
1539 TaskCompleted = false;
1541 SessionErrorBuffer[0] = '\0';
1542 SessionResult = CURLE_OK;
1545 if (HeaderList != nullptr){
1546 curl_slist_free_all(HeaderList);
1547 HeaderList = nullptr;
1552 string CardDAV2::GetETagValue(){
1554 xmlDocPtr xmlCardDAVDoc;
1556 xmlCardDAVDoc = xmlReadMemory(PageData.c_str(), (int)PageData.size(), "noname.xml", NULL, 0);
1558 xmlNodePtr nodeLevel1;
1559 xmlNodePtr nodeLevel2;
1560 xmlNodePtr nodeLevel3;
1561 xmlNodePtr nodeLevel4;
1562 xmlNodePtr nodeLevel5;
1563 xmlNodePtr nodeLevel6;
1565 //std::map<wxString,wxString> xmlDataMap;
1567 std::string DataFilename;
1568 std::string ETagData;
1570 std::string xmlStringSafe;
1571 std::string ETagValue;
1573 // Tranverse through the catacombs of the response to get our ETag for the file.
1575 for (nodeLevel1 = xmlCardDAVDoc->children;
1577 nodeLevel1 = nodeLevel1->next)
1580 bool HREFFound = FALSE;
1581 bool ETagFound = FALSE;
1583 for (nodeLevel2 = nodeLevel1->children;
1585 nodeLevel2 = nodeLevel2->next)
1588 for (nodeLevel3 = nodeLevel2->children;
1590 nodeLevel3 = nodeLevel3->next)
1593 if (!xmlStrcmp(nodeLevel3->name, (const xmlChar *)"href") ||
1594 !xmlStrcmp(nodeLevel3->name, (const xmlChar *)"d:href") ||
1595 !xmlStrcmp(nodeLevel3->name, (const xmlChar *)"D:href")
1598 // Get the filename.
1600 for (nodeLevel4 = nodeLevel3->children;
1602 nodeLevel4 = nodeLevel4->next)
1605 if (!xmlStrcmp(nodeLevel4->name, (const xmlChar *)"text") ||
1606 !xmlStrcmp(nodeLevel4->name, (const xmlChar *)"d:text") ||
1607 !xmlStrcmp(nodeLevel4->name, (const xmlChar *)"D:text")
1610 DataFilename = wxString::FromUTF8((const char*)nodeLevel4->content);
1611 wxStringTokenizer wSTDFilename(DataFilename, wxT("/"));
1613 while (wSTDFilename.HasMoreTokens()){
1615 DataFilename = wSTDFilename.GetNextToken().ToStdString();
1629 for (nodeLevel4 = nodeLevel3->children;
1631 nodeLevel4 = nodeLevel4->next)
1634 for (nodeLevel5 = nodeLevel4->children;
1636 nodeLevel5 = nodeLevel5->next)
1639 if (!xmlStrcmp(nodeLevel5->name, (const xmlChar *)"getetag") ||
1640 !xmlStrcmp(nodeLevel5->name, (const xmlChar *)"d:getetag") ||
1641 !xmlStrcmp(nodeLevel5->name, (const xmlChar *)"D:getetag")
1644 for (nodeLevel6 = nodeLevel5->children;
1646 nodeLevel6 = nodeLevel6->next)
1649 // Strip the quotes from the ETag.
1651 ETagData = (const char*)nodeLevel6->content;
1652 if (ETagData[0] == '"' && ETagData[(ETagData.size() - 1)] == '"'){
1654 ETagData.erase(0, 1);
1655 ETagData.erase((ETagData.size() - 1));
1675 if (HREFFound == TRUE && ETagFound == TRUE){
1677 // Add to the map data.
1679 ETagValue = ETagData;
1690 xmlFreeDoc(xmlCardDAVDoc);
1696 string CardDAV2::GetETagHeader(){
1698 // Go through each of the lines looking for the
1703 bool FastForward = false;
1705 for (int HeaderSeek = 0; HeaderSeek < PageHeader.size(); HeaderSeek++){
1707 if (FastForward == true){
1709 if (PageHeader[HeaderSeek] == '\n'){
1710 FastForward = false;
1718 PageHeader.substr(HeaderSeek, 5) == "ETag:";
1721 catch (const out_of_range &oor){
1725 if (PageHeader.substr(HeaderSeek, 5) == "ETag:"){
1727 int CharacterSeek = 5;
1729 while ((HeaderSeek + CharacterSeek) < PageHeader.size()){
1731 if (PageHeader.substr((HeaderSeek + CharacterSeek), 2) == "\r\n"){
1735 HeaderValue += PageHeader.substr((HeaderSeek + CharacterSeek), 1);
1748 if (PageHeader[HeaderSeek] == '\n'){
1752 //HeaderName += PageHeader.substr(HeaderSeek, 1);
1756 // Check for quotation marks at the start and end and strip
1759 if (HeaderValue.size() >= 2){
1761 if (HeaderValue[0] == '"'){
1762 HeaderValue.erase((HeaderValue.size() - 1));
1763 HeaderValue.erase(0);
1772 vector<string> CardDAV2::GetDAVHeader(){
1774 // Go through each of the lines looking for the
1779 bool FastForward = false;
1780 vector<string> DAVHeaderList;
1782 for (int HeaderSeek = 0; HeaderSeek < PageHeader.size(); HeaderSeek++){
1784 if (FastForward == true){
1786 if (PageHeader[HeaderSeek] == '\n'){
1787 FastForward = false;
1795 PageHeader.substr(HeaderSeek, 4) == "DAV:";
1798 catch (const out_of_range &oor){
1802 if (PageHeader.substr(HeaderSeek, 4) == "DAV:"){
1804 int CharacterSeek = 5;
1806 while ((HeaderSeek + CharacterSeek) < PageHeader.size()){
1808 if (PageHeader.substr((HeaderSeek + CharacterSeek), 2) == "\r\n"){
1812 HeaderValue += PageHeader.substr((HeaderSeek + CharacterSeek), 1);
1825 if (PageHeader[HeaderSeek] == '\n'){
1829 //HeaderName += PageHeader.substr(HeaderSeek, 1);
1833 // Split the header data.
1835 std::string DAVHeaderValue;
1837 for (int HeaderSeek = 0; HeaderSeek < HeaderValue.size(); HeaderSeek++){
1839 if (HeaderValue.substr(HeaderSeek, 1) == ","){
1840 DAVHeaderList.push_back(DAVHeaderValue);
1841 DAVHeaderValue = "";
1846 DAVHeaderValue += HeaderValue[HeaderSeek];
1850 if (DAVHeaderValue.size() > 0){
1852 DAVHeaderList.push_back(DAVHeaderValue);
1856 return DAVHeaderList;
1860 void CardDAV2::ProcessContactData(COContactList *ContactList){
1862 xmlDocPtr xmlCardDAVDoc;
1863 xmlCardDAVDoc = xmlReadMemory(PageData.c_str(), (int)PageData.size(), "noname.xml", NULL, 0);
1865 xmlNodePtr MultiStatusNode;
1866 xmlNodePtr ResponseNode;
1867 xmlNodePtr ResponseDataNode;
1868 xmlNodePtr PropStatNode;
1869 xmlNodePtr ValueNode;
1870 xmlNodePtr ETagNode;
1871 xmlNodePtr StatusNode;
1873 std::string HREFValue;
1874 std::string ETagValue;
1875 std::string StatusValue;
1876 std::string SyncValue;
1878 // Go through the document!
1880 MultiStatusNode = xmlCardDAVDoc->children;
1882 if (MultiStatusNode == nullptr){
1886 bool SyncTokenFound = false;
1888 // Tranverse through the catacombs of the response to get our ETag for the file and
1889 // the server syncronisation token.
1891 for (ResponseNode = MultiStatusNode->children;
1892 ResponseNode != nullptr;
1893 ResponseNode = ResponseNode->next){
1895 // Check if tag is response or sync-token.
1897 if (!xmlStrcmp(ResponseNode->name, (const xmlChar *)"response") ||
1898 !xmlStrcmp(ResponseNode->name, (const xmlChar *)"d:response") ||
1899 !xmlStrcmp(ResponseNode->name, (const xmlChar *)"D:response")){
1901 COContactStatus ContactStatus = COCS_UNKNOWN;
1903 for (ResponseDataNode = ResponseNode->children;
1904 ResponseDataNode != nullptr;
1905 ResponseDataNode = ResponseDataNode->next){
1907 if (!xmlStrcmp(ResponseDataNode->name, (const xmlChar *)"href") ||
1908 !xmlStrcmp(ResponseDataNode->name, (const xmlChar *)"d:href") ||
1909 !xmlStrcmp(ResponseDataNode->name, (const xmlChar *)"D:href")){
1911 HREFValue = (const char*)ResponseDataNode->children->content;
1913 // Get the filename after the last forward slash.
1917 for (int HREFValueSeek = 0; HREFValueSeek < HREFValue.size(); HREFValueSeek++){
1919 if (HREFValue[HREFValueSeek] == '/'){
1921 LastSlash = HREFValueSeek;
1927 HREFValue = HREFValue.substr((LastSlash + 1));
1929 } else if (!xmlStrcmp(ResponseDataNode->name, (const xmlChar *)"propstat") ||
1930 !xmlStrcmp(ResponseDataNode->name, (const xmlChar *)"d:propstat") ||
1931 !xmlStrcmp(ResponseDataNode->name, (const xmlChar *)"D:propstat")){
1933 for (PropStatNode = ResponseDataNode->children;
1934 PropStatNode != nullptr;
1935 PropStatNode = PropStatNode->next){
1937 if (!xmlStrcmp(PropStatNode->name, (const xmlChar *)"prop") ||
1938 !xmlStrcmp(PropStatNode->name, (const xmlChar *)"d:prop") ||
1939 !xmlStrcmp(PropStatNode->name, (const xmlChar *)"D:prop")){
1941 for (ETagNode = PropStatNode->children;
1942 ETagNode != nullptr;
1943 ETagNode = ETagNode->next){
1945 if (!xmlStrcmp(ETagNode->name, (const xmlChar *)"getetag") ||
1946 !xmlStrcmp(ETagNode->name, (const xmlChar *)"getetag") ||
1947 !xmlStrcmp(ETagNode->name, (const xmlChar *)"getetag")){
1949 ETagValue = (const char*)ETagNode->children->content;
1951 if (ETagValue.size() > 2 && ETagValue.substr(0,1) == "\""){
1952 ETagValue.erase((ETagValue.size() - 1),1);
1953 ETagValue.erase(0,1);
1961 } else if (!xmlStrcmp(PropStatNode->name, (const xmlChar *)"status") ||
1962 !xmlStrcmp(PropStatNode->name, (const xmlChar *)"d:status") ||
1963 !xmlStrcmp(PropStatNode->name, (const xmlChar *)"D:status")){
1965 StatusValue = (const char*)PropStatNode->children->content;
1967 if (StatusValue == "HTTP/1.1 200 OK"){
1969 ContactStatus = COCS_UPDATED;
1971 } else if (StatusValue == "HTTP/1.1 404 Not Found"){
1973 ContactStatus = COCS_DELETED;
1977 ContactStatus = COCS_UNKNOWN;
1989 COContactData ContactInformation;
1991 ContactInformation.Location = HREFValue;
1992 ContactInformation.Data = ETagValue;
1993 ContactInformation.Status = ContactStatus;
1997 StatusValue.clear();
1999 ContactList->ListData.push_back(ContactInformation);
2001 } else if (!xmlStrcmp(ResponseNode->name, (const xmlChar *)"sync-token") ||
2002 !xmlStrcmp(ResponseNode->name, (const xmlChar *)"d:sync-token") ||
2003 !xmlStrcmp(ResponseNode->name, (const xmlChar *)"D:sync-token")){
2005 SyncValue = (const char*)ResponseNode->children->content;
2011 ContactList->SyncToken = SyncValue;
2013 xmlFreeDoc(xmlCardDAVDoc);