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