Home | News | Projects | Releases
Bugs | RFE | Repositories | Help
macOS: Implemented support for adding, editing and deleting a CalDAV account
[xestiacalendar/.git] / source / forms / newaccount / frmNewAccount.cpp
index 6baed82..c50cf84 100644 (file)
+// frmNewAccount.cpp - frmNewAccount form functions
+//
+// (c) 2016-2017 Xestia Software Development.
+//
+// This file is part of Xestia Calendar.
+//
+// Xestia Calendar is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by the
+// Free Software Foundation, version 3 of the license.
+//
+// Xestia Calendar is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with Xestia Calendar. If not, see <http://www.gnu.org/licenses/>
+
 #include "frmNewAccount.h"
 
+#if defined(__WIN32__)
+#include "../common/win32ssl.h"
+#endif
+
+DEFINE_EVENT_TYPE(UPDATERESULTS);
+DEFINE_EVENT_TYPE(RUNCALDAVTEST);
+
+BEGIN_EVENT_TABLE(frmNewAccount, wxDialog)
+EVT_COMMAND(wxID_ANY, UPDATERESULTS, frmNewAccount::UpdateResults)
+EVT_COMMAND(wxID_ANY, RUNCALDAVTEST, frmNewAccount::RunCalDAVTest)
+END_EVENT_TABLE()
+
 frmNewAccount::frmNewAccount( wxWindow* parent )
 :
 frmNewAccountADT( parent )
 {
 
+       // Disable the previous button upon form creation.
+
+       btnPrevious->Disable();
+       txtServerAddress->Disable();
+       txtServerPort->Disable();
+       txtUsername->Disable();
+       txtPassword->Disable();
+       chkUseSSL->Disable();
+       
 }
 
 void frmNewAccount::UpdateRequirements( wxCommandEvent& event )
 {
-// TODO: Implement UpdateRequirements
+       // Update the options.
+    
+       if (cmbServerType->GetCurrentSelection() == 1){
+        
+               txtServerAddress->Enable();
+               txtServerPort->Enable();
+               txtUsername->Enable();
+               txtPassword->Enable();
+               chkUseSSL->Enable();
+        
+       } else if (cmbServerType->GetCurrentSelection() == 0){
+        
+               txtServerAddress->Disable();
+               txtServerPort->Disable();
+               txtUsername->Disable();
+               txtPassword->Disable();
+               chkUseSSL->Disable();
+        
+       }
+}
+
+void frmNewAccount::Navigate( wxCommandEvent& event )
+{
+
+       if (event.GetId() == wxID_NEXT)
+               pageSeek++;
+       else
+               pageSeek--;
+    
+       if (pageSeek == 1){
+        
+               // Skip this page.
+
+               btnPrevious->Disable();
+               btnNext->Enable();
+
+               tabConn->Hide();
+               tabFinish->Hide();
+               tabType->Show();
+               btnNext->SetLabel(_("Next >"));
+        
+       } else if (pageSeek == 2){
+       
+               if (cmbServerType->GetCurrentSelection() == 0){
+            
+                       tabType->Hide();
+                       tabConn->Hide();
+                       tabFinish->Show();
+                       szrNewAccount->RecalcSizes();
+                       pageSeek = 2;
+                       
+                       btnNext->Disable();
+                       btnPrevious->Enable();
+                       btnNext->SetLabel(_("Finish"));
+                       return;
+            
+               }
+               
+               // Check if server address matches against the blacklist.
+               // Bring up warning message if it does.
+               
+               if (CheckBlacklist(txtServerAddress->GetValue())){
+               
+                       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);
+               
+                       if (MessageBoxResult == wxNO){
+                               pageSeek--;
+                               return;
+                       }
+                       
+               }
+               
+               btnNext->Disable();
+               btnNext->SetLabel(_("Next >"));
+        
+               bool ServerResult = FALSE;
+               bool ServerAction = FALSE;
+               bool UseSSL = TRUE;
+               wxString ServerMessage;
+        
+               // Connection test screen.
+        
+               tabType->Hide();
+               tabConn->Show();
+               tabFinish->Hide();
+               szrNewAccount->RecalcSizes();
+               btnPrevious->Disable();
+        
+               // Reset screen.
+        
+               lblServerConnResult->SetLabel(wxT(""));
+               lblServerResponse->SetLabel(wxT(""));
+               lblServerSSLResult->SetLabel(wxT(""));
+               lblServerSSLValid->SetLabel(wxT(""));
+               lblAbleToLoginResult->SetLabel(wxT(""));
+               lblCalDAVSupportResult->SetLabel(wxT(""));
+       
+               // Depending on account type, run the test.
+        
+               if (cmbServerType->GetCurrentSelection() == 1){
+                       wxCommandEvent RunTest(RUNCALDAVTEST);
+                       wxPostEvent(this, RunTest);
+               }
+       
+       } else if (pageSeek == 3){
+        
+               // Finish screen.
+        
+               tabType->Hide();
+               tabConn->Hide();
+               tabFinish->Show();
+               szrNewAccount->RecalcSizes();
+
+               btnPrevious->Enable();
+               btnNext->SetLabel(_("Finish"));
+       
+               if (txtAccountName->IsEmpty() || txtAccountName->GetValue().Len() < 4 && pageSeek == 3){
+       
+                       btnNext->Disable();
+           
+               } else {
+       
+                       btnNext->Enable();
+           
+               }
+        
+       } else if (pageSeek == 4){
+        
+               // Finished.
+        
+               wxString xestiaCALPrefDirectory;
+               wxString xestiaCALDirectory;
+               wxString accountSettingsFile;
+               //wxFile ASFile;
+               
+               srand(time(0));
+               int randomNumber = rand() % 32767;
+               wxString randomNumberSuffix = wxString::Format(wxT("%i"), randomNumber);
+               bool directoryCreated = FALSE;
+        
+#if defined(__HAIKU__)
+        
+               //preffilename = wxT("noo");
+        
+#elif defined(__WIN32__)
+        
+               xestiaCALPrefDirectory = GetUserPrefDir();
+               xestiaCALDirectory = GetUserDir();
+       
+               accountSettingsFile = xestiaCALPrefDirectory + wxT("accounts");
+        
+               // Open the file for writing.
+        
+               wxFileConfig *cfgFile = new wxFileConfig("", "", accountSettingsFile);
+        
+               // Check if account name already exists and return an error message
+               // if this is the case.
+        
+               wxString accountName;
+               long itemIndex = 0;
+               bool continueAcc;
+               continueAcc = cfgFile->GetFirstGroup(accountName, itemIndex);
+        
+               while (continueAcc){
+            
+                       if (txtAccountName->GetValue() == accountName){
+                
+                               wxMessageBox(_("The selected account name is already used, please use another account name."), _("Account name already used"), wxICON_ERROR);
+                               return;
+                
+                       }
+            
+                       cfgFile->SetPath(wxT("/"));
+                       continueAcc = cfgFile->GetNextGroup(accountName, itemIndex);
+            
+               }
+        
+               wxString directoryName = txtAccountName->GetValue().Mid(0, 30) + randomNumberSuffix;
+       
+               if (cmbServerType->GetCurrentSelection() == 0){
+            
+                       // Create the account directory.
+            
+                       if (wxMkdir(xestiaCALDirectory + wxT("\\accounts\\") + directoryName + wxT(".Local"), 0740) == true){
+                
+                               WriteAccountDetails(cfgFile, wxT("Local"), directoryName);
+                
+                       } else {
+                
+                               wxMessageBox(_("An error occured whilst creating the account directory."), _("Cannot create account directory"));
+                               return;
+                
+                       }
+            
+               } else if (cmbServerType->GetCurrentSelection() == 1){
+                                               
+                       // Create the account directory.
+            
+                       if (wxMkdir(xestiaCALDirectory + wxT("\\accounts\\") + directoryName + wxT(".CalDAV"), 0740) == true){
+                
+                               WriteAccountDetails(cfgFile, wxT("CalDAV"), directoryName);
+                
+                       } else {
+                
+                               wxMessageBox(_("An error occured whilst creating the account directory."), _("Cannot create account directory"));
+                               return;
+                
+                       }
+                       
+               }
+        
+               delete cfgFile;
+               cfgFile = NULL;
+        
+               *reloadAccountConfig = TRUE;
+        
+#else
+        
+               xestiaCALPrefDirectory = GetUserPrefDir();
+               xestiaCALDirectory = GetUserDir();
+        
+               accountSettingsFile = xestiaCALPrefDirectory + wxT("accounts");
+        
+               // Open the file for writing.
+        
+               wxFileConfig *cfgFile = new wxFileConfig("", "", accountSettingsFile);
+        
+               // Check if account name already exists and return an error message
+               // if this is the case.
+        
+               wxString accountName;
+               long itemIndex = 0;
+               bool continueAcc;
+               continueAcc = cfgFile->GetFirstGroup(accountName, itemIndex);
+        
+               while (continueAcc){
+            
+                       if (txtAccountName->GetValue() == accountName){
+                
+                               wxMessageBox(_("The selected account name is already used, please use another account name."), _("Account name already used"), wxICON_ERROR);
+                               return;
+                
+                       }
+            
+                       cfgFile->SetPath(wxT("/"));
+                       continueAcc = cfgFile->GetNextGroup(accountName, itemIndex);
+            
+               }
+
+               wxString directoryName = txtAccountName->GetValue().Mid(0, 30) + randomNumberSuffix;
+        
+               if (cmbServerType->GetCurrentSelection() == 0){
+            
+                       // Create the account directory.
+            
+                       if (wxMkdir(xestiaCALDirectory + wxT("/accounts/") + directoryName + wxT(".Local"), 0740) == true){
+                
+                               WriteAccountDetails(cfgFile, wxT("Local"), directoryName);
+                       
+                       } else {
+                
+                               wxMessageBox(_("An error occured whilst creating the account directory."), _("Cannot create account directory"));
+                               return;
+                
+                       }
+            
+               } else if (cmbServerType->GetCurrentSelection() == 1){
+            
+                       // Create the account directory.
+            
+                       wxString directoryName = txtAccountName->GetValue().Mid(0, 30) + randomNumberSuffix;
+            
+                       if (wxMkdir(xestiaCALDirectory + wxT("/accounts/") + directoryName + wxT(".CalDAV"), 0740) == true){
+                
+                               WriteAccountDetails(cfgFile, wxT("CalDAV"), directoryName);
+                       
+                       } else {
+                
+                               wxMessageBox(_("An error occured whilst creating the account directory."), _("Cannot create account directory"));
+                               return;
+                
+                       }
+            
+               }
+        
+               delete cfgFile;
+               cfgFile = nullptr;
+        
+               *reloadAccountConfig = true;
+               
+#endif
+        
+               this->Close();
+        
+       }
+       
+}
+
+void frmNewAccount::CloseWindow( wxCommandEvent& event )
+{
+       
+       // Close the window.
+
+       *reloadAccountConfig = FALSE;
+       this->Close();
+       
+}
+
+void frmNewAccount::SetupPointers(bool *ReloadAccountInc, CalendarDataStorage *dataStorage){
+
+       // Setup the pointers for the new account window.
+   
+       reloadAccountConfig = ReloadAccountInc;
+    
 }
 
 void frmNewAccount::CheckAccountName( wxCommandEvent& event )
 {
-// TODO: Implement CheckAccountName
+    
+       // Check that the account name is valid.
+    
+       wxString checkAccName = txtAccountName->GetValue();
+    
+       if ((txtAccountName->IsEmpty() && pageSeek == 2) || checkAccName.Len() < 4){
+        
+               btnNext->Disable();
+        
+       } else {
+        
+               btnNext->Enable();
+        
+       }
+    
 }
 
