2 #include "../version.h"
4 #include <wx/tokenzr.h>
6 #include <libxml/parser.h>
7 #include <libxml/tree.h>
10 #include "../vcard/vcard.h"
11 #include "../common/dirs.h"
13 ContactListData CardDAV::GetContactList(wxString SyncTokenInc){
15 ContactListData ContactListFinal;
16 std::map<wxString,FileSyncData> ContactList;
23 AbortConnection = FALSE;
26 wxString ServerAddressURL;
28 wxString ServerAddressSSL;
29 wxString ServerAddressNormal;
31 conn = curl_easy_init();
33 struct CardDAVCURLPasser {
36 bool HeaderMode = TRUE;
38 } CardDAVHeader, CardDAVFooter;
40 CardDAVHeader.Data = this;
41 CardDAVHeader.HeaderMode = TRUE;
43 CardDAVFooter.Data = this;
44 CardDAVFooter.HeaderMode = FALSE;
49 ServerAddressURL = ServerAddress + wxT(":") + wxString::Format(wxT("%i"), ServerPort) + wxT("/") + ServerPrefix + wxT("/");
50 ServerAddressSSL = wxT("https://") + ServerAddressURL;
51 ServerAddressNormal = wxT("http://") + ServerAddressURL;
53 ServerAuth = ServerUser + wxT(":") + ServerPass;
55 // Load the sync token file (if it exists).
57 wxCharBuffer SyncDataBuffer;
64 if (!SyncTokenInc.IsEmpty()){
66 SyncData = wxT("<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n");
67 SyncData.Append(wxT("<D:sync-collection xmlns:D=\"DAV:\"\n"));
68 SyncData.Append(wxT(" xmlns:C=\"urn:ietf:params:xml:ns:carddav\">\n"));
69 SyncData.Append(wxT("<D:sync-token>"));
71 //SyncData.Append(wxT("data:,00378c55-1f44-44a2-a255-84f6560b5cac_580"));
72 SyncData.Append(SyncTokenInc);
74 SyncData.Append(wxT("</D:sync-token>\n"));
75 SyncData.Append(wxT("<D:sync-level>1</D:sync-level>\n"));
76 SyncData.Append(wxT("<D:prop>\n"));
77 SyncData.Append(wxT(" <D:getetag/>\n"));
78 SyncData.Append(wxT("</D:prop>\n"));
79 SyncData.Append(wxT("</D:sync-collection>"));
81 SyncDataBuffer = SyncData.ToUTF8();
85 SyncData = wxT("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
86 SyncData.Append(wxT("<D:sync-collection xmlns:D=\"DAV:\""));
87 SyncData.Append(wxT(" xmlns:C=\"urn:ietf:params:xml:ns:carddav\">\n"));
88 SyncData.Append(wxT("<D:sync-token/>\n"));
89 SyncData.Append(wxT("<D:sync-level>1</D:sync-level>\n"));
90 SyncData.Append(wxT("<D:prop>\n"));
91 SyncData.Append(wxT(" <D:getetag/>\n"));
92 SyncData.Append(wxT("</D:prop>\n"));
93 SyncData.Append(wxT("</D:sync-collection>\n"));
95 SyncDataBuffer = SyncData.ToUTF8();
99 //static const char* query = SyncData.mb_str();
101 /*char *query = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\
102 <D:sync-collection xmlns:D=\"DAV:\"\n\
103 xmlns:C=\"urn:ietf:params:xml:ns:carddav\">\n\
104 <D:sync-token>data:,00378c55-1f44-44a2-a255-84f6560b5cac_580</D:sync-token>\n\
105 <D:sync-level>1</D:sync-level>\n\
109 </D:sync-collection>\n";*/
110 const char* query = SyncDataBuffer.data();
114 std::map<int,int>::iterator ActIter;
115 struct UploadDataStruc UploadData;
117 ActIter = ActivityListPtr->find((int)ItemIndex);
119 curl_slist *slist = NULL;
121 slist = curl_slist_append(slist, "Depth: 1");
125 wxString ServerCertFilename;
126 bool MatchingCert = FALSE;
128 curl_easy_setopt(conn, CURLOPT_URL, (const char*)ServerAddressSSL.mb_str(wxConvUTF8));
129 curl_easy_setopt(conn, CURLOPT_NOPROGRESS, 0);
130 curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANYSAFE);
131 curl_easy_setopt(conn, CURLOPT_TIMEOUT, 60);
132 curl_easy_setopt(conn, CURLOPT_FAILONERROR, TRUE);
133 curl_easy_setopt(conn, CURLOPT_USERAGENT, XSDAB_USERAGENT);
134 curl_easy_setopt(conn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8));
135 curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc);
136 curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData);
137 curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader);
138 curl_easy_setopt(conn, CURLOPT_PROGRESSDATA, this);
139 curl_easy_setopt(conn, CURLOPT_PROGRESSFUNCTION, ProgressFunc);
140 curl_easy_setopt(conn, CURLOPT_CUSTOMREQUEST, "REPORT");
141 curl_easy_setopt(conn, CURLOPT_NOSIGNAL, 1);
142 curl_easy_setopt(conn, CURLOPT_HTTPHEADER, slist);
143 curl_easy_setopt(conn, CURLOPT_CERTINFO, 1);
145 ServerCertFilename = GetAccountDir(ServerAccount, TRUE);
147 if (wxFile::Exists(ServerCertFilename) == TRUE){
149 curl_easy_setopt(conn, CURLOPT_SSL_VERIFYPEER, 1);
150 curl_easy_setopt(conn, CURLOPT_SSL_VERIFYHOST, 2);
151 curl_easy_setopt(conn, CURLOPT_CAINFO, (const char*)ServerCertFilename.mb_str(wxConvUTF8));
155 //UploadData.readptr = &CardDAVDataQuery;
156 //UploadData.sizeleft = CardDAVDataQuery.Len();
157 //curl_easy_setopt(conn, CURLOPT_UPLOAD, 1);
158 //curl_easy_setopt(conn, CURLOPT_READDATA, &UploadData);
159 //curl_easy_setopt(conn, CURLOPT_READFUNCTION, UploadReadFunc);
161 //curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, writefunc);
162 curl_easy_setopt(conn, CURLOPT_POSTFIELDS, query);
163 curl_easy_setopt(conn, CURLOPT_POSTFIELDSIZE, strlen(query));
165 claconncode = (curl_easy_perform(conn));
167 // If CURLE_PEER_FAILED_VERIFICATION is returned, retry without
168 // the local certificate in use.
170 if (claconncode == CURLE_PEER_FAILED_VERIFICATION){
172 curl_easy_cleanup(conn);
173 conn = curl_easy_init();
175 curl_easy_setopt(conn, CURLOPT_URL, (const char*)ServerAddressSSL.mb_str(wxConvUTF8));
176 curl_easy_setopt(conn, CURLOPT_NOPROGRESS, 0);
177 curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANYSAFE);
178 curl_easy_setopt(conn, CURLOPT_TIMEOUT, 60);
179 curl_easy_setopt(conn, CURLOPT_FAILONERROR, TRUE);
180 curl_easy_setopt(conn, CURLOPT_USERAGENT, XSDAB_USERAGENT);
181 curl_easy_setopt(conn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8));
182 curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc);
183 curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData);
184 curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader);
185 curl_easy_setopt(conn, CURLOPT_PROGRESSDATA, this);
186 curl_easy_setopt(conn, CURLOPT_PROGRESSFUNCTION, ProgressFunc);
187 curl_easy_setopt(conn, CURLOPT_CUSTOMREQUEST, "REPORT");
188 curl_easy_setopt(conn, CURLOPT_NOSIGNAL, 1);
189 curl_easy_setopt(conn, CURLOPT_HTTPHEADER, slist);
190 curl_easy_setopt(conn, CURLOPT_CERTINFO, 1);
191 curl_easy_setopt(conn, CURLOPT_POSTFIELDS, query);
192 curl_easy_setopt(conn, CURLOPT_POSTFIELDSIZE, strlen(query));
194 claconncode = (curl_easy_perform(conn));
196 // If claconncode is CURLE_OK then delete the certificate file as that
197 // is no longer needed.
199 if (claconncode == CURLE_OK){
201 // Delete the certificate file.
203 wxRemoveFile(ServerCertFilename);
209 // Check if it fails with a CURLE_SSL_CACERT then compare
210 // the certificates as PEM files.
212 if (claconncode == CURLE_SSL_CACERT && wxFile::Exists(ServerCertFilename) == TRUE){
214 //curl_easy_cleanup(conn);
215 //conn = curl_easy_init();
218 sslerrconn = curl_easy_init();
219 CURLcode sslerrconncode;
221 //claconncode = (curl_easy_perform(conn));
223 wxString ServerAddressOnly = wxT("https://") + ServerAddress + wxT(":") + wxString::Format(wxT("%i"), ServerPort) + wxT("/");
225 curl_easy_setopt(sslerrconn, CURLOPT_URL, (const char*)ServerAddressOnly.mb_str(wxConvUTF8));
226 curl_easy_setopt(sslerrconn, CURLOPT_NOPROGRESS, 0);
227 curl_easy_setopt(sslerrconn, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
228 curl_easy_setopt(sslerrconn, CURLOPT_TIMEOUT, 60);
229 curl_easy_setopt(sslerrconn, CURLOPT_FAILONERROR, TRUE);
230 curl_easy_setopt(sslerrconn, CURLOPT_USERAGENT, XSDAB_USERAGENT);
231 curl_easy_setopt(sslerrconn, CURLOPT_WRITEFUNCTION, WritebackFunc);
232 curl_easy_setopt(sslerrconn, CURLOPT_WRITEDATA, &PageData);
233 curl_easy_setopt(sslerrconn, CURLOPT_WRITEHEADER, &PageHeader);
234 curl_easy_setopt(sslerrconn, CURLOPT_PROGRESSDATA, this);
235 curl_easy_setopt(sslerrconn, CURLOPT_PROGRESSFUNCTION, ProgressFunc);
236 curl_easy_setopt(sslerrconn, CURLOPT_NOSIGNAL, 1);
237 curl_easy_setopt(sslerrconn, CURLOPT_SSL_VERIFYPEER, 0);
238 curl_easy_setopt(sslerrconn, CURLOPT_CERTINFO, 1);
240 wxString SSLLocalData;
241 wxString SSLServerData;
243 sslerrconncode = (curl_easy_perform(sslerrconn));
245 SSLCertCol = BuildSSLCollection(sslerrconn);
246 std::map<int, SSLCertData>::iterator SSLCDIter = SSLCertCol.SSLCollection.find(0);
247 std::multimap<wxString,wxString>::iterator SSLDataIter = SSLCDIter->second.CertData.find(wxT("Cert"));
249 wxFFile SSLLocalFile;
251 #if wxABI_VERSION < 20900
252 SSLLocalFile.Open(ServerCertFilename.c_str(), wxT("r"));
254 SSLLocalFile.Open(ServerCertFilename, wxT("r"));
257 // Load the recovery database for tasks not done.
259 if (SSLLocalFile.IsOpened() == TRUE){
261 // Check if we are using wxWidgets version 2.8 or less and
262 // execute the required command accordingly.
264 SSLLocalFile.ReadAll(&SSLLocalData, wxConvAuto());
269 SSLServerData = SSLDataIter->second;
271 if (SSLLocalData == SSLServerData){
273 // Server key matches with local key so retry with CURLOPT_SSL_VERIFYPEER
274 // and CURLOPT_SSL_VERIFYHOST off.
276 curl_easy_cleanup(conn);
277 conn = curl_easy_init();
282 curl_easy_setopt(conn, CURLOPT_URL, (const char*)ServerAddressSSL.mb_str(wxConvUTF8));
283 curl_easy_setopt(conn, CURLOPT_NOPROGRESS, 0);
284 curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
285 curl_easy_setopt(conn, CURLOPT_TIMEOUT, 60);
286 curl_easy_setopt(conn, CURLOPT_FAILONERROR, TRUE);
287 curl_easy_setopt(conn, CURLOPT_USERAGENT, XSDAB_USERAGENT);
288 curl_easy_setopt(conn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8));
289 curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc);
290 curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData);
291 curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader);
292 curl_easy_setopt(conn, CURLOPT_PROGRESSDATA, this);
293 curl_easy_setopt(conn, CURLOPT_PROGRESSFUNCTION, ProgressFunc);
294 curl_easy_setopt(conn, CURLOPT_CUSTOMREQUEST, "REPORT");
295 curl_easy_setopt(conn, CURLOPT_NOSIGNAL, 1);
296 curl_easy_setopt(conn, CURLOPT_HTTPHEADER, slist);
297 curl_easy_setopt(conn, CURLOPT_CERTINFO, 1);
298 curl_easy_setopt(conn, CURLOPT_POSTFIELDS, query);
299 curl_easy_setopt(conn, CURLOPT_POSTFIELDSIZE, strlen(query));
300 curl_easy_setopt(conn, CURLOPT_SSL_VERIFYHOST, 0);
301 curl_easy_setopt(conn, CURLOPT_SSL_VERIFYPEER, 0);
303 claconncode = (curl_easy_perform(conn));
309 if (MatchingCert == FALSE){
311 claconncode = CURLE_SSL_CACERT;
312 return ContactListFinal;
316 curl_easy_cleanup(sslerrconn);
320 // Sort out SSL error.
322 // When SSL cert error occurs, connect again and fetch certificates.
323 // Display a message to the user explaining that an invalid
324 // certificate has been given and let the user decide what
327 if (claconncode == CURLE_OK){
329 } else if (claconncode == CURLE_SSL_CACERT || claconncode == CURLE_PEER_FAILED_VERIFICATION){
332 sslerrconn = curl_easy_init();
333 CURLcode sslerrconncode;
335 wxString ServerAddressOnly = wxT("https://") + ServerAddress + wxT(":") + wxString::Format(wxT("%i"), ServerPort) + wxT("/");
337 // Replace conn with sslerrconn!
339 curl_easy_setopt(sslerrconn, CURLOPT_URL, (const char*)ServerAddressOnly.mb_str(wxConvUTF8));
340 curl_easy_setopt(sslerrconn, CURLOPT_NOPROGRESS, 0);
341 curl_easy_setopt(sslerrconn, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
342 curl_easy_setopt(sslerrconn, CURLOPT_TIMEOUT, 60);
343 curl_easy_setopt(sslerrconn, CURLOPT_FAILONERROR, TRUE);
344 curl_easy_setopt(sslerrconn, CURLOPT_USERAGENT, XSDAB_USERAGENT);
345 curl_easy_setopt(sslerrconn, CURLOPT_WRITEFUNCTION, WritebackFunc);
346 curl_easy_setopt(sslerrconn, CURLOPT_WRITEDATA, &PageData);
347 curl_easy_setopt(sslerrconn, CURLOPT_WRITEHEADER, &PageHeader);
348 curl_easy_setopt(sslerrconn, CURLOPT_PROGRESSDATA, this);
349 curl_easy_setopt(sslerrconn, CURLOPT_PROGRESSFUNCTION, ProgressFunc);
350 curl_easy_setopt(sslerrconn, CURLOPT_NOSIGNAL, 1);
351 curl_easy_setopt(sslerrconn, CURLOPT_SSL_VERIFYPEER, 0);
352 curl_easy_setopt(sslerrconn, CURLOPT_CERTINFO, 1);
354 sslerrconncode = (curl_easy_perform(sslerrconn));
356 SSLCertCol = BuildSSLCollection(sslerrconn);
357 SSLCertCol.SuccessCode = 1;
359 return ContactListFinal;
361 } else if (claconncode == CURLE_HTTP_RETURNED_ERROR){
363 fprintf(stderr, "curl_easy_perform() failed: %s\n",
364 curl_easy_strerror(claconncode));
366 curl_easy_getinfo(conn, CURLINFO_RESPONSE_CODE, &http_code);
367 fprintf(stderr, "Error code was: %d\n", http_code);
369 return ContactListFinal;
373 fprintf(stderr, "curl_easy_perform() failed: %s\n",
374 curl_easy_strerror(claconncode));
376 curl_easy_getinfo(conn, CURLINFO_RESPONSE_CODE, &http_code);
377 fprintf(stderr, "Error code was: %d\n", http_code);
379 return ContactListFinal;
383 SSLCertCol = BuildSSLCollection(conn);
389 wxString EmptyString;
391 curl_easy_setopt(conn, CURLOPT_URL, (const char*)ServerAddressNormal.mb_str(wxConvUTF8));
392 curl_easy_setopt(conn, CURLOPT_NOPROGRESS, 0);
393 curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
394 curl_easy_setopt(conn, CURLOPT_TIMEOUT, 60);
395 curl_easy_setopt(conn, CURLOPT_FAILONERROR, TRUE);
396 curl_easy_setopt(conn, CURLOPT_USERAGENT, XSDAB_USERAGENT);
397 curl_easy_setopt(conn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8));
398 curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc);
399 curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData);
400 curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader);
401 curl_easy_setopt(conn, CURLOPT_PROGRESSDATA, this);
402 curl_easy_setopt(conn, CURLOPT_PROGRESSFUNCTION, ProgressFunc);
403 curl_easy_setopt(conn, CURLOPT_CUSTOMREQUEST, "REPORT");
404 curl_easy_setopt(conn, CURLOPT_NOSIGNAL, 1);
405 curl_easy_setopt(conn, CURLOPT_HTTPHEADER, slist);
407 //UploadData.readptr = &CardDAVDataQuery;
408 //UploadData.sizeleft = CardDAVDataQuery.Len();
409 //curl_easy_setopt(conn, CURLOPT_UPLOAD, 1);
410 //curl_easy_setopt(conn, CURLOPT_READDATA, &UploadData);
411 //curl_easy_setopt(conn, CURLOPT_READFUNCTION, UploadReadFunc);
413 //curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, writefunc);
414 curl_easy_setopt(conn, CURLOPT_POSTFIELDS, query);
415 curl_easy_setopt(conn, CURLOPT_POSTFIELDSIZE, strlen(query));
420 claconncode = (curl_easy_perform(conn));
422 if (claconncode == CURLE_OK){
426 } else if (claconncode == CURLE_HTTP_RETURNED_ERROR){
428 fprintf(stderr, "curl_easy_perform() failed: %s\n",
429 curl_easy_strerror(claconncode));
431 curl_easy_getinfo(conn, CURLINFO_RESPONSE_CODE, &http_code);
432 fprintf(stderr, "Error code was: %i\n", http_code);
434 return ContactListFinal;
438 fprintf(stderr, "curl_easy_perform() failed: %s\n",
439 curl_easy_strerror(claconncode));
441 curl_easy_getinfo(conn, CURLINFO_RESPONSE_CODE, &http_code);
442 fprintf(stderr, "Error code was: %i\n", http_code);
444 return ContactListFinal;
450 xmlDocPtr xmlCardDAVDoc;
451 xmlCardDAVDoc = xmlReadMemory(PageData.mb_str(wxConvUTF8), (int)PageData.Len(), "noname.xml", NULL, 0);
453 xmlNodePtr nodeLevel1;
454 xmlNodePtr nodeLevel2;
455 xmlNodePtr nodeLevel3;
456 xmlNodePtr nodeLevel4;
457 xmlNodePtr nodeLevel5;
458 xmlNodePtr nodeLevel6;
460 xmlNodePtr nodeStatusLv1;
461 xmlNodePtr nodeStatusLv2;
463 std::map<wxString,wxString> xmlDataMap;
464 std::map<wxString,wxString> ServerETagData;
466 wxString DataFilename;
467 wxString DataSyncToken;
470 bool SyncTokenFound = FALSE;
472 std::string xmlStringSafe;
474 // Tranverse through the catacombs of the response to get our ETag for the file and
475 // the server syncronisation token.
477 // Start by getting all the server ETag data.
479 for (nodeLevel1 = xmlCardDAVDoc->children;
481 nodeLevel1 = nodeLevel1->next)
484 for (nodeLevel2 = nodeLevel1->children;
486 nodeLevel2 = nodeLevel2->next)
489 for (nodeLevel3 = nodeLevel2->children;
491 nodeLevel3 = nodeLevel3->next)
495 bool HREFFound = FALSE;
496 bool ETagFound = FALSE;
497 bool HTTPStatus = FALSE;
499 if (!xmlStrcmp(nodeLevel3->name, (const xmlChar *)"href") ||
500 !xmlStrcmp(nodeLevel3->name, (const xmlChar *)"d:href") ||
501 !xmlStrcmp(nodeLevel3->name, (const xmlChar *)"D:href")
506 for (nodeLevel4 = nodeLevel3->children;
508 nodeLevel4 = nodeLevel4->next)
511 if (!xmlStrcmp(nodeLevel4->name, (const xmlChar *)"text") ||
512 !xmlStrcmp(nodeLevel4->name, (const xmlChar *)"d:text") ||
513 !xmlStrcmp(nodeLevel4->name, (const xmlChar *)"D:text")
516 DataFilename = wxString::FromUTF8((const char*)nodeLevel4->content);
517 wxStringTokenizer wSTDFilename(DataFilename, wxT("/"));
519 while (wSTDFilename.HasMoreTokens()){
521 DataFilename = wSTDFilename.GetNextToken();
536 for (nodeLevel4 = nodeLevel3->children;
538 nodeLevel4 = nodeLevel4->next)
541 for (nodeStatusLv1 = nodeLevel3->children;
542 nodeStatusLv1 != NULL;
543 nodeStatusLv1 = nodeStatusLv1->next)
546 if (wxString::FromUTF8((const char*)nodeStatusLv1->content) == wxT("HTTP/1.1 404 Not Found")){
554 if ((!xmlStrcmp(nodeStatusLv1->name, (const xmlChar *)"status") ||
555 !xmlStrcmp(nodeStatusLv1->name, (const xmlChar *)"d:status") ||
556 !xmlStrcmp(nodeStatusLv1->name, (const xmlChar *)"D:status")) && HTTPStatus == FALSE)
561 for (nodeStatusLv2 = nodeStatusLv1->children;
562 nodeStatusLv2 != NULL;
563 nodeStatusLv2 = nodeStatusLv2->next)
566 if (!xmlStrcmp(nodeStatusLv2->name, (const xmlChar *)"text") ||
567 !xmlStrcmp(nodeStatusLv2->name, (const xmlChar *)"d:text") ||
568 !xmlStrcmp(nodeStatusLv2->name, (const xmlChar *)"D:text")
571 if (wxString::FromUTF8((const char*)nodeStatusLv2->content) == wxT("HTTP/1.1 200 OK")){
577 // This is currently in a WebDAV draft and may hopefully be enabled when this changes.
579 //} else if (wxString::FromUTF8((const char*)nodeStatusLv2->content) == wxT("HTTP/1.1 201 Created")){
581 // DataFileStatus = 0;
596 for (nodeLevel5 = nodeLevel4->children;
598 nodeLevel5 = nodeLevel5->next)
601 if (!xmlStrcmp(nodeLevel5->name, (const xmlChar *)"getetag") ||
602 !xmlStrcmp(nodeLevel5->name, (const xmlChar *)"d:getetag") ||
603 !xmlStrcmp(nodeLevel5->name, (const xmlChar *)"D:getetag")
606 for (nodeLevel6 = nodeLevel5->children;
608 nodeLevel6 = nodeLevel6->next)
611 // Strip the quotes from the ETag.
613 ETagData = wxString::FromUTF8((const char*)nodeLevel6->content);
614 if (ETagData.Mid(0, 1) == wxT("\"") && ETagData.Mid((ETagData.Len() - 1), 1) == wxT("\"")){
616 ETagData.Remove(0, 1);
617 ETagData.RemoveLast();
633 if (HREFFound == TRUE && ETagFound == TRUE && HTTPStatus == TRUE){
635 // Add to the map data.
639 SData.ETagData = ETagData;
640 SData.DataFlag = DataFileStatus;
642 ContactListFinal.ListData.insert(std::make_pair(DataFilename, SData));
654 if ((!xmlStrcmp(nodeLevel2->name, (const xmlChar *)"sync-token") ||
655 !xmlStrcmp(nodeLevel2->name, (const xmlChar *)"d:sync-token") ||
656 !xmlStrcmp(nodeLevel2->name, (const xmlChar *)"D:sync-token")) &&
657 SyncTokenFound == FALSE
660 for (nodeLevel3 = nodeLevel2->children;
662 nodeLevel3 = nodeLevel3->next)
665 if (!xmlStrcmp(nodeLevel3->name, (const xmlChar *)"text") ||
666 !xmlStrcmp(nodeLevel3->name, (const xmlChar *)"d:text") ||
667 !xmlStrcmp(nodeLevel3->name, (const xmlChar *)"D:text")
670 DataSyncToken = wxString::FromUTF8((const char*)nodeLevel3->content);
672 SyncTokenFound = TRUE;
684 for (nodeLevel1 = xmlCardDAVDoc->children;
686 nodeLevel1 = nodeLevel1->next)
689 for (nodeLevel2 = nodeLevel1->children;
691 nodeLevel2 = nodeLevel2->next)
695 bool HREFFound = FALSE;
696 bool ETagFound = FALSE;
697 bool HTTPStatus = FALSE;
699 for (nodeLevel3 = nodeLevel2->children;
701 nodeLevel3 = nodeLevel3->next)
704 if (!xmlStrcmp(nodeLevel3->name, (const xmlChar *)"href") ||
705 !xmlStrcmp(nodeLevel3->name, (const xmlChar *)"d:href") ||
706 !xmlStrcmp(nodeLevel3->name, (const xmlChar *)"D:href")
711 for (nodeLevel4 = nodeLevel3->children;
713 nodeLevel4 = nodeLevel4->next)
716 if (!xmlStrcmp(nodeLevel4->name, (const xmlChar *)"text") ||
717 !xmlStrcmp(nodeLevel4->name, (const xmlChar *)"d:text") ||
718 !xmlStrcmp(nodeLevel4->name, (const xmlChar *)"D:text")
721 DataFilename = wxString::FromUTF8((const char*)nodeLevel4->content);
722 wxStringTokenizer wSTDFilename(DataFilename, wxT("/"));
724 while (wSTDFilename.HasMoreTokens()){
726 DataFilename = wSTDFilename.GetNextToken();
741 for (nodeLevel4 = nodeLevel3->children;
743 nodeLevel4 = nodeLevel4->next)
746 for (nodeStatusLv1 = nodeLevel3->children;
747 nodeStatusLv1 != NULL;
748 nodeStatusLv1 = nodeStatusLv1->next)
751 if (wxString::FromUTF8((const char*)nodeStatusLv1->content) == wxT("HTTP/1.1 404 Not Found")){
759 if ((!xmlStrcmp(nodeStatusLv1->name, (const xmlChar *)"status") ||
760 !xmlStrcmp(nodeStatusLv1->name, (const xmlChar *)"d:status") ||
761 !xmlStrcmp(nodeStatusLv1->name, (const xmlChar *)"D:status")) && HTTPStatus == FALSE)
766 for (nodeStatusLv2 = nodeStatusLv1->children;
767 nodeStatusLv2 != NULL;
768 nodeStatusLv2 = nodeStatusLv2->next)
771 if (!xmlStrcmp(nodeStatusLv2->name, (const xmlChar *)"text") ||
772 !xmlStrcmp(nodeStatusLv2->name, (const xmlChar *)"d:text") ||
773 !xmlStrcmp(nodeStatusLv2->name, (const xmlChar *)"D:text")
776 if (wxString::FromUTF8((const char*)nodeStatusLv2->content) == wxT("HTTP/1.1 200 OK")){
782 // This is currently in a WebDAV draft and may hopefully be enabled when this changes.
784 //} else if (wxString::FromUTF8((const char*)nodeStatusLv2->content) == wxT("HTTP/1.1 201 Created")){
786 // DataFileStatus = 0;
801 for (nodeLevel5 = nodeLevel4->children;
803 nodeLevel5 = nodeLevel5->next)
806 if (!xmlStrcmp(nodeLevel5->name, (const xmlChar *)"getetag") ||
807 !xmlStrcmp(nodeLevel5->name, (const xmlChar *)"d:getetag") ||
808 !xmlStrcmp(nodeLevel5->name, (const xmlChar *)"D:getetag")
811 for (nodeLevel6 = nodeLevel5->children;
813 nodeLevel6 = nodeLevel6->next)
816 // Strip the quotes from the ETag.
818 ETagData = wxString::FromUTF8((const char*)nodeLevel6->content);
819 if (ETagData.Mid(0, 1) == wxT("\"") && ETagData.Mid((ETagData.Len() - 1), 1) == wxT("\"")){
821 ETagData.Remove(0, 1);
822 ETagData.RemoveLast();
840 if (HREFFound == TRUE && HTTPStatus == TRUE && DataFileStatus == 2){
844 SData.ETagData = wxT("");
845 SData.DataFlag = DataFileStatus;
847 ContactListFinal.ListData.insert(std::make_pair(DataFilename, SData));
851 if (HREFFound == TRUE && ETagFound == TRUE && HTTPStatus == TRUE){
853 // Add to the map data.
857 SData.ETagData = ETagData;
858 SData.DataFlag = DataFileStatus;
860 ContactListFinal.ListData.insert(std::make_pair(DataFilename, SData));
869 DataFilename.Clear();
871 if ((!xmlStrcmp(nodeLevel2->name, (const xmlChar *)"sync-token") ||
872 !xmlStrcmp(nodeLevel2->name, (const xmlChar *)"d:sync-token") ||
873 !xmlStrcmp(nodeLevel2->name, (const xmlChar *)"D:sync-token")) &&
874 SyncTokenFound == FALSE
877 for (nodeLevel3 = nodeLevel2->children;
879 nodeLevel3 = nodeLevel3->next)
882 if (!xmlStrcmp(nodeLevel3->name, (const xmlChar *)"text") ||
883 !xmlStrcmp(nodeLevel3->name, (const xmlChar *)"d:text") ||
884 !xmlStrcmp(nodeLevel3->name, (const xmlChar *)"D:text")
887 DataSyncToken = wxString::FromUTF8((const char*)nodeLevel3->content);
889 SyncTokenFound = TRUE;
901 // Get the sync token.
903 if (SyncTokenFound == TRUE){
905 ContactListFinal.SyncToken = DataSyncToken;
911 SleepFor(2000000000);
916 n1.tv_nsec = 2000000000L;
918 nanosleep(&n1, &n2);*/
920 xmlFreeDoc(xmlCardDAVDoc);
921 curl_easy_cleanup(conn);
923 SyncDataBuffer.reset();
925 // Get the first result.
927 return ContactListFinal;