1 // frmNewAccount.cpp - frmNewAccount form functions
3 // (c) 2016-2017 Xestia Software Development.
5 // This file is part of Xestia Calendar.
7 // Xestia Calendar 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.
11 // Xestia Calendar 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.
16 // You should have received a copy of the GNU General Public License along
17 // with Xestia Calendar. If not, see <http://www.gnu.org/licenses/>
19 #include "frmNewAccount.h"
21 #if defined(__WIN32__)
22 #include "../common/win32ssl.h"
25 DEFINE_EVENT_TYPE(UPDATERESULTS);
26 DEFINE_EVENT_TYPE(RUNCALDAVTEST);
28 BEGIN_EVENT_TABLE(frmNewAccount, wxDialog)
29 EVT_COMMAND(wxID_ANY, UPDATERESULTS, frmNewAccount::UpdateResults)
30 EVT_COMMAND(wxID_ANY, RUNCALDAVTEST, frmNewAccount::RunCalDAVTest)
33 frmNewAccount::frmNewAccount( wxWindow* parent )
35 frmNewAccountADT( parent )
38 // Disable the previous button upon form creation.
40 btnPrevious->Disable();
41 txtServerAddress->Disable();
42 txtServerPort->Disable();
43 txtUsername->Disable();
44 txtPassword->Disable();
49 void frmNewAccount::UpdateRequirements( wxCommandEvent& event )
51 // Update the options.
53 if (cmbServerType->GetCurrentSelection() == 1){
55 txtServerAddress->Enable();
56 txtServerPort->Enable();
57 txtUsername->Enable();
58 txtPassword->Enable();
61 } else if (cmbServerType->GetCurrentSelection() == 0){
63 txtServerAddress->Disable();
64 txtServerPort->Disable();
65 txtUsername->Disable();
66 txtPassword->Disable();
72 void frmNewAccount::Navigate( wxCommandEvent& event )
75 if (event.GetId() == wxID_NEXT)
84 btnPrevious->Disable();
90 btnNext->SetLabel(_("Next >"));
92 } else if (pageSeek == 2){
94 if (cmbServerType->GetCurrentSelection() == 0){
99 szrNewAccount->RecalcSizes();
103 btnPrevious->Enable();
104 btnNext->SetLabel(_("Finish"));
109 // Check if server address matches against the blacklist.
110 // Bring up warning message if it does.
112 if (CheckBlacklist(txtServerAddress->GetValue())){
114 int MessageBoxResult = wxMessageBox(_("The server with the address given does not support the CalDAV protocol properly and shouldn't be used.\n\nData loss is very likely.\n\nDo you still want to continue using this server?"), _("Server warning"), wxYES_NO, this);
116 if (MessageBoxResult == wxNO){
124 btnNext->SetLabel(_("Next >"));
126 bool ServerResult = FALSE;
127 bool ServerAction = FALSE;
129 wxString ServerMessage;
131 // Connection test screen.
136 szrNewAccount->RecalcSizes();
137 btnPrevious->Disable();
141 lblServerConnResult->SetLabel(wxT(""));
142 lblServerResponse->SetLabel(wxT(""));
143 lblServerSSLResult->SetLabel(wxT(""));
144 lblServerSSLValid->SetLabel(wxT(""));
145 lblAbleToLoginResult->SetLabel(wxT(""));
146 lblCalDAVSupportResult->SetLabel(wxT(""));
148 // Depending on account type, run the test.
150 if (cmbServerType->GetCurrentSelection() == 1){
151 wxCommandEvent RunTest(RUNCALDAVTEST);
152 wxPostEvent(this, RunTest);
155 } else if (pageSeek == 3){
162 szrNewAccount->RecalcSizes();
164 btnPrevious->Enable();
165 btnNext->SetLabel(_("Finish"));
167 if (txtAccountName->IsEmpty() || txtAccountName->GetValue().Len() < 4 && pageSeek == 3){
177 } else if (pageSeek == 4){
181 wxString xestiaCALPrefDirectory;
182 wxString xestiaCALDirectory;
183 wxString accountSettingsFile;
187 int randomNumber = rand() % 32767;
188 wxString randomNumberSuffix = wxString::Format(wxT("%i"), randomNumber);
189 bool directoryCreated = FALSE;
191 #if defined(__HAIKU__)
193 //preffilename = wxT("noo");
195 #elif defined(__WIN32__)
197 xestiaCALPrefDirectory = GetUserPrefDir();
198 xestiaCALDirectory = GetUserDir();
200 accountSettingsFile = xestiaCALPrefDirectory + wxT("accounts");
202 // Open the file for writing.
204 wxFileConfig *cfgFile = new wxFileConfig("", "", accountSettingsFile);
206 // Check if account name already exists and return an error message
207 // if this is the case.
209 wxString accountName;
212 continueAcc = cfgFile->GetFirstGroup(accountName, itemIndex);
216 if (txtAccountName->GetValue() == accountName){
218 wxMessageBox(_("The selected account name is already used, please use another account name."), _("Account name already used"), wxICON_ERROR);
223 cfgFile->SetPath(wxT("/"));
224 continueAcc = cfgFile->GetNextGroup(accountName, itemIndex);
228 wxString directoryName = txtAccountName->GetValue().Mid(0, 30) + randomNumberSuffix;
230 if (cmbServerType->GetCurrentSelection() == 0){
232 // Create the account directory.
234 if (wxMkdir(xestiaCALDirectory + wxT("\\accounts\\") + directoryName + wxT(".Local"), 0740) == true){
236 WriteAccountDetails(cfgFile, wxT("Local"), directoryName);
240 wxMessageBox(_("An error occured whilst creating the account directory."), _("Cannot create account directory"));
245 } else if (cmbServerType->GetCurrentSelection() == 1){
247 // Create the account directory.
249 if (wxMkdir(xestiaCALDirectory + wxT("\\accounts\\") + directoryName + wxT(".CalDAV"), 0740) == true){
251 WriteAccountDetails(cfgFile, wxT("CalDAV"), directoryName);
255 wxMessageBox(_("An error occured whilst creating the account directory."), _("Cannot create account directory"));
265 *reloadAccountConfig = TRUE;
269 xestiaCALPrefDirectory = GetUserPrefDir();
270 xestiaCALDirectory = GetUserDir();
272 accountSettingsFile = xestiaCALPrefDirectory + wxT("accounts");
274 // Open the file for writing.
276 wxFileConfig *cfgFile = new wxFileConfig("", "", accountSettingsFile);
278 // Check if account name already exists and return an error message
279 // if this is the case.
281 wxString accountName;
284 continueAcc = cfgFile->GetFirstGroup(accountName, itemIndex);
288 if (txtAccountName->GetValue() == accountName){
290 wxMessageBox(_("The selected account name is already used, please use another account name."), _("Account name already used"), wxICON_ERROR);
295 cfgFile->SetPath(wxT("/"));
296 continueAcc = cfgFile->GetNextGroup(accountName, itemIndex);
300 wxString directoryName = txtAccountName->GetValue().Mid(0, 30) + randomNumberSuffix;
302 if (cmbServerType->GetCurrentSelection() == 0){
304 // Create the account directory.
306 if (wxMkdir(xestiaCALDirectory + wxT("/accounts/") + directoryName + wxT(".Local"), 0740) == true){
308 WriteAccountDetails(cfgFile, wxT("Local"), directoryName);
312 wxMessageBox(_("An error occured whilst creating the account directory."), _("Cannot create account directory"));
317 } else if (cmbServerType->GetCurrentSelection() == 1){
319 // Create the account directory.
321 wxString directoryName = txtAccountName->GetValue().Mid(0, 30) + randomNumberSuffix;
323 if (wxMkdir(xestiaCALDirectory + wxT("/accounts/") + directoryName + wxT(".CalDAV"), 0740) == true){
325 WriteAccountDetails(cfgFile, wxT("CalDAV"), directoryName);
329 wxMessageBox(_("An error occured whilst creating the account directory."), _("Cannot create account directory"));
339 *reloadAccountConfig = true;
349 void frmNewAccount::CloseWindow( wxCommandEvent& event )
354 *reloadAccountConfig = FALSE;
359 void frmNewAccount::SetupPointers(bool *ReloadAccountInc, CalendarDataStorage *dataStorage){
361 // Setup the pointers for the new account window.
363 reloadAccountConfig = ReloadAccountInc;
367 void frmNewAccount::CheckAccountName( wxCommandEvent& event )
370 // Check that the account name is valid.
372 wxString checkAccName = txtAccountName->GetValue();
374 if ((txtAccountName->IsEmpty() && pageSeek == 2) || checkAccName.Len() < 4){
386 void frmNewAccount::WriteAccountDetails(wxFileConfig *cfgFileIn, wxString accountType, wxString directoryName){
388 // Write the new account details.
390 cfgFileIn->SetPath(txtAccountName->GetValue());
391 cfgFileIn->Write(wxT("address"), txtServerAddress->GetValue());
392 cfgFileIn->Write(wxT("port"), txtServerPort->GetValue());
393 cfgFileIn->Write(wxT("username"), txtUsername->GetValue());
394 cfgFileIn->Write(wxT("password"), txtPassword->GetValue());
395 cfgFileIn->Write(wxT("prefix"), serverPrefix);
396 cfgFileIn->Write(wxT("accountdir"), directoryName);
398 if (chkUseSSL->GetValue() == TRUE){
400 cfgFileIn->Write(wxT("ssl"), wxT("true"));
404 cfgFileIn->Write(wxT("ssl"), wxT("false"));
408 cfgFileIn->Write(wxT("refresh"), wxT("1800"));
409 cfgFileIn->Write(wxT("type"), accountType);
413 void frmNewAccount::UpdateResults( wxCommandEvent &event )
415 NewAccountResult *resultData = static_cast<NewAccountResult*>(event.GetClientData());
417 lblServerConnResult->SetLabel((resultData->Connected ? _("Successful") : _("Failed")));
418 lblServerResponse->SetLabel((resultData->ValidResponse ? _("Yes") : _("No")));
419 if (chkUseSSL->GetValue())
421 lblServerSSLResult->SetLabel((resultData->SSLStatus ? _("Yes") : _("No")));
422 lblServerSSLValid->SetLabel((resultData->SSLVerified == COSSL_VERIFIED ? _("Yes") : _("No")));
424 lblServerSSLResult->SetLabel(_("Not Applicable"));
425 lblServerSSLValid->SetLabel(_("Not Applicable"));
427 lblAbleToLoginResult->SetLabel((resultData->AuthPassed ? _("Yes") : _("No")));
428 lblCalDAVSupportResult->SetLabel((resultData->CanProcess ? _("Yes") : _("No")));
430 if (resultData->ErrorMessage != "")
432 lblConnectionResultText->SetLabel(_("An error occured whilst connecting to the server: ") + resultData->ErrorMessage);
435 if (VerifyResultData(resultData))
437 lblConnectionResultText->SetLabel(_("Successfully connected to the server. Press Next to set the account name."));
438 btnNext->Enable(true);
442 btnNext->Enable(false);
446 btnPrevious->Enable(true);
449 resultData = nullptr;
452 bool frmNewAccount::VerifyResultData(NewAccountResult *resultData)
454 if (!resultData->Connected) return false;
455 if (!resultData->ValidResponse) return false;
456 if (chkUseSSL->GetValue())
458 if (!resultData->SSLStatus) return false;
459 if (resultData->SSLVerified != COSSL_VERIFIED) return false;
461 if (!resultData->AuthPassed) return false;
462 if (!resultData->CanProcess) return false;
467 void frmNewAccount::RunCalDAVTest( wxCommandEvent &event )
469 NewAccountResult *resultData = new NewAccountResult;
471 lblServerConnResult->SetLabel(_("Testing..."));
472 lblCalDAVSupportResult->SetLabel(wxT(""));
473 lblServerResponse->SetLabel(wxT(""));
474 lblServerSSLResult->SetLabel(wxT(""));
475 lblServerSSLValid->SetLabel(wxT(""));
476 lblAbleToLoginResult->SetLabel(wxT(""));
477 lblConnectionResultText->SetLabel(wxT(""));
478 bool usingSSLBypass = false;
480 // Setup a CalDAV connection object for testing.
482 CalDAVConnectionData connData;
483 connData.hostname = txtServerAddress->GetValue().ToStdString();
484 connData.port = wxAtoi(txtServerPort->GetValue());
485 connData.username = txtUsername->GetValue().ToStdString();
486 connData.password = txtPassword->GetValue().ToStdString();
487 connData.useSSL = chkUseSSL->GetValue() ? true : false;
489 CalDAV testConnection;
490 testConnection.SetupConnectionData(&connData);
492 /*CardDAV2 TestConnection(txtServerAddress->GetValue().ToStdString(),
493 wxAtoi(txtServerPort->GetValue()),
494 txtUsername->GetValue().ToStdString(),
495 txtPassword->GetValue().ToStdString(),
496 chkUseSSL->GetValue() ? true : false);*/
498 // Test the connection.
500 //testConnection.SetupConnectionObject();
501 CalDAVServerResult testConnectionResult = testConnection.Connect(false);
503 // If server is using SSL, verify that the SSL connection is valid.
505 if (testConnection.SSLVerify() == COSSL_UNABLETOVERIFY){
506 #if defined(__APPLE__)
508 testConnection.BypassSSLVerification(true);
510 CalDAVServerResult testConnection = testConnection.Connect(false);
512 testConnection.BypassSSLVerification(false);
514 int SSLResult = DisplayTrustPanel(&TestConnection);
516 if (SSLResult != NSOKButton){
518 lblServerConnResult->SetLabel(_("Failed"));
519 lblServerResponse->SetLabel(_("Not applicable"));
520 lblServerSSLResult->SetLabel(_("Used"));
521 lblServerSSLValid->SetLabel(_("No"));
522 lblConnectionResultText->SetLabel(_("An error occured whilst connnecting: ") + TestConnection.GetErrorMessage());
523 btnPrevious->Enable(true);
528 // Evalulate the trust object.
530 SecTrustResultType evalResult = ProcessResultType(&testConnection);
533 case kSecTrustResultProceed:
534 lblServerSSLValid->SetLabel(_("Verified"));
536 case kSecTrustResultConfirm:
537 lblServerSSLValid->SetLabel(_("Verified (user)"));
540 lblServerSSLValid->SetLabel(_("Unable to verify"));
543 lblServerResponse->SetLabel(_("Not applicable"));
544 lblServerSSLResult->SetLabel(_("Used"));
546 if (evalResult != kSecTrustResultProceed){
552 #elif defined(__WIN32__)
554 testConnection.BypassSSLVerification(true);
556 CalDAVServerResult testConnectionResult = testConnection.Connect(false);
558 testConnection.BypassSSLVerification(false);
560 BOOL modifiedCertificateData = false;
562 CRYPTUI_VIEWCERTIFICATE_STRUCTW certificateDialogData = BuildCertificateData(&testConnection, (HWND)this->GetHandle());
564 if (!CryptUIDlgViewCertificate(&certificateDialogData, &modifiedCertificateData)){
565 wxMessageBox(_("An error occured while trying to open the certificate dialog."), _("Error opening Certificate Information dialog"));
568 if (modifiedCertificateData == false){
570 lblServerConnResult->SetLabel(_("Failed"));
571 lblServerResponse->SetLabel(_("Not applicable"));
572 lblServerSSLResult->SetLabel(_("Used"));
573 lblServerSSLValid->SetLabel(_("No"));
574 lblConnectionResultText->SetLabel(_("An error occured whilst connnecting: ") + testConnection.GetErrorMessage());
575 btnPrevious->Enable(true);
582 // Connect again and fetch SSL certificate information.
584 testConnection.BypassSSLVerification(true);
586 CalDAVServerResult testConnectionResult = testConnection.Connect(false);
588 testConnection.BypassSSLVerification(false);
590 SSLCertCollectionString certData = testConnection.BuildSSLCollection();
591 frmInvalidSSLCertificate *frmICPtr = new frmInvalidSSLCertificate(this);
593 frmICPtr->LoadDataNew(certData, txtServerAddress->GetValue().ToStdString());
594 frmICPtr->ShowModal();
596 int sslResult = frmICPtr->GetResult();
598 // Clean up before processing response.
603 // Process the response from the user.
607 // Accept the Certificate.
609 usingSSLBypass = true;
610 testConnection.BypassSSLVerification(true);
612 CalDAVServerResult testConnectionResult = testConnection.Connect(true);
614 testConnection.BypassSSLVerification(false);
616 } else if (sslResult == 2){
618 // Reject the certificate, abort the task and mark as failed.
620 // TODO: Integrate into the code.
622 //lblConnectionResultText->SetLabel(_("An error occured whilst connnecting: ") + CardDAVConn.GetErrorMessage() + wxString::Format(wxT(" (%i)\n%s"), sslcode, CardDAVConn.GetErrorBuffer().mb_str()));
624 resultData->Connected = true;
625 resultData->SSLStatus = true;
626 resultData->SSLVerified = COSSL_UNABLETOVERIFY;
627 resultData->ValidResponse = false;
628 resultData->AuthPassed = false;
629 resultData->CanProcess = false;
630 resultData->ErrorMessage = _("Server is using self-signed certificate and was rejected.");
632 wxCommandEvent resultsEvent(UPDATERESULTS);
633 resultsEvent.SetClientData(resultData);
634 wxPostEvent(this, resultsEvent);
643 if (usingSSLBypass == true){
644 testConnection.BypassSSLVerification(true);
647 testConnectionResult = testConnection.Connect(true);
649 // Get the server prefix if the connection was successful.
651 if (testConnectionResult.result == CALDAVQUERYRESULT_OK){
653 std::string receivedServerPrefix;
655 receivedServerPrefix = testConnection.GetUserPrincipal();
656 serverPrefix = receivedServerPrefix;
660 CalDAVServerSupport testConnectionSupport = testConnection.GetServerSupport();
662 if (usingSSLBypass == true){
663 testConnection.BypassSSLVerification(false);
666 (testConnectionResult.result == CALDAVQUERYRESULT_OK || testConnectionResult.result == CALDAVQUERYRESULT_SSLFAILURE) ?
667 resultData->Connected = true : resultData->Connected = false;
669 resultData->SSLStatus = testConnection.CanDoSSL();
670 resultData->SSLVerified = testConnection.SSLVerify();
671 resultData->ValidResponse = testConnection.HasValidResponse();
672 resultData->AuthPassed = testConnection.AbleToLogin();
673 resultData->CanProcess = testConnectionSupport.basicSupport;
674 resultData->ErrorMessage = testConnection.GetErrorMessage();
676 // Post event back confirming the tests.
678 wxCommandEvent resultsEvent(UPDATERESULTS);
679 resultsEvent.SetClientData(resultData);
680 wxPostEvent(this, resultsEvent);