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 ContactListData ContactListFinal;
34 std::map<wxString,FileSyncData> ContactList;
41 AbortConnection = FALSE;
44 wxString ServerAddressURL;
46 wxString ServerAddressSSL;
47 wxString ServerAddressNormal;
49 conn = curl_easy_init();
51 struct CardDAVCURLPasser {
54 bool HeaderMode = TRUE;
56 } CardDAVHeader, CardDAVFooter;
58 CardDAVHeader.Data = this;
59 CardDAVHeader.HeaderMode = TRUE;
61 CardDAVFooter.Data = this;
62 CardDAVFooter.HeaderMode = FALSE;
67 ServerAddressURL = ServerAddress + wxT(":") + wxString::Format(wxT("%i"), ServerPort) + wxT("/") + ServerPrefix + wxT("/");
68 ServerAddressSSL = wxT("https://") + ServerAddressURL;
69 ServerAddressNormal = wxT("http://") + ServerAddressURL;
71 ServerAuth = ServerUser + wxT(":") + ServerPass;
73 // Load the sync token file (if it exists).
75 wxCharBuffer SyncDataBuffer;
82 if (!SyncTokenInc.IsEmpty()){
84 SyncData = wxT("<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n");
85 SyncData.Append(wxT("<D:sync-collection xmlns:D=\"DAV:\"\n"));
86 SyncData.Append(wxT(" xmlns:C=\"urn:ietf:params:xml:ns:carddav\">\n"));
87 SyncData.Append(wxT("<D:sync-token>"));
89 //SyncData.Append(wxT("data:,00378c55-1f44-44a2-a255-84f6560b5cac_580"));
90 SyncData.Append(SyncTokenInc);
92 SyncData.Append(wxT("</D:sync-token>\n"));
93 SyncData.Append(wxT("<D:sync-level>1</D:sync-level>\n"));
94 SyncData.Append(wxT("<D:prop>\n"));
95 SyncData.Append(wxT(" <D:getetag/>\n"));
96 SyncData.Append(wxT("</D:prop>\n"));
97 SyncData.Append(wxT("</D:sync-collection>"));
99 SyncDataBuffer = SyncData.ToUTF8();
103 SyncData = wxT("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
104 SyncData.Append(wxT("<D:sync-collection xmlns:D=\"DAV:\""));
105 SyncData.Append(wxT(" xmlns:C=\"urn:ietf:params:xml:ns:carddav\">\n"));
106 SyncData.Append(wxT("<D:sync-token/>\n"));
107 SyncData.Append(wxT("<D:sync-level>1</D:sync-level>\n"));
108 SyncData.Append(wxT("<D:prop>\n"));
109 SyncData.Append(wxT(" <D:getetag/>\n"));
110 SyncData.Append(wxT("</D:prop>\n"));
111 SyncData.Append(wxT("</D:sync-collection>\n"));
113 SyncDataBuffer = SyncData.ToUTF8();
117 //static const char* query = SyncData.mb_str();
119 /*char *query = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\
120 <D:sync-collection xmlns:D=\"DAV:\"\n\
121 xmlns:C=\"urn:ietf:params:xml:ns:carddav\">\n\
122 <D:sync-token>data:,00378c55-1f44-44a2-a255-84f6560b5cac_580</D:sync-token>\n\
123 <D:sync-level>1</D:sync-level>\n\
127 </D:sync-collection>\n";*/
128 const char* query = SyncDataBuffer.data();
132 std::map<int,int>::iterator ActIter;
133 struct UploadDataStruc UploadData;
135 ActIter = ActivityListPtr->find((int)ItemIndex);
137 curl_slist *slist = NULL;
139 slist = curl_slist_append(slist, "Depth: 1");
143 wxString ServerCertFilename;
144 bool MatchingCert = FALSE;
146 curl_easy_setopt(conn, CURLOPT_URL, (const char*)ServerAddressSSL.mb_str(wxConvUTF8));
147 curl_easy_setopt(conn, CURLOPT_NOPROGRESS, 0);
148 curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANYSAFE);
149 curl_easy_setopt(conn, CURLOPT_TIMEOUT, 60);
150 curl_easy_setopt(conn, CURLOPT_FAILONERROR, TRUE);
151 curl_easy_setopt(conn, CURLOPT_USERAGENT, XSDAB_USERAGENT);
152 curl_easy_setopt(conn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8));
153 curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc);
154 curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData);
155 curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader);
156 curl_easy_setopt(conn, CURLOPT_PROGRESSDATA, this);
157 curl_easy_setopt(conn, CURLOPT_PROGRESSFUNCTION, ProgressFunc);
158 curl_easy_setopt(conn, CURLOPT_CUSTOMREQUEST, "REPORT");
159 curl_easy_setopt(conn, CURLOPT_NOSIGNAL, 1);
160 curl_easy_setopt(conn, CURLOPT_HTTPHEADER, slist);
161 curl_easy_setopt(conn, CURLOPT_CERTINFO, 1);
163 ServerCertFilename = GetAccountDir(ServerAccount, TRUE);
165 if (wxFile::Exists(ServerCertFilename) == TRUE){
167 curl_easy_setopt(conn, CURLOPT_SSL_VERIFYPEER, 1);
168 curl_easy_setopt(conn, CURLOPT_SSL_VERIFYHOST, 2);
169 curl_easy_setopt(conn, CURLOPT_CAINFO, (const char*)ServerCertFilename.mb_str(wxConvUTF8));
173 //UploadData.readptr = &CardDAVDataQuery;
174 //UploadData.sizeleft = CardDAVDataQuery.Len();
175 //curl_easy_setopt(conn, CURLOPT_UPLOAD, 1);
176 //curl_easy_setopt(conn, CURLOPT_READDATA, &UploadData);
177 //curl_easy_setopt(conn, CURLOPT_READFUNCTION, UploadReadFunc);
179 //curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, writefunc);
180 curl_easy_setopt(conn, CURLOPT_POSTFIELDS, query);
181 curl_easy_setopt(conn, CURLOPT_POSTFIELDSIZE, strlen(query));
183 claconncode = (curl_easy_perform(conn));
185 // If CURLE_PEER_FAILED_VERIFICATION is returned, retry without
186 // the local certificate in use.
188 if (claconncode == CURLE_PEER_FAILED_VERIFICATION){
190 curl_easy_cleanup(conn);
191 conn = curl_easy_init();
193 curl_easy_setopt(conn, CURLOPT_URL, (const char*)ServerAddressSSL.mb_str(wxConvUTF8));
194 curl_easy_setopt(conn, CURLOPT_NOPROGRESS, 0);
195 curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANYSAFE);
196 curl_easy_setopt(conn, CURLOPT_TIMEOUT, 60);
197 curl_easy_setopt(conn, CURLOPT_FAILONERROR, TRUE);
198 curl_easy_setopt(conn, CURLOPT_USERAGENT, XSDAB_USERAGENT);
199 curl_easy_setopt(conn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8));
200 curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc);
201 curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData);
202 curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader);
203 curl_easy_setopt(conn, CURLOPT_PROGRESSDATA, this);
204 curl_easy_setopt(conn, CURLOPT_PROGRESSFUNCTION, ProgressFunc);
205 curl_easy_setopt(conn, CURLOPT_CUSTOMREQUEST, "REPORT");
206 curl_easy_setopt(conn, CURLOPT_NOSIGNAL, 1);
207 curl_easy_setopt(conn, CURLOPT_HTTPHEADER, slist);
208 curl_easy_setopt(conn, CURLOPT_CERTINFO, 1);
209 curl_easy_setopt(conn, CURLOPT_POSTFIELDS, query);
210 curl_easy_setopt(conn, CURLOPT_POSTFIELDSIZE, strlen(query));
212 claconncode = (curl_easy_perform(conn));
214 // If claconncode is CURLE_OK then delete the certificate file as that
215 // is no longer needed.
217 if (claconncode == CURLE_OK){
219 // Delete the certificate file.
221 wxRemoveFile(ServerCertFilename);
227 // Check if it fails with a CURLE_SSL_CACERT then compare
228 // the certificates as PEM files.
230 if (claconncode == CURLE_SSL_CACERT && wxFile::Exists(ServerCertFilename) == TRUE){
232 //curl_easy_cleanup(conn);
233 //conn = curl_easy_init();
236 sslerrconn = curl_easy_init();
237 CURLcode sslerrconncode;
239 //claconncode = (curl_easy_perform(conn));
241 wxString ServerAddressOnly = wxT("https://") + ServerAddress + wxT(":") + wxString::Format(wxT("%i"), ServerPort) + wxT("/");
243 curl_easy_setopt(sslerrconn, CURLOPT_URL, (const char*)ServerAddressOnly.mb_str(wxConvUTF8));
244 curl_easy_setopt(sslerrconn, CURLOPT_NOPROGRESS, 0);
245 curl_easy_setopt(sslerrconn, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
246 curl_easy_setopt(sslerrconn, CURLOPT_TIMEOUT, 60);
247 curl_easy_setopt(sslerrconn, CURLOPT_FAILONERROR, TRUE);
248 curl_easy_setopt(sslerrconn, CURLOPT_USERAGENT, XSDAB_USERAGENT);
249 curl_easy_setopt(sslerrconn, CURLOPT_WRITEFUNCTION, WritebackFunc);
250 curl_easy_setopt(sslerrconn, CURLOPT_WRITEDATA, &PageData);
251 curl_easy_setopt(sslerrconn, CURLOPT_WRITEHEADER, &PageHeader);
252 curl_easy_setopt(sslerrconn, CURLOPT_PROGRESSDATA, this);
253 curl_easy_setopt(sslerrconn, CURLOPT_PROGRESSFUNCTION, ProgressFunc);
254 curl_easy_setopt(sslerrconn, CURLOPT_NOSIGNAL, 1);
255 curl_easy_setopt(sslerrconn, CURLOPT_SSL_VERIFYPEER, 0);
256 curl_easy_setopt(sslerrconn, CURLOPT_CERTINFO, 1);
258 wxString SSLLocalData;
259 wxString SSLServerData;
261 sslerrconncode = (curl_easy_perform(sslerrconn));
263 SSLCertCol = BuildSSLCollection(sslerrconn);
264 std::map<int, SSLCertData>::iterator SSLCDIter = SSLCertCol.SSLCollection.find(0);
265 std::multimap<wxString,wxString>::iterator SSLDataIter = SSLCDIter->second.CertData.find(wxT("Cert"));
267 wxFFile SSLLocalFile;
269 #if wxABI_VERSION < 20900
270 SSLLocalFile.Open(ServerCertFilename.c_str(), wxT("r"));
272 SSLLocalFile.Open(ServerCertFilename, wxT("r"));
275 // Load the recovery database for tasks not done.
277 if (SSLLocalFile.IsOpened() == TRUE){
279 // Check if we are using wxWidgets version 2.8 or less and
280 // execute the required command accordingly.
282 SSLLocalFile.ReadAll(&SSLLocalData, wxConvAuto());
287 SSLServerData = SSLDataIter->second;
289 if (SSLLocalData == SSLServerData){
291 // Server key matches with local key so retry with CURLOPT_SSL_VERIFYPEER
292 // and CURLOPT_SSL_VERIFYHOST off.
294 curl_easy_cleanup(conn);
295 conn = curl_easy_init();
300 curl_easy_setopt(conn, CURLOPT_URL, (const char*)ServerAddressSSL.mb_str(wxConvUTF8));
301 curl_easy_setopt(conn, CURLOPT_NOPROGRESS, 0);
302 curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
303 curl_easy_setopt(conn, CURLOPT_TIMEOUT, 60);
304 curl_easy_setopt(conn, CURLOPT_FAILONERROR, TRUE);
305 curl_easy_setopt(conn, CURLOPT_USERAGENT, XSDAB_USERAGENT);
306 curl_easy_setopt(conn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8));
307 curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc);
308 curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData);
309 curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader);
310 curl_easy_setopt(conn, CURLOPT_PROGRESSDATA, this);
311 curl_easy_setopt(conn, CURLOPT_PROGRESSFUNCTION, ProgressFunc);
312 curl_easy_setopt(conn, CURLOPT_CUSTOMREQUEST, "REPORT");
313 curl_easy_setopt(conn, CURLOPT_NOSIGNAL, 1);
314 curl_easy_setopt(conn, CURLOPT_HTTPHEADER, slist);
315 curl_easy_setopt(conn, CURLOPT_CERTINFO, 1);
316 curl_easy_setopt(conn, CURLOPT_POSTFIELDS, query);
317 curl_easy_setopt(conn, CURLOPT_POSTFIELDSIZE, strlen(query));
318 curl_easy_setopt(conn, CURLOPT_SSL_VERIFYHOST, 0);
319 curl_easy_setopt(conn, CURLOPT_SSL_VERIFYPEER, 0);
321 claconncode = (curl_easy_perform(conn));
327 if (MatchingCert == FALSE){
329 claconncode = CURLE_SSL_CACERT;
330 return ContactListFinal;
334 curl_easy_cleanup(sslerrconn);
338 // Sort out SSL error.
340 // When SSL cert error occurs, connect again and fetch certificates.
341 // Display a message to the user explaining that an invalid
342 // certificate has been given and let the user decide what
345 if (claconncode == CURLE_OK){
347 } else if (claconncode == CURLE_SSL_CACERT || claconncode == CURLE_PEER_FAILED_VERIFICATION){
350 sslerrconn = curl_easy_init();
351 CURLcode sslerrconncode;
353 wxString ServerAddressOnly = wxT("https://") + ServerAddress + wxT(":") + wxString::Format(wxT("%i"), ServerPort) + wxT("/");
355 // Replace conn with sslerrconn!
357 curl_easy_setopt(sslerrconn, CURLOPT_URL, (const char*)ServerAddressOnly.mb_str(wxConvUTF8));
358 curl_easy_setopt(sslerrconn, CURLOPT_NOPROGRESS, 0);
359 curl_easy_setopt(sslerrconn, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
360 curl_easy_setopt(sslerrconn, CURLOPT_TIMEOUT, 60);
361 curl_easy_setopt(sslerrconn, CURLOPT_FAILONERROR, TRUE);
362 curl_easy_setopt(sslerrconn, CURLOPT_USERAGENT, XSDAB_USERAGENT);
363 curl_easy_setopt(sslerrconn, CURLOPT_WRITEFUNCTION, WritebackFunc);
364 curl_easy_setopt(sslerrconn, CURLOPT_WRITEDATA, &PageData);
365 curl_easy_setopt(sslerrconn, CURLOPT_WRITEHEADER, &PageHeader);
366 curl_easy_setopt(sslerrconn, CURLOPT_PROGRESSDATA, this);
367 curl_easy_setopt(sslerrconn, CURLOPT_PROGRESSFUNCTION, ProgressFunc);
368 curl_easy_setopt(sslerrconn, CURLOPT_NOSIGNAL, 1);
369 curl_easy_setopt(sslerrconn, CURLOPT_SSL_VERIFYPEER, 0);
370 curl_easy_setopt(sslerrconn, CURLOPT_CERTINFO, 1);
372 sslerrconncode = (curl_easy_perform(sslerrconn));
374 SSLCertCol = BuildSSLCollection(sslerrconn);
375 SSLCertCol.SuccessCode = 1;
377 return ContactListFinal;
379 } else if (claconncode == CURLE_HTTP_RETURNED_ERROR){
381 fprintf(stderr, "curl_easy_perform() failed: %s\n",
382 curl_easy_strerror(claconncode));
384 curl_easy_getinfo(conn, CURLINFO_RESPONSE_CODE, &http_code);
385 fprintf(stderr, "Error code was: %d\n", http_code);
387 return ContactListFinal;
391 fprintf(stderr, "curl_easy_perform() failed: %s\n",
392 curl_easy_strerror(claconncode));
394 curl_easy_getinfo(conn, CURLINFO_RESPONSE_CODE, &http_code);
395 fprintf(stderr, "Error code was: %d\n", http_code);
397 return ContactListFinal;
401 SSLCertCol = BuildSSLCollection(conn);
407 wxString EmptyString;
409 curl_easy_setopt(conn, CURLOPT_URL, (const char*)ServerAddressNormal.mb_str(wxConvUTF8));
410 curl_easy_setopt(conn, CURLOPT_NOPROGRESS, 0);
411 curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
412 curl_easy_setopt(conn, CURLOPT_TIMEOUT, 60);
413 curl_easy_setopt(conn, CURLOPT_FAILONERROR, TRUE);
414 curl_easy_setopt(conn, CURLOPT_USERAGENT, XSDAB_USERAGENT);
415 curl_easy_setopt(conn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8));
416 curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc);
417 curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData);
418 curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader);
419 curl_easy_setopt(conn, CURLOPT_PROGRESSDATA, this);
420 curl_easy_setopt(conn, CURLOPT_PROGRESSFUNCTION, ProgressFunc);
421 curl_easy_setopt(conn, CURLOPT_CUSTOMREQUEST, "REPORT");
422 curl_easy_setopt(conn, CURLOPT_NOSIGNAL, 1);
423 curl_easy_setopt(conn, CURLOPT_HTTPHEADER, slist);
425 //UploadData.readptr = &CardDAVDataQuery;
426 //UploadData.sizeleft = CardDAVDataQuery.Len();
427 //curl_easy_setopt(conn, CURLOPT_UPLOAD, 1);
428 //curl_easy_setopt(conn, CURLOPT_READDATA, &UploadData);
429 //curl_easy_setopt(conn, CURLOPT_READFUNCTION, UploadReadFunc);
431 //curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, writefunc);
432 curl_easy_setopt(conn, CURLOPT_POSTFIELDS, query);
433 curl_easy_setopt(conn, CURLOPT_POSTFIELDSIZE, strlen(query));
438 claconncode = (curl_easy_perform(conn));
440 if (claconncode == CURLE_OK){
444 } else if (claconncode == CURLE_HTTP_RETURNED_ERROR){
446 fprintf(stderr, "curl_easy_perform() failed: %s\n",
447 curl_easy_strerror(claconncode));
449 curl_easy_getinfo(conn, CURLINFO_RESPONSE_CODE, &http_code);
450 fprintf(stderr, "Error code was: %i\n", http_code);
452 return ContactListFinal;
456 fprintf(stderr, "curl_easy_perform() failed: %s\n",
457 curl_easy_strerror(claconncode));
459 curl_easy_getinfo(conn, CURLINFO_RESPONSE_CODE, &http_code);
460 fprintf(stderr, "Error code was: %i\n", http_code);
462 return ContactListFinal;
468 xmlDocPtr xmlCardDAVDoc;
469 xmlCardDAVDoc = xmlReadMemory(PageData.mb_str(wxConvUTF8), (int)PageData.Len(), "noname.xml", NULL, 0);
471 xmlNodePtr nodeLevel1;
472 xmlNodePtr nodeLevel2;
473 xmlNodePtr nodeLevel3;
474 xmlNodePtr nodeLevel4;
475 xmlNodePtr nodeLevel5;
476 xmlNodePtr nodeLevel6;
478 xmlNodePtr nodeStatusLv1;
479 xmlNodePtr nodeStatusLv2;
481 std::map<wxString,wxString> xmlDataMap;
482 std::map<wxString,wxString> ServerETagData;
484 wxString DataFilename;
485 wxString DataSyncToken;
488 bool SyncTokenFound = FALSE;
490 std::string xmlStringSafe;
492 // Tranverse through the catacombs of the response to get our ETag for the file and
493 // the server syncronisation token.
495 // Start by getting all the server ETag data.
497 for (nodeLevel1 = xmlCardDAVDoc->children;
499 nodeLevel1 = nodeLevel1->next)
502 for (nodeLevel2 = nodeLevel1->children;
504 nodeLevel2 = nodeLevel2->next)
507 for (nodeLevel3 = nodeLevel2->children;
509 nodeLevel3 = nodeLevel3->next)
513 bool HREFFound = FALSE;
514 bool ETagFound = FALSE;
515 bool HTTPStatus = FALSE;
517 if (!xmlStrcmp(nodeLevel3->name, (const xmlChar *)"href") ||
518 !xmlStrcmp(nodeLevel3->name, (const xmlChar *)"d:href") ||
519 !xmlStrcmp(nodeLevel3->name, (const xmlChar *)"D:href")
524 for (nodeLevel4 = nodeLevel3->children;
526 nodeLevel4 = nodeLevel4->next)
529 if (!xmlStrcmp(nodeLevel4->name, (const xmlChar *)"text") ||
530 !xmlStrcmp(nodeLevel4->name, (const xmlChar *)"d:text") ||
531 !xmlStrcmp(nodeLevel4->name, (const xmlChar *)"D:text")
534 DataFilename = wxString::FromUTF8((const char*)nodeLevel4->content);
535 wxStringTokenizer wSTDFilename(DataFilename, wxT("/"));
537 while (wSTDFilename.HasMoreTokens()){
539 DataFilename = wSTDFilename.GetNextToken();
554 for (nodeLevel4 = nodeLevel3->children;
556 nodeLevel4 = nodeLevel4->next)
559 for (nodeStatusLv1 = nodeLevel3->children;
560 nodeStatusLv1 != NULL;
561 nodeStatusLv1 = nodeStatusLv1->next)
564 if (wxString::FromUTF8((const char*)nodeStatusLv1->content) == wxT("HTTP/1.1 404 Not Found")){
572 if ((!xmlStrcmp(nodeStatusLv1->name, (const xmlChar *)"status") ||
573 !xmlStrcmp(nodeStatusLv1->name, (const xmlChar *)"d:status") ||
574 !xmlStrcmp(nodeStatusLv1->name, (const xmlChar *)"D:status")) && HTTPStatus == FALSE)
579 for (nodeStatusLv2 = nodeStatusLv1->children;
580 nodeStatusLv2 != NULL;
581 nodeStatusLv2 = nodeStatusLv2->next)
584 if (!xmlStrcmp(nodeStatusLv2->name, (const xmlChar *)"text") ||
585 !xmlStrcmp(nodeStatusLv2->name, (const xmlChar *)"d:text") ||
586 !xmlStrcmp(nodeStatusLv2->name, (const xmlChar *)"D:text")
589 if (wxString::FromUTF8((const char*)nodeStatusLv2->content) == wxT("HTTP/1.1 200 OK")){
595 // This is currently in a WebDAV draft and may hopefully be enabled when this changes.
597 //} else if (wxString::FromUTF8((const char*)nodeStatusLv2->content) == wxT("HTTP/1.1 201 Created")){
599 // DataFileStatus = 0;
614 for (nodeLevel5 = nodeLevel4->children;
616 nodeLevel5 = nodeLevel5->next)
619 if (!xmlStrcmp(nodeLevel5->name, (const xmlChar *)"getetag") ||
620 !xmlStrcmp(nodeLevel5->name, (const xmlChar *)"d:getetag") ||
621 !xmlStrcmp(nodeLevel5->name, (const xmlChar *)"D:getetag")
624 for (nodeLevel6 = nodeLevel5->children;
626 nodeLevel6 = nodeLevel6->next)
629 // Strip the quotes from the ETag.
631 ETagData = wxString::FromUTF8((const char*)nodeLevel6->content);
632 if (ETagData.Mid(0, 1) == wxT("\"") && ETagData.Mid((ETagData.Len() - 1), 1) == wxT("\"")){
634 ETagData.Remove(0, 1);
635 ETagData.RemoveLast();
651 if (HREFFound == TRUE && ETagFound == TRUE && HTTPStatus == TRUE){
653 // Add to the map data.
657 SData.ETagData = ETagData;
658 SData.DataFlag = DataFileStatus;
660 ContactListFinal.ListData.insert(std::make_pair(DataFilename, SData));
672 if ((!xmlStrcmp(nodeLevel2->name, (const xmlChar *)"sync-token") ||
673 !xmlStrcmp(nodeLevel2->name, (const xmlChar *)"d:sync-token") ||
674 !xmlStrcmp(nodeLevel2->name, (const xmlChar *)"D:sync-token")) &&
675 SyncTokenFound == FALSE
678 for (nodeLevel3 = nodeLevel2->children;
680 nodeLevel3 = nodeLevel3->next)
683 if (!xmlStrcmp(nodeLevel3->name, (const xmlChar *)"text") ||
684 !xmlStrcmp(nodeLevel3->name, (const xmlChar *)"d:text") ||
685 !xmlStrcmp(nodeLevel3->name, (const xmlChar *)"D:text")
688 DataSyncToken = wxString::FromUTF8((const char*)nodeLevel3->content);
690 SyncTokenFound = TRUE;
702 for (nodeLevel1 = xmlCardDAVDoc->children;
704 nodeLevel1 = nodeLevel1->next)
707 for (nodeLevel2 = nodeLevel1->children;
709 nodeLevel2 = nodeLevel2->next)
713 bool HREFFound = FALSE;
714 bool ETagFound = FALSE;
715 bool HTTPStatus = FALSE;
717 for (nodeLevel3 = nodeLevel2->children;
719 nodeLevel3 = nodeLevel3->next)
722 if (!xmlStrcmp(nodeLevel3->name, (const xmlChar *)"href") ||
723 !xmlStrcmp(nodeLevel3->name, (const xmlChar *)"d:href") ||
724 !xmlStrcmp(nodeLevel3->name, (const xmlChar *)"D:href")
729 for (nodeLevel4 = nodeLevel3->children;
731 nodeLevel4 = nodeLevel4->next)
734 if (!xmlStrcmp(nodeLevel4->name, (const xmlChar *)"text") ||
735 !xmlStrcmp(nodeLevel4->name, (const xmlChar *)"d:text") ||
736 !xmlStrcmp(nodeLevel4->name, (const xmlChar *)"D:text")
739 DataFilename = wxString::FromUTF8((const char*)nodeLevel4->content);
740 wxStringTokenizer wSTDFilename(DataFilename, wxT("/"));
742 while (wSTDFilename.HasMoreTokens()){
744 DataFilename = wSTDFilename.GetNextToken();
759 for (nodeLevel4 = nodeLevel3->children;
761 nodeLevel4 = nodeLevel4->next)
764 for (nodeStatusLv1 = nodeLevel3->children;
765 nodeStatusLv1 != NULL;
766 nodeStatusLv1 = nodeStatusLv1->next)
769 if (wxString::FromUTF8((const char*)nodeStatusLv1->content) == wxT("HTTP/1.1 404 Not Found")){
777 if ((!xmlStrcmp(nodeStatusLv1->name, (const xmlChar *)"status") ||
778 !xmlStrcmp(nodeStatusLv1->name, (const xmlChar *)"d:status") ||
779 !xmlStrcmp(nodeStatusLv1->name, (const xmlChar *)"D:status")) && HTTPStatus == FALSE)
784 for (nodeStatusLv2 = nodeStatusLv1->children;
785 nodeStatusLv2 != NULL;
786 nodeStatusLv2 = nodeStatusLv2->next)
789 if (!xmlStrcmp(nodeStatusLv2->name, (const xmlChar *)"text") ||
790 !xmlStrcmp(nodeStatusLv2->name, (const xmlChar *)"d:text") ||
791 !xmlStrcmp(nodeStatusLv2->name, (const xmlChar *)"D:text")
794 if (wxString::FromUTF8((const char*)nodeStatusLv2->content) == wxT("HTTP/1.1 200 OK")){
800 // This is currently in a WebDAV draft and may hopefully be enabled when this changes.
802 //} else if (wxString::FromUTF8((const char*)nodeStatusLv2->content) == wxT("HTTP/1.1 201 Created")){
804 // DataFileStatus = 0;
819 for (nodeLevel5 = nodeLevel4->children;
821 nodeLevel5 = nodeLevel5->next)
824 if (!xmlStrcmp(nodeLevel5->name, (const xmlChar *)"getetag") ||
825 !xmlStrcmp(nodeLevel5->name, (const xmlChar *)"d:getetag") ||
826 !xmlStrcmp(nodeLevel5->name, (const xmlChar *)"D:getetag")
829 for (nodeLevel6 = nodeLevel5->children;
831 nodeLevel6 = nodeLevel6->next)
834 // Strip the quotes from the ETag.
836 ETagData = wxString::FromUTF8((const char*)nodeLevel6->content);
837 if (ETagData.Mid(0, 1) == wxT("\"") && ETagData.Mid((ETagData.Len() - 1), 1) == wxT("\"")){
839 ETagData.Remove(0, 1);
840 ETagData.RemoveLast();
858 if (HREFFound == TRUE && HTTPStatus == TRUE && DataFileStatus == 2){
862 SData.ETagData = wxT("");
863 SData.DataFlag = DataFileStatus;
865 ContactListFinal.ListData.insert(std::make_pair(DataFilename, SData));
869 if (HREFFound == TRUE && ETagFound == TRUE && HTTPStatus == TRUE){
871 // Add to the map data.
875 SData.ETagData = ETagData;
876 SData.DataFlag = DataFileStatus;
878 ContactListFinal.ListData.insert(std::make_pair(DataFilename, SData));
887 DataFilename.Clear();
889 if ((!xmlStrcmp(nodeLevel2->name, (const xmlChar *)"sync-token") ||
890 !xmlStrcmp(nodeLevel2->name, (const xmlChar *)"d:sync-token") ||
891 !xmlStrcmp(nodeLevel2->name, (const xmlChar *)"D:sync-token")) &&
892 SyncTokenFound == FALSE
895 for (nodeLevel3 = nodeLevel2->children;
897 nodeLevel3 = nodeLevel3->next)
900 if (!xmlStrcmp(nodeLevel3->name, (const xmlChar *)"text") ||
901 !xmlStrcmp(nodeLevel3->name, (const xmlChar *)"d:text") ||
902 !xmlStrcmp(nodeLevel3->name, (const xmlChar *)"D:text")
905 DataSyncToken = wxString::FromUTF8((const char*)nodeLevel3->content);
907 SyncTokenFound = TRUE;
919 // Get the sync token.
921 if (SyncTokenFound == TRUE){
923 ContactListFinal.SyncToken = DataSyncToken;
929 SleepFor(2000000000);
934 n1.tv_nsec = 2000000000L;
936 nanosleep(&n1, &n2);*/
938 xmlFreeDoc(xmlCardDAVDoc);
939 curl_easy_cleanup(conn);
941 SyncDataBuffer.reset();
943 // Get the first result.
945 return ContactListFinal;