Home | News | Projects | Releases
Bugs | RFE | Repositories | Help
Altered CardDAV object to accommodate for SSL support for OS X (and other OSes in...
[xestiaab/.git] / source / carddav / carddav-serveretag.cpp
1 // carddav-serveretag.cpp - CardDAV Object - Server ETag subroutines.
2 //
3 // (c) 2012-2015 Xestia Software Development.
4 //
5 // This file is part of Xestia Address Book.
6 //
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.
10 //
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.
15 //
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/>
19 #include "carddav.h"
20 #include "../version.h"
21 #include <wx/wx.h>
22 #include <wx/tokenzr.h>
23 #include <wx/ffile.h>
24 #include <libxml/parser.h>
25 #include <libxml/tree.h>
26 #include <map>
27 #include <thread>
28 #include "../vcard/vcard.h"
29 #include "../common/dirs.h"
31 void CardDAV::GetServerETagValueThread()
32 {
33         
34         // Get the server etag value (threaded).
36         PageData.Clear();
37         PageHeader.Clear();
39         SSLStatus = TRUE;
40         AuthPassed = TRUE;
41         AbortConnection = FALSE;
42         
43         bool FilenameIsDirectory = FALSE;
44         CURL *conn;
45         CURLcode conncode;
46         wxString ServerAddressURL;
47         wxString ServerAuth;
48         wxString ServerAddressSSL;
49         wxString ServerAddressNormal;   
51         conn = curl_easy_init();
52         
53         SetConnectionObject(conn);
54         
55         struct CardDAVCURLPasser {
56         
57                 CardDAV *Data;
58                 bool HeaderMode = TRUE;
59         
60         } CardDAVHeader, CardDAVFooter;
62         CardDAVHeader.Data = this;
63         CardDAVHeader.HeaderMode = TRUE;
64         
65         CardDAVFooter.Data = this;
66         CardDAVFooter.HeaderMode = FALSE;
68         wxString Data1;
69         wxString Data2;
70         
71         ServerAddressURL = ServerAddress + wxT(":") + wxString::Format(wxT("%i"), ServerPort) + ServerPrefix + ServerFilenameLocation;
72         ServerAddressSSL = wxT("https://") + ServerAddressURL;
73         ServerAddressNormal = wxT("http://") + ServerAddressURL;
74         
75         ServerAuth = ServerUser + wxT(":") + ServerPass;
77         std::map<int,int>::iterator ActIter;
78         struct UploadDataStruc UploadData;
79         
80         
81         ActIter = ActivityListPtr->find((int)ItemIndex);
82         
83         static const char* query =
84         "<?xml version=\"1.0\" encoding=\"utf-8\" ?>"
85         "<C:addressbook-query xmlns:D=\"DAV:\""
86         "       xmlns:C=\"urn:ietf:params:xml:ns:carddav\">"
87         "<D:prop><D:getetag/>"
88         "</D:prop>"
89         "<C:filter/>"
90         "</C:addressbook-query>";
92         if (ServerSSL){
94                 wxString ServerCertFilename;
95                 bool MatchingCert = FALSE;
97                 curl_easy_setopt(conn, CURLOPT_URL, (const char*)ServerAddressSSL.mb_str(wxConvUTF8));
98                 curl_easy_setopt(conn, CURLOPT_NOPROGRESS, 0);
99                 curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
100                 curl_easy_setopt(conn, CURLOPT_TIMEOUT, 60);
101                 curl_easy_setopt(conn, CURLOPT_FAILONERROR, TRUE);
102                 curl_easy_setopt(conn, CURLOPT_USERAGENT, XSDAB_USERAGENT);
103                 curl_easy_setopt(conn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8));
104                 curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc);
105                 curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData);
106                 curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader);
107                 curl_easy_setopt(conn, CURLOPT_PROGRESSDATA, this);
108                 curl_easy_setopt(conn, CURLOPT_PROGRESSFUNCTION, ProgressFunc);
109                 curl_easy_setopt(conn, CURLOPT_CUSTOMREQUEST, "REPORT");
110                 curl_easy_setopt(conn, CURLOPT_NOSIGNAL, 1);
111                 curl_easy_setopt(conn, CURLOPT_POSTFIELDS, query);
112                 curl_easy_setopt(conn, CURLOPT_POSTFIELDSIZE, strlen(query));
114 #if defined(__APPLE__)
115                 
116 #else
117                 
118                 ServerCertFilename = GetAccountDir(ServerAccount, TRUE);
120                 if (wxFile::Exists(ServerCertFilename) == TRUE){
121                 
122                         curl_easy_setopt(conn, CURLOPT_SSL_VERIFYPEER, 1);
123                         curl_easy_setopt(conn, CURLOPT_SSL_VERIFYHOST, 2);
124                         curl_easy_setopt(conn, CURLOPT_CAINFO, (const char*)ServerCertFilename.mb_str(wxConvUTF8));
125                 
126                 }
128 #endif
129                 
130                 claconncode = (curl_easy_perform(conn));
132                 // If CURLE_PEER_FAILED_VERIFICATION is returned, retry without
133                 // the local certificate in use.
135                 if (claconncode == CURLE_PEER_FAILED_VERIFICATION){
136                         
137                         curl_easy_cleanup(conn);
138                         conn = curl_easy_init();
139                         
140                         curl_easy_setopt(conn, CURLOPT_URL, (const char*)ServerAddressSSL.mb_str(wxConvUTF8));
141                         curl_easy_setopt(conn, CURLOPT_NOPROGRESS, 0);
142                         curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
143                         curl_easy_setopt(conn, CURLOPT_TIMEOUT, 60);
144                         curl_easy_setopt(conn, CURLOPT_FAILONERROR, TRUE);
145                         curl_easy_setopt(conn, CURLOPT_USERAGENT, XSDAB_USERAGENT);
146                         curl_easy_setopt(conn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8));
147                         curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc);
148                         curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData);
149                         curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader);
150                         curl_easy_setopt(conn, CURLOPT_PROGRESSDATA, this);
151                         curl_easy_setopt(conn, CURLOPT_PROGRESSFUNCTION, ProgressFunc);
152                         curl_easy_setopt(conn, CURLOPT_CUSTOMREQUEST, "REPORT");
153                         curl_easy_setopt(conn, CURLOPT_NOSIGNAL, 1);
154                         curl_easy_setopt(conn, CURLOPT_POSTFIELDS, query);
155                         curl_easy_setopt(conn, CURLOPT_POSTFIELDSIZE, strlen(query));
156                         
157                         claconncode = (curl_easy_perform(conn));
158                         
159                         // If claconncode is CURLE_OK then delete the certificate file as that
160                         // is no longer needed.
161                         
162                         if (claconncode == CURLE_OK){
163                         
164                                 // Delete the certificate file.
165                                 
166                                 wxRemoveFile(ServerCertFilename);
167                         
168                         }
169                 
170                 }
172                 // Check if it fails with a CURLE_SSL_CACERT then compare
173                 // the certificates as PEM files.
174                 
175 #if defined(__APPLE__)
176                 
177 #else
178                 
179                 if (claconncode == CURLE_SSL_CACERT && wxFile::Exists(ServerCertFilename) == TRUE){
181                         CURL *sslerrconn;
182                         sslerrconn = curl_easy_init();
183                         CURLcode sslerrconncode;
185                         wxString ServerAddressOnly = wxT("https://") + ServerAddress + wxT(":") + wxString::Format(wxT("%i"), ServerPort) + wxT("/");
187                         PageData.clear();
188                         PageHeader.clear();
190                         curl_easy_setopt(sslerrconn, CURLOPT_URL, (const char*)ServerAddressOnly.mb_str(wxConvUTF8));
191                         curl_easy_setopt(sslerrconn, CURLOPT_NOPROGRESS, 0);
192                         curl_easy_setopt(sslerrconn, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
193                         curl_easy_setopt(sslerrconn, CURLOPT_TIMEOUT, 60);
194                         curl_easy_setopt(sslerrconn, CURLOPT_FAILONERROR, TRUE);
195                         curl_easy_setopt(sslerrconn, CURLOPT_USERAGENT, XSDAB_USERAGENT);
196                         curl_easy_setopt(sslerrconn, CURLOPT_WRITEFUNCTION, WritebackFunc);
197                         curl_easy_setopt(sslerrconn, CURLOPT_WRITEDATA, &PageData);
198                         curl_easy_setopt(sslerrconn, CURLOPT_WRITEHEADER, &PageHeader);
199                         curl_easy_setopt(sslerrconn, CURLOPT_PROGRESSDATA, this);
200                         curl_easy_setopt(sslerrconn, CURLOPT_PROGRESSFUNCTION, ProgressFunc);
201                         curl_easy_setopt(sslerrconn, CURLOPT_NOSIGNAL, 1);
202                         curl_easy_setopt(sslerrconn, CURLOPT_SSL_VERIFYPEER, 0);
203                         curl_easy_setopt(sslerrconn, CURLOPT_CERTINFO, 1);
204                         curl_easy_setopt(sslerrconn, CURLOPT_SSL_VERIFYPEER, 1);
205                         curl_easy_setopt(sslerrconn, CURLOPT_SSL_VERIFYHOST, 2);
206                         curl_easy_setopt(sslerrconn, CURLOPT_CAINFO, (const char*)ServerCertFilename.mb_str(wxConvUTF8));
207                 
208                         wxString SSLLocalData;
209                         wxString SSLServerData;
210                 
211                         sslerrconncode = (curl_easy_perform(sslerrconn));
212                 
213                         SSLCertCol = BuildSSLCollection(sslerrconn);
214                         std::map<int, SSLCertData>::iterator SSLCDIter = SSLCertCol.SSLCollection.find(0);
215                         std::multimap<wxString,wxString>::iterator SSLDataIter = SSLCDIter->second.CertData.find(wxT("Cert"));
216                         
217                         wxFFile SSLLocalFile;
218                         
219 #if wxABI_VERSION < 20900
220                         SSLLocalFile.Open(ServerCertFilename.c_str(), wxT("r"));
221 #else
222                         SSLLocalFile.Open(ServerCertFilename, wxT("r"));
223 #endif  
225                         // Load the recovery database for tasks not done.
226         
227                         if (SSLLocalFile.IsOpened() == TRUE){
229                         // Check if we are using wxWidgets version 2.8 or less and
230                         // execute the required command accordingly.
231         
232                                 SSLLocalFile.ReadAll(&SSLLocalData, wxConvAuto());
233                 
234         
235                         }
236                         
237                         SSLServerData = SSLDataIter->second;
238                         
239                         if (SSLLocalData == SSLServerData){
240                         
241                                 // Server key matches with local key so retry with CURLOPT_SSL_VERIFYPEER
242                                 // and CURLOPT_SSL_VERIFYHOST off.
243                         
244                                 curl_easy_cleanup(conn);
245                                 conn = curl_easy_init();
246                                 
247                                 PageData.clear();
248                                 PageHeader.clear();
249                         
250                                 curl_easy_setopt(conn, CURLOPT_URL, (const char*)ServerAddressSSL.mb_str(wxConvUTF8));
251                                 curl_easy_setopt(conn, CURLOPT_NOPROGRESS, 0);
252                                 curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
253                                 curl_easy_setopt(conn, CURLOPT_TIMEOUT, 60);
254                                 curl_easy_setopt(conn, CURLOPT_FAILONERROR, TRUE);
255                                 curl_easy_setopt(conn, CURLOPT_USERAGENT, XSDAB_USERAGENT);
256                                 curl_easy_setopt(conn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8));
257                                 curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc);
258                                 curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData);
259                                 curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader);
260                                 curl_easy_setopt(conn, CURLOPT_PROGRESSDATA, this);
261                                 curl_easy_setopt(conn, CURLOPT_PROGRESSFUNCTION, ProgressFunc);
262                                 curl_easy_setopt(conn, CURLOPT_CUSTOMREQUEST, "REPORT");
263                                 curl_easy_setopt(conn, CURLOPT_NOSIGNAL, 1);
264                                 curl_easy_setopt(conn, CURLOPT_POSTFIELDS, query);
265                                 curl_easy_setopt(conn, CURLOPT_POSTFIELDSIZE, strlen(query));
266                                 curl_easy_setopt(conn, CURLOPT_SSL_VERIFYPEER, 0);
267                                 curl_easy_setopt(conn, CURLOPT_SSL_VERIFYHOST, 0);              
268                         
269                                 claconncode = (curl_easy_perform(conn));
270                                 
271                                 MatchingCert = TRUE;
272                         
273                         }
274                         
275                         if (MatchingCert == FALSE){
276                 
277                                 claconncode = CURLE_SSL_CACERT;
278                                 return;
279                 
280                         }
281                         
282                         curl_easy_cleanup(sslerrconn);
283                 
284                 }
285                 
286 #endif
288                 // Sort out SSL error.
289                 
290                 // When SSL cert error occurs, connect again and fetch certificates.
291                 // Display a message to the user explaining that an invalid
292                 // certificate has been given and let the user decide what
293                 // to do next.
295                 if (claconncode == CURLE_OK){
297                 } else if (claconncode == CURLE_SSL_CACERT || claconncode == CURLE_PEER_FAILED_VERIFICATION){
298                 
299                         CURL *sslerrconn;
300                         sslerrconn = curl_easy_init();
301                         CURLcode sslerrconncode;
302                 
303                         wxString ServerAddressOnly = wxT("https://") + ServerAddress + wxT(":") + wxString::Format(wxT("%i"), ServerPort) + wxT("/");
304                 
305                         // Replace conn with sslerrconn!
306                 
307                         curl_easy_setopt(sslerrconn, CURLOPT_URL, (const char*)ServerAddressOnly.mb_str(wxConvUTF8));
308                         curl_easy_setopt(sslerrconn, CURLOPT_NOPROGRESS, 0);
309                         curl_easy_setopt(sslerrconn, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
310                         curl_easy_setopt(sslerrconn, CURLOPT_TIMEOUT, 60);
311                         curl_easy_setopt(sslerrconn, CURLOPT_FAILONERROR, TRUE);
312                         curl_easy_setopt(sslerrconn, CURLOPT_USERAGENT, XSDAB_USERAGENT);
313                         curl_easy_setopt(sslerrconn, CURLOPT_WRITEFUNCTION, WritebackFunc);
314                         curl_easy_setopt(sslerrconn, CURLOPT_WRITEDATA, &PageData);
315                         curl_easy_setopt(sslerrconn, CURLOPT_WRITEHEADER, &PageHeader);
316                         curl_easy_setopt(sslerrconn, CURLOPT_PROGRESSDATA, this);
317                         curl_easy_setopt(sslerrconn, CURLOPT_PROGRESSFUNCTION, ProgressFunc);
318                         curl_easy_setopt(sslerrconn, CURLOPT_NOSIGNAL, 1);
319                         curl_easy_setopt(sslerrconn, CURLOPT_SSL_VERIFYPEER, 0);
320                         curl_easy_setopt(sslerrconn, CURLOPT_CERTINFO, 1);
321                                         
322                         sslerrconncode = (curl_easy_perform(sslerrconn));
324                         SetConnectionObject(sslerrconn);
325                         
326                         SSLCertCol = BuildSSLCollection(sslerrconn);
327                         SSLCertCol.SuccessCode = 1;
329                         curl_easy_cleanup(conn);
330                         curl_easy_cleanup(sslerrconn);
332                         return;
333                 
334                 } else if (claconncode == CURLE_HTTP_RETURNED_ERROR){
335                 
336                         fprintf(stderr, "GetServerETagValueThread(): curl_easy_perform() failed: %s\n",
337                                         curl_easy_strerror(claconncode));
338                         int http_code = 0;
339                         curl_easy_getinfo(conn, CURLINFO_RESPONSE_CODE, &http_code);
340                         fprintf(stderr, "Error code was: %d\n", http_code);
342                         curl_easy_cleanup(conn);
343                                         
344                         return;
345                 
346                 } else {
348                         fprintf(stderr, "GetServerETagValueThread(): curl_easy_perform() failed: %s\n",
349                                         curl_easy_strerror(claconncode));
350                         int http_code = 0;
351                         curl_easy_getinfo(conn, CURLINFO_RESPONSE_CODE, &http_code);
352                         fprintf(stderr, "Error code was: %d\n", http_code);
354                         curl_easy_cleanup(conn);
356                         return;
358                 }
360         } else {
361         
362                 // No SSL.
363         
364                 wxString EmptyString;
365                 
366                 curl_easy_setopt(conn, CURLOPT_URL, (const char*)ServerAddressNormal.mb_str(wxConvUTF8));
367                 curl_easy_setopt(conn, CURLOPT_NOPROGRESS, 0);
368                 curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
369                 curl_easy_setopt(conn, CURLOPT_TIMEOUT, 60);
370                 curl_easy_setopt(conn, CURLOPT_FAILONERROR, TRUE);
371                 curl_easy_setopt(conn, CURLOPT_USERAGENT, XSDAB_USERAGENT);
372                 curl_easy_setopt(conn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8));
373                 curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc);
374                 curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData);
375                 curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader);
376                 curl_easy_setopt(conn, CURLOPT_PROGRESSDATA, this);
377                 curl_easy_setopt(conn, CURLOPT_PROGRESSFUNCTION, ProgressFunc);
378                 curl_easy_setopt(conn, CURLOPT_CUSTOMREQUEST, "REPORT");
379                 curl_easy_setopt(conn, CURLOPT_NOSIGNAL, 1);
380                 curl_easy_setopt(conn, CURLOPT_POSTFIELDS, query);
381                 curl_easy_setopt(conn, CURLOPT_POSTFIELDSIZE, strlen(query));           
382                 
383                 PageData.Clear();
384                 PageHeader.Clear();
385                 
386                 conncode = (curl_easy_perform(conn));
388                 if (conncode == CURLE_OK){
390                 } else if (conncode == CURLE_HTTP_RETURNED_ERROR){
391                 
392                         fprintf(stderr, "curl_easy_perform() failed: %s\n",
393                                         curl_easy_strerror(conncode));
394                                 
395                         return;
396                 
397                 } else {
399                         fprintf(stderr, "curl_easy_perform() failed: %s\n",
400                                         curl_easy_strerror(conncode));
401                                 
402                         return;
404                 }
405                 
406         }
407         
408         xmlDocPtr xmlCardDAVDoc;
410         xmlCardDAVDoc = xmlReadMemory(PageData.mb_str(wxConvUTF8), (int)PageData.Len(), "noname.xml", NULL, 0);
412         xmlNodePtr nodeLevel1;
413         xmlNodePtr nodeLevel2;
414         xmlNodePtr nodeLevel3;
415         xmlNodePtr nodeLevel4;
416         xmlNodePtr nodeLevel5;
417         xmlNodePtr nodeLevel6;
419         std::map<wxString,wxString> xmlDataMap;
421         wxString DataFilename;
422         wxString ETagData;
424         std::string xmlStringSafe;
426         // Tranverse through the catacombs of the response to get our ETag for the file.
428         for (nodeLevel1 = xmlCardDAVDoc->children;
429                 nodeLevel1 != NULL;
430                 nodeLevel1 = nodeLevel1->next)
431         {
433                 bool HREFFound = FALSE;
434                 bool ETagFound = FALSE;
436                 for (nodeLevel2 = nodeLevel1->children;
437                         nodeLevel2 != NULL;
438                         nodeLevel2 = nodeLevel2->next)
439                 {
441                         for (nodeLevel3 = nodeLevel2->children;
442                         nodeLevel3 != NULL;
443                         nodeLevel3 = nodeLevel3->next)
444                         {
446                                 if (!xmlStrcmp(nodeLevel3->name, (const xmlChar *)"href") ||
447                                 !xmlStrcmp(nodeLevel3->name, (const xmlChar *)"d:href") ||
448                                 !xmlStrcmp(nodeLevel3->name, (const xmlChar *)"D:href")
449                                 ){
451                                         // Get the filename.
452                                         
453                                         for (nodeLevel4 = nodeLevel3->children;
454                                         nodeLevel4 != NULL;
455                                         nodeLevel4 = nodeLevel4->next)
456                                         {
457                                         
458                                                 if (!xmlStrcmp(nodeLevel4->name, (const xmlChar *)"text") ||
459                                                 !xmlStrcmp(nodeLevel4->name, (const xmlChar *)"d:text") ||
460                                                 !xmlStrcmp(nodeLevel4->name, (const xmlChar *)"D:text")
461                                                 ){
463                                                         DataFilename = wxString::FromUTF8((const char*)nodeLevel4->content);
464                                                         wxStringTokenizer wSTDFilename(DataFilename, wxT("/"));
465                                                 
466                                                         while (wSTDFilename.HasMoreTokens()){
467                                                         
468                                                                 DataFilename = wSTDFilename.GetNextToken();
469                                                         
470                                                         }
471                                                         
472                                                         HREFFound = TRUE;
473                                                 
474                                                 }
475                                                 
476         
477                                         
478                                         }
480                                 } else {
482                                         for (nodeLevel4 = nodeLevel3->children;
483                                         nodeLevel4 != NULL;
484                                         nodeLevel4 = nodeLevel4->next)
485                                         {
486                                                         
487                                                         for (nodeLevel5 = nodeLevel4->children;
488                                                         nodeLevel5 != NULL;
489                                                         nodeLevel5 = nodeLevel5->next)
490                                                         {
492                                                                 if (!xmlStrcmp(nodeLevel5->name, (const xmlChar *)"getetag") ||
493                                                                 !xmlStrcmp(nodeLevel5->name, (const xmlChar *)"d:getetag") ||
494                                                                 !xmlStrcmp(nodeLevel5->name, (const xmlChar *)"D:getetag")
495                                                                 ){
497                                                                         for (nodeLevel6 = nodeLevel5->children;
498                                                                         nodeLevel6 != NULL;
499                                                                         nodeLevel6 = nodeLevel6->next)
500                                                                         {
501                                                         
502                                                                                 // Strip the quotes from the ETag.
503                                                         
504                                                                                 ETagData = wxString::FromUTF8((const char*)nodeLevel6->content);
505                                                                                 if (ETagData.Mid(0, 1) == wxT("\"") && ETagData.Mid((ETagData.Len() - 1), 1) == wxT("\"")){
506                                                         
507                                                                                         ETagData.Remove(0, 1);
508                                                                                         ETagData.RemoveLast();
509                                                         
510                                                                                 }
511                                                                         
512                                                                                 ETagFound = TRUE;
514                                                                         }
515                                                                         
516                                                                 }
518                                                         }       
520                                         }
522                                 }
524                         }
526                 }
527                 
528                 if (HREFFound == TRUE && ETagFound == TRUE){
529                                 
530                         // Add to the map data.
531                                         
532                         xmlDataMap.insert(std::make_pair(DataFilename, ETagData));
533                                 
534                         HREFFound = FALSE;
535                         ETagFound = FALSE;
536                                 
537                 }
540         }
542         xmlFreeDoc(xmlCardDAVDoc);
544         // Get the first result.
546         for (std::map<wxString,wxString>::iterator iter = xmlDataMap.begin(); 
547                 iter != xmlDataMap.end(); ++iter){
548         
549                 ETagResult = iter->second;
550                 break;
551                 
552         }
553         
554         if (ETagResult.IsEmpty()){
555         
556                 return;
557         
558         }
559         
560         return;
561         
564 void CardDAV::GetServerETagValue(){
566         // Get the server etag value.
567         
568         std::thread ConnectThread(&CardDAV::GetServerETagValueThread, this);
569         ConnectThread.detach();
Xestia Software Development
Yn Maystri
© 2006 - 2019 Xestia Software Development
Software

Xestia Address Book
Xestia Calendar
Development

Xestia Gelforn
Everything else

About
News
Privacy Policy