-void frmNewAccount::ProcessPrevious( wxCommandEvent& event )
+void frmNewAccount::WriteAccountDetails(wxFileConfig *cfgFileIn, wxString accountType, wxString directoryName){
+    
+       // Write the new account details.
+    
+       cfgFileIn->SetPath(txtAccountName->GetValue());
+       cfgFileIn->Write(wxT("address"), txtServerAddress->GetValue());
+       cfgFileIn->Write(wxT("port"), txtServerPort->GetValue());
+       cfgFileIn->Write(wxT("username"), txtUsername->GetValue());
+       cfgFileIn->Write(wxT("password"), txtPassword->GetValue());
+       cfgFileIn->Write(wxT("prefix"), serverPrefix);
+       cfgFileIn->Write(wxT("accountdir"), directoryName);
+    
+       if (chkUseSSL->GetValue() == TRUE){
+        
+               cfgFileIn->Write(wxT("ssl"), wxT("true"));
+        
+       } else {
+        
+               cfgFileIn->Write(wxT("ssl"), wxT("false"));
+        
+       }
+    
+       cfgFileIn->Write(wxT("refresh"), wxT("1800"));
+       cfgFileIn->Write(wxT("type"), accountType);
+    
+}
+
+void frmNewAccount::UpdateResults( wxCommandEvent &event )
 {
-// TODO: Implement ProcessPrevious
+       NewAccountResult *resultData = static_cast<NewAccountResult*>(event.GetClientData());
+
+       lblServerConnResult->SetLabel((resultData->Connected ? _("Successful") : _("Failed")));
+       lblServerResponse->SetLabel((resultData->ValidResponse ? _("Yes") : _("No")));
+       if (chkUseSSL->GetValue())
+       {
+               lblServerSSLResult->SetLabel((resultData->SSLStatus ? _("Yes") : _("No")));
+               lblServerSSLValid->SetLabel((resultData->SSLVerified == COSSL_VERIFIED ? _("Yes") : _("No")));
+       } else {
+               lblServerSSLResult->SetLabel(_("Not Applicable"));
+               lblServerSSLValid->SetLabel(_("Not Applicable"));
+       }
+       lblAbleToLoginResult->SetLabel((resultData->AuthPassed ? _("Yes") : _("No")));
+       lblCalDAVSupportResult->SetLabel((resultData->CanProcess ? _("Yes") : _("No")));
+       
+       if (resultData->ErrorMessage != "")
+       {
+               lblConnectionResultText->SetLabel(_("An error occured whilst connecting to the server: ") + resultData->ErrorMessage);
+       }
+       
+       if (VerifyResultData(resultData))
+       {
+               lblConnectionResultText->SetLabel(_("Successfully connected to the server. Press Next to set the account name."));
+               btnNext->Enable(true);
+       }
+       else
+       {
+               btnNext->Enable(false);
+       }
+       
+       tabConn->Layout();
+       btnPrevious->Enable(true);
+       
+       delete resultData;
+       resultData = nullptr;
 }
 
