1 // frmNewAccount.cpp - New Account form.
3 // (c) 2012-2015 Xestia Software Development.
5 // This file is part of Xestia Address Book.
7 // Xestia Address Book 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 Address Book 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 Address Book. If not, see <http://www.gnu.org/licenses/>
19 #include "frmNewAccount.h"
22 #include <wx/filefn.h>
23 #include <wx/fileconf.h>
25 #if defined(__WIN32__)
26 #include <cryptuiapi.h>
27 #include "common/win32ssl.h"
30 #include "carddav/carddav.h"
31 #include "common/dirs.h"
32 #include "common/svrblist.h"
33 #include "frmInvalidSSLCertificate.h"
35 frmNewAccount::frmNewAccount( wxWindow* parent )
37 frmNewAccountADT( parent )
40 // Disable the previous button upon form creation.
42 btnPrevious->Disable();
46 void frmNewAccount::CheckAccountName( wxCommandEvent& event )
49 // Check that the account name is valid.
51 wxString CheckAccName = txtAccountName->GetValue();
53 if ((txtAccountName->IsEmpty() && PageSeek == 2) || CheckAccName.Len() < 4){
65 void frmNewAccount::ProcessPrevious( wxCommandEvent& event )
68 // Go to the previous page.
74 // Currently at the Connection test screen.
79 szrNewAccount->RecalcSizes();
81 btnPrevious->Disable();
84 } else if (PageSeek == 1){
86 if (cmbServerType->GetCurrentSelection() == 0){
92 btnPrevious->Disable();
94 btnNext->SetLabel(_("Next >"));
99 // Currently at the Finish screen.
104 szrNewAccount->RecalcSizes();
106 btnNext->SetLabel(_("Next >"));
113 void frmNewAccount::ProcessNext( wxCommandEvent& event )
116 // Go to the next page or setup the new account.
122 if (cmbServerType->GetCurrentSelection() == 0){
128 btnPrevious->Enable();
129 szrNewAccount->RecalcSizes();
131 btnNext->SetLabel(_("Finish"));
136 // Check if server address matches against the blacklist.
137 // Bring up warning message if it does.
139 if (CheckBlacklist(txtServerAddress->GetValue())){
141 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);
143 if (MessageBoxResult == wxNO){
152 bool ServerResult = FALSE;
153 bool ServerAction = FALSE;
155 wxString ServerMessage;
157 // Connection test screen.
162 szrNewAccount->RecalcSizes();
163 btnPrevious->Enable();
167 lblServerConnResult->SetLabel(wxT(""));
168 lblServerResponse->SetLabel(wxT(""));
169 lblServerSSLResult->SetLabel(wxT(""));
170 lblServerSSLValid->SetLabel(wxT(""));
171 lblAbleToLoginResult->SetLabel(wxT(""));
172 lblCardDAVSupportResult->SetLabel(wxT(""));
174 // Spawn a thread and check if server supports CardDAV.
178 lblServerConnResult->SetLabel(_("Testing..."));
180 UseSSL = chkUseSSL->GetValue();
181 CardDAVConn.SetupConnection(txtServerAddress->GetValue(),
182 wxAtoi(txtServerPort->GetValue()),
183 txtUsername->GetValue(),
184 txtPassword->GetValue(),
186 CardDAVConn.SetupResultBools(&ServerResult, &ServerAction);
188 #if defined(__WIN32__)
190 BOOL ModifiedCertificateData = FALSE;
194 // Verify SSL trust first before doing anything.
198 CURLcode sslcode = CardDAVConn.SSLVerifyTest();
200 if (sslcode == CURLE_OK){
204 } else if (sslcode == CURLE_SSL_CACERT || sslcode == CURLE_SSL_CONNECT_ERROR){
206 // Certificate is more than likely a self-signed or
207 // expired certificate so display the invalid
208 // SSL certificate message.
210 // Setup the data to be sent in the wxPostEvent command.
214 #if defined(__APPLE__)
216 SSLResult = DisplayTrustPanel(&CardDAVConn);
218 if (SSLResult != NSOKButton){
220 lblServerConnResult->SetLabel(_("Failed"));
221 lblServerResponse->SetLabel(_("Not applicable"));
222 lblServerSSLResult->SetLabel(_("Used"));
223 lblServerSSLValid->SetLabel(_("No"));
224 lblConnectionResultText->SetLabel(_("An error occured whilst connnecting: ") + CardDAVConn.GetErrorMessage() + wxString::Format(wxT(" (%i)\n%s"), sslcode, CardDAVConn.GetErrorBuffer().mb_str()));
229 // Evalulate the trust object.
231 SecTrustResultType EvalResult = ProcessResultType(&CardDAVConn);
234 case kSecTrustResultProceed:
235 lblServerSSLValid->SetLabel(_("Verified"));
237 case kSecTrustResultConfirm:
238 lblServerSSLValid->SetLabel(_("Verified (user)"));
241 lblServerSSLValid->SetLabel(_("Unable to verify"));
244 lblServerResponse->SetLabel(_("Not applicable"));
245 lblServerSSLResult->SetLabel(_("Used"));
247 if (EvalResult != kSecTrustResultProceed){
253 #elif defined(__WIN32__)
255 CRYPTUI_VIEWCERTIFICATE_STRUCTW CertificateData = BuildCertificateData(&CardDAVConn, (HWND)this->GetHandle());
257 if (!CryptUIDlgViewCertificate(&CertificateData, &ModifiedCertificateData)){
258 wxMessageBox(_("An error occured while trying to open the certificate dialog."), _("Error opening Certificate Information dialog"));
261 if (ModifiedCertificateData == FALSE){
263 lblServerConnResult->SetLabel(_("Failed"));
264 lblServerResponse->SetLabel(_("Not applicable"));
265 lblServerSSLResult->SetLabel(_("Used"));
266 lblServerSSLValid->SetLabel(_("No"));
267 lblConnectionResultText->SetLabel(_("An error occured whilst connnecting: ") + CardDAVConn.GetErrorMessage() + wxString::Format(wxT(" (%i)\n%s"), sslcode, CardDAVConn.GetErrorBuffer().mb_str()));
274 frmInvalidSSLCertificate *frmICPtr = new frmInvalidSSLCertificate(this);
276 frmICPtr->LoadDataNew(CardDAVConn.GetSSLVerifyResults(), txtServerAddress->GetValue());
277 frmICPtr->ShowModal();
279 SSLResult = frmICPtr->GetResult();
281 // Clean up before processing response.
286 // Process the response from the user.
290 // Accept the Certificate.
292 CardDAVConn.AllowSelfSignTest(TRUE);
294 } else if (SSLResult == 2){
296 // Reject the certificate, abort the task and mark as failed.
298 lblServerConnResult->SetLabel(_("Failed"));
299 lblConnectionResultText->SetLabel(_("An error occured whilst connnecting: ") + CardDAVConn.GetErrorMessage() + wxString::Format(wxT(" (%i)\n%s"), sslcode, CardDAVConn.GetErrorBuffer().mb_str()));
308 // Something else happened. Stop the process and
309 // display an error message instead.
311 CURLcode sslcode = CardDAVConn.SSLVerifyTest();
313 lblServerConnResult->SetLabel(_("Failed"));
314 lblConnectionResultText->SetLabel(_("An error occured whilst connnecting: ") + CardDAVConn.GetErrorMessage() + wxString::Format(wxT(" (%i)\n%s"), sslcode, CardDAVConn.GetErrorBuffer().mb_str()));
321 std::thread ConnTest(&CardDAV::Connect, &CardDAVConn);
325 #if defined(__WIN32__)
326 if (ServerResult == FALSE && ModifiedCertificateData == FALSE){
328 if (ServerResult == FALSE){
331 lblServerConnResult->SetLabel(_("Failed"));
332 lblConnectionResultText->SetLabel(_("An error occured whilst connnecting: ") + CardDAVConn.GetErrorMessage());
337 lblServerConnResult->SetLabel(_("Connected"));
341 if (CardDAVConn.CanDoSSL() == TRUE){
343 lblServerSSLResult->SetLabel(_("Used"));
347 lblServerSSLResult->SetLabel(_("Not Used"));
348 lblServerSSLValid->SetLabel(_("Not Applicable"));
352 #if defined(__APPLE__)
354 // Evalulate the trust object.
356 SecTrustResultType EvalResult = ProcessResultType(&CardDAVConn);
359 case kSecTrustResultProceed:
360 lblServerSSLValid->SetLabel(_("Verified"));
362 case kSecTrustResultConfirm:
363 lblServerSSLValid->SetLabel(_("Verified (user)"));
366 lblServerSSLValid->SetLabel(_("Unable to verify"));
369 #elif defined(__WIN32__)
371 if (ModifiedCertificateData == TRUE){
372 lblServerSSLValid->SetLabel(_("Verified (user)"));
374 lblServerSSLValid->SetLabel(_("Verified"));
379 if (CardDAVConn.SSLVerify() == TRUE && CardDAVConn.CanDoSSL() == TRUE){
381 lblServerSSLValid->SetLabel(_("Verified"));
383 } else if (CardDAVConn.SSLVerify() == FALSE && CardDAVConn.CanDoSSL() == TRUE && CardDAVConn.IsSelfSigned() == TRUE){
385 lblServerSSLValid->SetLabel(_("Verified (user)"));
387 } else if (CardDAVConn.SSLVerify() == FALSE && CardDAVConn.CanDoSSL() == TRUE) {
389 lblServerSSLValid->SetLabel(_("Unable to verify"));
395 if (CardDAVConn.CanDoCardDAV() == TRUE){
397 lblCardDAVSupportResult->SetLabel(_("Supported"));
401 lblCardDAVSupportResult->SetLabel(_("Unsupported"));
402 SetErrorMessageLabel();
407 if (CardDAVConn.AbleToLogin() == TRUE){
409 lblAbleToLoginResult->SetLabel(_("Yes"));
413 lblAbleToLoginResult->SetLabel(_("No"));
414 SetErrorMessageLabel();
419 // Get the address to process CardDAV requests.
421 ServerPrefix = CardDAVConn.GetDefaultAddressBookURL();
423 if (CardDAVConn.HasValidResponse() == TRUE){
425 lblServerResponse->SetLabel(_("Yes"));
429 lblServerResponse->SetLabel(_("No"));
430 SetErrorMessageLabel();
435 if (ServerResult == TRUE && CardDAVConn.HasValidResponse() == TRUE &&
437 CardDAVConn.CanDoCardDAV() == TRUE && CardDAVConn.AbleToLogin() == TRUE){
441 lblConnectionResultText->SetLabel(_("Click on Next to set the account name."));
445 SetErrorMessageLabel();
449 } else if (PageSeek == 2){
456 szrNewAccount->RecalcSizes();
459 btnNext->SetLabel(_("Finish"));
461 if (txtAccountName->IsEmpty() && PageSeek == 2){
471 } else if (PageSeek == 3){
475 wxString XestiaABPrefDirectory;
476 wxString XestiaABDirectory;
477 wxString AccountSettingsFile;
479 wxString RandomNumberSuffix = wxString::Format(wxT("%i"), rand() % 32767);
480 bool DirectoryCreated = FALSE;
482 #if defined(__HAIKU__)
484 //preffilename = wxT("noo");
486 #elif defined(__WIN32__)
488 XestiaABPrefDirectory = GetUserPrefDir();
489 XestiaABDirectory = GetUserDir();
491 AccountSettingsFile = XestiaABPrefDirectory + wxT("accounts");
493 // Open the file for writing.
495 wxFileConfig *cfgfile = new wxFileConfig("", "", AccountSettingsFile);
497 // Check if account name already exists and return an error message
498 // if this is the case.
500 wxString AccountName;
503 ContinueAcc = cfgfile->GetFirstGroup(AccountName, itemindex);
507 if (txtAccountName->GetValue() == AccountName){
509 wxMessageBox(_("The selected account name is already used, please use another account name."), _("Account name already used"), wxICON_ERROR);
514 cfgfile->SetPath(wxT("/"));
515 ContinueAcc = cfgfile->GetNextGroup(AccountName, itemindex);
519 if (cmbServerType->GetCurrentSelection() == 1){
521 // Create the account directory.
523 wxString DirectoryName = txtAccountName->GetValue().Mid(0, 30) + RandomNumberSuffix;
525 if (wxMkdir(XestiaABDirectory + wxT("\\accounts\\") + DirectoryName + wxT(".carddav"), 0740) == TRUE){
527 DirectoryCreated = TRUE;
531 if (DirectoryCreated == TRUE){
533 WriteAccountDetails(cfgfile, wxT("CardDAV"), DirectoryName);
537 wxMessageBox(_("An error occured whilst creating the account directory."), _("Cannot create account directory"));
542 } else if (cmbServerType->GetCurrentSelection() == 0){
544 // Create the account directory.
546 wxString DirectoryName = txtAccountName->GetValue().Mid(0, 30) + RandomNumberSuffix;
548 if (wxMkdir(XestiaABDirectory + wxT("\\accounts\\") + DirectoryName + wxT(".local"), 0740) == TRUE){
550 DirectoryCreated = TRUE;
554 if (DirectoryCreated == TRUE){
556 WriteAccountDetails(cfgfile, wxT("Local"), DirectoryName);
560 wxMessageBox(_("An error occured whilst creating the account directory."), _("Cannot create account directory"));
570 *ReloadAccountConfig = TRUE;
574 XestiaABPrefDirectory = GetUserPrefDir();
575 XestiaABDirectory = GetUserDir();
577 AccountSettingsFile = XestiaABPrefDirectory + wxT("accounts");
579 // Open the file for writing.
581 wxFileConfig *cfgfile = new wxFileConfig("", "", AccountSettingsFile);
583 // Check if account name already exists and return an error message
584 // if this is the case.
586 wxString AccountName;
589 ContinueAcc = cfgfile->GetFirstGroup(AccountName, itemindex);
593 if (txtAccountName->GetValue() == AccountName){
595 wxMessageBox(_("The selected account name is already used, please use another account name."), _("Account name already used"), wxICON_ERROR);
600 cfgfile->SetPath(wxT("/"));
601 ContinueAcc = cfgfile->GetNextGroup(AccountName, itemindex);
605 if (cmbServerType->GetCurrentSelection() == 1){
607 // Create the account directory.
609 wxString DirectoryName = txtAccountName->GetValue().Mid(0, 30) + RandomNumberSuffix;
611 if (wxMkdir(XestiaABDirectory + wxT("/accounts/") + DirectoryName + wxT(".carddav"), 0740) == TRUE){
613 DirectoryCreated = TRUE;
617 if (DirectoryCreated == TRUE){
619 WriteAccountDetails(cfgfile, wxT("CardDAV"), DirectoryName);
623 wxMessageBox(_("An error occured whilst creating the account directory."), _("Cannot create account directory"));
628 } else if (cmbServerType->GetCurrentSelection() == 0){
630 // Create the account directory.
632 wxString DirectoryName = txtAccountName->GetValue().Mid(0, 30) + RandomNumberSuffix;
634 if (wxMkdir(XestiaABDirectory + wxT("/accounts/") + DirectoryName + wxT(".local"), 0740) == TRUE){
636 DirectoryCreated = TRUE;
640 if (DirectoryCreated == TRUE){
642 WriteAccountDetails(cfgfile, wxT("Local"), DirectoryName);
646 wxMessageBox(_("An error occured whilst creating the account directory."), _("Cannot create account directory"));
656 *ReloadAccountConfig = TRUE;
666 void frmNewAccount::WriteAccountDetails(wxFileConfig *cfgfilein, wxString AccountType, wxString DirectoryName){
668 // Write the new account details.
670 cfgfilein->SetPath(txtAccountName->GetValue());
671 cfgfilein->Write(wxT("address"), txtServerAddress->GetValue());
672 cfgfilein->Write(wxT("port"), txtServerPort->GetValue());
673 cfgfilein->Write(wxT("username"), txtUsername->GetValue());
674 cfgfilein->Write(wxT("password"), txtPassword->GetValue());
675 cfgfilein->Write(wxT("prefix"), ServerPrefix);
676 cfgfilein->Write(wxT("accountdir"), DirectoryName);
678 if (chkUseSSL->GetValue() == TRUE){
680 cfgfilein->Write(wxT("ssl"), wxT("true"));
684 cfgfilein->Write(wxT("ssl"), wxT("false"));
688 cfgfilein->Write(wxT("refresh"), wxT("1800"));
689 cfgfilein->Write(wxT("type"), AccountType);
693 void frmNewAccount::CloseWindow( wxCommandEvent& event )
698 *ReloadAccountConfig = FALSE;
703 void frmNewAccount::UpdateRequirements( wxCommandEvent& event )
706 // Update the options.
708 if (cmbServerType->GetCurrentSelection() == 1){
710 txtServerAddress->Enable();
711 txtServerPort->Enable();
712 txtUsername->Enable();
713 txtPassword->Enable();
716 } else if (cmbServerType->GetCurrentSelection() == 0){
718 txtServerAddress->Disable();
719 txtServerPort->Disable();
720 txtUsername->Disable();
721 txtPassword->Disable();
722 chkUseSSL->Disable();
728 void frmNewAccount::SetupPointers(bool *ReloadAccountInc){
730 // Setup the pointers for the new account window.
732 ReloadAccountConfig = ReloadAccountInc;
736 void frmNewAccount::SetErrorMessageLabel(){
738 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)."));