1 // import.cpp - Import subroutines.
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 <wx/filedlg.h>
20 #include <wx/filename.h>
22 #include <wx/tokenzr.h>
26 #include "import-vcard3.h"
27 #include "import-vcard4.h"
28 #include "import-struct.h"
29 #include "../frmMain.h"
30 #include "frmImportContacts.h"
31 #include "frmImportResults.h"
32 #include "../common/uuid.h"
33 #include "../common/dirs.h"
35 void ImportRun(frmMain *frmMainPtrInc){
37 // Bring up a dialog selecting one or multiple
38 // files for processing based on type.
40 frmMainPtrInc->PauseAllTimers();
44 long ContactsImported = 0;
45 long ContactsCollected = 0;
47 wxString FinalFilename;
48 wxArrayString SelectedFileList;
49 wxString SelectedFileDirectory;
52 int ImportErrorCount = 0;
54 std::map<int,wxString> *ResultData = new std::map<int,wxString>;
56 FileTypes.Append(wxT("vCard 4.0 Contact(s) (*.vcf)"));
57 FileTypes.Append(wxT("|*.vcf|"));
58 FileTypes.Append(wxT("vCard 3.0 Contact(s) (*.vcf)"));
59 FileTypes.Append(wxT("|*.vcf"));
61 // Open up the dialog to import file data.
63 wxFileDialog ImportDlg(frmMainPtrInc, wxT("Import Contacts"), wxT(""), wxT(""),
64 FileTypes, wxFD_OPEN|wxFD_MULTIPLE);
66 if (ImportDlg.ShowModal() == wxID_CANCEL){
68 frmMainPtrInc->ResumeAllTimers();
73 // Get the list of filenames.
75 ImportDlg.GetPaths(SelectedFileList);
77 // Find which data type is being used.
79 ImportType = ImportDlg.GetFilterIndex();
81 std::map<int, ImportDataContact> ContactData;
85 ContactData = ImportVCard4(&SelectedFileList);
93 ContactData = ImportVCard3(&SelectedFileList);
97 // Check how many contacts are in the set. If zero, throw an error
100 if (ContactData.size() == 0){
102 wxMessageBox(_("No valid contacts within the file(s) selected."), _("Unable to import"));
108 // Show a form to let the user select the
109 // contacts needed to import and which account
112 frmImportContacts *frmIC = new frmImportContacts(frmMainPtrInc);
114 frmIC->SetupList(&ContactData);
116 frmIC->GetResults(&ContactData);
117 AccountName = frmIC->GetAccount();
118 AccountType = frmIC->GetAccountType();
120 if (frmIC->GetDialogResult() == FALSE){
122 // User decided not to import. Clean up the
127 frmMainPtrInc->ResumeAllTimers();
135 // Import the contacts into the selected account.
140 // Setup the directory for writing into.
142 wxString AccountDirFinal = GetAccountDir(AccountName, FALSE);
144 wxString GeneratedFilename;
145 wxString OutputFilename;
146 wxString UIDValueFinal;
148 bool UIDFilterOK = FALSE;
151 GeneratedFilename.Clear();
152 OutputFilename.Clear();
154 static wxString BadCharList = wxFileName::GetForbiddenChars(wxPATH_NATIVE);
155 wxString BadCharListFinal;
156 BadCharListFinal.Append(wxT("["));
157 BadCharListFinal.Append(BadCharList);
158 BadCharListFinal.Append(wxT("]"));
161 BadCharRex.Compile(BadCharListFinal);
163 for(std::map<int,ImportDataContact>::iterator iter = ContactData.begin();
164 iter != ContactData.end(); iter++){
166 if (iter->second.ContactSelected == TRUE){
168 // Workout the file name. void CloseWindow( wxCommandEvent& event );
169 // Get the UID value and check if it is empty.
170 // If it isn't empty, check it can be used for a valid
171 // filename other wise generate a file name for the purposes
174 // Filter UID incase writing outside the
175 // directory is attempted.
177 #if defined(__HAIKU__)
181 #elif defined(__WIN32__)
183 wxStringTokenizer UIDValueCheck(iter->second.UIDValue, wxT("\\"));
184 while (UIDValueCheck.HasMoreTokens()){
185 UIDValueCheck.GetNextToken();
191 wxStringTokenizer UIDValueCheck(iter->second.UIDValue, wxT("/"));
192 while (UIDValueCheck.HasMoreTokens()){
193 UIDValueCheck.GetNextToken();
199 if (FilterCount == 1){
203 if (BadCharRex.Matches(iter->second.UIDValue) && UIDFilterOK == TRUE){
205 bool NewFileExists = TRUE;
207 while (NewFileExists){
209 // Generate the UID and check if it exists.
211 wxString CheckFilename;
213 UIDToken = GenerateUUID();
215 CheckFilename.Append(AccountDirFinal);
216 CheckFilename.Append(UIDToken);
217 CheckFilename.Append(wxT(".vcf"));
219 if (!wxFileExists(CheckFilename)){
221 NewFileExists = FALSE;
229 UIDToken = iter->second.UIDValue;
233 // Check if the file exists in the directory already.
235 OutputFilename.Append(AccountDirFinal);
236 OutputFilename.Append(wxT("/"));
237 OutputFilename.Append(UIDToken);
238 OutputFilename.Append(wxT(".vcf"));
240 if(wxFileExists(OutputFilename)){
242 // File already exists so mark as an error.
244 ResultData->insert(std::make_pair(ImportSeek, wxString::Format(_("Unable to import '%s'(%s): %s"), iter->second.FriendlyName, UIDToken, _("Contact already exists."))));
247 GeneratedFilename.Clear();
248 OutputFilename.Clear();
249 UIDValueFinal.Clear();
256 // Write to the file.
260 #if wxABI_VERSION < 20900
261 if(!OutputFile.Open(OutputFilename, wxT("w"))){
263 if(!OutputFile.Open(OutputFilename, wxT("w"))){
265 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."))));
269 OutputFile.Write(iter->second.ContactData, wxConvAuto());
273 ResultData->insert(std::make_pair(ImportSeek, wxString::Format(_("Contact '%s'(%s) was successfully imported."), iter->second.FriendlyName, UIDToken)));
277 // Check if there is a UID value set. If there is not a UID
278 // value set then generate a new one.
284 GeneratedFilename.Clear();
285 OutputFilename.Clear();
286 UIDValueFinal.Clear();
295 // Check if the import error count is more than 0. If it is, then
296 // display the results dialog.
298 wxCommandEvent imprres(IMPORT_RESULTSSHOW);
299 imprres.SetClientData(ResultData);
300 imprres.SetInt(ImportCount);
301 imprres.SetExtraLong(ImportErrorCount);
302 wxPostEvent(frmMainPtrInc, imprres);
304 // Syncronise the account which the contacts got imported to.
305 // (If the account is not a local account).
307 if (AccountType != wxT("Local") && AccountType != wxT("local")){
309 wxString AccNamePostEvent;
311 AccNamePostEvent.Clear();
312 AccNamePostEvent.Append(AccountName);
313 AccNamePostEvent.Trim();
315 wxCommandEvent accevent(SYNCACCOUNT);
316 accevent.SetString(AccNamePostEvent);
318 wxPostEvent(frmMainPtrInc, accevent);
322 // Resume the timers.
324 frmMainPtrInc->ResumeAllTimers();