// frmNewAccount.cpp - New Account form.
//
// (c) 2012-2015 Xestia Software Development.
//
// This file is part of Xestia Address Book.
//
// Xestia Address Book 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 Address Book 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 Address Book. If not, see
#include "frmNewAccount.h"
#include
#include
#include
#include
#if defined(__WIN32__)
#include
#endif
#include "carddav/carddav.h"
#include "common/dirs.h"
#include "common/svrblist.h"
#include "common/win32ssl.h"
#include "frmInvalidSSLCertificate.h"
frmNewAccount::frmNewAccount( wxWindow* parent )
:
frmNewAccountADT( parent )
{
// Disable the previous button upon form creation.
btnPrevious->Disable();
}
void frmNewAccount::CheckAccountName( wxCommandEvent& event )
{
// 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 )
{
// Go to the previous page.
PageSeek--;
if (PageSeek == 0){
// Currently at the Connection test screen.
tabConn->Hide();
tabFinish->Hide();
tabType->Show();
szrNewAccount->RecalcSizes();
btnPrevious->Disable();
btnNext->Enable();
} else if (PageSeek == 1){
if (cmbServerType->GetCurrentSelection() == 0){
tabConn->Hide();
tabFinish->Hide();
tabType->Show();
PageSeek = 0;
btnPrevious->Disable();
btnNext->Enable();
btnNext->SetLabel(_("Next >"));
return;
}
// Currently at the Finish screen.
tabType->Hide();
tabConn->Show();
tabFinish->Hide();
szrNewAccount->RecalcSizes();
btnNext->SetLabel(_("Next >"));
btnNext->Enable();
}
}
void frmNewAccount::ProcessNext( wxCommandEvent& event )
{
// Go to the next page or setup the new account.
PageSeek++;
if (PageSeek == 1){
if (cmbServerType->GetCurrentSelection() == 0){
tabType->Hide();
tabConn->Hide();
tabFinish->Show();
PageSeek = 2;
btnPrevious->Enable();
szrNewAccount->RecalcSizes();
btnNext->Disable();
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 CardDAV 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();
bool ServerResult = FALSE;
bool ServerAction = FALSE;
bool UseSSL = TRUE;
wxString ServerMessage;
// Connection test screen.
tabType->Hide();
tabConn->Show();
tabFinish->Hide();
szrNewAccount->RecalcSizes();
btnPrevious->Enable();
// Reset screen.
lblServerConnResult->SetLabel(wxT(""));
lblServerResponse->SetLabel(wxT(""));
lblServerSSLResult->SetLabel(wxT(""));
lblServerSSLValid->SetLabel(wxT(""));
lblAbleToLoginResult->SetLabel(wxT(""));
lblCardDAVSupportResult->SetLabel(wxT(""));
// Spawn a thread and check if server supports CardDAV.
CardDAV CardDAVConn;
lblServerConnResult->SetLabel(_("Testing..."));
UseSSL = chkUseSSL->GetValue();
CardDAVConn.SetupConnection(txtServerAddress->GetValue(),
wxAtoi(txtServerPort->GetValue()),
txtUsername->GetValue(),
txtPassword->GetValue(),
UseSSL);
CardDAVConn.SetupResultBools(&ServerResult, &ServerAction);
#if defined(__WIN32__)
BOOL ModifiedCertificateData = FALSE;
#endif
// Verify SSL trust first before doing anything.
if (UseSSL == TRUE){
CURLcode sslcode = CardDAVConn.SSLVerifyTest();
if (sslcode == CURLE_OK){
} else if (sslcode == CURLE_SSL_CACERT || sslcode == CURLE_SSL_CONNECT_ERROR){
// Certificate is more than likely a self-signed or
// expired certificate so display the invalid
// SSL certificate message.
// Setup the data to be sent in the wxPostEvent command.
int SSLResult;
#if defined(__APPLE__)
SSLResult = DisplayTrustPanel(&CardDAVConn);
if (SSLResult != NSOKButton){
lblServerConnResult->SetLabel(_("Failed"));
lblServerResponse->SetLabel(_("Not applicable"));
lblServerSSLResult->SetLabel(_("Used"));
lblServerSSLValid->SetLabel(_("No"));
lblConnectionResultText->SetLabel(_("An error occured whilst connnecting: ") + CardDAVConn.GetErrorMessage() + wxString::Format(wxT(" (%i)\n%s"), sslcode, CardDAVConn.GetErrorBuffer().mb_str()));
return;
} else {
// Evalulate the trust object.
SecTrustResultType EvalResult = ProcessResultType(&CardDAVConn);
switch(EvalResult){
case kSecTrustResultProceed:
lblServerSSLValid->SetLabel(_("Verified"));
break;
case kSecTrustResultConfirm:
lblServerSSLValid->SetLabel(_("Verified (user)"));
break;
default:
lblServerSSLValid->SetLabel(_("Unable to verify"));
}
lblServerResponse->SetLabel(_("Not applicable"));
lblServerSSLResult->SetLabel(_("Used"));
if (EvalResult != kSecTrustResultProceed){
return;
}
}
#elif defined(__WIN32__)
CRYPTUI_VIEWCERTIFICATE_STRUCTW CertificateData = BuildCertificateData(&CardDAVConn, (HWND)this->GetHandle());
if (!CryptUIDlgViewCertificate(&CertificateData, &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: ") + CardDAVConn.GetErrorMessage() + wxString::Format(wxT(" (%i)\n%s"), sslcode, CardDAVConn.GetErrorBuffer().mb_str()));
return;
}
#else
frmInvalidSSLCertificate *frmICPtr = new frmInvalidSSLCertificate(this);
frmICPtr->LoadDataNew(CardDAVConn.GetSSLVerifyResults(), txtServerAddress->GetValue());
frmICPtr->ShowModal();
SSLResult = frmICPtr->GetResult();
// Clean up before processing response.
delete frmICPtr;
frmICPtr = NULL;
// Process the response from the user.
if (SSLResult == 1){
// Accept the Certificate.
CardDAVConn.AllowSelfSignTest(TRUE);
} else if (SSLResult == 2){
// Reject the certificate, abort the task and mark as failed.
lblServerConnResult->SetLabel(_("Failed"));
lblConnectionResultText->SetLabel(_("An error occured whilst connnecting: ") + CardDAVConn.GetErrorMessage() + wxString::Format(wxT(" (%i)\n%s"), sslcode, CardDAVConn.GetErrorBuffer().mb_str()));
return;
}
#endif
} else {
// Something else happened. Stop the process and
// display an error message instead.
CURLcode sslcode = CardDAVConn.SSLVerifyTest();
lblServerConnResult->SetLabel(_("Failed"));
lblConnectionResultText->SetLabel(_("An error occured whilst connnecting: ") + CardDAVConn.GetErrorMessage() + wxString::Format(wxT(" (%i)\n%s"), sslcode, CardDAVConn.GetErrorBuffer().mb_str()));
return;
}
}
std::thread ConnTest(&CardDAV::Connect, &CardDAVConn);
ConnTest.join();
if (ServerResult == FALSE && ModifiedCertificateData == FALSE){
lblServerConnResult->SetLabel(_("Failed"));
lblConnectionResultText->SetLabel(_("An error occured whilst connnecting: ") + CardDAVConn.GetErrorMessage());
return;
} else {
lblServerConnResult->SetLabel(_("Connected"));
}
if (CardDAVConn.CanDoSSL() == TRUE){
lblServerSSLResult->SetLabel(_("Used"));
} else {
lblServerSSLResult->SetLabel(_("Not Used"));
lblServerSSLValid->SetLabel(_("Not Applicable"));
}
#if defined(__APPLE__)
// Evalulate the trust object.
SecTrustResultType EvalResult = ProcessResultType(&CardDAVConn);
switch(EvalResult){
case kSecTrustResultProceed:
lblServerSSLValid->SetLabel(_("Verified"));
break;
case kSecTrustResultConfirm:
lblServerSSLValid->SetLabel(_("Verified (user)"));
break;
default:
lblServerSSLValid->SetLabel(_("Unable to verify"));
}
#elif defined(__WIN32__)
if (ModifiedCertificateData == TRUE){
lblServerSSLValid->SetLabel(_("Verified (user)"));
} else {
lblServerSSLValid->SetLabel(_("Verified"));
}
#else
if (CardDAVConn.SSLVerify() == TRUE && CardDAVConn.CanDoSSL() == TRUE){
lblServerSSLValid->SetLabel(_("Verified"));
} else if (CardDAVConn.SSLVerify() == FALSE && CardDAVConn.CanDoSSL() == TRUE && CardDAVConn.IsSelfSigned() == TRUE){
lblServerSSLValid->SetLabel(_("Verified (user)"));
} else if (CardDAVConn.SSLVerify() == FALSE && CardDAVConn.CanDoSSL() == TRUE) {
lblServerSSLValid->SetLabel(_("Unable to verify"));
}
#endif
if (CardDAVConn.CanDoCardDAV() == TRUE){
lblCardDAVSupportResult->SetLabel(_("Supported"));
} else {
lblCardDAVSupportResult->SetLabel(_("Unsupported"));
SetErrorMessageLabel();
return;
}
if (CardDAVConn.AbleToLogin() == TRUE){
lblAbleToLoginResult->SetLabel(_("Yes"));
} else {
lblAbleToLoginResult->SetLabel(_("No"));
SetErrorMessageLabel();
return;
}
// Get the address to process CardDAV requests.
ServerPrefix = CardDAVConn.GetDefaultAddressBookURL();
if (CardDAVConn.HasValidResponse() == TRUE){
lblServerResponse->SetLabel(_("Yes"));
} else {
lblServerResponse->SetLabel(_("No"));
SetErrorMessageLabel();
return;
}
if (ServerResult == TRUE && CardDAVConn.HasValidResponse() == TRUE &&
CardDAVConn.CanDoCardDAV() == TRUE && CardDAVConn.AbleToLogin() == TRUE){
btnNext->Enable();
lblConnectionResultText->SetLabel(_("Click on Next to set the account name."));
} else {
SetErrorMessageLabel();
}
} else if (PageSeek == 2){
// Finish screen.
tabType->Hide();
tabConn->Hide();
tabFinish->Show();
szrNewAccount->RecalcSizes();
btnNext->Disable();
btnNext->SetLabel(_("Finish"));
if (txtAccountName->IsEmpty() && PageSeek == 2){
btnNext->Disable();
} else {
btnNext->Enable();
}
} else if (PageSeek == 3){
// Finished.
wxString XestiaABPrefDirectory;
wxString XestiaABDirectory;
wxString AccountSettingsFile;
//wxFile ASFile;
wxString RandomNumberSuffix = wxString::Format(wxT("%i"), rand() % 32767);
bool DirectoryCreated = FALSE;
#if defined(__HAIKU__)
//preffilename = wxT("noo");
#elif defined(__WIN32__)
XestiaABPrefDirectory = GetUserPrefDir();
XestiaABDirectory = GetUserDir();
AccountSettingsFile = XestiaABPrefDirectory + 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);
}
if (cmbServerType->GetCurrentSelection() == 1){
// Create the account directory.
wxString DirectoryName = txtAccountName->GetValue().Mid(0, 30) + RandomNumberSuffix;
if (wxMkdir(XestiaABDirectory + wxT("\\accounts\\") + DirectoryName + wxT(".carddav"), 0740) == TRUE){
DirectoryCreated = TRUE;
}
if (DirectoryCreated == TRUE){
WriteAccountDetails(cfgfile, wxT("CardDAV"), DirectoryName);
} else {
wxMessageBox(_("An error occured whilst creating the account directory."), _("Cannot create account directory"));
return;
}
} else if (cmbServerType->GetCurrentSelection() == 0){
// Create the account directory.
wxString DirectoryName = txtAccountName->GetValue().Mid(0, 30) + RandomNumberSuffix;
if (wxMkdir(XestiaABDirectory + wxT("\\accounts\\") + DirectoryName + wxT(".local"), 0740) == TRUE){
DirectoryCreated = TRUE;
}
if (DirectoryCreated == TRUE){
WriteAccountDetails(cfgfile, wxT("Local"), DirectoryName);
} else {
wxMessageBox(_("An error occured whilst creating the account directory."), _("Cannot create account directory"));
return;
}
}
delete cfgfile;
cfgfile = NULL;
*ReloadAccountConfig = TRUE;
#else
XestiaABPrefDirectory = GetUserPrefDir();
XestiaABDirectory = GetUserDir();
AccountSettingsFile = XestiaABPrefDirectory + 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);
}
if (cmbServerType->GetCurrentSelection() == 1){
// Create the account directory.
wxString DirectoryName = txtAccountName->GetValue().Mid(0, 30) + RandomNumberSuffix;
if (wxMkdir(XestiaABDirectory + wxT("/accounts/") + DirectoryName + wxT(".carddav"), 0740) == TRUE){
DirectoryCreated = TRUE;
}
if (DirectoryCreated == TRUE){
WriteAccountDetails(cfgfile, wxT("CardDAV"), DirectoryName);
} else {
wxMessageBox(_("An error occured whilst creating the account directory."), _("Cannot create account directory"));
return;
}
} else if (cmbServerType->GetCurrentSelection() == 0){
// Create the account directory.
wxString DirectoryName = txtAccountName->GetValue().Mid(0, 30) + RandomNumberSuffix;
if (wxMkdir(XestiaABDirectory + wxT("/accounts/") + DirectoryName + wxT(".local"), 0740) == TRUE){
DirectoryCreated = TRUE;
}
if (DirectoryCreated == TRUE){
WriteAccountDetails(cfgfile, wxT("Local"), DirectoryName);
} else {
wxMessageBox(_("An error occured whilst creating the account directory."), _("Cannot create account directory"));
return;
}
}
delete cfgfile;
cfgfile = NULL;
*ReloadAccountConfig = TRUE;
#endif
this->Close();
}
}
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::CloseWindow( wxCommandEvent& event )
{
// Close the window.
*ReloadAccountConfig = FALSE;
this->Close();
}
void frmNewAccount::UpdateRequirements( wxCommandEvent& event )
{
// 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::SetupPointers(bool *ReloadAccountInc){
// Setup the pointers for the new account window.
ReloadAccountConfig = ReloadAccountInc;
}
void frmNewAccount::SetErrorMessageLabel(){
lblConnectionResultText->SetLabel(_("A problem has occured whilst connecting to the CardDAV server.\nPlease review the above information and change the server details if needed.\nIf there are still problems, please speak to your system administrator(s)."));
}