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