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 DEFINE_EVENT_TYPE(UPDATERESULTS);
22 DEFINE_EVENT_TYPE(RUNCALDAVTEST);
24 BEGIN_EVENT_TABLE(frmNewAccount, wxDialog)
25 EVT_COMMAND(wxID_ANY, UPDATERESULTS, frmNewAccount::UpdateResults)
26 EVT_COMMAND(wxID_ANY, RUNCALDAVTEST, frmNewAccount::RunCalDAVTest)
29 frmNewAccount::frmNewAccount( wxWindow* parent )
31 frmNewAccountADT( parent )
34 // Disable the previous button upon form creation.
36 btnPrevious->Disable();
37 txtServerAddress->Disable();
38 txtServerPort->Disable();
39 txtUsername->Disable();
40 txtPassword->Disable();
45 void frmNewAccount::UpdateRequirements( wxCommandEvent& event )
47 // Update the options.
49 if (cmbServerType->GetCurrentSelection() == 1){
51 txtServerAddress->Enable();
52 txtServerPort->Enable();
53 txtUsername->Enable();
54 txtPassword->Enable();
57 } else if (cmbServerType->GetCurrentSelection() == 0){
59 txtServerAddress->Disable();
60 txtServerPort->Disable();
61 txtUsername->Disable();
62 txtPassword->Disable();
68 void frmNewAccount::Navigate( wxCommandEvent& event )
71 if (event.GetId() == wxID_NEXT)
80 btnPrevious->Disable();
86 btnNext->SetLabel(_("Next >"));
88 } else if (pageSeek == 2){
90 if (cmbServerType->GetCurrentSelection() == 0){
95 szrNewAccount->RecalcSizes();
99 btnPrevious->Enable();
100 btnNext->SetLabel(_("Finish"));
105 // Check if server address matches against the blacklist.
106 // Bring up warning message if it does.
108 if (CheckBlacklist(txtServerAddress->GetValue())){
110 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);
112 if (MessageBoxResult == wxNO){
120 btnNext->SetLabel(_("Next >"));
122 bool ServerResult = FALSE;
123 bool ServerAction = FALSE;
125 wxString ServerMessage;
127 // Connection test screen.
132 szrNewAccount->RecalcSizes();
133 btnPrevious->Disable();
137 lblServerConnResult->SetLabel(wxT(""));
138 lblServerResponse->SetLabel(wxT(""));
139 lblServerSSLResult->SetLabel(wxT(""));
140 lblServerSSLValid->SetLabel(wxT(""));
141 lblAbleToLoginResult->SetLabel(wxT(""));
142 lblCalDAVSupportResult->SetLabel(wxT(""));
144 // Depending on account type, run the test.
146 if (cmbServerType->GetCurrentSelection() == 1){
147 wxCommandEvent RunTest(RUNCALDAVTEST);
148 wxPostEvent(this, RunTest);
151 } else if (pageSeek == 3){
158 szrNewAccount->RecalcSizes();
160 btnPrevious->Enable();
161 btnNext->SetLabel(_("Finish"));
163 if (txtAccountName->IsEmpty() || txtAccountName->GetValue().Len() < 4 && pageSeek == 3){
173 } else if (pageSeek == 4){
177 wxString xestiaCALPrefDirectory;
178 wxString xestiaCALDirectory;
179 wxString accountSettingsFile;
183 int randomNumber = rand() % 32767;
184 wxString randomNumberSuffix = wxString::Format(wxT("%i"), randomNumber);
185 bool directoryCreated = FALSE;
187 #if defined(__HAIKU__)
189 //preffilename = wxT("noo");
191 #elif defined(__WIN32__)
193 xestiaCALPrefDirectory = GetUserPrefDir();
194 xestiaCALDirectory = GetUserDir();
196 accountSettingsFile = xestiaCALPrefDirectory + wxT("accounts");
198 // Open the file for writing.
200 wxFileConfig *cfgFile = new wxFileConfig("", "", accountSettingsFile);
202 // Check if account name already exists and return an error message
203 // if this is the case.
205 wxString accountName;
208 continueAcc = cfgFile->GetFirstGroup(accountName, itemIndex);
212 if (txtAccountName->GetValue() == accountName){
214 wxMessageBox(_("The selected account name is already used, please use another account name."), _("Account name already used"), wxICON_ERROR);
219 cfgFile->SetPath(wxT("/"));
220 continueAcc = cfgFile->GetNextGroup(accountName, itemIndex);
224 wxString directoryName = txtAccountName->GetValue().Mid(0, 30) + randomNumberSuffix;
226 if (cmbServerType->GetCurrentSelection() == 0){
228 // Create the account directory.
230 if (wxMkdir(xestiaCALDirectory + wxT("\\accounts\\") + directoryName + wxT(".local"), 0740) == true){
232 WriteAccountDetails(cfgFile, wxT("Local"), directoryName);
236 wxMessageBox(_("An error occured whilst creating the account directory."), _("Cannot create account directory"));
241 } else if (cmbServerType->GetCurrentSelection() == 1){
243 // Create the account directory.
245 if (wxMkdir(xestiaCALDirectory + wxT("\\accounts\\") + directoryName + wxT(".caldav"), 0740) == true){
247 WriteAccountDetails(cfgFile, wxT("CalDAV"), directoryName);
251 wxMessageBox(_("An error occured whilst creating the account directory."), _("Cannot create account directory"));
261 *reloadAccountConfig = TRUE;
265 xestiaCALPrefDirectory = GetUserPrefDir();
266 xestiaCALDirectory = GetUserDir();
268 accountSettingsFile = xestiaCALPrefDirectory + wxT("accounts");
270 // Open the file for writing.
272 wxFileConfig *cfgFile = new wxFileConfig("", "", accountSettingsFile);
274 // Check if account name already exists and return an error message
275 // if this is the case.
277 wxString accountName;
280 continueAcc = cfgFile->GetFirstGroup(accountName, itemIndex);
284 if (txtAccountName->GetValue() == accountName){
286 wxMessageBox(_("The selected account name is already used, please use another account name."), _("Account name already used"), wxICON_ERROR);
291 cfgFile->SetPath(wxT("/"));
292 continueAcc = cfgFile->GetNextGroup(accountName, itemIndex);
296 wxString directoryName = txtAccountName->GetValue().Mid(0, 30) + randomNumberSuffix;
298 if (cmbServerType->GetCurrentSelection() == 0){
300 // Create the account directory.
302 if (wxMkdir(xestiaCALDirectory + wxT("/accounts/") + directoryName + wxT(".Local"), 0740) == true){
304 WriteAccountDetails(cfgFile, wxT("Local"), directoryName);
308 wxMessageBox(_("An error occured whilst creating the account directory."), _("Cannot create account directory"));
313 } else if (cmbServerType->GetCurrentSelection() == 1){
315 // Create the account directory.
317 wxString directoryName = txtAccountName->GetValue().Mid(0, 30) + randomNumberSuffix;
319 if (wxMkdir(xestiaCALDirectory + wxT("/accounts/") + directoryName + wxT(".caldav"), 0740) == true){
321 WriteAccountDetails(cfgFile, wxT("CalDAV"), directoryName);
325 wxMessageBox(_("An error occured whilst creating the account directory."), _("Cannot create account directory"));
335 *reloadAccountConfig = true;
345 void frmNewAccount::CloseWindow( wxCommandEvent& event )
350 *reloadAccountConfig = FALSE;
355 void frmNewAccount::SetupPointers(bool *ReloadAccountInc, CalendarDataStorage *dataStorage){
357 // Setup the pointers for the new account window.
359 reloadAccountConfig = ReloadAccountInc;
363 void frmNewAccount::CheckAccountName( wxCommandEvent& event )
366 // Check that the account name is valid.
368 wxString checkAccName = txtAccountName->GetValue();
370 if ((txtAccountName->IsEmpty() && pageSeek == 2) || checkAccName.Len() < 4){
382 void frmNewAccount::WriteAccountDetails(wxFileConfig *cfgFileIn, wxString accountType, wxString directoryName){
384 // Write the new account details.
386 cfgFileIn->SetPath(txtAccountName->GetValue());
387 cfgFileIn->Write(wxT("address"), txtServerAddress->GetValue());
388 cfgFileIn->Write(wxT("port"), txtServerPort->GetValue());
389 cfgFileIn->Write(wxT("username"), txtUsername->GetValue());
390 cfgFileIn->Write(wxT("password"), txtPassword->GetValue());
391 cfgFileIn->Write(wxT("prefix"), serverPrefix);
392 cfgFileIn->Write(wxT("accountdir"), directoryName);
394 if (chkUseSSL->GetValue() == TRUE){
396 cfgFileIn->Write(wxT("ssl"), wxT("true"));
400 cfgFileIn->Write(wxT("ssl"), wxT("false"));
404 cfgFileIn->Write(wxT("refresh"), wxT("1800"));
405 cfgFileIn->Write(wxT("type"), accountType);
409 void frmNewAccount::UpdateResults( wxCommandEvent &event )
411 NewAccountResult *resultData = static_cast<NewAccountResult*>(event.GetClientData());
413 lblServerConnResult->SetLabel((resultData->Connected ? _("Successful") : _("Failed")));
414 lblServerResponse->SetLabel((resultData->ValidResponse ? _("Yes") : _("No")));
415 if (chkUseSSL->GetValue())
417 lblServerSSLResult->SetLabel((resultData->SSLStatus ? _("Yes") : _("No")));
418 lblServerSSLValid->SetLabel((resultData->SSLVerified == COSSL_VERIFIED ? _("Yes") : _("No")));
420 lblServerSSLResult->SetLabel(_("Not Applicable"));
421 lblServerSSLValid->SetLabel(_("Not Applicable"));
423 lblAbleToLoginResult->SetLabel((resultData->AuthPassed ? _("Yes") : _("No")));
424 lblCalDAVSupportResult->SetLabel((resultData->CanProcess ? _("Yes") : _("No")));
426 if (resultData->ErrorMessage != "")
428 lblConnectionResultText->SetLabel(_("An error occured whilst connecting to the server: ") + resultData->ErrorMessage);
431 if (VerifyResultData(resultData))
433 lblConnectionResultText->SetLabel(_("Successfully connected to the server. Press Next to set the account name."));
434 btnNext->Enable(true);
438 btnNext->Enable(false);
442 btnPrevious->Enable(true);
445 resultData = nullptr;
448 bool frmNewAccount::VerifyResultData(NewAccountResult *resultData)
450 if (!resultData->Connected) return false;
451 if (!resultData->ValidResponse) return false;
452 if (chkUseSSL->GetValue())
454 if (!resultData->SSLStatus) return false;
455 if (resultData->SSLVerified != COSSL_VERIFIED) return false;
457 if (!resultData->AuthPassed) return false;
458 if (!resultData->CanProcess) return false;
463 void frmNewAccount::RunCalDAVTest( wxCommandEvent &event )
465 NewAccountResult *resultData = new NewAccountResult;
467 lblServerConnResult->SetLabel(_("Testing..."));
468 lblCalDAVSupportResult->SetLabel(wxT(""));
469 lblServerResponse->SetLabel(wxT(""));
470 lblServerSSLResult->SetLabel(wxT(""));
471 lblServerSSLValid->SetLabel(wxT(""));
472 lblAbleToLoginResult->SetLabel(wxT(""));
473 lblConnectionResultText->SetLabel(wxT(""));
474 bool usingSSLBypass = false;
476 // Setup a CalDAV connection object for testing.
478 CalDAVConnectionData connData;
479 connData.hostname = txtServerAddress->GetValue().ToStdString();
480 connData.port = wxAtoi(txtServerPort->GetValue());
481 connData.username = txtUsername->GetValue().ToStdString();
482 connData.password = txtPassword->GetValue().ToStdString();
483 connData.useSSL = chkUseSSL->GetValue() ? true : false;
485 CalDAV testConnection;
486 testConnection.SetupConnectionData(&connData);
488 /*CardDAV2 TestConnection(txtServerAddress->GetValue().ToStdString(),
489 wxAtoi(txtServerPort->GetValue()),
490 txtUsername->GetValue().ToStdString(),
491 txtPassword->GetValue().ToStdString(),
492 chkUseSSL->GetValue() ? true : false);*/
494 // Test the connection.
496 //testConnection.SetupConnectionObject();
497 CalDAVServerResult testConnectionResult = testConnection.Connect(false);
499 // If server is using SSL, verify that the SSL connection is valid.
501 if (testConnection.SSLVerify() == COSSL_UNABLETOVERIFY){
502 #if defined(__APPLE__)
504 testConnection.BypassSSLVerification(true);
506 CalDAVServerResult testConnection = testConnection.Connect(false);
508 testConnection.BypassSSLVerification(false);
510 int SSLResult = DisplayTrustPanel(&TestConnection);
512 if (SSLResult != NSOKButton){
514 lblServerConnResult->SetLabel(_("Failed"));
515 lblServerResponse->SetLabel(_("Not applicable"));
516 lblServerSSLResult->SetLabel(_("Used"));
517 lblServerSSLValid->SetLabel(_("No"));
518 lblConnectionResultText->SetLabel(_("An error occured whilst connnecting: ") + TestConnection.GetErrorMessage());
519 btnPrevious->Enable(true);
524 // Evalulate the trust object.
526 SecTrustResultType evalResult = ProcessResultType(&testConnection);
529 case kSecTrustResultProceed:
530 lblServerSSLValid->SetLabel(_("Verified"));
532 case kSecTrustResultConfirm:
533 lblServerSSLValid->SetLabel(_("Verified (user)"));
536 lblServerSSLValid->SetLabel(_("Unable to verify"));
539 lblServerResponse->SetLabel(_("Not applicable"));
540 lblServerSSLResult->SetLabel(_("Used"));
542 if (evalResult != kSecTrustResultProceed){
548 #elif defined(__WIN32__)
550 testConnection.BypassSSLVerification(true);
552 CalDAVServerResult testConnectionResult = testConnection.Connect(false);
554 testConnection.BypassSSLVerification(false);
556 bool modifiedCertificateData = false;
558 CRYPTUI_VIEWCERTIFICATE_STRUCTW certificateDialogData = BuildCertificateData(&testConnection, (HWND)this->GetHandle());
560 if (!CryptUIDlgViewCertificate(&certificateDialogData, &modifiedCertificateData)){
561 wxMessageBox(_("An error occured while trying to open the certificate dialog."), _("Error opening Certificate Information dialog"));
564 if (modifiedCertificateData == false){
566 lblServerConnResult->SetLabel(_("Failed"));
567 lblServerResponse->SetLabel(_("Not applicable"));
568 lblServerSSLResult->SetLabel(_("Used"));
569 lblServerSSLValid->SetLabel(_("No"));
570 lblConnectionResultText->SetLabel(_("An error occured whilst connnecting: ") + testConnection.GetErrorMessage());
571 btnPrevious->Enable(true);
578 // Connect again and fetch SSL certificate information.
580 testConnection.BypassSSLVerification(true);
582 CalDAVServerResult testConnectionResult = testConnection.Connect(false);
584 testConnection.BypassSSLVerification(false);
586 SSLCertCollectionString certData = testConnection.BuildSSLCollection();
587 frmInvalidSSLCertificate *frmICPtr = new frmInvalidSSLCertificate(this);
589 frmICPtr->LoadDataNew(certData, txtServerAddress->GetValue().ToStdString());
590 frmICPtr->ShowModal();
592 int sslResult = frmICPtr->GetResult();
594 // Clean up before processing response.
599 // Process the response from the user.
603 // Accept the Certificate.
605 usingSSLBypass = true;
606 testConnection.BypassSSLVerification(true);
608 CalDAVServerResult testConnectionResult = testConnection.Connect(true);
610 testConnection.BypassSSLVerification(false);
612 } else if (sslResult == 2){
614 // Reject the certificate, abort the task and mark as failed.
616 // TODO: Integrate into the code.
618 //lblConnectionResultText->SetLabel(_("An error occured whilst connnecting: ") + CardDAVConn.GetErrorMessage() + wxString::Format(wxT(" (%i)\n%s"), sslcode, CardDAVConn.GetErrorBuffer().mb_str()));
620 resultData->Connected = true;
621 resultData->SSLStatus = true;
622 resultData->SSLVerified = COSSL_UNABLETOVERIFY;
623 resultData->ValidResponse = false;
624 resultData->AuthPassed = false;
625 resultData->CanProcess = false;
626 resultData->ErrorMessage = _("Server is using self-signed certificate and was rejected.");
628 wxCommandEvent resultsEvent(UPDATERESULTS);
629 resultsEvent.SetClientData(resultData);
630 wxPostEvent(this, resultsEvent);
639 if (usingSSLBypass == true){
640 testConnection.BypassSSLVerification(true);
643 testConnectionResult = testConnection.Connect(true);
645 // Get the server prefix if the connection was successful.
647 if (testConnectionResult.result == CALDAVQUERYRESULT_OK){
649 std::string receivedServerPrefix;
651 receivedServerPrefix = testConnection.GetUserPrincipal();
652 serverPrefix = receivedServerPrefix;
656 CalDAVServerSupport testConnectionSupport = testConnection.GetServerSupport();
658 if (usingSSLBypass == true){
659 testConnection.BypassSSLVerification(false);
662 (testConnectionResult.result == CALDAVQUERYRESULT_OK || testConnectionResult.result == CALDAVQUERYRESULT_SSLFAILURE) ?
663 resultData->Connected = true : resultData->Connected = false;
665 resultData->SSLStatus = testConnection.CanDoSSL();
666 resultData->SSLVerified = testConnection.SSLVerify();
667 resultData->ValidResponse = testConnection.HasValidResponse();
668 resultData->AuthPassed = testConnection.AbleToLogin();
669 resultData->CanProcess = testConnectionSupport.basicSupport;
670 resultData->ErrorMessage = testConnection.GetErrorMessage();
672 // Post event back confirming the tests.
674 wxCommandEvent resultsEvent(UPDATERESULTS);
675 resultsEvent.SetClientData(resultData);
676 wxPostEvent(this, resultsEvent);