-void frmNewAccount::ProcessNext( wxCommandEvent& event )
+bool frmNewAccount::VerifyResultData(NewAccountResult *resultData)
 {
-// TODO: Implement ProcessNext
+       if (!resultData->Connected) return false;
+       if (!resultData->ValidResponse) return false;
+       if (chkUseSSL->GetValue())
+       {
+               if (!resultData->SSLStatus) return false;
+               if (resultData->SSLVerified != COSSL_VERIFIED) return false;
+       }
+       if (!resultData->AuthPassed) return false;
+       if (!resultData->CanProcess) return false;
+       
+       return true;
 }
 
-void frmNewAccount::CloseWindow( wxCommandEvent& event )
+void frmNewAccount::RunCalDAVTest( wxCommandEvent &event )
 {
-// TODO: Implement CloseWindow
+       NewAccountResult *resultData = new NewAccountResult;
+       
+       lblServerConnResult->SetLabel(_("Testing..."));
+       lblCalDAVSupportResult->SetLabel(wxT(""));
+       lblServerResponse->SetLabel(wxT(""));
+       lblServerSSLResult->SetLabel(wxT(""));
+       lblServerSSLValid->SetLabel(wxT(""));
+       lblAbleToLoginResult->SetLabel(wxT(""));
+       lblConnectionResultText->SetLabel(wxT(""));
+       bool usingSSLBypass = false;
+       
+       // Setup a CalDAV connection object for testing.
+
+       CalDAVConnectionData connData;
+       connData.hostname = txtServerAddress->GetValue().ToStdString();
+       connData.port = wxAtoi(txtServerPort->GetValue());
+       connData.username = txtUsername->GetValue().ToStdString();
+       connData.password = txtPassword->GetValue().ToStdString();
+       connData.useSSL = chkUseSSL->GetValue() ? true : false;
+
+       CalDAV testConnection;
+       testConnection.SetupConnectionData(&connData);
+
+       /*CardDAV2 TestConnection(txtServerAddress->GetValue().ToStdString(),
+               wxAtoi(txtServerPort->GetValue()),
+               txtUsername->GetValue().ToStdString(),
+               txtPassword->GetValue().ToStdString(),
+               chkUseSSL->GetValue() ? true : false);*/
+       
+       // Test the connection.
+       
+       //testConnection.SetupConnectionObject();
+       CalDAVServerResult testConnectionResult = testConnection.Connect(false);
+       
+       // If server is using SSL, verify that the SSL connection is valid.
+       
+       if (testConnection.SSLVerify() == COSSL_UNABLETOVERIFY){
+#if defined(__APPLE__)
+        
+               testConnection.BypassSSLVerification(true);
+               
+               CalDAVServerResult testConnectionResult = testConnection.Connect(false);
+               
+               testConnection.BypassSSLVerification(false);
+               
+               int SSLResult = DisplayTrustPanel(&testConnection);
+               
+               if (SSLResult != NSOKButton){
+                       
+                       lblServerConnResult->SetLabel(_("Failed"));
+                       lblServerResponse->SetLabel(_("Not applicable"));
+                       lblServerSSLResult->SetLabel(_("Used"));
+                       lblServerSSLValid->SetLabel(_("No"));
+                       lblConnectionResultText->SetLabel(_("An error occured whilst connnecting: ") + testConnection.GetErrorMessage());
+                       btnPrevious->Enable(true);
+                       return;
+                       
+               } else {
+                       
+                       // Evalulate the trust object.
+                       
+                       SecTrustResultType evalResult = ProcessResultType(&testConnection);
+                       
+                       switch(evalResult){
+                               case kSecTrustResultProceed:
+                                       lblServerSSLValid->SetLabel(_("Verified"));
+                    break;
+                case kSecTrustResultUnspecified:
+                               case kSecTrustResultConfirm:
+                                       lblServerSSLValid->SetLabel(_("Verified (user)"));
+                                       break;
+                               default:
+                                       lblServerSSLValid->SetLabel(_("Unable to verify"));
+                       }
+                       
+            lblServerConnResult->SetLabel(_("Connected"));
+                       lblServerResponse->SetLabel(_("Not applicable"));
+                       lblServerSSLResult->SetLabel(_("Used"));
+                       
+            btnPrevious->Enable(true);
+            
+                       if (evalResult != kSecTrustResultProceed && evalResult != kSecTrustResultUnspecified){
+                lblConnectionResultText->SetLabel(_("An error occured whilst connnecting: ") + testConnection.GetErrorMessage());
+                               return;
+                       }
+                       
+               }
+               
+#elif defined(__WIN32__)
+
+               testConnection.BypassSSLVerification(true);
+
+               CalDAVServerResult testConnectionResult = testConnection.Connect(false);
+
+               testConnection.BypassSSLVerification(false);
+
+               BOOL modifiedCertificateData = false;
+
+               CRYPTUI_VIEWCERTIFICATE_STRUCTW certificateDialogData = BuildCertificateData(&testConnection, (HWND)this->GetHandle());
+
+               if (!CryptUIDlgViewCertificate(&certificateDialogData, &modifiedCertificateData)){
+                       wxMessageBox(_("An error occured while trying to open the certificate dialog."), _("Error opening Certificate Information dialog"));
+               }
+
+               if (modifiedCertificateData == false){
+
+                       lblServerConnResult->SetLabel(_("Failed"));
+                       lblServerResponse->SetLabel(_("Not applicable"));
+                       lblServerSSLResult->SetLabel(_("Used"));
+                       lblServerSSLValid->SetLabel(_("No"));
+                       lblConnectionResultText->SetLabel(_("An error occured whilst connnecting: ") + testConnection.GetErrorMessage());
+                       btnPrevious->Enable(true);
+                       return;
+
+               }
+
+#else
+       
+               // Connect again and fetch SSL certificate information.
+               
+               testConnection.BypassSSLVerification(true);
+               
+               CalDAVServerResult testConnectionResult = testConnection.Connect(false);
+               
+               testConnection.BypassSSLVerification(false);
+
+               SSLCertCollectionString certData = testConnection.BuildSSLCollection();
+               frmInvalidSSLCertificate *frmICPtr = new frmInvalidSSLCertificate(this);
+               
+               frmICPtr->LoadDataNew(certData, txtServerAddress->GetValue().ToStdString());
+               frmICPtr->ShowModal();
+                                                               
+               int sslResult = frmICPtr->GetResult();
+                                                       
+               // Clean up before processing response.
+                               
+               delete frmICPtr;
+               frmICPtr = nullptr;
+                                                       
+               // Process the response from the user.
+                                                       
+               if (sslResult == 1){
+                                                               
+                       // Accept the Certificate.
+                       
+                       usingSSLBypass = true;
+                       testConnection.BypassSSLVerification(true);
+               
+                       CalDAVServerResult testConnectionResult = testConnection.Connect(true);
+               
+                       testConnection.BypassSSLVerification(false);
+                                                               
+               } else if (sslResult == 2){
+                                                               
+                       // Reject the certificate, abort the task and mark as failed.
+
+                       // TODO: Integrate into the code.
+                       
+                       //lblConnectionResultText->SetLabel(_("An error occured whilst connnecting: ") + CardDAVConn.GetErrorMessage() + wxString::Format(wxT(" (%i)\n%s"), sslcode, CardDAVConn.GetErrorBuffer().mb_str()));
+                       
+                       resultData->Connected = true;
+                       resultData->SSLStatus = true;
+                       resultData->SSLVerified = COSSL_UNABLETOVERIFY;
+                       resultData->ValidResponse = false;
+                       resultData->AuthPassed = false;
+                       resultData->CanProcess = false;
+                       resultData->ErrorMessage = _("Server is using self-signed certificate and was rejected.");
+                       
+                       wxCommandEvent resultsEvent(UPDATERESULTS);
+                       resultsEvent.SetClientData(resultData);
+                       wxPostEvent(this, resultsEvent);
+                       
+                       return;
+                                               
+               }               
+               
+#endif
+       }
+       
+       if (usingSSLBypass == true){
+               testConnection.BypassSSLVerification(true);                     
+       }
+       
+       testConnectionResult = testConnection.Connect(true);
+
+       // Get the server prefix if the connection was successful.
+       
+       if (testConnectionResult.result == CALDAVQUERYRESULT_OK){
+               
+               std::string receivedServerPrefix;
+               
+               receivedServerPrefix = testConnection.GetUserPrincipal();
+               serverPrefix = receivedServerPrefix;
+               
+       }
+       
+       CalDAVServerSupport testConnectionSupport = testConnection.GetServerSupport();
+       
+       if (usingSSLBypass == true){
+               testConnection.BypassSSLVerification(false);
+       }
+       
+       (testConnectionResult.result == CALDAVQUERYRESULT_OK || testConnectionResult.result == CALDAVQUERYRESULT_SSLFAILURE) ? 
+               resultData->Connected = true : resultData->Connected = false;
+       
+       resultData->SSLStatus = testConnection.CanDoSSL();
+       resultData->SSLVerified = testConnection.SSLVerify();
+       resultData->ValidResponse = testConnection.HasValidResponse();
+       resultData->AuthPassed = testConnection.AbleToLogin();
+       resultData->CanProcess = testConnectionSupport.basicSupport;
+       resultData->ErrorMessage = testConnection.GetErrorMessage();
+       
+       // Post event back confirming the tests.
+       
+       wxCommandEvent resultsEvent(UPDATERESULTS);
+       resultsEvent.SetClientData(resultData);
+       wxPostEvent(this, resultsEvent);
 }
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