2 #include "../version.h"
4 #include <wx/tokenzr.h>
6 #include <libxml/parser.h>
7 #include <libxml/tree.h>
10 #include "../vcard/vcard.h"
11 #include "../common/dirs.h"
13 void CardDAV::ProcessDataThread(){
20 AbortConnection = FALSE;
24 wxString ServerAddressURL;
26 wxString ServerAddressSSL;
27 wxString ServerAddressNormal;
29 conn = curl_easy_init();
31 struct CardDAVCURLPasser {
34 bool HeaderMode = TRUE;
36 } CardDAVHeader, CardDAVFooter;
38 CardDAVHeader.Data = this;
39 CardDAVHeader.HeaderMode = TRUE;
41 CardDAVFooter.Data = this;
42 CardDAVFooter.HeaderMode = FALSE;
48 wxString ETagOriginal;
51 ServerAddressURL = ServerAddress + wxT(":") + wxString::Format(wxT("%i"), ServerPort) + wxT("/") + ServerPrefix + ServerFilenameLocation;
52 ServerAddressSSL = wxT("https://") + ServerAddressURL;
53 ServerAddressNormal = wxT("http://") + ServerAddressURL;
55 ServerAuth = ServerUser + wxT(":") + ServerPass;
61 char *ServerAdrSSLChar = new char[(ServerAddressSSL.Length() - 1)];
62 //memset(ServerAdrSSLChar, 0, ServerAddressSSL.Length());
63 strncpy(ServerAdrSSLChar, (const char*)ServerAddressSSL.mb_str(wxConvUTF8), (ServerAddressSSL.Length() - 1));
65 char *ServerAdrNorChar = new char[(ServerAddressNormal.Length() - 1)];
66 //memset(ServerAdrNorChar, 0, ServerAddressSSL.Length());
67 strncpy(ServerAdrNorChar, (const char*)ServerAddressNormal.mb_str(wxConvUTF8), (ServerAddressNormal.Length() - 1));
69 char *ServerAuthChar = new char[(ServerAuth.Length() - 1)];
70 //memset(ServerAuthChar, 0, ServerAddressSSL.Length());
71 strncpy(ServerAuthChar, (const char*)ServerAuth.mb_str(wxConvUTF8), (ServerAuth.Length() - 1));
75 //std::string WriteDataString = std::string(ServerUploadData.mb_str());
77 std::map<int,int>::iterator ActIter;
78 struct UploadDataStruc UploadData;
81 ActIter = ActivityListPtr->find((int)ItemIndex);
83 // Update result flag.
87 // Setup the request mode if it is not empty.
89 if (!ServerMethod.IsEmpty()){
91 curl_easy_setopt(conn, CURLOPT_CUSTOMREQUEST, (const char*)ServerMethod.mb_str(wxConvUTF8));
97 wxString ServerCertFilename;
98 bool MatchingCert = FALSE;
100 curl_easy_setopt(conn, CURLOPT_URL, (const char*)ServerAddressSSL.mb_str(wxConvUTF8));
101 curl_easy_setopt(conn, CURLOPT_NOPROGRESS, 0);
102 curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
103 curl_easy_setopt(conn, CURLOPT_TIMEOUT, 60);
104 curl_easy_setopt(conn, CURLOPT_FAILONERROR, TRUE);
105 curl_easy_setopt(conn, CURLOPT_USERAGENT, XSDAB_USERAGENT);
106 curl_easy_setopt(conn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8));
107 curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc);
108 curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData);
109 curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader);
110 curl_easy_setopt(conn, CURLOPT_PROGRESSDATA, this);
111 curl_easy_setopt(conn, CURLOPT_PROGRESSFUNCTION, ProgressFunc);
112 curl_easy_setopt(conn, CURLOPT_NOSIGNAL, 1);
114 if (UploadMode == TRUE){
116 UploadData.readptr = &ServerUploadData;
117 UploadData.sizeleft = ServerUploadData.Len();
118 curl_easy_setopt(conn, CURLOPT_UPLOAD, 1);
119 curl_easy_setopt(conn, CURLOPT_READDATA, &UploadData);
120 curl_easy_setopt(conn, CURLOPT_READFUNCTION, UploadReadFunc);
124 ServerCertFilename = GetAccountDir(ServerAccount, TRUE);
126 if (wxFile::Exists(ServerCertFilename) == TRUE){
128 curl_easy_setopt(conn, CURLOPT_SSL_VERIFYPEER, 1);
129 curl_easy_setopt(conn, CURLOPT_SSL_VERIFYHOST, 2);
130 curl_easy_setopt(conn, CURLOPT_CAINFO, (const char*)ServerCertFilename.mb_str(wxConvUTF8));
134 //UploadData.readptr = &CardDAVDataQuery;
135 //UploadData.sizeleft = CardDAVDataQuery.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);
140 //curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, writefunc);
142 claconncode = (curl_easy_perform(conn));
144 // If CURLE_PEER_FAILED_VERIFICATION is returned, retry without
145 // the local certificate in use.
147 if (claconncode == CURLE_PEER_FAILED_VERIFICATION){
149 curl_easy_cleanup(conn);
150 conn = curl_easy_init();
152 curl_easy_setopt(conn, CURLOPT_URL, (const char*)ServerAddressSSL.mb_str(wxConvUTF8));
153 curl_easy_setopt(conn, CURLOPT_NOPROGRESS, 0);
154 curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
155 curl_easy_setopt(conn, CURLOPT_TIMEOUT, 60);
156 curl_easy_setopt(conn, CURLOPT_FAILONERROR, TRUE);
157 curl_easy_setopt(conn, CURLOPT_USERAGENT, XSDAB_USERAGENT);
158 curl_easy_setopt(conn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8));
159 curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc);
160 curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData);
161 curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader);
162 curl_easy_setopt(conn, CURLOPT_PROGRESSDATA, this);
163 curl_easy_setopt(conn, CURLOPT_PROGRESSFUNCTION, ProgressFunc);
164 curl_easy_setopt(conn, CURLOPT_NOSIGNAL, 1);
166 if (UploadMode == TRUE){
168 UploadData.readptr = &ServerUploadData;
169 UploadData.sizeleft = ServerUploadData.Len();
170 curl_easy_setopt(conn, CURLOPT_UPLOAD, 1);
171 curl_easy_setopt(conn, CURLOPT_READDATA, &UploadData);
172 curl_easy_setopt(conn, CURLOPT_READFUNCTION, UploadReadFunc);
176 claconncode = (curl_easy_perform(conn));
178 // If claconncode is CURLE_OK then delete the certificate file as that
179 // is no longer needed.
181 if (claconncode == CURLE_OK){
183 // Delete the certificate file.
185 wxRemoveFile(ServerCertFilename);
191 // Check if it fails with a CURLE_SSL_CACERT then compare
192 // the certificates as PEM files.
194 if (claconncode == CURLE_SSL_CACERT && wxFile::Exists(ServerCertFilename) == TRUE){
196 //curl_easy_cleanup(conn);
197 //conn = curl_easy_init();
200 sslerrconn = curl_easy_init();
201 CURLcode sslerrconncode;
203 //claconncode = (curl_easy_perform(conn));
205 wxString ServerAddressOnly = wxT("https://") + ServerAddress + wxT(":") + wxString::Format(wxT("%i"), ServerPort) + wxT("/");
207 curl_easy_setopt(sslerrconn, CURLOPT_URL, (const char*)ServerAddressOnly.mb_str(wxConvUTF8));
208 curl_easy_setopt(sslerrconn, CURLOPT_NOPROGRESS, 0);
209 curl_easy_setopt(sslerrconn, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
210 curl_easy_setopt(sslerrconn, CURLOPT_TIMEOUT, 60);
211 curl_easy_setopt(sslerrconn, CURLOPT_FAILONERROR, TRUE);
212 curl_easy_setopt(sslerrconn, CURLOPT_USERAGENT, XSDAB_USERAGENT);
213 curl_easy_setopt(sslerrconn, CURLOPT_WRITEFUNCTION, WritebackFunc);
214 curl_easy_setopt(sslerrconn, CURLOPT_WRITEDATA, &PageData);
215 curl_easy_setopt(sslerrconn, CURLOPT_WRITEHEADER, &PageHeader);
216 curl_easy_setopt(sslerrconn, CURLOPT_PROGRESSDATA, this);
217 curl_easy_setopt(sslerrconn, CURLOPT_PROGRESSFUNCTION, ProgressFunc);
218 curl_easy_setopt(sslerrconn, CURLOPT_NOSIGNAL, 1);
219 curl_easy_setopt(sslerrconn, CURLOPT_SSL_VERIFYPEER, 0);
220 curl_easy_setopt(sslerrconn, CURLOPT_CERTINFO, 1);
222 wxString SSLLocalData;
223 wxString SSLServerData;
225 sslerrconncode = (curl_easy_perform(sslerrconn));
227 SSLCertCol = BuildSSLCollection(sslerrconn);
228 std::map<int, SSLCertData>::iterator SSLCDIter = SSLCertCol.SSLCollection.find(0);
229 std::multimap<wxString,wxString>::iterator SSLDataIter = SSLCDIter->second.CertData.find(wxT("Cert"));
231 wxFFile SSLLocalFile;
233 #if wxABI_VERSION < 20900
234 SSLLocalFile.Open(ServerCertFilename.c_str(), wxT("r"));
236 SSLLocalFile.Open(ServerCertFilename, wxT("r"));
239 // Load the recovery database for tasks not done.
241 if (SSLLocalFile.IsOpened() == TRUE){
243 // Check if we are using wxWidgets version 2.8 or less and
244 // execute the required command accordingly.
246 SSLLocalFile.ReadAll(&SSLLocalData, wxConvAuto());
251 SSLServerData = SSLDataIter->second;
253 if (SSLLocalData == SSLServerData){
255 // Server key matches with local key so retry with CURLOPT_SSL_VERIFYPEER
256 // and CURLOPT_SSL_VERIFYHOST off.
258 curl_easy_cleanup(conn);
259 conn = curl_easy_init();
264 curl_easy_setopt(conn, CURLOPT_URL, (const char*)ServerAddressSSL.mb_str(wxConvUTF8));
265 curl_easy_setopt(conn, CURLOPT_NOPROGRESS, 0);
266 curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
267 curl_easy_setopt(conn, CURLOPT_TIMEOUT, 60);
268 curl_easy_setopt(conn, CURLOPT_FAILONERROR, TRUE);
269 curl_easy_setopt(conn, CURLOPT_USERAGENT, XSDAB_USERAGENT);
270 curl_easy_setopt(conn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8));
271 curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc);
272 curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData);
273 curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader);
274 curl_easy_setopt(conn, CURLOPT_PROGRESSDATA, this);
275 curl_easy_setopt(conn, CURLOPT_PROGRESSFUNCTION, ProgressFunc);
276 curl_easy_setopt(conn, CURLOPT_NOSIGNAL, 1);
278 if (UploadMode == TRUE){
280 UploadData.readptr = &ServerUploadData;
281 UploadData.sizeleft = ServerUploadData.Len();
282 curl_easy_setopt(conn, CURLOPT_UPLOAD, 1);
283 curl_easy_setopt(conn, CURLOPT_READDATA, &UploadData);
284 curl_easy_setopt(conn, CURLOPT_READFUNCTION, UploadReadFunc);
288 curl_easy_setopt(conn, CURLOPT_SSL_VERIFYHOST, 0);
289 curl_easy_setopt(conn, CURLOPT_SSL_VERIFYPEER, 0);
291 claconncode = (curl_easy_perform(conn));
297 if (MatchingCert == FALSE){
299 claconncode = CURLE_SSL_CACERT;
304 curl_easy_cleanup(sslerrconn);
308 // Sort out SSL error.
310 // When SSL cert error occurs, connect again and fetch certificates.
311 // Display a message to the user explaining that an invalid
312 // certificate has been given and let the user decide what
315 if (claconncode == CURLE_OK){
317 } else if (claconncode == CURLE_SSL_CACERT || claconncode == CURLE_PEER_FAILED_VERIFICATION){
320 sslerrconn = curl_easy_init();
321 CURLcode sslerrconncode;
323 wxString ServerAddressOnly = wxT("https://") + ServerAddress + wxT(":") + wxString::Format(wxT("%i"), ServerPort) + wxT("/");
325 // Replace conn with sslerrconn!
327 curl_easy_setopt(sslerrconn, CURLOPT_URL, (const char*)ServerAddressOnly.mb_str(wxConvUTF8));
328 curl_easy_setopt(sslerrconn, CURLOPT_NOPROGRESS, 0);
329 curl_easy_setopt(sslerrconn, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
330 curl_easy_setopt(sslerrconn, CURLOPT_TIMEOUT, 60);
331 curl_easy_setopt(sslerrconn, CURLOPT_FAILONERROR, TRUE);
332 curl_easy_setopt(sslerrconn, CURLOPT_USERAGENT, XSDAB_USERAGENT);
333 curl_easy_setopt(sslerrconn, CURLOPT_WRITEFUNCTION, WritebackFunc);
334 curl_easy_setopt(sslerrconn, CURLOPT_WRITEDATA, &PageData);
335 curl_easy_setopt(sslerrconn, CURLOPT_WRITEHEADER, &PageHeader);
336 curl_easy_setopt(sslerrconn, CURLOPT_PROGRESSDATA, this);
337 curl_easy_setopt(sslerrconn, CURLOPT_PROGRESSFUNCTION, ProgressFunc);
338 curl_easy_setopt(sslerrconn, CURLOPT_NOSIGNAL, 1);
339 curl_easy_setopt(sslerrconn, CURLOPT_SSL_VERIFYPEER, 0);
340 curl_easy_setopt(sslerrconn, CURLOPT_CERTINFO, 1);
342 sslerrconncode = (curl_easy_perform(sslerrconn));
344 SSLCertCol = BuildSSLCollection(sslerrconn);
345 SSLCertCol.SuccessCode = 1;
349 } else if (claconncode == CURLE_HTTP_RETURNED_ERROR){
351 fprintf(stderr, "curl_easy_perform() failed: %s\n",
352 curl_easy_strerror(claconncode));
354 curl_easy_getinfo(conn, CURLINFO_RESPONSE_CODE, &http_code);
355 fprintf(stderr, "Error code was: %d\n", http_code);
361 fprintf(stderr, "curl_easy_perform() failed: %s\n",
362 curl_easy_strerror(claconncode));
364 curl_easy_getinfo(conn, CURLINFO_RESPONSE_CODE, &http_code);
365 fprintf(stderr, "Error code was: %d\n", http_code);
375 curl_easy_setopt(conn, CURLOPT_URL, (const char*)ServerAddressNormal.mb_str(wxConvUTF8));
376 curl_easy_setopt(conn, CURLOPT_NOPROGRESS, 0);
377 curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
378 curl_easy_setopt(conn, CURLOPT_TIMEOUT, 60);
379 curl_easy_setopt(conn, CURLOPT_FAILONERROR, TRUE);
380 curl_easy_setopt(conn, CURLOPT_USERAGENT, XSDAB_USERAGENT);
381 curl_easy_setopt(conn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8));
382 curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc);
383 curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData);
384 curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader);
385 curl_easy_setopt(conn, CURLOPT_PROGRESSDATA, this);
386 curl_easy_setopt(conn, CURLOPT_PROGRESSFUNCTION, ProgressFunc);
387 curl_easy_setopt(conn, CURLOPT_NOSIGNAL, 1);
389 if (UploadMode == TRUE){
391 UploadData.readptr = &ServerUploadData;
392 UploadData.sizeleft = ServerUploadData.Len();
393 curl_easy_setopt(conn, CURLOPT_UPLOAD, 1);
394 curl_easy_setopt(conn, CURLOPT_READDATA, &UploadData);
395 curl_easy_setopt(conn, CURLOPT_READFUNCTION, UploadReadFunc);
399 conncode = (curl_easy_perform(conn));
401 if (conncode == CURLE_OK){
403 // Process the server header response and look for
404 // 'addressbook' within the DAV header.
406 wxStringTokenizer wxSHeaderLines(PageHeader, wxT("\r\n"));
407 wxString wxSHeaderLine;
408 std::map<int, wxString> DAVHeaderLines;
410 while (wxSHeaderLines.HasMoreTokens()){
412 wxSHeaderLine = wxSHeaderLines.GetNextToken();
414 if (wxSHeaderLine.Mid(0, 5) == wxT("ETag:")){
416 ETagData = wxSHeaderLine.Mid(5);
418 ETagData.Trim(FALSE);
422 if (ETagData.Mid(0, 1) == wxT("\"") && ETagData.Mid((ETagData.Len() - 1), 1) == wxT("\"")){
424 ETagData.Remove(0, 1);
425 ETagData.RemoveLast();
431 if (wxSHeaderLine.Mid(0, 4) == wxT("DAV:")){
433 // Look for address book in the line.
435 if (wxSHeaderLine.Find(wxT("addressbook")) != wxNOT_FOUND){
437 HasCalDAVSupport = TRUE;
445 // Get the ETag from the header.
447 if (UploadMode == TRUE){
449 wxString PageHeaderLine;
451 wxStringTokenizer PageHeaderSplit(PageHeader, wxT("\r\n"));
453 if (PageHeaderSplit.HasMoreTokens()){
455 PageHeaderLine = PageHeaderSplit.GetNextToken();
464 } else if (conncode == CURLE_HTTP_RETURNED_ERROR){
466 curl_easy_getinfo(conn, CURLINFO_RESPONSE_CODE, &HTTPErrorCode);
468 fprintf(stderr, "curl_easy_perform() failed: %s\n",
469 curl_easy_strerror(conncode));
471 fprintf(stderr, "curl_easy_perform() HTTP code was: %i\n",
479 fprintf(stderr, "curl_easy_perform() failed: %s\n",
480 curl_easy_strerror(conncode));
491 //ActIter->second = 1;
492 *ServerResult = TRUE;
497 void CardDAV::ProcessData(){
499 std::thread ConnectThread(&CardDAV::ProcessDataThread, this);
500 ConnectThread.detach();