// import.cpp - Import subroutines. // // (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 #include #include #include #include #include #include "import.h" #include "import-vcard3.h" #include "import-vcard4.h" #include "import-struct.h" #include "../frmMain.h" #include "frmImportContacts.h" #include "frmImportResults.h" #include "../common/uuid.h" #include "../common/dirs.h" void ImportRun(frmMain *frmMainPtrInc){ // Bring up a dialog selecting one or multiple // files for processing based on type. frmMainPtrInc->PauseAllTimers(); wxString FileTypes; int ImportType = 0; wxString FinalFilename; wxArrayString SelectedFileList; wxString SelectedFileDirectory; wxString AccountName; wxString AccountType; int ImportErrorCount = 0; std::map *ResultData = new std::map; FileTypes.Append(wxT("vCard 4.0 Contact(s) (*.vcf)")); FileTypes.Append(wxT("|*.vcf|")); FileTypes.Append(wxT("vCard 3.0 Contact(s) (*.vcf)")); FileTypes.Append(wxT("|*.vcf")); // Open up the dialog to import file data. wxFileDialog ImportDlg(frmMainPtrInc, wxT("Import Contacts"), wxT(""), wxT(""), FileTypes, wxFD_OPEN|wxFD_MULTIPLE); if (ImportDlg.ShowModal() == wxID_CANCEL){ frmMainPtrInc->ResumeAllTimers(); return; } // Get the list of filenames. ImportDlg.GetPaths(SelectedFileList); // Find which data type is being used. ImportType = ImportDlg.GetFilterIndex(); std::map ContactData; if (ImportType == 0){ ContactData = ImportVCard4(&SelectedFileList); } // vCard 3.0 import if (ImportType == 1){ ContactData = ImportVCard3(&SelectedFileList); } // Check how many contacts are in the set. If zero, throw an error // message and exit. if (ContactData.size() == 0){ wxMessageBox(_("No valid contacts within the file(s) selected."), _("Unable to import")); return; } // Show a form to let the user select the // contacts needed to import and which account // they go to. frmImportContacts *frmIC = new frmImportContacts(frmMainPtrInc); frmIC->SetupList(&ContactData); frmIC->ShowModal(); frmIC->GetResults(&ContactData); AccountName = frmIC->GetAccount(); AccountType = frmIC->GetAccountType(); if (frmIC->GetDialogResult() == FALSE){ // User decided not to import. Clean up the // dialog. delete frmIC; frmIC = NULL; frmMainPtrInc->ResumeAllTimers(); return; } delete frmIC; frmIC = NULL; // Import the contacts into the selected account. int ImportCount = 0; int ImportSeek = 0; // Setup the directory for writing into. wxString AccountDirFinal = GetAccountDir(AccountName, FALSE); wxString GeneratedFilename; wxString OutputFilename; wxString UIDValueFinal; wxString UIDToken; bool UIDFilterOK = FALSE; int FilterCount = 0; GeneratedFilename.Clear(); OutputFilename.Clear(); static wxString BadCharList = wxFileName::GetForbiddenChars(wxPATH_NATIVE); wxString BadCharListFinal; BadCharListFinal.Append(wxT("[")); BadCharListFinal.Append(BadCharList); BadCharListFinal.Append(wxT("]")); wxRegEx BadCharRex; BadCharRex.Compile(BadCharListFinal); for(std::map::iterator iter = ContactData.begin(); iter != ContactData.end(); iter++){ if (iter->second.ContactSelected == TRUE){ // Workout the file name. // Get the UID value and check if it is empty. // If it isn't empty, check it can be used for a valid // filename other wise generate a file name for the purposes // of storage. // Filter UID incase writing outside the // directory is attempted. #if defined(__HAIKU__) #elif defined(__WIN32__) wxStringTokenizer UIDValueCheck(iter->second.UIDValue, wxT("\\")); while (UIDValueCheck.HasMoreTokens()){ UIDValueCheck.GetNextToken(); FilterCount++; } #else wxStringTokenizer UIDValueCheck(iter->second.UIDValue, wxT("/")); while (UIDValueCheck.HasMoreTokens()){ UIDValueCheck.GetNextToken(); FilterCount++; } #endif if (FilterCount == 1){ UIDFilterOK = TRUE; } if (BadCharRex.Matches(iter->second.UIDValue) && UIDFilterOK == TRUE){ bool NewFileExists = TRUE; while (NewFileExists){ // Generate the UID and check if it exists. wxString CheckFilename; UIDToken = GenerateUUID(); CheckFilename.Append(AccountDirFinal); CheckFilename.Append(UIDToken); CheckFilename.Append(wxT(".vcf")); if (!wxFileExists(CheckFilename)){ NewFileExists = FALSE; } } } else { UIDToken = iter->second.UIDValue; } // Check if the file exists in the directory already. OutputFilename.Append(AccountDirFinal); OutputFilename.Append(wxT("/")); OutputFilename.Append(UIDToken); OutputFilename.Append(wxT(".vcf")); if(wxFileExists(OutputFilename)){ // File already exists so mark as an error. ResultData->insert(std::make_pair(ImportSeek, wxString::Format(_("Unable to import '%s'(%s): %s"), iter->second.FriendlyName, UIDToken, _("Contact already exists.")))); ImportErrorCount++; ImportSeek++; GeneratedFilename.Clear(); OutputFilename.Clear(); UIDValueFinal.Clear(); UIDFilterOK = FALSE; FilterCount = 0; continue; } else { // Write to the file. wxFFile OutputFile; #if wxABI_VERSION < 20900 if(!OutputFile.Open(OutputFilename, wxT("w"))){ #else if(!OutputFile.Open(OutputFilename, wxT("w"))){ #endif ResultData->insert(std::make_pair(ImportSeek, wxString::Format(_("Unable to import '%s'(%s): %s"), iter->second.FriendlyName, UIDToken, _("Error occured whilst trying to create this contact. Please check permissions and storage device.")))); } OutputFile.Write(iter->second.ContactData, wxConvAuto()); OutputFile.Close(); ResultData->insert(std::make_pair(ImportSeek, wxString::Format(_("Contact '%s'(%s) was successfully imported."), iter->second.FriendlyName, UIDToken))); } // Check if there is a UID value set. If there is not a UID // value set then generate a new one. ImportCount++; ImportSeek++; GeneratedFilename.Clear(); OutputFilename.Clear(); UIDValueFinal.Clear(); UIDToken.Clear(); UIDFilterOK = FALSE; FilterCount = 0; } } // Check if the import error count is more than 0. If it is, then // display the results dialog. wxCommandEvent imprres(IMPORT_RESULTSSHOW); imprres.SetClientData(ResultData); imprres.SetInt(ImportCount); imprres.SetExtraLong(ImportErrorCount); wxPostEvent(frmMainPtrInc, imprres); // Syncronise the account which the contacts got imported to. // (If the account is not a local account). if (AccountType != wxT("Local") && AccountType != wxT("local")){ wxString AccNamePostEvent; AccNamePostEvent.Clear(); AccNamePostEvent.Append(AccountName); AccNamePostEvent.Trim(); wxCommandEvent accevent(SYNCACCOUNT); accevent.SetString(AccNamePostEvent); wxPostEvent(frmMainPtrInc, accevent); } // Resume the timers. frmMainPtrInc->ResumeAllTimers(); }