+// 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);
}