Home | News | Projects | Releases
Bugs | RFE | Repositories | Help
Added comments to describe functions carddav/carddav-processdata.cpp
[xestiaab/.git] / source / carddav / carddav-processdata.cpp
1 // carddav-processdata.cpp - CardDAV Object - Process Data 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::ProcessDataThread(){
33         // Process the data (threaded).
34         
35         PageData.Clear();
36         PageHeader.Clear();
38         SSLStatus = TRUE;
39         AuthPassed = TRUE;
40         AbortConnection = FALSE;
42         CURL *conn;
43         CURLcode conncode;
44         wxString ServerAddressURL;
45         wxString ServerAuth;
46         wxString ServerAddressSSL;
47         wxString ServerAddressNormal;   
49         conn = curl_easy_init();
50         
51         struct CardDAVCURLPasser {
52         
53                 CardDAV *Data;
54                 bool HeaderMode = TRUE;
55         
56         } CardDAVHeader, CardDAVFooter;
58         CardDAVHeader.Data = this;
59         CardDAVHeader.HeaderMode = TRUE;
60         
61         CardDAVFooter.Data = this;
62         CardDAVFooter.HeaderMode = FALSE;
64         wxString Data1;
65         wxString Data2;
66         
67         wxString ETag;
68         wxString ETagOriginal;
69         wxString ETagServer;
70                 
71         ServerAddressURL = ServerAddress + wxT(":") + wxString::Format(wxT("%i"), ServerPort) + wxT("/") + ServerPrefix + ServerFilenameLocation;
72         ServerAddressSSL = wxT("https://") + ServerAddressURL;
73         ServerAddressNormal = wxT("http://") + ServerAddressURL;
74         
75         ServerAuth = ServerUser + wxT(":") + ServerPass;
76         
77         // Try SSL first.
80         /*
81         char *ServerAdrSSLChar = new char[(ServerAddressSSL.Length() - 1)];
82         //memset(ServerAdrSSLChar, 0, ServerAddressSSL.Length());
83         strncpy(ServerAdrSSLChar, (const char*)ServerAddressSSL.mb_str(wxConvUTF8), (ServerAddressSSL.Length() - 1));
84         
85         char *ServerAdrNorChar = new char[(ServerAddressNormal.Length() - 1)];
86         //memset(ServerAdrNorChar, 0, ServerAddressSSL.Length());       
87         strncpy(ServerAdrNorChar, (const char*)ServerAddressNormal.mb_str(wxConvUTF8), (ServerAddressNormal.Length() - 1));
89         char *ServerAuthChar = new char[(ServerAuth.Length() - 1)];
90         //memset(ServerAuthChar, 0, ServerAddressSSL.Length()); 
91         strncpy(ServerAuthChar, (const char*)ServerAuth.mb_str(wxConvUTF8), (ServerAuth.Length() - 1));
92         
93         */
95         //std::string WriteDataString = std::string(ServerUploadData.mb_str());
97         std::map<int,int>::iterator ActIter;
98         struct UploadDataStruc UploadData;
99         
100         
101         ActIter = ActivityListPtr->find((int)ItemIndex);
102         
103         // Update result flag.
105         ActIter->second = 1;
106         
107         // Setup the request mode if it is not empty.
108         
109         if (!ServerMethod.IsEmpty()){
110         
111                 curl_easy_setopt(conn, CURLOPT_CUSTOMREQUEST, (const char*)ServerMethod.mb_str(wxConvUTF8));
113         }
115         if (ServerSSL){
117                 wxString ServerCertFilename;
118                 bool MatchingCert = FALSE;
120                 curl_easy_setopt(conn, CURLOPT_URL, (const char*)ServerAddressSSL.mb_str(wxConvUTF8));
121                 curl_easy_setopt(conn, CURLOPT_NOPROGRESS, 0);
122                 curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
123                 curl_easy_setopt(conn, CURLOPT_TIMEOUT, 60);
124                 curl_easy_setopt(conn, CURLOPT_FAILONERROR, TRUE);
125                 curl_easy_setopt(conn, CURLOPT_USERAGENT, XSDAB_USERAGENT);
126                 curl_easy_setopt(conn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8));
127                 curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc);
128                 curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData);
129                 curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader);
130                 curl_easy_setopt(conn, CURLOPT_PROGRESSDATA, this);
131                 curl_easy_setopt(conn, CURLOPT_PROGRESSFUNCTION, ProgressFunc);
132                 curl_easy_setopt(conn, CURLOPT_NOSIGNAL, 1);
133                 
134                 if (UploadMode == TRUE){
135                         
136                         UploadData.readptr = &ServerUploadData;
137                         UploadData.sizeleft = ServerUploadData.Len();
138                         curl_easy_setopt(conn, CURLOPT_UPLOAD, 1);
139                         curl_easy_setopt(conn, CURLOPT_READDATA, &UploadData);
140                         curl_easy_setopt(conn, CURLOPT_READFUNCTION, UploadReadFunc);
141                 
142                 }
144                 ServerCertFilename = GetAccountDir(ServerAccount, TRUE);
146                 if (wxFile::Exists(ServerCertFilename) == TRUE){
147                 
148                         curl_easy_setopt(conn, CURLOPT_SSL_VERIFYPEER, 1);
149                         curl_easy_setopt(conn, CURLOPT_SSL_VERIFYHOST, 2);
150                         curl_easy_setopt(conn, CURLOPT_CAINFO, (const char*)ServerCertFilename.mb_str(wxConvUTF8));
151                 
152                 }
154                 //UploadData.readptr = &CardDAVDataQuery;
155                 //UploadData.sizeleft = CardDAVDataQuery.Len();
156                 //curl_easy_setopt(conn, CURLOPT_UPLOAD, 1);
157                 //curl_easy_setopt(conn, CURLOPT_READDATA, &UploadData);
158                 //curl_easy_setopt(conn, CURLOPT_READFUNCTION, UploadReadFunc);
159                 
160                 //curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, writefunc);
161                 
162                 claconncode = (curl_easy_perform(conn));
164                 // If CURLE_PEER_FAILED_VERIFICATION is returned, retry without
165                 // the local certificate in use.
167                 if (claconncode == CURLE_PEER_FAILED_VERIFICATION){
168                         
169                         curl_easy_cleanup(conn);
170                         conn = curl_easy_init();
171                         
172                         curl_easy_setopt(conn, CURLOPT_URL, (const char*)ServerAddressSSL.mb_str(wxConvUTF8));
173                         curl_easy_setopt(conn, CURLOPT_NOPROGRESS, 0);
174                         curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
175                         curl_easy_setopt(conn, CURLOPT_TIMEOUT, 60);
176                         curl_easy_setopt(conn, CURLOPT_FAILONERROR, TRUE);
177                         curl_easy_setopt(conn, CURLOPT_USERAGENT, XSDAB_USERAGENT);
178                         curl_easy_setopt(conn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8));
179                         curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc);
180                         curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData);
181                         curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader);
182                         curl_easy_setopt(conn, CURLOPT_PROGRESSDATA, this);
183                         curl_easy_setopt(conn, CURLOPT_PROGRESSFUNCTION, ProgressFunc);
184                         curl_easy_setopt(conn, CURLOPT_NOSIGNAL, 1);
186                         if (UploadMode == TRUE){
188                                 UploadData.readptr = &ServerUploadData;
189                                 UploadData.sizeleft = ServerUploadData.Len();
190                                 curl_easy_setopt(conn, CURLOPT_UPLOAD, 1);
191                                 curl_easy_setopt(conn, CURLOPT_READDATA, &UploadData);
192                                 curl_easy_setopt(conn, CURLOPT_READFUNCTION, UploadReadFunc);
193                 
194                         }
195                         
196                         claconncode = (curl_easy_perform(conn));
197                         
198                         // If claconncode is CURLE_OK then delete the certificate file as that
199                         // is no longer needed.
200                         
201                         if (claconncode == CURLE_OK){
202                         
203                                 // Delete the certificate file.
204                                 
205                                 wxRemoveFile(ServerCertFilename);
206                         
207                         }
208                 
209                 }
211                 // Check if it fails with a CURLE_SSL_CACERT then compare
212                 // the certificates as PEM files.
213                 
214                 if (claconncode == CURLE_SSL_CACERT && wxFile::Exists(ServerCertFilename) == TRUE){
215                 
216                         //curl_easy_cleanup(conn);
217                         //conn = curl_easy_init();
219                         CURL *sslerrconn;
220                         sslerrconn = curl_easy_init();
221                         CURLcode sslerrconncode;
223                         //claconncode = (curl_easy_perform(conn));
225                         wxString ServerAddressOnly = wxT("https://") + ServerAddress + wxT(":") + wxString::Format(wxT("%i"), ServerPort) + wxT("/");
227                         curl_easy_setopt(sslerrconn, CURLOPT_URL, (const char*)ServerAddressOnly.mb_str(wxConvUTF8));
228                         curl_easy_setopt(sslerrconn, CURLOPT_NOPROGRESS, 0);
229                         curl_easy_setopt(sslerrconn, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
230                         curl_easy_setopt(sslerrconn, CURLOPT_TIMEOUT, 60);
231                         curl_easy_setopt(sslerrconn, CURLOPT_FAILONERROR, TRUE);
232                         curl_easy_setopt(sslerrconn, CURLOPT_USERAGENT, XSDAB_USERAGENT);
233                         curl_easy_setopt(sslerrconn, CURLOPT_WRITEFUNCTION, WritebackFunc);
234                         curl_easy_setopt(sslerrconn, CURLOPT_WRITEDATA, &PageData);
235                         curl_easy_setopt(sslerrconn, CURLOPT_WRITEHEADER, &PageHeader);
236                         curl_easy_setopt(sslerrconn, CURLOPT_PROGRESSDATA, this);
237                         curl_easy_setopt(sslerrconn, CURLOPT_PROGRESSFUNCTION, ProgressFunc);
238                         curl_easy_setopt(sslerrconn, CURLOPT_NOSIGNAL, 1);
239                         curl_easy_setopt(sslerrconn, CURLOPT_SSL_VERIFYPEER, 0);
240                         curl_easy_setopt(sslerrconn, CURLOPT_CERTINFO, 1);
241                 
242                         wxString SSLLocalData;
243                         wxString SSLServerData;
244                 
245                         sslerrconncode = (curl_easy_perform(sslerrconn));
246                 
247                         SSLCertCol = BuildSSLCollection(sslerrconn);
248                         std::map<int, SSLCertData>::iterator SSLCDIter = SSLCertCol.SSLCollection.find(0);
249                         std::multimap<wxString,wxString>::iterator SSLDataIter = SSLCDIter->second.CertData.find(wxT("Cert"));
250                         
251                         wxFFile SSLLocalFile;
252                         
253 #if wxABI_VERSION < 20900
254                         SSLLocalFile.Open(ServerCertFilename.c_str(), wxT("r"));
255 #else
256                         SSLLocalFile.Open(ServerCertFilename, wxT("r"));
257 #endif  
258         
259                         // Load the recovery database for tasks not done.
260         
261                         if (SSLLocalFile.IsOpened() == TRUE){
263                         // Check if we are using wxWidgets version 2.8 or less and
264                         // execute the required command accordingly.
265         
266                                 SSLLocalFile.ReadAll(&SSLLocalData, wxConvAuto());
267                 
268         
269                         }
270                         
271                         SSLServerData = SSLDataIter->second;
272                         
273                         if (SSLLocalData == SSLServerData){
274                         
275                                 // Server key matches with local key so retry with CURLOPT_SSL_VERIFYPEER
276                                 // and CURLOPT_SSL_VERIFYHOST off.
277                         
278                                 curl_easy_cleanup(conn);
279                                 conn = curl_easy_init();
280                                 
281                                 PageData.clear();
282                                 PageHeader.clear();
283                         
284                                 curl_easy_setopt(conn, CURLOPT_URL, (const char*)ServerAddressSSL.mb_str(wxConvUTF8));
285                                 curl_easy_setopt(conn, CURLOPT_NOPROGRESS, 0);
286                                 curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
287                                 curl_easy_setopt(conn, CURLOPT_TIMEOUT, 60);
288                                 curl_easy_setopt(conn, CURLOPT_FAILONERROR, TRUE);
289                                 curl_easy_setopt(conn, CURLOPT_USERAGENT, XSDAB_USERAGENT);
290                                 curl_easy_setopt(conn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8));
291                                 curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc);
292                                 curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData);
293                                 curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader);
294                                 curl_easy_setopt(conn, CURLOPT_PROGRESSDATA, this);
295                                 curl_easy_setopt(conn, CURLOPT_PROGRESSFUNCTION, ProgressFunc);
296                                 curl_easy_setopt(conn, CURLOPT_NOSIGNAL, 1);
298                                 if (UploadMode == TRUE){
300                                         UploadData.readptr = &ServerUploadData;
301                                         UploadData.sizeleft = ServerUploadData.Len();
302                                         curl_easy_setopt(conn, CURLOPT_UPLOAD, 1);
303                                         curl_easy_setopt(conn, CURLOPT_READDATA, &UploadData);
304                                         curl_easy_setopt(conn, CURLOPT_READFUNCTION, UploadReadFunc);
305                 
306                                 }
307                                 
308                                 curl_easy_setopt(conn, CURLOPT_SSL_VERIFYHOST, 0);
309                                 curl_easy_setopt(conn, CURLOPT_SSL_VERIFYPEER, 0);
310                         
311                                 claconncode = (curl_easy_perform(conn));
312                                 
313                                 MatchingCert = TRUE;
314                         
315                         }
316                         
317                         if (MatchingCert == FALSE){
318                 
319                                 claconncode = CURLE_SSL_CACERT;
320                                 return;
321                 
322                         }
323                         
324                         curl_easy_cleanup(sslerrconn);
325                 
326                 }
328                 // Sort out SSL error.
329                 
330                 // When SSL cert error occurs, connect again and fetch certificates.
331                 // Display a message to the user explaining that an invalid
332                 // certificate has been given and let the user decide what
333                 // to do next.
335                 if (claconncode == CURLE_OK){
337                 } else if (claconncode == CURLE_SSL_CACERT || claconncode == CURLE_PEER_FAILED_VERIFICATION){
338                 
339                         CURL *sslerrconn;
340                         sslerrconn = curl_easy_init();
341                         CURLcode sslerrconncode;
342                 
343                         wxString ServerAddressOnly = wxT("https://") + ServerAddress + wxT(":") + wxString::Format(wxT("%i"), ServerPort) + wxT("/");
344                 
345                         // Replace conn with sslerrconn!
346                 
347                         curl_easy_setopt(sslerrconn, CURLOPT_URL, (const char*)ServerAddressOnly.mb_str(wxConvUTF8));
348                         curl_easy_setopt(sslerrconn, CURLOPT_NOPROGRESS, 0);
349                         curl_easy_setopt(sslerrconn, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
350                         curl_easy_setopt(sslerrconn, CURLOPT_TIMEOUT, 60);
351                         curl_easy_setopt(sslerrconn, CURLOPT_FAILONERROR, TRUE);
352                         curl_easy_setopt(sslerrconn, CURLOPT_USERAGENT, XSDAB_USERAGENT);
353                         curl_easy_setopt(sslerrconn, CURLOPT_WRITEFUNCTION, WritebackFunc);
354                         curl_easy_setopt(sslerrconn, CURLOPT_WRITEDATA, &PageData);
355                         curl_easy_setopt(sslerrconn, CURLOPT_WRITEHEADER, &PageHeader);
356                         curl_easy_setopt(sslerrconn, CURLOPT_PROGRESSDATA, this);
357                         curl_easy_setopt(sslerrconn, CURLOPT_PROGRESSFUNCTION, ProgressFunc);
358                         curl_easy_setopt(sslerrconn, CURLOPT_NOSIGNAL, 1);
359                         curl_easy_setopt(sslerrconn, CURLOPT_SSL_VERIFYPEER, 0);
360                         curl_easy_setopt(sslerrconn, CURLOPT_CERTINFO, 1);
361                 
362                         sslerrconncode = (curl_easy_perform(sslerrconn));
364                         SSLCertCol = BuildSSLCollection(sslerrconn);
365                         SSLCertCol.SuccessCode = 1;
367                         return;
368                 
369                 } else if (claconncode == CURLE_HTTP_RETURNED_ERROR){
370                 
371                         fprintf(stderr, "curl_easy_perform() failed: %s\n",
372                                         curl_easy_strerror(claconncode));
373                         int http_code = 0;
374                         curl_easy_getinfo(conn, CURLINFO_RESPONSE_CODE, &http_code);
375                         fprintf(stderr, "Error code was: %d\n", http_code);
376                                         
377                         return;
378                 
379                 } else {
381                         fprintf(stderr, "curl_easy_perform() failed: %s\n",
382                                         curl_easy_strerror(claconncode));
383                         int http_code = 0;
384                         curl_easy_getinfo(conn, CURLINFO_RESPONSE_CODE, &http_code);
385                         fprintf(stderr, "Error code was: %d\n", http_code);
387                         return;
389                 }
391         } else {
392         
393         // No SSL.
394                 
395                 curl_easy_setopt(conn, CURLOPT_URL, (const char*)ServerAddressNormal.mb_str(wxConvUTF8));
396                 curl_easy_setopt(conn, CURLOPT_NOPROGRESS, 0);
397                 curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
398                 curl_easy_setopt(conn, CURLOPT_TIMEOUT, 60);
399                 curl_easy_setopt(conn, CURLOPT_FAILONERROR, TRUE);
400                 curl_easy_setopt(conn, CURLOPT_USERAGENT, XSDAB_USERAGENT);
401                 curl_easy_setopt(conn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8));
402                 curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc);
403                 curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData);
404                 curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader);
405                 curl_easy_setopt(conn, CURLOPT_PROGRESSDATA, this);
406                 curl_easy_setopt(conn, CURLOPT_PROGRESSFUNCTION, ProgressFunc);
407                 curl_easy_setopt(conn, CURLOPT_NOSIGNAL, 1);
408                 
409                 if (UploadMode == TRUE){
410                         
411                         UploadData.readptr = &ServerUploadData;
412                         UploadData.sizeleft = ServerUploadData.Len();
413                         curl_easy_setopt(conn, CURLOPT_UPLOAD, 1);
414                         curl_easy_setopt(conn, CURLOPT_READDATA, &UploadData);
415                         curl_easy_setopt(conn, CURLOPT_READFUNCTION, UploadReadFunc);
416                 
417                 }
418                 
419                 conncode = (curl_easy_perform(conn));
421                 if (conncode == CURLE_OK){
423                         // Process the server header response and look for
424                         // 'addressbook' within the DAV header.
425                         
426                         wxStringTokenizer wxSHeaderLines(PageHeader, wxT("\r\n"));
427                         wxString wxSHeaderLine;
428                         std::map<int, wxString> DAVHeaderLines;
429                         
430                         while (wxSHeaderLines.HasMoreTokens()){
431                         
432                                 wxSHeaderLine = wxSHeaderLines.GetNextToken();
433                                 
434                                 if (wxSHeaderLine.Mid(0, 5) == wxT("ETag:")){
435                                 
436                                         ETagData = wxSHeaderLine.Mid(5);
437                                         ETagData.Trim();
438                                         ETagData.Trim(FALSE);
439                                         
440                                         // Check for commas.
441                                         
442                                         if (ETagData.Mid(0, 1) == wxT("\"") && ETagData.Mid((ETagData.Len() - 1), 1) == wxT("\"")){
443                                                         
444                                                 ETagData.Remove(0, 1);
445                                                 ETagData.RemoveLast();
446                                                         
447                                         }
448                                 
449                                 }
450                                 
451                                 if (wxSHeaderLine.Mid(0, 4) == wxT("DAV:")){
452                                 
453                                         // Look for address book in the line.
454                                         
455                                         if (wxSHeaderLine.Find(wxT("addressbook")) != wxNOT_FOUND){
456                                         
457                                                 HasCalDAVSupport = TRUE;
458                                         
459                                         }
460                                 
461                                 }
462                         
463                         }
464                         
465                         // Get the ETag from the header.
466                         
467                         if (UploadMode == TRUE){
468                 
469                                 wxString PageHeaderLine;
470                 
471                                 wxStringTokenizer PageHeaderSplit(PageHeader, wxT("\r\n"));
472                                 
473                                 if (PageHeaderSplit.HasMoreTokens()){
474                                 
475                                         PageHeaderLine = PageHeaderSplit.GetNextToken();
476                                 
477                                 }
478                 
479                         }
481                         ActIter->second = 4;
482                         return;
484                 } else if (conncode == CURLE_HTTP_RETURNED_ERROR){
486                         curl_easy_getinfo(conn, CURLINFO_RESPONSE_CODE, &HTTPErrorCode);
487                 
488                         fprintf(stderr, "curl_easy_perform() failed: %s\n",
489                                         curl_easy_strerror(conncode));
491                         fprintf(stderr, "curl_easy_perform() HTTP code was: %i\n",
492                                         GetHTTPCode());
494                         ActIter->second = 2;
495                         return;
496                 
497                 } else {
499                         fprintf(stderr, "curl_easy_perform() failed: %s\n",
500                                         curl_easy_strerror(conncode));
501                                 
502                         ActIter->second = 2;
503                         return;
505                 }
506                 
507         }
508         
509         // Catch all.
510         
511         //ActIter->second = 1;
512         *ServerResult = TRUE;
513         return;
517 void CardDAV::ProcessData(){
519         // Process the data.
520         
521         std::thread ConnectThread(&CardDAV::ProcessDataThread, this);
522         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