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/>
23 CardDAV2::CardDAV2(string ServerAddress, int ServerPort, string ServerUser, string ServerPass, bool ServerSSL){
25 this->ServerAddress = ServerAddress;
26 this->ServerPort = ServerPort;
27 this->ServerUser = ServerUser;
28 this->ServerPass = ServerPass;
29 this->ServerSSL = ServerSSL;
32 this->SetupConnectionObject();
36 CardDAV2::CardDAV2(string ServerAddress, int ServerPort, string ServerUser, string ServerPass, bool ServerSSL, string ServerPrefix, string ServerAccount){
38 this->ServerAddress = ServerAddress;
39 this->ServerPort = ServerPort;
40 this->ServerUser = ServerUser;
41 this->ServerPass = ServerPass;
42 this->ServerSSL = ServerSSL;
43 this->ServerPrefix = ServerPrefix;
44 this->ServerAccount = ServerAccount;
48 this->SetupConnectionObject();
52 size_t CardDAV2::WritebackFunc(char *ptr, size_t size, size_t nmemb, void *stream){
54 return static_cast<CardDAV2PassObject*>(stream)->CardDAV2Object->WritebackFuncImplementation(ptr, size, nmemb, stream);
58 size_t CardDAV2::WritebackFuncImplementation(char *ptr, size_t size, size_t nmemb, void *stream){
60 // Writeback function for the CardDAV object.
62 CardDAV2PassObject *data = static_cast<CardDAV2PassObject*>(stream);
63 data->DataSetting->append(ptr);
65 // Get the SSL engine pointer and trust if required on certain operating systems.
67 if (data->ServerUsingSSL == true) {
69 #if defined(__APPLE__)
71 const struct curl_tlssessioninfo *TLSInfo;
73 TLSCode = curl_easy_getinfo(data->ConnectionSessionObject, CURLINFO_TLS_SSL_PTR, &TLSInfo);
75 SecTrustRef CertificateData;
77 if (TLSInfo->internals != nullptr && TLSCode == CURLE_OK) {
78 SSLCopyPeerTrust((SSLContext*)TLSInfo->internals, &CertificateData);
79 data->SSLContext = CertificateData;
82 #elif defined(__WIN32__)
84 const struct curl_tlssessioninfo *TLSInfo;
86 TLSCode = curl_easy_getinfo(data->ConnectionSessionObject, CURLINFO_TLS_SSL_PTR, &TLSInfo);
88 if (TLSInfo->internals != nullptr && TLSCode == CURLE_OK) {
90 // Free the previous certificate data.
92 //CertFreeCertificateContext(CertificateData);
94 PCCERT_CONTEXT CertificateData;
96 PCtxtHandle SSLHandle = (PCtxtHandle)TLSInfo->internals;
97 SECURITY_STATUS GetData = QueryContextAttributes(SSLHandle, SECPKG_ATTR_REMOTE_CERT_CONTEXT, &CertificateData);
99 data->SSLContext = CertificateData;
111 void CardDAV2::SetCertificateData() {
115 CardDAV2::~CardDAV2(){
117 curl_easy_cleanup(ConnectionSession);
118 ConnectionSession = nullptr;
120 if (HeaderList != nullptr){
121 curl_slist_free_all(HeaderList);
122 HeaderList = nullptr;
125 #if defined(__WIN32__)
127 if (CertificateData != nullptr) {
129 CertFreeCertificateContext(CertificateData);
137 #if defined(__APPLE__)
139 SecTrustRef CardDAV2::BuildSSLCollection(){
141 return CertificateData;
145 #elif defined(__WIN32__)
147 PCCERT_CONTEXT CardDAV2::BuildSSLCollection(){
149 return CertificateData;
155 SSLCertCollectionString CardDAV2::BuildSSLCollection(){
157 // Build and return the SSL collection.
159 SSLCertCollectionString SSLCertInfo;
161 // Grab the certificate data.
164 struct curl_slist *certdata;
165 struct curl_certinfo *certinfo;
168 certptr.certdata = NULL;
170 CURLcode result = curl_easy_getinfo(ConnectionSession, CURLINFO_CERTINFO, &certptr.certinfo);
172 std::string CertPropName;
173 std::string CertPropValue;
175 for (int i = 0; i < certptr.certinfo->num_of_certs; i++){
177 struct curl_slist *slist;
178 SSLCertDataString SSLCertDataInc;
180 for (slist = certptr.certinfo->certinfo[i]; slist; slist = slist->next){
182 // Using wxStringTokenizer from wxWidgets.
184 wxStringTokenizer CertDataInc(wxString::FromUTF8(slist->data), ":");
186 // Get first token as the property name.
188 CertPropName = CertDataInc.GetNextToken().ToStdString();
190 // Get remaining tokens as the property value.
192 while(CertDataInc.HasMoreTokens()){
194 CertPropValue.append(CertDataInc.GetNextToken());
198 SSLCertDataInc.CertData.insert(std::make_pair(CertPropName, CertPropValue));
199 CertPropName.clear();
200 CertPropValue.clear();
204 SSLCertInfo.SSLCollection.insert(std::make_pair(i, SSLCertDataInc));
214 void CardDAV2::BypassSSLVerification(bool EnableBypass) {
215 EnableSSLBypass = EnableBypass;
216 SSLSelfSigned = EnableBypass;
219 void CardDAV2::SetupConnectionObject(){
220 ConnectionSession = curl_easy_init();
223 bool CardDAV2::IsTaskCompleted(){
227 COConnectResult CardDAV2::Connect(bool DoAuthentication){
229 ServerSSL ? SetupDefaultParametersSSL(DoAuthentication) : SetupDefaultParametersNonSSL(DoAuthentication);
232 COConnectResult ConnectResult = COCONNECT_UNITTESTFAIL;
233 string ServerAddressURL = BuildURL("/principals/");
235 curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str());
237 if (TestMode == true){
238 SessionResult = curl_easy_perform(ConnectionSession);
240 SessionResult = curl_easy_perform(ConnectionSession);
243 switch(SessionResult){
245 case CURLE_HTTP_RETURNED_ERROR:
247 SSLVerified = COSSL_VERIFIED;
248 ConnectResult = COCONNECT_OK;
250 case CURLE_SSL_CACERT:
251 case CURLE_SSL_CONNECT_ERROR:
253 ConnectResult = COCONNECT_OK;
254 SSLVerified = COSSL_UNABLETOVERIFY;
257 ConnectResult = COCONNECT_INVALID;
261 // Set the certificate data (if required).
263 #if defined(__APPLE__)
267 CertificateData = PageHeaderObject.SSLContext;
271 #elif defined(__WIN32__)
275 CertificateData = PageHeaderObject.SSLContext;
281 // Check if an error occured before continuing.
283 // Check if authentication was successful.
285 long SessionResponseCode = 0;
287 curl_easy_getinfo(ConnectionSession, CURLINFO_RESPONSE_CODE, &SessionResponseCode);
289 if (DoAuthentication == true){
291 // Get the HTTP status code (Should be 200 and not 403).
292 // Return error otherwise.
294 if (SessionResponseCode == 200){
295 ConnectResult = COCONNECT_OK;
297 ValidResponse = true;
298 } else if (SessionResponseCode == 401){
299 ConnectResult = COCONNECT_AUTHFAIL;
301 ValidResponse = true;
302 } else if (SessionResponseCode >= 200) {
303 ConnectResult = COCONNECT_INVALID;
305 ValidResponse = true;
307 ConnectResult = COCONNECT_INVALID;
309 ValidResponse = false;
314 ValidResponse = true;
318 // Check the header to see if CardDAV is supported.
320 vector<string> DAVHeaderValues = GetDAVHeader();
322 for (vector<string>::iterator DAVHeaderValuesIter = DAVHeaderValues.begin();
323 DAVHeaderValuesIter != DAVHeaderValues.end(); DAVHeaderValuesIter++){
325 if ((*DAVHeaderValuesIter) == "addressbook"){
332 return ConnectResult;
336 COServerResponse CardDAV2::GetDefaultPrefix(string *ServerPrefix){
338 // Check if authentication was successful, otherwise don't do anything.
340 COServerResponse ServerResponse;
342 if (AuthPassed == false){
343 ServerResponse.RequestResult = COREQUEST_ERROR_NOTCONNECTED;
344 ServerResponse.EntityTag = "";
345 ServerResponse.SessionCode = 0;
346 ServerResponse.ResultCode = 0;
347 ServerResponse.ResultMessage = "";
348 return ServerResponse;
351 ServerSSL ? SetupDefaultParametersSSL(true) : SetupDefaultParametersNonSSL(true);
354 // Need to do three requests:
356 // 1. Get the current user principal URI.
357 // 2. Get the address book home URI.
358 // 3. Get the default address book URI.
360 // Setup the first query finding out where the principal URL is.
362 const char* CurrentUserPrincipalXMLQuery = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
363 "<D:propfind xmlns:D=\"DAV:\">\n"
365 " <D:current-user-principal/>\n"
369 // Setup the second query finding out where the address book home URL is.
371 const char* AddressBookHomeXMLQuery = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
372 "<D:propfind xmlns:D=\"DAV:\""
373 " xmlns:C=\"urn:ietf:params:xml:ns:carddav\">\n"
375 " <C:addressbook-home-set/>\n"
379 // Setup the third query finding out where the default address book URL is.
381 const char* DefaultAddressBookXMLQuery = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
382 "<D:propfind xmlns:D=\"DAV:\""
383 " xmlns:C=\"urn:ietf:params:xml:ns:carddav\">\n"
385 " <C:default-addressbook-URL/>\n"
389 string ServerAddressURL = BuildURL("/principals/");
390 curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str());
391 curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "PROPFIND");
392 curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDS, CurrentUserPrincipalXMLQuery);
393 curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDSIZE, strlen(CurrentUserPrincipalXMLQuery));
395 if (TestMode == true){
396 SessionResult = curl_easy_perform(ConnectionSession);
401 switch(SessionResult){
404 SSLVerified = COSSL_VERIFIED;
406 case CURLE_SSL_CACERT:
407 case CURLE_SSL_CONNECT_ERROR:
409 SSLVerified = COSSL_UNABLETOVERIFY;
415 long SessionResponseCode = 0;
417 curl_easy_getinfo(ConnectionSession, CURLINFO_RESPONSE_CODE, &SessionResponseCode);
419 if (SessionResponseCode == 200 || SessionResponseCode == 207){
421 ValidResponse = true;
422 } else if (SessionResponseCode == 403){
424 ValidResponse = true;
425 } else if (SessionResponseCode >= 400) {
427 ValidResponse = true;
430 ValidResponse = false;
433 if (ValidResponse == false && AuthPassed == false){
434 ServerResponse.RequestResult = COREQUEST_ERROR_SERVER;
435 ServerResponse.EntityTag = "";
436 ServerResponse.SessionCode = SessionResult;
437 ServerResponse.ResultCode = SessionResponseCode;
438 ServerResponse.ResultMessage = "";
439 return ServerResponse;
442 // Process the first response.
444 string UserPrincipalURI = GetUserPrincipalURI();
446 // Cleanup and reset for the second connection.
448 ServerSSL ? SetupDefaultParametersSSL(true) : SetupDefaultParametersNonSSL(true);
451 ServerAddressURL = BuildURL(UserPrincipalURI);
452 curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str());
453 curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "PROPFIND");
454 curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDS, AddressBookHomeXMLQuery);
455 curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDSIZE, strlen(AddressBookHomeXMLQuery));
457 if (TestMode == true){
458 SessionResult = curl_easy_perform(ConnectionSession);
463 switch(SessionResult){
466 SSLVerified = COSSL_VERIFIED;
468 case CURLE_SSL_CACERT:
469 case CURLE_SSL_CONNECT_ERROR:
471 SSLVerified = COSSL_UNABLETOVERIFY;
477 SessionResponseCode = 0;
479 curl_easy_getinfo(ConnectionSession, CURLINFO_RESPONSE_CODE, &SessionResponseCode);
481 if (SessionResponseCode == 200 || SessionResponseCode == 207){
483 ValidResponse = true;
484 } else if (SessionResponseCode == 403){
486 ValidResponse = true;
487 } else if (SessionResponseCode >= 400) {
489 ValidResponse = true;
492 ValidResponse = false;
495 if (ValidResponse == false && AuthPassed == false){
496 ServerResponse.RequestResult = COREQUEST_ERROR_SERVER;
497 ServerResponse.EntityTag = "";
498 ServerResponse.SessionCode = SessionResult;
499 ServerResponse.ResultCode = SessionResponseCode;
500 ServerResponse.ResultMessage = "";
501 return ServerResponse;
504 // Process the second response.
506 string AddressBookHomeURI = GetAddressBookHomeURI();
508 // Cleanup and reset for the second connection.
510 ServerSSL ? SetupDefaultParametersSSL(true) : SetupDefaultParametersNonSSL(true);
513 ServerAddressURL = BuildURL(AddressBookHomeURI);
514 curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str());
515 curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "PROPFIND");
516 curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDS, DefaultAddressBookXMLQuery);
517 curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDSIZE, strlen(DefaultAddressBookXMLQuery));
519 if (TestMode == true){
520 SessionResult = curl_easy_perform(ConnectionSession);
525 switch(SessionResult){
528 SSLVerified = COSSL_VERIFIED;
530 case CURLE_SSL_CACERT:
531 case CURLE_SSL_CONNECT_ERROR:
533 SSLVerified = COSSL_UNABLETOVERIFY;
539 SessionResponseCode = 0;
541 curl_easy_getinfo(ConnectionSession, CURLINFO_RESPONSE_CODE, &SessionResponseCode);
543 if (SessionResponseCode == 200 || SessionResponseCode == 207){
545 ValidResponse = true;
546 } else if (SessionResponseCode == 403){
548 ValidResponse = true;
549 } else if (SessionResponseCode >= 200) {
551 ValidResponse = true;
554 ValidResponse = false;
557 if (ValidResponse == false || AuthPassed == false){
558 ServerResponse.RequestResult = COREQUEST_ERROR_SERVER;
559 ServerResponse.EntityTag = "";
560 ServerResponse.SessionCode = SessionResult;
561 ServerResponse.ResultCode = SessionResponseCode;
562 ServerResponse.ResultMessage = "";
563 return ServerResponse;
566 // Process the second response.
568 (*ServerPrefix) = GetDefaultAddressBookURI();
572 ServerResponse.RequestResult = COREQUEST_OK;
573 ServerResponse.EntityTag = "";
574 ServerResponse.SessionCode = SessionResult;
575 ServerResponse.ResultCode = SessionResponseCode;
576 ServerResponse.ResultMessage = SessionErrorBuffer;
577 return ServerResponse;
581 std::string CardDAV2::GetUserPrincipalURI(){
583 xmlDocPtr xmlCardDAVDoc;
584 xmlCardDAVDoc = xmlReadMemory(PageData.c_str(), (int)PageData.size(), "noname.xml", NULL, 0);
585 string UserPrincipalURI = "";
587 xmlNodePtr nodeLevel1;
588 xmlNodePtr nodeLevel2;
589 xmlNodePtr nodeLevel3;
590 xmlNodePtr nodeLevel4;
591 xmlNodePtr nodeLevel5;
592 xmlNodePtr nodeLevel6;
593 xmlNodePtr nodeLevel7;
595 for (nodeLevel1 = xmlCardDAVDoc->children;
597 nodeLevel1 = nodeLevel1->next)
600 for (nodeLevel2 = nodeLevel1->children;
602 nodeLevel2 = nodeLevel2->next)
606 for (nodeLevel3 = nodeLevel2->children;
608 nodeLevel3 = nodeLevel3->next)
611 for (nodeLevel4 = nodeLevel3->children;
613 nodeLevel4 = nodeLevel4->next)
616 for (nodeLevel5 = nodeLevel4->children;
618 nodeLevel5 = nodeLevel5->next)
621 for (nodeLevel6 = nodeLevel5->children;
623 nodeLevel6 = nodeLevel6->next)
626 if (!xmlStrcmp(nodeLevel6->name, (const xmlChar *)"href") ||
627 !xmlStrcmp(nodeLevel6->name, (const xmlChar *)"d:href") ||
628 !xmlStrcmp(nodeLevel6->name, (const xmlChar *)"D:href")
631 // Found the <href> part so extract the principal URL address.
633 for (nodeLevel7 = nodeLevel6->children;
635 nodeLevel7 = nodeLevel7->next)
638 UserPrincipalURI = ((const char*)nodeLevel7->content);
656 xmlFreeDoc(xmlCardDAVDoc);
658 return UserPrincipalURI;
662 std::string CardDAV2::GetAddressBookHomeURI(){
664 xmlDocPtr xmlCardDAVDoc;
665 xmlCardDAVDoc = xmlReadMemory(PageData.c_str(), (int)PageData.size(), "noname.xml", NULL, 0);
666 string AddressBookHomeURI = "";
668 xmlNodePtr nodeLevel1;
669 xmlNodePtr nodeLevel2;
670 xmlNodePtr nodeLevel3;
671 xmlNodePtr nodeLevel4;
672 xmlNodePtr nodeLevel5;
673 xmlNodePtr nodeLevel6;
674 xmlNodePtr nodeLevel7;
676 for (nodeLevel1 = xmlCardDAVDoc->children;
678 nodeLevel1 = nodeLevel1->next)
681 for (nodeLevel2 = nodeLevel1->children;
683 nodeLevel2 = nodeLevel2->next)
687 for (nodeLevel3 = nodeLevel2->children;
689 nodeLevel3 = nodeLevel3->next)
692 for (nodeLevel4 = nodeLevel3->children;
694 nodeLevel4 = nodeLevel4->next)
697 for (nodeLevel5 = nodeLevel4->children;
699 nodeLevel5 = nodeLevel5->next)
702 for (nodeLevel6 = nodeLevel5->children;
704 nodeLevel6 = nodeLevel6->next)
707 if (!xmlStrcmp(nodeLevel6->name, (const xmlChar *)"href") ||
708 !xmlStrcmp(nodeLevel6->name, (const xmlChar *)"d:href") ||
709 !xmlStrcmp(nodeLevel6->name, (const xmlChar *)"D:href")
712 // Found the <href> part so extract the principal URL address.
714 for (nodeLevel7 = nodeLevel6->children;
716 nodeLevel7 = nodeLevel7->next)
719 AddressBookHomeURI = ((const char*)nodeLevel7->content);
737 xmlFreeDoc(xmlCardDAVDoc);
739 return AddressBookHomeURI;
743 std::string CardDAV2::GetDefaultAddressBookURI(){
745 xmlDocPtr xmlCardDAVDoc;
746 xmlCardDAVDoc = xmlReadMemory(PageData.c_str(), (int)PageData.size(), "noname.xml", NULL, 0);
747 string DefaultAddressBookURI = "";
749 xmlNodePtr nodeLevel1;
750 xmlNodePtr nodeLevel2;
751 xmlNodePtr nodeLevel3;
752 xmlNodePtr nodeLevel4;
753 xmlNodePtr nodeLevel5;
754 xmlNodePtr nodeLevel6;
755 xmlNodePtr nodeLevel7;
757 for (nodeLevel1 = xmlCardDAVDoc->children;
759 nodeLevel1 = nodeLevel1->next)
762 for (nodeLevel2 = nodeLevel1->children;
764 nodeLevel2 = nodeLevel2->next)
768 for (nodeLevel3 = nodeLevel2->children;
770 nodeLevel3 = nodeLevel3->next)
773 for (nodeLevel4 = nodeLevel3->children;
775 nodeLevel4 = nodeLevel4->next)
778 for (nodeLevel5 = nodeLevel4->children;
780 nodeLevel5 = nodeLevel5->next)
783 for (nodeLevel6 = nodeLevel5->children;
785 nodeLevel6 = nodeLevel6->next)
788 if (!xmlStrcmp(nodeLevel6->name, (const xmlChar *)"href") ||
789 !xmlStrcmp(nodeLevel6->name, (const xmlChar *)"d:href") ||
790 !xmlStrcmp(nodeLevel6->name, (const xmlChar *)"D:href")
793 // Found the <href> part so extract the principal URL address.
795 for (nodeLevel7 = nodeLevel6->children;
797 nodeLevel7 = nodeLevel7->next)
800 DefaultAddressBookURI = ((const char*)nodeLevel7->content);
818 xmlFreeDoc(xmlCardDAVDoc);
820 return DefaultAddressBookURI;
824 COServerResponse CardDAV2::AddContact(std::string Location, std::string Data){
826 // Check if authentication was successful, otherwise don't do anything.
828 COServerResponse ServerResponse;
830 if (AuthPassed == false){
831 ServerResponse.RequestResult = COREQUEST_ERROR_NOTCONNECTED;
832 ServerResponse.EntityTag = "";
833 ServerResponse.SessionCode = 0;
834 ServerResponse.ResultCode = 0;
835 ServerResponse.ResultMessage = "";
836 return ServerResponse;
839 ServerSSL ? SetupDefaultParametersSSL(true) : SetupDefaultParametersNonSSL(true);
842 string ServerAddressURL = BuildURL(ServerPrefix + Location);
843 curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str());
844 curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "PUT");
845 curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDS, Data.c_str());
846 curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDSIZE, strlen(Data.c_str()));
848 HeaderList = curl_slist_append(HeaderList, "Content-Type: text/vcard; charset=utf-8");
850 curl_easy_setopt(ConnectionSession, CURLOPT_HTTPHEADER, HeaderList);
852 if (TestMode == true){
853 SessionResult = curl_easy_perform(ConnectionSession);
855 SessionResult = curl_easy_perform(ConnectionSession);
858 switch(SessionResult){
861 SSLVerified = COSSL_VERIFIED;
863 case CURLE_SSL_CACERT:
864 case CURLE_SSL_CONNECT_ERROR:
866 SSLVerified = COSSL_UNABLETOVERIFY;
872 long SessionResponseCode = 0;
874 curl_easy_getinfo(ConnectionSession, CURLINFO_RESPONSE_CODE, &SessionResponseCode);
876 if (SessionResponseCode == 200 || SessionResponseCode == 201 || SessionResponseCode == 204){
878 ValidResponse = true;
879 } else if (SessionResponseCode == 403){
881 ValidResponse = true;
882 } else if (SessionResponseCode >= 400){
884 ValidResponse = true;
887 ValidResponse = false;
890 if (ValidResponse == false || AuthPassed == false){
891 ServerResponse.RequestResult = COREQUEST_ERROR_SERVER;
892 ServerResponse.EntityTag = "";
893 ServerResponse.SessionCode = SessionResult;
894 ServerResponse.ResultCode = SessionResponseCode;
895 ServerResponse.ResultMessage = "";
896 return ServerResponse;
901 ServerResponse.RequestResult = COREQUEST_OK;
902 ServerResponse.EntityTag = "";
903 ServerResponse.SessionCode = SessionResult;
904 ServerResponse.ResultCode = SessionResponseCode;
905 ServerResponse.ResultMessage = SessionErrorBuffer;
906 return ServerResponse;
910 COServerResponse CardDAV2::EditContact(std::string Location, std::string Data){
912 // Check if authentication was successful, otherwise don't do anything.
914 COServerResponse ServerResponse;
916 if (AuthPassed == false){
917 ServerResponse.RequestResult = COREQUEST_ERROR_NOTCONNECTED;
918 ServerResponse.EntityTag = "";
919 ServerResponse.SessionCode = 0;
920 ServerResponse.ResultCode = 0;
921 ServerResponse.ResultMessage = "";
922 return ServerResponse;
925 ServerSSL ? SetupDefaultParametersSSL(true) : SetupDefaultParametersNonSSL(true);
928 string ServerAddressURL = BuildURL(ServerPrefix + Location);
929 curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str());
930 curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "PUT");
931 curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDS, Data.c_str());
932 curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDSIZE, strlen(Data.c_str()));
934 HeaderList = curl_slist_append(HeaderList, "Content-Type: text/vcard; charset=utf-8");
936 curl_easy_setopt(ConnectionSession, CURLOPT_HTTPHEADER, HeaderList);
938 if (TestMode == true){
939 SessionResult = curl_easy_perform(ConnectionSession);
941 SessionResult = curl_easy_perform(ConnectionSession);
944 switch(SessionResult){
947 SSLVerified = COSSL_VERIFIED;
949 case CURLE_SSL_CACERT:
950 case CURLE_SSL_CONNECT_ERROR:
952 SSLVerified = COSSL_UNABLETOVERIFY;
958 long SessionResponseCode = 0;
960 curl_easy_getinfo(ConnectionSession, CURLINFO_RESPONSE_CODE, &SessionResponseCode);
962 if (SessionResponseCode == 200 || SessionResponseCode == 201 || SessionResponseCode == 204){
964 ValidResponse = true;
965 } else if (SessionResponseCode == 403){
967 ValidResponse = true;
968 } else if (SessionResponseCode >= 400){
970 ValidResponse = true;
973 ValidResponse = false;
976 if (ValidResponse == false || AuthPassed == false){
977 ServerResponse.RequestResult = COREQUEST_ERROR_SERVER;
978 ServerResponse.EntityTag = "";
979 ServerResponse.SessionCode = SessionResult;
980 ServerResponse.ResultCode = SessionResponseCode;
981 ServerResponse.ResultMessage = "";
982 return ServerResponse;
987 ServerResponse.RequestResult = COREQUEST_OK;
988 ServerResponse.EntityTag = "";
989 ServerResponse.SessionCode = SessionResult;
990 ServerResponse.ResultCode = SessionResponseCode;
991 ServerResponse.ResultMessage = SessionErrorBuffer;
992 return ServerResponse;
996 COServerResponse CardDAV2::DeleteContact(std::string Location){
998 // Check if authentication was successful, otherwise don't do anything.
1000 COServerResponse ServerResponse;
1002 if (AuthPassed == false){
1003 ServerResponse.RequestResult = COREQUEST_ERROR_NOTCONNECTED;
1004 ServerResponse.EntityTag = "";
1005 ServerResponse.SessionCode = 0;
1006 ServerResponse.ResultCode = 0;
1007 ServerResponse.ResultMessage = "";
1008 return ServerResponse;
1011 ServerSSL ? SetupDefaultParametersSSL(true) : SetupDefaultParametersNonSSL(true);
1014 string ServerAddressURL = BuildURL(ServerPrefix + Location);
1015 curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str());
1016 curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "DELETE");
1018 if (TestMode == true){
1019 SessionResult = curl_easy_perform(ConnectionSession);
1021 SessionResult = curl_easy_perform(ConnectionSession);
1024 switch(SessionResult){
1027 SSLVerified = COSSL_VERIFIED;
1029 case CURLE_SSL_CACERT:
1030 case CURLE_SSL_CONNECT_ERROR:
1032 SSLVerified = COSSL_UNABLETOVERIFY;
1038 long SessionResponseCode = 0;
1040 curl_easy_getinfo(ConnectionSession, CURLINFO_RESPONSE_CODE, &SessionResponseCode);
1042 if (SessionResponseCode == 200 || SessionResponseCode == 202 || SessionResponseCode == 204){
1044 ValidResponse = true;
1045 } else if (SessionResponseCode == 403){
1047 ValidResponse = true;
1048 } else if (SessionResponseCode >= 400){
1050 ValidResponse = true;
1053 ValidResponse = false;
1056 if (ValidResponse == false || AuthPassed == false){
1057 ServerResponse.RequestResult = COREQUEST_ERROR_SERVER;
1058 ServerResponse.EntityTag = "";
1059 ServerResponse.SessionCode = SessionResult;
1060 ServerResponse.ResultCode = SessionResponseCode;
1061 ServerResponse.ResultMessage = "";
1062 return ServerResponse;
1067 ServerResponse.RequestResult = COREQUEST_OK;
1068 ServerResponse.EntityTag = "";
1069 ServerResponse.SessionCode = SessionResult;
1070 ServerResponse.ResultCode = SessionResponseCode;
1071 ServerResponse.ResultMessage = SessionErrorBuffer;
1072 return ServerResponse;
1076 COServerResponse CardDAV2::GetServerEntityTagValue(std::string Location){
1078 // Check if authentication was successful, otherwise don't do anything.
1080 COServerResponse ServerResponse;
1082 if (AuthPassed == false){
1083 ServerResponse.RequestResult = COREQUEST_ERROR_NOTCONNECTED;
1084 ServerResponse.EntityTag = "";
1085 ServerResponse.SessionCode = 0;
1086 ServerResponse.ResultCode = 0;
1087 ServerResponse.ResultMessage = "";
1088 return ServerResponse;
1091 ServerSSL ? SetupDefaultParametersSSL(true) : SetupDefaultParametersNonSSL(true);
1094 static const char* GetETagQuery =
1095 "<?xml version=\"1.0\" encoding=\"utf-8\" ?>"
1096 "<C:addressbook-query xmlns:D=\"DAV:\""
1097 " xmlns:C=\"urn:ietf:params:xml:ns:carddav\">"
1098 "<D:prop><D:getetag/>"
1101 "</C:addressbook-query>";
1103 string ServerAddressURL = BuildURL(ServerPrefix + Location);
1104 curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str());
1105 curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "REPORT");
1106 curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDS, GetETagQuery);
1107 curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDSIZE, strlen(GetETagQuery));
1109 if (TestMode == true){
1110 SessionResult = curl_easy_perform(ConnectionSession);
1112 SessionResult = curl_easy_perform(ConnectionSession);
1115 switch(SessionResult){
1118 SSLVerified = COSSL_VERIFIED;
1120 case CURLE_SSL_CACERT:
1121 case CURLE_SSL_CONNECT_ERROR:
1123 SSLVerified = COSSL_UNABLETOVERIFY;
1129 long SessionResponseCode = 0;
1131 curl_easy_getinfo(ConnectionSession, CURLINFO_RESPONSE_CODE, &SessionResponseCode);
1133 if (SessionResponseCode == 207){
1135 ValidResponse = true;
1136 } else if (SessionResponseCode == 403){
1138 ValidResponse = true;
1139 } else if (SessionResponseCode >= 400){
1141 ValidResponse = true;
1144 ValidResponse = false;
1147 if (ValidResponse == false || AuthPassed == false){
1148 ServerResponse.RequestResult = COREQUEST_ERROR_SERVER;
1149 ServerResponse.EntityTag = "";
1150 ServerResponse.SessionCode = SessionResult;
1151 ServerResponse.ResultCode = SessionResponseCode;
1152 ServerResponse.ResultMessage = "";
1153 return ServerResponse;
1158 ServerResponse.RequestResult = COREQUEST_OK;
1159 ServerResponse.EntityTag = GetETagValue();
1160 ServerResponse.SessionCode = SessionResult;
1161 ServerResponse.ResultCode = SessionResponseCode;
1162 ServerResponse.ResultMessage = SessionErrorBuffer;
1164 return ServerResponse;
1168 COServerResponse CardDAV2::GetContact(std::string Location, std::string *ContactData){
1170 // Check if authentication was successful, otherwise don't do anything.
1172 COServerResponse ServerResponse;
1174 if (AuthPassed == false){
1175 ServerResponse.RequestResult = COREQUEST_ERROR_NOTCONNECTED;
1176 ServerResponse.EntityTag = "";
1177 ServerResponse.SessionCode = 0;
1178 ServerResponse.ResultCode = 0;
1179 ServerResponse.ResultMessage = "";
1180 return ServerResponse;
1183 ServerSSL ? SetupDefaultParametersSSL(true) : SetupDefaultParametersNonSSL(true);
1186 string ServerAddressURL = BuildURL(ServerPrefix + Location);
1187 curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str());
1188 curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "GET");
1190 if (TestMode == true){
1191 SessionResult = curl_easy_perform(ConnectionSession);
1193 SessionResult = curl_easy_perform(ConnectionSession);
1196 switch(SessionResult){
1199 SSLVerified = COSSL_VERIFIED;
1201 case CURLE_SSL_CACERT:
1202 case CURLE_SSL_CONNECT_ERROR:
1204 SSLVerified = COSSL_UNABLETOVERIFY;
1210 long SessionResponseCode = 0;
1212 curl_easy_getinfo(ConnectionSession, CURLINFO_RESPONSE_CODE, &SessionResponseCode);
1214 if (SessionResponseCode == 200){
1216 ValidResponse = true;
1217 } else if (SessionResponseCode == 403){
1219 ValidResponse = true;
1220 } else if (SessionResponseCode >= 400){
1222 ValidResponse = true;
1225 ValidResponse = false;
1228 if (ValidResponse == false && AuthPassed == false){
1229 ServerResponse.RequestResult = COREQUEST_ERROR_SERVER;
1230 ServerResponse.EntityTag = "";
1231 ServerResponse.SessionCode = SessionResult;
1232 ServerResponse.ResultCode = SessionResponseCode;
1233 ServerResponse.ResultMessage = "";
1234 return ServerResponse;
1239 ServerResponse.RequestResult = COREQUEST_OK;
1240 ServerResponse.EntityTag = "";
1241 ServerResponse.SessionCode = SessionResult;
1242 ServerResponse.ResultCode = SessionResponseCode;
1243 ServerResponse.ResultMessage = SessionErrorBuffer;
1245 (*ContactData) = PageData;
1247 return ServerResponse;
1251 COContactList CardDAV2::GetContactList(std::string SyncToken){
1253 COContactList ServerContactList;
1255 // Check if authentication was successful, otherwise don't do anything.
1257 if (AuthPassed == false){
1258 ServerContactList.ServerResponse.RequestResult = COREQUEST_ERROR_NOTCONNECTED;
1259 ServerContactList.ServerResponse.EntityTag = "";
1260 ServerContactList.ServerResponse.SessionCode = 0;
1261 ServerContactList.ServerResponse.ResultCode = 0;
1262 ServerContactList.ServerResponse.ResultMessage = "";
1263 return ServerContactList;
1266 ServerSSL ? SetupDefaultParametersSSL(true) : SetupDefaultParametersNonSSL(true);
1269 std::string SyncData;
1271 // TODO: Copy old code from CardDAV class as needed.
1273 if (SyncToken.size() > 0){
1275 SyncData = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
1276 "<D:sync-collection xmlns:D=\"DAV:\"\n"
1277 " xmlns:C=\"urn:ietf:params:xml:ns:carddav\">\n"
1279 SyncData.append(SyncToken);
1280 SyncData.append("</D:sync-token>\n"
1281 "<D:sync-level>1</D:sync-level>\n"
1285 "</D:sync-collection>");
1289 SyncData = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
1290 "<D:sync-collection xmlns:D=\"DAV:\"\n"
1291 " xmlns:C=\"urn:ietf:params:xml:ns:carddav\">\n"
1292 "<D:sync-level>1</D:sync-level>\n"
1296 "</D:sync-collection>";
1300 string ServerAddressURL = BuildURL(ServerPrefix);
1302 curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str());
1303 curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDS, SyncData.c_str());
1304 curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDSIZE, strlen(SyncData.c_str()));
1305 curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "REPORT");
1307 HeaderList = curl_slist_append(HeaderList, "Content-Type: application/xml; charset=utf-8");
1308 HeaderList = curl_slist_append(HeaderList, "Depth: 1");
1310 curl_easy_setopt(ConnectionSession, CURLOPT_HTTPHEADER, HeaderList);
1312 if (TestMode == true){
1313 SessionResult = curl_easy_perform(ConnectionSession);
1315 SessionResult = curl_easy_perform(ConnectionSession);
1318 switch(SessionResult){
1321 SSLVerified = COSSL_VERIFIED;
1323 case CURLE_SSL_CACERT:
1324 case CURLE_SSL_CONNECT_ERROR:
1326 SSLVerified = COSSL_UNABLETOVERIFY;
1332 long SessionResponseCode = 0;
1334 curl_easy_getinfo(ConnectionSession, CURLINFO_RESPONSE_CODE, &SessionResponseCode);
1336 if (SessionResponseCode == 207){
1338 ValidResponse = true;
1339 } else if (SessionResponseCode == 403){
1341 ValidResponse = true;
1342 } else if (SessionResponseCode >= 400){
1344 ValidResponse = true;
1347 ValidResponse = false;
1350 if (ValidResponse == false || AuthPassed == false){
1351 ServerContactList.ServerResponse.RequestResult = COREQUEST_ERROR_SERVER;
1352 ServerContactList.ServerResponse.EntityTag = "";
1353 ServerContactList.ServerResponse.SessionCode = SessionResult;
1354 ServerContactList.ServerResponse.ResultCode = SessionResponseCode;
1355 ServerContactList.ServerResponse.ResultMessage = "";
1356 return ServerContactList;
1361 ProcessContactData(&ServerContactList);
1363 ServerContactList.ServerResponse.RequestResult = COREQUEST_OK;
1364 ServerContactList.ServerResponse.EntityTag = "";
1365 ServerContactList.ServerResponse.SessionCode = SessionResult;
1366 ServerContactList.ServerResponse.ResultCode = SessionResponseCode;
1367 ServerContactList.ServerResponse.ResultMessage = SessionErrorBuffer;
1369 return ServerContactList;
1373 bool CardDAV2::CanDoProcessing(){
1377 bool CardDAV2::CanDoSSL(){
1381 COSSLVerified CardDAV2::SSLVerify(){
1385 bool CardDAV2::AbleToLogin(){
1389 bool CardDAV2::HasValidResponse(){
1390 return ValidResponse;
1393 bool CardDAV2::IsSelfSigned(){
1394 return SSLSelfSigned;
1397 void CardDAV2::SetupDefaultParametersNonSSL(bool DoAuthentication){
1399 std::string ServerAddress = "";
1401 string ServerAddressURL = "http://" + ServerAddress + ":" + to_string(ServerPort) + "/";
1402 string UsernamePassword = ServerUser + ":" + ServerPass;
1404 PageDataObject.CardDAV2Object = this;
1405 PageDataObject.ConnectionSessionObject = ConnectionSession;
1406 PageDataObject.DataSetting = &PageData;
1407 PageDataObject.ServerUsingSSL = false;
1409 PageHeaderObject.CardDAV2Object = this;
1410 PageHeaderObject.ConnectionSessionObject = ConnectionSession;
1411 PageHeaderObject.DataSetting = &PageHeader;
1412 PageHeaderObject.ServerUsingSSL = false;
1414 curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddress.c_str());
1415 curl_easy_setopt(ConnectionSession, CURLOPT_NOPROGRESS, 1L);
1416 curl_easy_setopt(ConnectionSession, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST|CURLAUTH_BASIC);
1417 curl_easy_setopt(ConnectionSession, CURLOPT_TIMEOUT, 60);
1418 curl_easy_setopt(ConnectionSession, CURLOPT_FAILONERROR, true);
1419 curl_easy_setopt(ConnectionSession, CURLOPT_USERAGENT, XSDAB_USERAGENT);
1420 curl_easy_setopt(ConnectionSession, CURLOPT_WRITEFUNCTION, CardDAV2::WritebackFunc);
1421 curl_easy_setopt(ConnectionSession, CURLOPT_WRITEDATA, &PageDataObject);
1422 curl_easy_setopt(ConnectionSession, CURLOPT_WRITEHEADER, &PageHeaderObject);
1423 curl_easy_setopt(ConnectionSession, CURLOPT_NOSIGNAL, 1L);
1424 curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "GET");
1425 curl_easy_setopt(ConnectionSession, CURLOPT_HTTPHEADER, nullptr);
1426 curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDS, nullptr);
1427 curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDSIZE, 0L);
1429 if (DoAuthentication == true){
1430 curl_easy_setopt(ConnectionSession, CURLOPT_USERPWD, UsernamePassword.c_str());
1432 curl_easy_setopt(ConnectionSession, CURLOPT_USERPWD, NULL);
1437 void CardDAV2::SetupDefaultParametersSSL(bool DoAuthentication){
1439 // Setup the default parameters.
1441 string ServerAddressURL = "https://" + ServerAddress + ":" + to_string(ServerPort) + "/";
1442 string UsernamePassword = ServerUser + ":" + ServerPass;
1444 PageDataObject.CardDAV2Object = this;
1445 PageDataObject.ConnectionSessionObject = ConnectionSession;
1446 PageDataObject.DataSetting = &PageData;
1447 PageDataObject.ServerUsingSSL = true;
1449 PageHeaderObject.CardDAV2Object = this;
1450 PageHeaderObject.ConnectionSessionObject = ConnectionSession;
1451 PageHeaderObject.DataSetting = &PageHeader;
1452 PageHeaderObject.ServerUsingSSL = true;
1454 curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str());
1455 curl_easy_setopt(ConnectionSession, CURLOPT_NOPROGRESS, 1L);
1456 curl_easy_setopt(ConnectionSession, CURLOPT_CERTINFO, 1L);
1457 curl_easy_setopt(ConnectionSession, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST|CURLAUTH_BASIC);
1458 curl_easy_setopt(ConnectionSession, CURLOPT_TIMEOUT, 60);
1459 curl_easy_setopt(ConnectionSession, CURLOPT_FAILONERROR, 0L);
1460 curl_easy_setopt(ConnectionSession, CURLOPT_USERAGENT, XSDAB_USERAGENT);
1461 curl_easy_setopt(ConnectionSession, CURLOPT_WRITEFUNCTION, CardDAV2::WritebackFunc);
1462 curl_easy_setopt(ConnectionSession, CURLOPT_WRITEDATA, &PageDataObject);
1463 curl_easy_setopt(ConnectionSession, CURLOPT_WRITEHEADER, &PageHeaderObject);
1464 curl_easy_setopt(ConnectionSession, CURLOPT_ERRORBUFFER, SessionErrorBuffer);
1465 curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "GET");
1466 curl_easy_setopt(ConnectionSession, CURLOPT_HTTPHEADER, nullptr);
1467 curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDS, nullptr);
1468 curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDSIZE, 0L);
1470 if (DoAuthentication == true){
1471 curl_easy_setopt(ConnectionSession, CURLOPT_USERPWD, UsernamePassword.c_str());
1473 curl_easy_setopt(ConnectionSession, CURLOPT_USERPWD, NULL);
1476 if (EnableSSLBypass == true){
1477 curl_easy_setopt(ConnectionSession, CURLOPT_SSL_VERIFYHOST, 0L);
1478 curl_easy_setopt(ConnectionSession, CURLOPT_SSL_VERIFYPEER, 0L);
1479 curl_easy_setopt(ConnectionSession, CURLOPT_SSL_VERIFYSTATUS, 0L);
1481 curl_easy_setopt(ConnectionSession, CURLOPT_SSL_VERIFYHOST, 2L);
1482 curl_easy_setopt(ConnectionSession, CURLOPT_SSL_VERIFYPEER, 1L);
1483 curl_easy_setopt(ConnectionSession, CURLOPT_SSL_VERIFYSTATUS, 1L);
1486 #if !defined(__APPLE__) || defined(__WIN32__)
1488 if (TestMode == false && ServerAccount.size() > 0){
1490 // Check if the server certificate file exists.
1492 string CertificateFilename = GetAccountDir(ServerAccount, true);
1494 if (wxFile::Exists(CertificateFilename)){
1496 curl_easy_setopt(ConnectionSession, CURLOPT_CAINFO, CertificateFilename.c_str());
1506 string CardDAV2::BuildURL(string URI){
1508 string ServerAddressURL;
1510 if (ServerSSL == true){
1511 ServerAddressURL = "https://" + ServerAddress + ":" + to_string(ServerPort) + URI;
1513 ServerAddressURL = "http://" + ServerAddress + ":" + to_string(ServerPort) + URI;
1516 return ServerAddressURL;
1520 string CardDAV2::GetErrorMessage(){
1522 ErrorMessage = SessionErrorBuffer;
1523 return ErrorMessage;
1527 void CardDAV2::ResetResults(){
1530 COSSLVerified SSLVerified = COSSL_NORESULT;
1531 ValidResponse = false;
1534 SSLSelfSigned = false;
1535 TaskCompleted = false;
1537 SessionErrorBuffer[0] = '\0';
1538 SessionResult = CURLE_OK;
1541 if (HeaderList != nullptr){
1542 curl_slist_free_all(HeaderList);
1543 HeaderList = nullptr;
1548 string CardDAV2::GetETagValue(){
1550 xmlDocPtr xmlCardDAVDoc;
1552 xmlCardDAVDoc = xmlReadMemory(PageData.c_str(), (int)PageData.size(), "noname.xml", NULL, 0);
1554 xmlNodePtr nodeLevel1;
1555 xmlNodePtr nodeLevel2;
1556 xmlNodePtr nodeLevel3;
1557 xmlNodePtr nodeLevel4;
1558 xmlNodePtr nodeLevel5;
1559 xmlNodePtr nodeLevel6;
1561 //std::map<wxString,wxString> xmlDataMap;
1563 std::string DataFilename;
1564 std::string ETagData;
1566 std::string xmlStringSafe;
1567 std::string ETagValue;
1569 // Tranverse through the catacombs of the response to get our ETag for the file.
1571 for (nodeLevel1 = xmlCardDAVDoc->children;
1573 nodeLevel1 = nodeLevel1->next)
1576 bool HREFFound = FALSE;
1577 bool ETagFound = FALSE;
1579 for (nodeLevel2 = nodeLevel1->children;
1581 nodeLevel2 = nodeLevel2->next)
1584 for (nodeLevel3 = nodeLevel2->children;
1586 nodeLevel3 = nodeLevel3->next)
1589 if (!xmlStrcmp(nodeLevel3->name, (const xmlChar *)"href") ||
1590 !xmlStrcmp(nodeLevel3->name, (const xmlChar *)"d:href") ||
1591 !xmlStrcmp(nodeLevel3->name, (const xmlChar *)"D:href")
1594 // Get the filename.
1596 for (nodeLevel4 = nodeLevel3->children;
1598 nodeLevel4 = nodeLevel4->next)
1601 if (!xmlStrcmp(nodeLevel4->name, (const xmlChar *)"text") ||
1602 !xmlStrcmp(nodeLevel4->name, (const xmlChar *)"d:text") ||
1603 !xmlStrcmp(nodeLevel4->name, (const xmlChar *)"D:text")
1606 DataFilename = wxString::FromUTF8((const char*)nodeLevel4->content);
1607 wxStringTokenizer wSTDFilename(DataFilename, wxT("/"));
1609 while (wSTDFilename.HasMoreTokens()){
1611 DataFilename = wSTDFilename.GetNextToken().ToStdString();
1625 for (nodeLevel4 = nodeLevel3->children;
1627 nodeLevel4 = nodeLevel4->next)
1630 for (nodeLevel5 = nodeLevel4->children;
1632 nodeLevel5 = nodeLevel5->next)
1635 if (!xmlStrcmp(nodeLevel5->name, (const xmlChar *)"getetag") ||
1636 !xmlStrcmp(nodeLevel5->name, (const xmlChar *)"d:getetag") ||
1637 !xmlStrcmp(nodeLevel5->name, (const xmlChar *)"D:getetag")
1640 for (nodeLevel6 = nodeLevel5->children;
1642 nodeLevel6 = nodeLevel6->next)
1645 // Strip the quotes from the ETag.
1647 ETagData = (const char*)nodeLevel6->content;
1648 if (ETagData[0] == '"' && ETagData[(ETagData.size() - 1)] == '"'){
1650 ETagData.erase(0, 1);
1651 ETagData.erase((ETagData.size() - 1));
1671 if (HREFFound == TRUE && ETagFound == TRUE){
1673 // Add to the map data.
1675 ETagValue = ETagData;
1686 xmlFreeDoc(xmlCardDAVDoc);
1692 string CardDAV2::GetETagHeader(){
1694 // Go through each of the lines looking for the
1699 bool FastForward = false;
1701 for (int HeaderSeek = 0; HeaderSeek < PageHeader.size(); HeaderSeek++){
1703 if (FastForward == true){
1705 if (PageHeader[HeaderSeek] == '\n'){
1706 FastForward = false;
1714 PageHeader.substr(HeaderSeek, 5) == "ETag:";
1717 catch (const out_of_range &oor){
1721 if (PageHeader.substr(HeaderSeek, 5) == "ETag:"){
1723 int CharacterSeek = 5;
1725 while ((HeaderSeek + CharacterSeek) < PageHeader.size()){
1727 if (PageHeader.substr((HeaderSeek + CharacterSeek), 2) == "\r\n"){
1731 HeaderValue += PageHeader.substr((HeaderSeek + CharacterSeek), 1);
1744 if (PageHeader[HeaderSeek] == '\n'){
1748 //HeaderName += PageHeader.substr(HeaderSeek, 1);
1752 // Check for quotation marks at the start and end and strip
1755 if (HeaderValue.size() >= 2){
1757 if (HeaderValue[0] == '"'){
1758 HeaderValue.erase((HeaderValue.size() - 1));
1759 HeaderValue.erase(0);
1768 vector<string> CardDAV2::GetDAVHeader(){
1770 // Go through each of the lines looking for the
1775 bool FastForward = false;
1776 vector<string> DAVHeaderList;
1778 for (int HeaderSeek = 0; HeaderSeek < PageHeader.size(); HeaderSeek++){
1780 if (FastForward == true){
1782 if (PageHeader[HeaderSeek] == '\n'){
1783 FastForward = false;
1791 PageHeader.substr(HeaderSeek, 4) == "DAV:";
1794 catch (const out_of_range &oor){
1798 if (PageHeader.substr(HeaderSeek, 4) == "DAV:"){
1800 int CharacterSeek = 5;
1802 while ((HeaderSeek + CharacterSeek) < PageHeader.size()){
1804 if (PageHeader.substr((HeaderSeek + CharacterSeek), 2) == "\r\n"){
1808 HeaderValue += PageHeader.substr((HeaderSeek + CharacterSeek), 1);
1821 if (PageHeader[HeaderSeek] == '\n'){
1825 //HeaderName += PageHeader.substr(HeaderSeek, 1);
1829 // Split the header data.
1831 std::string DAVHeaderValue;
1833 for (int HeaderSeek = 0; HeaderSeek < HeaderValue.size(); HeaderSeek++){
1835 if (HeaderValue.substr(HeaderSeek, 1) == ","){
1836 DAVHeaderList.push_back(DAVHeaderValue);
1837 DAVHeaderValue = "";
1842 DAVHeaderValue += HeaderValue[HeaderSeek];
1846 if (DAVHeaderValue.size() > 0){
1848 DAVHeaderList.push_back(DAVHeaderValue);
1852 return DAVHeaderList;
1856 void CardDAV2::ProcessContactData(COContactList *ContactList){
1858 xmlDocPtr xmlCardDAVDoc;
1859 xmlCardDAVDoc = xmlReadMemory(PageData.c_str(), (int)PageData.size(), "noname.xml", NULL, 0);
1861 xmlNodePtr MultiStatusNode;
1862 xmlNodePtr ResponseNode;
1863 xmlNodePtr ResponseDataNode;
1864 xmlNodePtr PropStatNode;
1865 xmlNodePtr ValueNode;
1866 xmlNodePtr ETagNode;
1867 xmlNodePtr StatusNode;
1869 std::string HREFValue;
1870 std::string ETagValue;
1871 std::string StatusValue;
1872 std::string SyncValue;
1874 // Go through the document!
1876 MultiStatusNode = xmlCardDAVDoc->children;
1878 if (MultiStatusNode == nullptr){
1882 bool SyncTokenFound = false;
1884 // Tranverse through the catacombs of the response to get our ETag for the file and
1885 // the server syncronisation token.
1887 for (ResponseNode = MultiStatusNode->children;
1888 ResponseNode != nullptr;
1889 ResponseNode = ResponseNode->next){
1891 // Check if tag is response or sync-token.
1893 if (!xmlStrcmp(ResponseNode->name, (const xmlChar *)"response") ||
1894 !xmlStrcmp(ResponseNode->name, (const xmlChar *)"d:response") ||
1895 !xmlStrcmp(ResponseNode->name, (const xmlChar *)"D:response")){
1897 COContactStatus ContactStatus = COCS_UNKNOWN;
1899 for (ResponseDataNode = ResponseNode->children;
1900 ResponseDataNode != nullptr;
1901 ResponseDataNode = ResponseDataNode->next){
1903 if (!xmlStrcmp(ResponseDataNode->name, (const xmlChar *)"href") ||
1904 !xmlStrcmp(ResponseDataNode->name, (const xmlChar *)"d:href") ||
1905 !xmlStrcmp(ResponseDataNode->name, (const xmlChar *)"D:href")){
1907 HREFValue = (const char*)ResponseDataNode->children->content;
1909 // Get the filename after the last forward slash.
1913 for (int HREFValueSeek = 0; HREFValueSeek < HREFValue.size(); HREFValueSeek++){
1915 if (HREFValue[HREFValueSeek] == '/'){
1917 LastSlash = HREFValueSeek;
1923 HREFValue = HREFValue.substr((LastSlash + 1));
1925 } else if (!xmlStrcmp(ResponseDataNode->name, (const xmlChar *)"propstat") ||
1926 !xmlStrcmp(ResponseDataNode->name, (const xmlChar *)"d:propstat") ||
1927 !xmlStrcmp(ResponseDataNode->name, (const xmlChar *)"D:propstat")){
1929 for (PropStatNode = ResponseDataNode->children;
1930 PropStatNode != nullptr;
1931 PropStatNode = PropStatNode->next){
1933 if (!xmlStrcmp(PropStatNode->name, (const xmlChar *)"prop") ||
1934 !xmlStrcmp(PropStatNode->name, (const xmlChar *)"d:prop") ||
1935 !xmlStrcmp(PropStatNode->name, (const xmlChar *)"D:prop")){
1937 for (ETagNode = PropStatNode->children;
1938 ETagNode != nullptr;
1939 ETagNode = ETagNode->next){
1941 if (!xmlStrcmp(ETagNode->name, (const xmlChar *)"getetag") ||
1942 !xmlStrcmp(ETagNode->name, (const xmlChar *)"getetag") ||
1943 !xmlStrcmp(ETagNode->name, (const xmlChar *)"getetag")){
1945 ETagValue = (const char*)ETagNode->children->content;
1947 if (ETagValue.size() > 2 && ETagValue.substr(0,1) == "\""){
1948 ETagValue.erase((ETagValue.size() - 1),1);
1949 ETagValue.erase(0,1);
1957 } else if (!xmlStrcmp(PropStatNode->name, (const xmlChar *)"status") ||
1958 !xmlStrcmp(PropStatNode->name, (const xmlChar *)"d:status") ||
1959 !xmlStrcmp(PropStatNode->name, (const xmlChar *)"D:status")){
1961 StatusValue = (const char*)PropStatNode->children->content;
1963 if (StatusValue == "HTTP/1.1 200 OK"){
1965 ContactStatus = COCS_UPDATED;
1967 } else if (StatusValue == "HTTP/1.1 404 Not Found"){
1969 ContactStatus = COCS_DELETED;
1973 ContactStatus = COCS_UNKNOWN;
1985 COContactData ContactInformation;
1987 ContactInformation.Location = HREFValue;
1988 ContactInformation.Data = ETagValue;
1989 ContactInformation.Status = ContactStatus;
1993 StatusValue.clear();
1995 ContactList->ListData.push_back(ContactInformation);
1997 } else if (!xmlStrcmp(ResponseNode->name, (const xmlChar *)"sync-token") ||
1998 !xmlStrcmp(ResponseNode->name, (const xmlChar *)"d:sync-token") ||
1999 !xmlStrcmp(ResponseNode->name, (const xmlChar *)"D:sync-token")){
2001 SyncValue = (const char*)ResponseNode->children->content;
2007 ContactList->SyncToken = SyncValue;
2009 xmlFreeDoc(xmlCardDAVDoc);