// frmContactEditor-Save.cpp - frmContactEditor save contact subroutines. // // (c) 2012-2016 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 "frmContactEditor.h" #include "../enums.h" #include "../version.h" #include "../vcard/vcard.h" #include "../vcard/vcard34conv.h" #include "../common/textprocessing.h" #include "../common/preferences.h" #include "../common/uuid.h" #include "../common/dirs.h" void frmContactEditor::SaveContact( wxCommandEvent& event ) { // Do not save if the account is an unsupported account. if (boolUnsupportedAccount == true){ wxMessageBox(_("Cannot make changes to a contact from an unsupported account type."), _("Unsupported account"), wxICON_ERROR); saveSuccess = false; return; } // Check if Display As combo box has a value in it. // Do not go any further if there is no value. wxString cmbDisplayAsValue = cmbDisplayAs->GetValue(); if (cmbDisplayAsValue.IsEmpty()){ wxMessageBox(_("Display As value cannot be left blank."), _("Display As value empty"), wxICON_ERROR); saveSuccess = false; return; } // Check if a value has been entered either in the Title, // Forename, Surname, Other Names and Suffix text boxes. if (txtTitle->IsEmpty() && txtForename->IsEmpty() && txtSurname->IsEmpty() && txtOtherNames->IsEmpty() && txtSuffix->IsEmpty()) { wxMessageBox(_("A value must be as minimum eithered in either the Title, Forename, Surname, Other Names or Suffix text boxes."), _("No name information entered"), wxICON_ERROR); saveSuccess = false; return; } // Save the updated contact data. //vCard ContactData; wxString FilenameFinal; bool ReplaceContact = FALSE; if (StartupEditMode == TRUE){ if (cmbType->GetCurrentSelection() == 1 || cmbType->GetCurrentSelection() == 3 || cmbType->GetCurrentSelection() == 4){ if (IsGroup == TRUE){ // Mark contact for replacing. ReplaceContact = TRUE; IsGroup = FALSE; } } else if (cmbType->GetCurrentSelection() == 2){ if (IsGroup == FALSE){ // Mark contact for replacing. ReplaceContact = TRUE; IsGroup = TRUE; } } if (ReplaceContact == TRUE){ wxString wxDelSplitFilename; wxString wxDelFinalFilename; wxString wxSDelDataURL; wxStringTokenizer wSTDelFilename(wxSContactFilename, wxT("/")); while(wSTDelFilename.HasMoreTokens()){ wxDelSplitFilename = wSTDelFilename.GetNextToken(); } wxSDelDataURL = wxDelSplitFilename; // Delete the contact from the server as it will be useless in certain // address book clients. ActMgrPtr->AddTask(2, cmbDisplayAs->GetValue(), wxSContactAccount, wxSDelDataURL, wxDelSplitFilename, wxSContactFilename, wxT("")); // Clear the filename so the trigger to recreate the UID is done. wxSContactFilename.Clear(); EditMode = FALSE; } } if (wxSContactFilename.IsEmpty()){ // Generate a random UUID. ContactEditorData.UIDToken = GenerateUUID(); ContactEditorData.UIDToken = ContactEditorData.UIDToken.MakeUpper(); // Setup the filename. FilenameFinal = GetAccountDir(wxSContactAccount, FALSE); #if defined(__HAIKU__) #elif defined(__WIN32__) FilenameFinal = GetAccountDir(wxSContactAccount, FALSE); FilenameFinal.Append(ContactEditorData.UIDToken); FilenameFinal.Append(wxT(".vcf")); wxSContactFilename = FilenameFinal; #else FilenameFinal = GetAccountDir(wxSContactAccount, FALSE); FilenameFinal.Append(ContactEditorData.UIDToken); FilenameFinal.Append(wxT(".vcf")); wxSContactFilename = FilenameFinal; #endif } else { if (ContactEditorData.UIDToken.IsEmpty()){ // UID Token is empty. (Shouldn't be). // Generate a new UID Token. ContactEditorData.UIDToken = GenerateUUID(); ContactEditorData.UIDToken = ContactEditorData.UIDToken.MakeUpper(); } FilenameFinal = wxSContactFilename; } // Setup the data and write it into the account folder. // Begin preperations to write the contact to a file. bool FNFirst = TRUE; std::map::iterator intiter; std::map::iterator striter; // Set some values for saving. ContactEditorData.NameForename = txtForename->GetValue(); ContactEditorData.NameSurname = txtSurname->GetValue(); ContactEditorData.NameOtherNames = txtOtherNames->GetValue(); ContactEditorData.NameTitle = txtTitle->GetValue(); ContactEditorData.NameSuffix = txtSuffix->GetValue(); ContactEditorData.GenderDetails = txtGenderDescription->GetValue(); // Process Birthday: Get Day, Month & Year. wxDateTime BirthdayDate; wxDateTime::Month BirthdayMonth; int BirthdayDay; int BirthdayYear; wxString DataBeforeT; wxString DataAfterT; wxString FinalBirthdayString; bool ProcessDataAfterT = FALSE; BirthdayDate = dapBirthday->GetValue(); if (!txtBirthday->IsEmpty()){ // Birthday value is text so use this. ContactEditorData.Birthday = txtBirthday->GetValue(); } else if (BirthdayDate.IsValid()){ BirthdayDay = BirthdayDate.GetDay(); BirthdayMonth = BirthdayDate.GetMonth(); BirthdayYear = BirthdayDate.GetYear(); // Look for T and replace data before this. wxStringTokenizer wSTDate(ContactEditorData.Birthday, wxT("T")); while (wSTDate.HasMoreTokens()){ if (ProcessDataAfterT == FALSE){ DataBeforeT = wSTDate.GetNextToken(); ProcessDataAfterT = TRUE; } else { DataAfterT = wSTDate.GetNextToken(); break; } } // If there is not T then replace altogether. wxString FinalBirthdayDay; wxString FinalBirthdayMonth; wxString FinalBirthdayYear; if (BirthdayDay < 10){ FinalBirthdayDay = wxT("0") + wxString::Format(wxT("%i"), BirthdayDay); } else { FinalBirthdayDay = wxString::Format(wxT("%i"), BirthdayDay); } if (((int)BirthdayMonth + 1) < 10){ FinalBirthdayMonth = wxT("0") + wxString::Format(wxT("%i"), ((int)BirthdayMonth + 1)); } else { FinalBirthdayMonth = wxString::Format(wxT("%i"), ((int)BirthdayMonth + 1)); } if (BirthdayYear == 0){ FinalBirthdayYear = wxT("--"); } else { FinalBirthdayYear = wxString::Format(wxT("%i"), BirthdayYear); } if (!DataAfterT.IsEmpty()){ FinalBirthdayString = FinalBirthdayYear + FinalBirthdayMonth + FinalBirthdayDay + wxT("T") + DataAfterT; } else { FinalBirthdayString = FinalBirthdayYear + FinalBirthdayMonth + FinalBirthdayDay; } if(!FinalBirthdayString.IsEmpty()){ ContactEditorData.Birthday = FinalBirthdayString; } } // Process Anniversary: Get Day, Month & Year. wxDateTime AnniversaryDate; wxDateTime::Month AnniversaryMonth; int AnniversaryDay; int AnniversaryYear; DataBeforeT = ""; DataAfterT = ""; wxString FinalAnniversaryString; ProcessDataAfterT = FALSE; AnniversaryDate = dapAnniversary->GetValue(); if (!txtAnniversary->IsEmpty()){ // Birthday value is text so use this. ContactEditorData.Anniversary = txtAnniversary->GetValue(); } else if (AnniversaryDate.IsValid()){ AnniversaryDay = AnniversaryDate.GetDay(); AnniversaryMonth = AnniversaryDate.GetMonth(); AnniversaryYear = AnniversaryDate.GetYear(); // Look for T and replace data before this. wxStringTokenizer wSTDate(ContactEditorData.Anniversary, wxT("T")); while (wSTDate.HasMoreTokens()){ if (ProcessDataAfterT == FALSE){ DataBeforeT = wSTDate.GetNextToken(); ProcessDataAfterT = TRUE; } else { DataAfterT = wSTDate.GetNextToken(); break; } } // If there is not T then replace altogether. wxString FinalAnniversaryDay; wxString FinalAnniversaryMonth; wxString FinalAnniversaryYear; if (AnniversaryDay < 10){ FinalAnniversaryDay = wxT("0") + wxString::Format(wxT("%i"), AnniversaryDay); } else { FinalAnniversaryDay = wxString::Format(wxT("%i"), AnniversaryDay); } if (((int)AnniversaryMonth + 1) < 10){ FinalAnniversaryMonth = wxT("0") + wxString::Format(wxT("%i"), ((int)AnniversaryMonth + 1)); } else { FinalAnniversaryMonth = wxString::Format(wxT("%i"), ((int)AnniversaryMonth + 1)); } if (AnniversaryYear == 0){ FinalAnniversaryYear = wxT("--"); } else { FinalAnniversaryYear = wxString::Format(wxT("%i"), AnniversaryYear); } if (!DataAfterT.IsEmpty()){ FinalAnniversaryString = FinalAnniversaryYear + FinalAnniversaryMonth + FinalAnniversaryDay + wxT("T") + DataAfterT; } else { FinalAnniversaryString = FinalAnniversaryYear + FinalAnniversaryMonth + FinalAnniversaryDay; } if(!FinalAnniversaryString.IsEmpty()){ ContactEditorData.Anniversary = FinalAnniversaryString; } } // Process full name. if (ContactEditorData.FullNamesList.size() > 0){ ContactEditorData.FullNamesList[0] = cmbDisplayAs->GetValue(); } else { ContactEditorData.FullNamesList.insert(std::make_pair(0, cmbDisplayAs->GetValue())); ContactEditorData.FullNamesListAltID.insert(std::make_pair(0, wxT(""))); ContactEditorData.FullNamesListPID.insert(std::make_pair(0, wxT(""))); ContactEditorData.FullNamesListType.insert(std::make_pair(0, wxT(""))); ContactEditorData.FullNamesListLanguage.insert(std::make_pair(0, wxT(""))); ContactEditorData.FullNamesListPref.insert(std::make_pair(0, 0)); ContactEditorData.FullNamesListTokens.insert(std::make_pair(0, wxT(""))); } FMTimer.Stop(); ContactEditorData.SaveFile(FilenameFinal); vCard34Conv ConvFileFun; wxString wxSData; ConvFileFun.ConvertToV3(FilenameFinal, &wxSData); wxString AccountDirPrefix; wxString AccountDir; wxString PrefDir; #if defined(__HAIKU__) #elif defined(__APPLE__) PrefDir = GetUserPrefDir(); wxStringTokenizer wSTFilename(wxSContactFilename, wxT("/")); #elif defined(__WIN32__) PrefDir = GetUserPrefDir(); wxStringTokenizer wSTFilename(wxSContactFilename, wxT("\\")); #else PrefDir = GetUserPrefDir(); wxStringTokenizer wSTFilename(wxSContactFilename, wxT("/")); #endif XABPreferences PrefData(PrefDir); wxString AccountType; for (int i = 0; i < PrefData.accounts.GetCount(); i++){ AccountDir = PrefData.accounts.GetAccountDirectory(i) + wxT(".carddav"); if (AccountDir == wxSContactAccount){ AccountDirPrefix = PrefData.accounts.GetAccountDirPrefix(i); AccountDirPrefix.Trim(); AccountType = PrefData.accounts.GetAccountType(i); break; } } wxString wxSplitFilename; wxString wxSDataURL; while(wSTFilename.HasMoreTokens()){ wxSplitFilename = wSTFilename.GetNextToken(); } wxSDataURL = wxSplitFilename; // Find out if the filename exists in the table. if (AccountType == wxT("CardDAV") || AccountType == wxT("carddav")){ wxString ETagResult; wxString ETagOriginal; ETagDB *ETagDBPtr = NULL; ETagDBPtr = ETagTmrPtr->GetPointer(wxSContactAccount); wxString wxSETag = ETagDBPtr->GetETag(wxSplitFilename); wxString wxSETagOrig = ETagDBPtr->GetETagOriginal(wxSplitFilename); if (wxSETagOrig.IsEmpty()){ // Generate the ETag. wxSETagOrig = wxString::Format(wxT("%X%X%X%X"), rand() % 1024, rand() % 1024, rand() % 1024, rand() % 1024); } if (wxSETag.IsEmpty()){ // Update empty ETag. wxSETag = wxSETagOrig; ETagDBPtr->AddETag(wxSplitFilename, wxSETag, ""); } else { // Don't change original ETag. wxSETag = wxString::Format(wxT("%X%X%X%X"), rand() % 1024, rand() % 1024, rand() % 1024, rand() % 1024); ETagDBPtr->UpdateETag(wxSplitFilename, wxSETag); } if (EditMode == FALSE){ ActMgrPtr->AddTask(0, cmbDisplayAs->GetValue(), wxSContactAccount, wxSDataURL, wxSplitFilename, FilenameFinal, wxSData); EditMode = TRUE; FMTimer.SetFilename(FilenameFinal); FMTimer.UpdateTimestamp(); FMTimer.Start(10000, FALSE); wxCommandEvent reloadevent(RELOADCONTACTLIST); reloadevent.SetString(wxSContactAccount); wxPostEvent(this->GetParent(), reloadevent); } else { ActMgrPtr->AddTask(1, cmbDisplayAs->GetValue(), wxSContactAccount, wxSDataURL, wxSplitFilename, FilenameFinal, wxSData); FMTimer.UpdateTimestamp(); FMTimer.Start(10000, FALSE); } } // Send a notification to update the main window // with the new details. UCNotif *ucd; ucd = new UCNotif; // TODO: Workout nickname settings by priority and // type. vCardName NameData; NameData.Forename = txtForename->GetValue(); NameData.Surname = txtSurname->GetValue(); NameData.OtherNames = txtOtherNames->GetValue(); NameData.Title = txtTitle->GetValue(); NameData.Suffix = txtSuffix->GetValue(); if (this->GetParent() != nullptr) { ucd->ContactAccount = wxSContactAccount; ucd->ContactFilename = FilenameFinal; ucd->ContactName = cmbDisplayAs->GetValue(); ucd->ContactNameArray = NameData; for (std::map::iterator gniter = ContactEditorData.GeneralNicknamesList.begin(); gniter != ContactEditorData.GeneralNicknamesList.end(); gniter++){ ucd->ContactNickname = gniter->second; break; } wxCommandEvent event2(CE_UPDATECONTACTLIST); event2.SetClientData(ucd); wxPostEvent(MainPtr, event2); } saveSuccess = true; } void frmContactEditor::SaveCloseContact( wxCommandEvent& event ) { // Save the updated contact data and close the form. wxCommandEvent NullEvent; this->SaveContact(NullEvent); if (saveSuccess) { this->Close(); } }