1 // carddav-contactlist.cpp - CardDAV Object - Contact list subroutines.
3 // (c) 2012-2015 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/>
20 #include "../version.h"
22 #include <wx/tokenzr.h>
24 #include <libxml/parser.h>
25 #include <libxml/tree.h>
28 #include "../vcard/vcard.h"
29 #include "../common/dirs.h"
31 ContactListData CardDAV::GetContactList(wxString SyncTokenInc){
33 // Get the contact list.
35 ContactListData ContactListFinal;
36 std::map<wxString,FileSyncData> ContactList;
43 AbortConnection = FALSE;
46 wxString ServerAddressURL;
48 wxString ServerAddressSSL;
49 wxString ServerAddressNormal;
51 conn = curl_easy_init();
53 struct CardDAVCURLPasser {
56 bool HeaderMode = TRUE;
58 } CardDAVHeader, CardDAVFooter;
60 CardDAVHeader.Data = this;
61 CardDAVHeader.HeaderMode = TRUE;
63 CardDAVFooter.Data = this;
64 CardDAVFooter.HeaderMode = FALSE;
69 ServerAddressURL = ServerAddress + wxT(":") + wxString::Format(wxT("%i"), ServerPort) + wxT("/") + ServerPrefix + wxT("/");
70 ServerAddressSSL = wxT("https://") + ServerAddressURL;
71 ServerAddressNormal = wxT("http://") + ServerAddressURL;
73 ServerAuth = ServerUser + wxT(":") + ServerPass;
75 // Load the sync token file (if it exists).
77 wxCharBuffer SyncDataBuffer;
84 if (!SyncTokenInc.IsEmpty()){
86 SyncData = wxT("<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n");
87 SyncData.Append(wxT("<D:sync-collection xmlns:D=\"DAV:\"\n"));
88 SyncData.Append(wxT(" xmlns:C=\"urn:ietf:params:xml:ns:carddav\">\n"));
89 SyncData.Append(wxT("<D:sync-token>"));
91 //SyncData.Append(wxT("data:,00378c55-1f44-44a2-a255-84f6560b5cac_580"));
92 SyncData.Append(SyncTokenInc);
94 SyncData.Append(wxT("</D:sync-token>\n"));
95 SyncData.Append(wxT("<D:sync-level>1</D:sync-level>\n"));
96 SyncData.Append(wxT("<D:prop>\n"));
97 SyncData.Append(wxT(" <D:getetag/>\n"));
98 SyncData.Append(wxT("</D:prop>\n"));
99 SyncData.Append(wxT("</D:sync-collection>"));
101 SyncDataBuffer = SyncData.ToUTF8();
105 SyncData = wxT("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
106 SyncData.Append(wxT("<D:sync-collection xmlns:D=\"DAV:\""));
107 SyncData.Append(wxT(" xmlns:C=\"urn:ietf:params:xml:ns:carddav\">\n"));
108 SyncData.Append(wxT("<D:sync-token/>\n"));
109 SyncData.Append(wxT("<D:sync-level>1</D:sync-level>\n"));
110 SyncData.Append(wxT("<D:prop>\n"));
111 SyncData.Append(wxT(" <D:getetag/>\n"));
112 SyncData.Append(wxT("</D:prop>\n"));
113 SyncData.Append(wxT("</D:sync-collection>\n"));
115 SyncDataBuffer = SyncData.ToUTF8();
119 //static const char* query = SyncData.mb_str();
121 /*char *query = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\
122 <D:sync-collection xmlns:D=\"DAV:\"\n\
123 xmlns:C=\"urn:ietf:params:xml:ns:carddav\">\n\
124 <D:sync-token>data:,00378c55-1f44-44a2-a255-84f6560b5cac_580</D:sync-token>\n\
125 <D:sync-level>1</D:sync-level>\n\
129 </D:sync-collection>\n";*/
130 const char* query = SyncDataBuffer.data();
134 std::map<int,int>::iterator ActIter;
135 struct UploadDataStruc UploadData;
137 ActIter = ActivityListPtr->find((int)ItemIndex);
139 curl_slist *slist = NULL;
141 slist = curl_slist_append(slist, "Depth: 1");
145 wxString ServerCertFilename;
146 bool MatchingCert = FALSE;
148 curl_easy_setopt(conn, CURLOPT_URL, (const char*)ServerAddressSSL.mb_str(wxConvUTF8));
149 curl_easy_setopt(conn, CURLOPT_NOPROGRESS, 0);
150 curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANYSAFE);
151 curl_easy_setopt(conn, CURLOPT_TIMEOUT, 60);
152 curl_easy_setopt(conn, CURLOPT_FAILONERROR, TRUE);
153 curl_easy_setopt(conn, CURLOPT_USERAGENT, XSDAB_USERAGENT);
154 curl_easy_setopt(conn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8));
155 curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc);
156 curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData);
157 curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader);
158 curl_easy_setopt(conn, CURLOPT_PROGRESSDATA, this);
159 curl_easy_setopt(conn, CURLOPT_PROGRESSFUNCTION, ProgressFunc);
160 curl_easy_setopt(conn, CURLOPT_CUSTOMREQUEST, "REPORT");
161 curl_easy_setopt(conn, CURLOPT_NOSIGNAL, 1);
162 curl_easy_setopt(conn, CURLOPT_HTTPHEADER, slist);
163 curl_easy_setopt(conn, CURLOPT_CERTINFO, 1);
165 ServerCertFilename = GetAccountDir(ServerAccount, TRUE);
167 if (wxFile::Exists(ServerCertFilename) == TRUE){
169 curl_easy_setopt(conn, CURLOPT_SSL_VERIFYPEER, 1);
170 curl_easy_setopt(conn, CURLOPT_SSL_VERIFYHOST, 2);
171 curl_easy_setopt(conn, CURLOPT_CAINFO, (const char*)ServerCertFilename.mb_str(wxConvUTF8));
175 //UploadData.readptr = &CardDAVDataQuery;
176 //UploadData.sizeleft = CardDAVDataQuery.Len();
177 //curl_easy_setopt(conn, CURLOPT_UPLOAD, 1);
178 //curl_easy_setopt(conn, CURLOPT_READDATA, &UploadData);
179 //curl_easy_setopt(conn, CURLOPT_READFUNCTION, UploadReadFunc);
181 //curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, writefunc);
182 curl_easy_setopt(conn, CURLOPT_POSTFIELDS, query);
183 curl_easy_setopt(conn, CURLOPT_POSTFIELDSIZE, strlen(query));
185 claconncode = (curl_easy_perform(conn));
187 // If CURLE_PEER_FAILED_VERIFICATION is returned, retry without
188 // the local certificate in use.
190 if (claconncode == CURLE_PEER_FAILED_VERIFICATION){
192 curl_easy_cleanup(conn);
193 conn = curl_easy_init();
195 curl_easy_setopt(conn, CURLOPT_URL, (const char*)ServerAddressSSL.mb_str(wxConvUTF8));
196 curl_easy_setopt(conn, CURLOPT_NOPROGRESS, 0);
197 curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANYSAFE);
198 curl_easy_setopt(conn, CURLOPT_TIMEOUT, 60);
199 curl_easy_setopt(conn, CURLOPT_FAILONERROR, TRUE);
200 curl_easy_setopt(conn, CURLOPT_USERAGENT, XSDAB_USERAGENT);
201 curl_easy_setopt(conn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8));
202 curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc);
203 curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData);
204 curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader);
205 curl_easy_setopt(conn, CURLOPT_PROGRESSDATA, this);
206 curl_easy_setopt(conn, CURLOPT_PROGRESSFUNCTION, ProgressFunc);
207 curl_easy_setopt(conn, CURLOPT_CUSTOMREQUEST, "REPORT");
208 curl_easy_setopt(conn, CURLOPT_NOSIGNAL, 1);
209 curl_easy_setopt(conn, CURLOPT_HTTPHEADER, slist);
210 curl_easy_setopt(conn, CURLOPT_CERTINFO, 1);
211 curl_easy_setopt(conn, CURLOPT_POSTFIELDS, query);
212 curl_easy_setopt(conn, CURLOPT_POSTFIELDSIZE, strlen(query));
214 claconncode = (curl_easy_perform(conn));
216 // If claconncode is CURLE_OK then delete the certificate file as that
217 // is no longer needed.
219 if (claconncode == CURLE_OK){
221 // Delete the certificate file.
223 wxRemoveFile(ServerCertFilename);
229 // Check if it fails with a CURLE_SSL_CACERT then compare
230 // the certificates as PEM files.
232 if (claconncode == CURLE_SSL_CACERT && wxFile::Exists(ServerCertFilename) == TRUE){
234 //curl_easy_cleanup(conn);
235 //conn = curl_easy_init();
238 sslerrconn = curl_easy_init();
239 CURLcode sslerrconncode;
241 //claconncode = (curl_easy_perform(conn));
243 wxString ServerAddressOnly = wxT("https://") + ServerAddress + wxT(":") + wxString::Format(wxT("%i"), ServerPort) + wxT("/");
245 curl_easy_setopt(sslerrconn, CURLOPT_URL, (const char*)ServerAddressOnly.mb_str(wxConvUTF8));
246 curl_easy_setopt(sslerrconn, CURLOPT_NOPROGRESS, 0);
247 curl_easy_setopt(sslerrconn, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
248 curl_easy_setopt(sslerrconn, CURLOPT_TIMEOUT, 60);
249 curl_easy_setopt(sslerrconn, CURLOPT_FAILONERROR, TRUE);
250 curl_easy_setopt(sslerrconn, CURLOPT_USERAGENT, XSDAB_USERAGENT);
251 curl_easy_setopt(sslerrconn, CURLOPT_WRITEFUNCTION, WritebackFunc);
252 curl_easy_setopt(sslerrconn, CURLOPT_WRITEDATA, &PageData);
253 curl_easy_setopt(sslerrconn, CURLOPT_WRITEHEADER, &PageHeader);
254 curl_easy_setopt(sslerrconn, CURLOPT_PROGRESSDATA, this);
255 curl_easy_setopt(sslerrconn, CURLOPT_PROGRESSFUNCTION, ProgressFunc);
256 curl_easy_setopt(sslerrconn, CURLOPT_NOSIGNAL, 1);
257 curl_easy_setopt(sslerrconn, CURLOPT_SSL_VERIFYPEER, 0);
258 curl_easy_setopt(sslerrconn, CURLOPT_CERTINFO, 1);
260 wxString SSLLocalData;
261 wxString SSLServerData;
263 sslerrconncode = (curl_easy_perform(sslerrconn));
265 SSLCertCol = BuildSSLCollection(sslerrconn);
266 std::map<int, SSLCertData>::iterator SSLCDIter = SSLCertCol.SSLCollection.find(0);
267 std::multimap<wxString,wxString>::iterator SSLDataIter = SSLCDIter->second.CertData.find(wxT("Cert"));
269 wxFFile SSLLocalFile;
271 #if wxABI_VERSION < 20900
272 SSLLocalFile.Open(ServerCertFilename.c_str(), wxT("r"));
274 SSLLocalFile.Open(ServerCertFilename, wxT("r"));
277 // Load the recovery database for tasks not done.
279 if (SSLLocalFile.IsOpened() == TRUE){
281 // Check if we are using wxWidgets version 2.8 or less and
282 // execute the required command accordingly.
284 SSLLocalFile.ReadAll(&SSLLocalData, wxConvAuto());
289 SSLServerData = SSLDataIter->second;
291 if (SSLLocalData == SSLServerData){
293 // Server key matches with local key so retry with CURLOPT_SSL_VERIFYPEER
294 // and CURLOPT_SSL_VERIFYHOST off.
296 curl_easy_cleanup(conn);
297 conn = curl_easy_init();
302 curl_easy_setopt(conn, CURLOPT_URL, (const char*)ServerAddressSSL.mb_str(wxConvUTF8));
303 curl_easy_setopt(conn, CURLOPT_NOPROGRESS, 0);
304 curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
305 curl_easy_setopt(conn, CURLOPT_TIMEOUT, 60);
306 curl_easy_setopt(conn, CURLOPT_FAILONERROR, TRUE);
307 curl_easy_setopt(conn, CURLOPT_USERAGENT, XSDAB_USERAGENT);
308 curl_easy_setopt(conn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8));
309 curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc);
310 curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData);
311 curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader);
312 curl_easy_setopt(conn, CURLOPT_PROGRESSDATA, this);
313 curl_easy_setopt(conn, CURLOPT_PROGRESSFUNCTION, ProgressFunc);
314 curl_easy_setopt(conn, CURLOPT_CUSTOMREQUEST, "REPORT");
315 curl_easy_setopt(conn, CURLOPT_NOSIGNAL, 1);
316 curl_easy_setopt(conn, CURLOPT_HTTPHEADER, slist);
317 curl_easy_setopt(conn, CURLOPT_CERTINFO, 1);
318 curl_easy_setopt(conn, CURLOPT_POSTFIELDS, query);
319 curl_easy_setopt(conn, CURLOPT_POSTFIELDSIZE, strlen(query));
320 curl_easy_setopt(conn, CURLOPT_SSL_VERIFYHOST, 0);
321 curl_easy_setopt(conn, CURLOPT_SSL_VERIFYPEER, 0);
323 claconncode = (curl_easy_perform(conn));
329 if (MatchingCert == FALSE){
331 claconncode = CURLE_SSL_CACERT;
332 return ContactListFinal;
336 curl_easy_cleanup(sslerrconn);
340 // Sort out SSL error.
342 // When SSL cert error occurs, connect again and fetch certificates.
343 // Display a message to the user explaining that an invalid
344 // certificate has been given and let the user decide what
347 if (claconncode == CURLE_OK){
349 } else if (claconncode == CURLE_SSL_CACERT || claconncode == CURLE_PEER_FAILED_VERIFICATION){
352 sslerrconn = curl_easy_init();
353 CURLcode sslerrconncode;
355 wxString ServerAddressOnly = wxT("https://") + ServerAddress + wxT(":") + wxString::Format(wxT("%i"), ServerPort) + wxT("/");
357 // Replace conn with sslerrconn!
359 curl_easy_setopt(sslerrconn, CURLOPT_URL, (const char*)ServerAddressOnly.mb_str(wxConvUTF8));
360 curl_easy_setopt(sslerrconn, CURLOPT_NOPROGRESS, 0);
361 curl_easy_setopt(sslerrconn, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
362 curl_easy_setopt(sslerrconn, CURLOPT_TIMEOUT, 60);
363 curl_easy_setopt(sslerrconn, CURLOPT_FAILONERROR, TRUE);
364 curl_easy_setopt(sslerrconn, CURLOPT_USERAGENT, XSDAB_USERAGENT);
365 curl_easy_setopt(sslerrconn, CURLOPT_WRITEFUNCTION, WritebackFunc);
366 curl_easy_setopt(sslerrconn, CURLOPT_WRITEDATA, &PageData);
367 curl_easy_setopt(sslerrconn, CURLOPT_WRITEHEADER, &PageHeader);
368 curl_easy_setopt(sslerrconn, CURLOPT_PROGRESSDATA, this);
369 curl_easy_setopt(sslerrconn, CURLOPT_PROGRESSFUNCTION, ProgressFunc);
370 curl_easy_setopt(sslerrconn, CURLOPT_NOSIGNAL, 1);
371 curl_easy_setopt(sslerrconn, CURLOPT_SSL_VERIFYPEER, 0);
372 curl_easy_setopt(sslerrconn, CURLOPT_CERTINFO, 1);
374 sslerrconncode = (curl_easy_perform(sslerrconn));
376 SSLCertCol = BuildSSLCollection(sslerrconn);
377 SSLCertCol.SuccessCode = 1;
379 return ContactListFinal;
381 } else if (claconncode == CURLE_HTTP_RETURNED_ERROR){
383 fprintf(stderr, "curl_easy_perform() failed: %s\n",
384 curl_easy_strerror(claconncode));
386 curl_easy_getinfo(conn, CURLINFO_RESPONSE_CODE, &http_code);
387 fprintf(stderr, "Error code was: %d\n", http_code);
389 return ContactListFinal;
393 fprintf(stderr, "curl_easy_perform() failed: %s\n",
394 curl_easy_strerror(claconncode));
396 curl_easy_getinfo(conn, CURLINFO_RESPONSE_CODE, &http_code);
397 fprintf(stderr, "Error code was: %d\n", http_code);
399 return ContactListFinal;
403 SSLCertCol = BuildSSLCollection(conn);
409 wxString EmptyString;
411 curl_easy_setopt(conn, CURLOPT_URL, (const char*)ServerAddressNormal.mb_str(wxConvUTF8));
412 curl_easy_setopt(conn, CURLOPT_NOPROGRESS, 0);
413 curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
414 curl_easy_setopt(conn, CURLOPT_TIMEOUT, 60);
415 curl_easy_setopt(conn, CURLOPT_FAILONERROR, TRUE);
416 curl_easy_setopt(conn, CURLOPT_USERAGENT, XSDAB_USERAGENT);
417 curl_easy_setopt(conn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8));
418 curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc);
419 curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData);
420 curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader);
421 curl_easy_setopt(conn, CURLOPT_PROGRESSDATA, this);
422 curl_easy_setopt(conn, CURLOPT_PROGRESSFUNCTION, ProgressFunc);
423 curl_easy_setopt(conn, CURLOPT_CUSTOMREQUEST, "REPORT");
424 curl_easy_setopt(conn, CURLOPT_NOSIGNAL, 1);
425 curl_easy_setopt(conn, CURLOPT_HTTPHEADER, slist);
427 //UploadData.readptr = &CardDAVDataQuery;
428 //UploadData.sizeleft = CardDAVDataQuery.Len();
429 //curl_easy_setopt(conn, CURLOPT_UPLOAD, 1);
430 //curl_easy_setopt(conn, CURLOPT_READDATA, &UploadData);
431 //curl_easy_setopt(conn, CURLOPT_READFUNCTION, UploadReadFunc);
433 //curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, writefunc);
434 curl_easy_setopt(conn, CURLOPT_POSTFIELDS, query);
435 curl_easy_setopt(conn, CURLOPT_POSTFIELDSIZE, strlen(query));
440 claconncode = (curl_easy_perform(conn));
442 if (claconncode == CURLE_OK){
446 } else if (claconncode == CURLE_HTTP_RETURNED_ERROR){
448 fprintf(stderr, "curl_easy_perform() failed: %s\n",
449 curl_easy_strerror(claconncode));
451 curl_easy_getinfo(conn, CURLINFO_RESPONSE_CODE, &http_code);
452 fprintf(stderr, "Error code was: %i\n", http_code);
454 return ContactListFinal;
458 fprintf(stderr, "curl_easy_perform() failed: %s\n",
459 curl_easy_strerror(claconncode));
461 curl_easy_getinfo(conn, CURLINFO_RESPONSE_CODE, &http_code);
462 fprintf(stderr, "Error code was: %i\n", http_code);
464 return ContactListFinal;
470 xmlDocPtr xmlCardDAVDoc;
471 xmlCardDAVDoc = xmlReadMemory(PageData.mb_str(wxConvUTF8), (int)PageData.Len(), "noname.xml", NULL, 0);
473 xmlNodePtr nodeLevel1;
474 xmlNodePtr nodeLevel2;
475 xmlNodePtr nodeLevel3;
476 xmlNodePtr nodeLevel4;
477 xmlNodePtr nodeLevel5;
478 xmlNodePtr nodeLevel6;
480 xmlNodePtr nodeStatusLv1;
481 xmlNodePtr nodeStatusLv2;
483 std::map<wxString,wxString> xmlDataMap;
484 std::map<wxString,wxString> ServerETagData;
486 wxString DataFilename;
487 wxString DataSyncToken;
490 bool SyncTokenFound = FALSE;
492 std::string xmlStringSafe;
494 // Tranverse through the catacombs of the response to get our ETag for the file and
495 // the server syncronisation token.
497 // Start by getting all the server ETag data.
499 for (nodeLevel1 = xmlCardDAVDoc->children;
501 nodeLevel1 = nodeLevel1->next)
504 for (nodeLevel2 = nodeLevel1->children;
506 nodeLevel2 = nodeLevel2->next)
509 for (nodeLevel3 = nodeLevel2->children;
511 nodeLevel3 = nodeLevel3->next)
515 bool HREFFound = FALSE;
516 bool ETagFound = FALSE;
517 bool HTTPStatus = FALSE;
519 if (!xmlStrcmp(nodeLevel3->name, (const xmlChar *)"href") ||
520 !xmlStrcmp(nodeLevel3->name, (const xmlChar *)"d:href") ||
521 !xmlStrcmp(nodeLevel3->name, (const xmlChar *)"D:href")
526 for (nodeLevel4 = nodeLevel3->children;
528 nodeLevel4 = nodeLevel4->next)
531 if (!xmlStrcmp(nodeLevel4->name, (const xmlChar *)"text") ||
532 !xmlStrcmp(nodeLevel4->name, (const xmlChar *)"d:text") ||
533 !xmlStrcmp(nodeLevel4->name, (const xmlChar *)"D:text")
536 DataFilename = wxString::FromUTF8((const char*)nodeLevel4->content);
537 wxStringTokenizer wSTDFilename(DataFilename, wxT("/"));
539 while (wSTDFilename.HasMoreTokens()){
541 DataFilename = wSTDFilename.GetNextToken();
556 for (nodeLevel4 = nodeLevel3->children;
558 nodeLevel4 = nodeLevel4->next)
561 for (nodeStatusLv1 = nodeLevel3->children;
562 nodeStatusLv1 != NULL;
563 nodeStatusLv1 = nodeStatusLv1->next)
566 if (wxString::FromUTF8((const char*)nodeStatusLv1->content) == wxT("HTTP/1.1 404 Not Found")){
574 if ((!xmlStrcmp(nodeStatusLv1->name, (const xmlChar *)"status") ||
575 !xmlStrcmp(nodeStatusLv1->name, (const xmlChar *)"d:status") ||
576 !xmlStrcmp(nodeStatusLv1->name, (const xmlChar *)"D:status")) && HTTPStatus == FALSE)
581 for (nodeStatusLv2 = nodeStatusLv1->children;
582 nodeStatusLv2 != NULL;
583 nodeStatusLv2 = nodeStatusLv2->next)
586 if (!xmlStrcmp(nodeStatusLv2->name, (const xmlChar *)"text") ||
587 !xmlStrcmp(nodeStatusLv2->name, (const xmlChar *)"d:text") ||
588 !xmlStrcmp(nodeStatusLv2->name, (const xmlChar *)"D:text")
591 if (wxString::FromUTF8((const char*)nodeStatusLv2->content) == wxT("HTTP/1.1 200 OK")){
597 // This is currently in a WebDAV draft and may hopefully be enabled when this changes.
599 //} else if (wxString::FromUTF8((const char*)nodeStatusLv2->content) == wxT("HTTP/1.1 201 Created")){
601 // DataFileStatus = 0;
616 for (nodeLevel5 = nodeLevel4->children;
618 nodeLevel5 = nodeLevel5->next)
621 if (!xmlStrcmp(nodeLevel5->name, (const xmlChar *)"getetag") ||
622 !xmlStrcmp(nodeLevel5->name, (const xmlChar *)"d:getetag") ||
623 !xmlStrcmp(nodeLevel5->name, (const xmlChar *)"D:getetag")
626 for (nodeLevel6 = nodeLevel5->children;
628 nodeLevel6 = nodeLevel6->next)
631 // Strip the quotes from the ETag.
633 ETagData = wxString::FromUTF8((const char*)nodeLevel6->content);
634 if (ETagData.Mid(0, 1) == wxT("\"") && ETagData.Mid((ETagData.Len() - 1), 1) == wxT("\"")){
636 ETagData.Remove(0, 1);
637 ETagData.RemoveLast();
653 if (HREFFound == TRUE && ETagFound == TRUE && HTTPStatus == TRUE){
655 // Add to the map data.
659 SData.ETagData = ETagData;
660 SData.DataFlag = DataFileStatus;
662 ContactListFinal.ListData.insert(std::make_pair(DataFilename, SData));
674 if ((!xmlStrcmp(nodeLevel2->name, (const xmlChar *)"sync-token") ||
675 !xmlStrcmp(nodeLevel2->name, (const xmlChar *)"d:sync-token") ||
676 !xmlStrcmp(nodeLevel2->name, (const xmlChar *)"D:sync-token")) &&
677 SyncTokenFound == FALSE
680 for (nodeLevel3 = nodeLevel2->children;
682 nodeLevel3 = nodeLevel3->next)
685 if (!xmlStrcmp(nodeLevel3->name, (const xmlChar *)"text") ||
686 !xmlStrcmp(nodeLevel3->name, (const xmlChar *)"d:text") ||
687 !xmlStrcmp(nodeLevel3->name, (const xmlChar *)"D:text")
690 DataSyncToken = wxString::FromUTF8((const char*)nodeLevel3->content);
692 SyncTokenFound = TRUE;
704 for (nodeLevel1 = xmlCardDAVDoc->children;
706 nodeLevel1 = nodeLevel1->next)
709 for (nodeLevel2 = nodeLevel1->children;
711 nodeLevel2 = nodeLevel2->next)
715 bool HREFFound = FALSE;
716 bool ETagFound = FALSE;
717 bool HTTPStatus = FALSE;
719 for (nodeLevel3 = nodeLevel2->children;
721 nodeLevel3 = nodeLevel3->next)
724 if (!xmlStrcmp(nodeLevel3->name, (const xmlChar *)"href") ||
725 !xmlStrcmp(nodeLevel3->name, (const xmlChar *)"d:href") ||
726 !xmlStrcmp(nodeLevel3->name, (const xmlChar *)"D:href")
731 for (nodeLevel4 = nodeLevel3->children;
733 nodeLevel4 = nodeLevel4->next)
736 if (!xmlStrcmp(nodeLevel4->name, (const xmlChar *)"text") ||
737 !xmlStrcmp(nodeLevel4->name, (const xmlChar *)"d:text") ||
738 !xmlStrcmp(nodeLevel4->name, (const xmlChar *)"D:text")
741 DataFilename = wxString::FromUTF8((const char*)nodeLevel4->content);
742 wxStringTokenizer wSTDFilename(DataFilename, wxT("/"));
744 while (wSTDFilename.HasMoreTokens()){
746 DataFilename = wSTDFilename.GetNextToken();
761 for (nodeLevel4 = nodeLevel3->children;
763 nodeLevel4 = nodeLevel4->next)
766 for (nodeStatusLv1 = nodeLevel3->children;
767 nodeStatusLv1 != NULL;
768 nodeStatusLv1 = nodeStatusLv1->next)
771 if (wxString::FromUTF8((const char*)nodeStatusLv1->content) == wxT("HTTP/1.1 404 Not Found")){
779 if ((!xmlStrcmp(nodeStatusLv1->name, (const xmlChar *)"status") ||
780 !xmlStrcmp(nodeStatusLv1->name, (const xmlChar *)"d:status") ||
781 !xmlStrcmp(nodeStatusLv1->name, (const xmlChar *)"D:status")) && HTTPStatus == FALSE)
786 for (nodeStatusLv2 = nodeStatusLv1->children;
787 nodeStatusLv2 != NULL;
788 nodeStatusLv2 = nodeStatusLv2->next)
791 if (!xmlStrcmp(nodeStatusLv2->name, (const xmlChar *)"text") ||
792 !xmlStrcmp(nodeStatusLv2->name, (const xmlChar *)"d:text") ||
793 !xmlStrcmp(nodeStatusLv2->name, (const xmlChar *)"D:text")
796 if (wxString::FromUTF8((const char*)nodeStatusLv2->content) == wxT("HTTP/1.1 200 OK")){
802 // This is currently in a WebDAV draft and may hopefully be enabled when this changes.
804 //} else if (wxString::FromUTF8((const char*)nodeStatusLv2->content) == wxT("HTTP/1.1 201 Created")){
806 // DataFileStatus = 0;
821 for (nodeLevel5 = nodeLevel4->children;
823 nodeLevel5 = nodeLevel5->next)
826 if (!xmlStrcmp(nodeLevel5->name, (const xmlChar *)"getetag") ||
827 !xmlStrcmp(nodeLevel5->name, (const xmlChar *)"d:getetag") ||
828 !xmlStrcmp(nodeLevel5->name, (const xmlChar *)"D:getetag")
831 for (nodeLevel6 = nodeLevel5->children;
833 nodeLevel6 = nodeLevel6->next)
836 // Strip the quotes from the ETag.
838 ETagData = wxString::FromUTF8((const char*)nodeLevel6->content);
839 if (ETagData.Mid(0, 1) == wxT("\"") && ETagData.Mid((ETagData.Len() - 1), 1) == wxT("\"")){
841 ETagData.Remove(0, 1);
842 ETagData.RemoveLast();
860 if (HREFFound == TRUE && HTTPStatus == TRUE && DataFileStatus == 2){
864 SData.ETagData = wxT("");
865 SData.DataFlag = DataFileStatus;
867 ContactListFinal.ListData.insert(std::make_pair(DataFilename, SData));
871 if (HREFFound == TRUE && ETagFound == TRUE && HTTPStatus == TRUE){
873 // Add to the map data.
877 SData.ETagData = ETagData;
878 SData.DataFlag = DataFileStatus;
880 ContactListFinal.ListData.insert(std::make_pair(DataFilename, SData));
889 DataFilename.Clear();
891 if ((!xmlStrcmp(nodeLevel2->name, (const xmlChar *)"sync-token") ||
892 !xmlStrcmp(nodeLevel2->name, (const xmlChar *)"d:sync-token") ||
893 !xmlStrcmp(nodeLevel2->name, (const xmlChar *)"D:sync-token")) &&
894 SyncTokenFound == FALSE
897 for (nodeLevel3 = nodeLevel2->children;
899 nodeLevel3 = nodeLevel3->next)
902 if (!xmlStrcmp(nodeLevel3->name, (const xmlChar *)"text") ||
903 !xmlStrcmp(nodeLevel3->name, (const xmlChar *)"d:text") ||
904 !xmlStrcmp(nodeLevel3->name, (const xmlChar *)"D:text")
907 DataSyncToken = wxString::FromUTF8((const char*)nodeLevel3->content);
909 SyncTokenFound = TRUE;
921 // Get the sync token.
923 if (SyncTokenFound == TRUE){
925 ContactListFinal.SyncToken = DataSyncToken;
931 SleepFor(2000000000);
936 n1.tv_nsec = 2000000000L;
938 nanosleep(&n1, &n2);*/
940 xmlFreeDoc(xmlCardDAVDoc);
941 curl_easy_cleanup(conn);
943 SyncDataBuffer.reset();
945 // Get the first result.
947 return ContactListFinal;