Home | News | Projects | Releases
Bugs | RFE | Repositories | Help
Added property value, ALTID, LANGUAGE source, header and unit tests for the N vCard...
[xestiaab/.git] / source / contacteditor / ContactDataObject.cpp
1 // ContactDataObject.cpp - Client Data Object.
2 //
3 // (c) 2012-2015 Xestia Software Development.
4 //
5 // This file is part of Xestia Address Book.
6 //
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.
10 //
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.
15 //
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 "ContactDataObject.h"
21 ContactLoadStatus ContactDataObject::LoadFile(wxString Filename){
22         
23         if (!wxFileExists(Filename)){
24         
25                 return CONTACTLOAD_FILEMISSING;
26         
27         }
28         
29         wxFile ContactFile;
30         
31         if (!ContactFile.Open(Filename, wxFile::read, wxS_DEFAULT)){
32         
33                 return CONTACTLOAD_FILEERROR;
34         
35         }
36         
37         // Check that the vCard is a valid vCard 4.0 file.
39         vCard vCard4FormatCheck;
40         
41         vCard4FormatCheck.LoadFile(Filename);
42         
43         if (vCard4FormatCheck.Get("VERSION") != wxT("4.0")){
44         
45                 return CONTACTLOAD_FILEINVALIDFORMAT;
46         
47         }
49         // Check that the vCard meets the base specification.
50         
51         if (!vCard4FormatCheck.MeetBaseSpecification()){
52         
53                 return CONTACTLOAD_FILEBASESPECFAIL;
54         
55         }
56         
57         wxStringTokenizer wSTContactFileLines(vCard4FormatCheck.WriteString(), wxT("\r\n"));
58         
59         std::map<int, wxString> ContactFileLines;
61         int ContactLineSeek = 0;
63         while (wSTContactFileLines.HasMoreTokens() == TRUE){
65                 wxString ContactLine = wSTContactFileLines.GetNextToken();
66                 ContactFileLines.insert(std::make_pair(ContactLineSeek, ContactLine));
67                 ContactLineSeek++;              
68         
69         }
70         
71         wxString wxSPropertyNextLine;
72         
73         bool ExtraLineSeek = TRUE;
74         bool QuoteMode = FALSE;
75         bool PropertyFind = TRUE;
76         bool KindProcessed = FALSE;
77         bool NameProcessed = FALSE;
78         int ContactLineLen = 0;
79         int QuoteBreakPoint = 0;
80         int GroupCount = 0;
81         int FNCount = 0;
82         wxString ContactLine;
83         wxString PropertyLine;
84         wxString PropertySeg1;
85         wxString PropertySeg2;
86         wxString PropertyNextLine;
87         wxString Property;
88         
89         for (std::map<int,wxString>::iterator iter = ContactFileLines.begin(); 
90          iter != ContactFileLines.end(); ++iter){
92                 ExtraLineSeek = TRUE;
93                 QuoteMode = FALSE;
94                 PropertyFind = TRUE;
95                 ContactLineLen = 0;
96                 QuoteBreakPoint = 0;
97                 ContactLine.Clear();
98                 PropertyLine.Clear();
99                 PropertySeg1.Clear();
100                 PropertySeg2.Clear();
101                 Property.Clear();
102          
103                 ContactLine = iter->second;
104                 
105                 while (ExtraLineSeek == TRUE){
106                 
107                         // Check if there is extra data on the next line 
108                         // (indicated by space or tab at the start) and add data.
109                 
110                         iter++;
111                         
112                         if (iter == ContactFileLines.end()){
113                         
114                                 iter--;
115                                 break;
116                         
117                         }                       
118                 
119                         PropertyNextLine = iter->second;
120                 
121                         if (PropertyNextLine.Mid(0, 1) == wxT(" ") || PropertyNextLine.Mid(0, 1) == wxT("\t")){
122                 
123                                 PropertyNextLine.Remove(0, 1);
124                                 ContactLine.Append(PropertyNextLine);
125                 
126                         } else {
127                         
128                                 iter--;
129                                 ExtraLineSeek = FALSE;
130                         
131                         }
132                 
133                 }
135                 ContactLineLen = ContactLine.Len();
136                 
137                 // Make sure we are not in quotation mode.
138                 // Make sure colon does not have \ or \\ before it.
139                 
140                 for (int i = 0; i <= ContactLineLen; i++){
141                 
142                         if ((ContactLine.Mid(i, 1) == wxT(";") || ContactLine.Mid(i, 1) == wxT(":")) && PropertyFind == TRUE){
143                         
144                                 PropertyFind = FALSE;
145                         
146                         } else if (PropertyFind == TRUE){
147                         
148                                 Property.Append(ContactLine.Mid(i, 1));
149                         
150                         }               
151                 
152                         if (ContactLine.Mid(i, 1) == wxT("\"")){
153                         
154                                 if (QuoteMode == TRUE){
155                                 
156                                         QuoteMode = FALSE;
157                                 
158                                 } else {
159                         
160                                         QuoteMode = TRUE;
161                                         
162                                 }
163                         
164                         }
165                         
166                         if (ContactLine.Mid(i, 1) == wxT(":") && ContactLine.Mid((i - 1), 1) != wxT("\\") && QuoteMode == FALSE){
167                         
168                                 QuoteBreakPoint = i;
169                                 break;
170                         
171                         }
172                 
173                 }
174                 
175                 // Split that line at the point into two variables (ignore the colon).
176                 
177                 PropertySeg1 = ContactLine.Mid(0, QuoteBreakPoint);
178                 PropertySeg2 = ContactLine.Mid((QuoteBreakPoint + 1));
179                 
180                  if (Property == wxT("KIND") && KindProcessed == FALSE){
181                                 
182                         ProcessKind(PropertySeg2);
183                 
184                 } else if (Property == wxT("MEMBER")){
186                         ProcessMember(PropertySeg1, PropertySeg2, &GroupCount);
187                         GroupCount++;   
188                 
189                 } else if (Property == wxT("FN")){
190                 
191                         ProcessFN(PropertySeg1, PropertySeg2, &FNCount);
192                         FNCount++;
193                 
194                 } else if (Property == wxT("N") && NameProcessed == FALSE){
195                 
196                         ProcessN(PropertySeg1, PropertySeg2);
197                         NameProcessed = TRUE;
198                 
199                 }
200                 
201         }
202         
203         return CONTACTLOAD_OK;
207 void ContactDataObject::ProcessKind(wxString KindType){
209         if (KindType == wxT("individual")){
210                         
211                 ContactKind = CONTACTKIND_INDIVIDUAL;
212                         
213         } else if (KindType == wxT("group")){
214                         
215                 ContactKind = CONTACTKIND_GROUP;
216                         
217         } else if (KindType == wxT("org")){
218                         
219                 ContactKind = CONTACTKIND_ORGANISATION;
220                         
221         } else if (KindType == wxT("location")){
222                         
223                 ContactKind = CONTACTKIND_LOCATION;
224                         
225         } else {
226                         
227                 ContactKind = CONTACTKIND_NONE;                 
228         }
232 void ContactDataObject::ProcessMember(wxString PropertySeg1, wxString PropertySeg2, int *GroupCount){
234         std::map<int, int> SplitPoints;
235         std::map<int, int> SplitLength;
237         int intPrevValue = 8;
238         int intPref = 0;                        
239         int intType = 0;
240         
241         SplitValues(&PropertySeg1, &SplitPoints, &SplitLength, intPrevValue);
243         intPrevValue = 7;
244         
245         wxString PropertyName;
246         wxString PropertyValue;
247         wxString PropertyData;
248         wxString PropertyTokens;
249         std::map<int,int>::iterator SLiter;
250         bool FirstToken = TRUE;
251         
252         for (std::map<int, int>::iterator intiter = SplitPoints.begin(); 
253         intiter != SplitPoints.end(); ++intiter){
254         
255                 SLiter = SplitLength.find(intiter->first);
256         
257                 PropertyData = PropertySeg1.Mid(intPrevValue, (SLiter->second));
258                 
259                 wxStringTokenizer PropertyElement (PropertyData, wxT("="));
260                 PropertyName = PropertyElement.GetNextToken();                          
261                 PropertyValue = PropertyElement.GetNextToken();
262                 
263                 intPrevValue = intiter->second;
264                 
265                 CaptureString(&PropertyValue, FALSE);
266         
267                 if (PropertyName == wxT("ALTID")){
269                         GroupsListAltID.erase(*GroupCount);
270                         GroupsListAltID.insert(std::make_pair(*GroupCount, PropertyValue));
271                 
272                 } else if (PropertyName == wxT("PID")){
274                         GroupsListPID.erase(*GroupCount);
275                         GroupsListPID.insert(std::make_pair(*GroupCount, PropertyValue));
276                 
277                 } else if (PropertyName == wxT("PREF")){
279                         int PriorityNumber = 0;
280                         bool ValidNumber = TRUE;
281                         
282                         try{
283                                 PriorityNumber = std::stoi(PropertyValue.ToStdString());
284                         }
285                         
286                         catch(std::invalid_argument &e){
287                                 ValidNumber = FALSE;
288                         }
290                         if (ValidNumber == TRUE){
292                                 GroupsListPref.erase(*GroupCount);
293                                 GroupsListPref.insert(std::make_pair(*GroupCount, PriorityNumber));
294                 
295                         }
296                 
297                 } else if (PropertyName == wxT("MEDIATYPE")){
299                         GroupsListMediaType.erase(*GroupCount);
300                         GroupsListMediaType.insert(std::make_pair(*GroupCount, PropertyValue));
301                 
302                 } else if (!PropertyName.IsEmpty() && !PropertyValue.IsEmpty()){
303                         
304                         if (FirstToken == TRUE){
305                                 
306                                 PropertyTokens.Append(PropertyName + wxT("=") + PropertyValue);
307                                 FirstToken = FALSE;
308                                 
309                         } else {
310                         
311                                 PropertyTokens.Append(wxT(";") + PropertyName + wxT("=") + PropertyValue);
312                                 
313                         }
314                         
315                 }
316                 
317         }
319         GroupsList.insert(std::make_pair(*GroupCount, PropertySeg2));
321         if (!PropertyTokens.IsEmpty()){
322         
323                 GroupsListTokens.insert(std::make_pair(*GroupCount, PropertyTokens));
324         
325         }
330 void ContactDataObject::ProcessFN(wxString PropertySeg1, wxString PropertySeg2, int *FNCount){
332         std::map<int, int> SplitPoints;
333         std::map<int, int> SplitLength;
335         int intPrevValue = 4;
336         int intPref = 0;                        
337         int intType = 0;
338         
339         SplitValues(&PropertySeg1, &SplitPoints, &SplitLength, intPrevValue);
341         intPrevValue = 3;
342         
343         wxString PropertyName;
344         wxString PropertyValue;
345         wxString PropertyData;
346         wxString PropertyTokens;
347         std::map<int,int>::iterator SLiter;
348         bool FirstToken = TRUE;
349         
350         for (std::map<int, int>::iterator intiter = SplitPoints.begin(); 
351         intiter != SplitPoints.end(); ++intiter){
352         
353                 SLiter = SplitLength.find(intiter->first);
354         
355                 PropertyData = PropertySeg1.Mid(intPrevValue, (SLiter->second));
356                 
357                 wxStringTokenizer PropertyElement (PropertyData, wxT("="));
358                 PropertyName = PropertyElement.GetNextToken();                          
359                 PropertyValue = PropertyElement.GetNextToken();
360                 
361                 intPrevValue = intiter->second;
362                 
363                 CaptureString(&PropertyValue, FALSE);
364                 
365                 if (PropertyName == wxT("TYPE")){
367                         if (!PropertyValue.IsEmpty() || PropertyValue == wxT("home") ||
368                                 PropertyValue == wxT("work") ){
370                                 FullNamesListType.erase(*FNCount);
371                                 FullNamesListType.insert(std::make_pair(*FNCount, PropertyValue));
372                 
373                         }
374                 
375                 } else if (PropertyName == wxT("LANGUAGE")){
377                         FullNamesListLanguage.erase(*FNCount);
378                         FullNamesListLanguage.insert(std::make_pair(*FNCount, PropertyValue));
379                 
380                 } else if (PropertyName == wxT("ALTID")){
381                 
382                         FullNamesListAltID.erase(*FNCount);
383                         FullNamesListAltID.insert(std::make_pair(*FNCount, PropertyValue));
384                 
385                 } else if (PropertyName == wxT("PID")){
387                         FullNamesListPID.erase(*FNCount);
388                         FullNamesListPID.insert(std::make_pair(*FNCount, PropertyValue));
389                 
390                 } else if (PropertyName == wxT("PREF")){
392                         int PriorityNumber = 0;
393                         bool ValidNumber = TRUE;
394                         
395                         try{
396                                 PriorityNumber = std::stoi(PropertyValue.ToStdString());
397                         }
398                         
399                         catch(std::invalid_argument &e){
400                                 ValidNumber = FALSE;
401                         }
403                         if (ValidNumber == TRUE){
405                                 FullNamesListPref.erase(*FNCount);
406                                 FullNamesListPref.insert(std::make_pair(*FNCount, PriorityNumber));
408                         }
409                 
410                 } else if (!PropertyName.IsEmpty() && !PropertyValue.IsEmpty()){
411                         
412                         if (FirstToken == TRUE){
413                                 
414                                 PropertyTokens.Append(PropertyName + wxT("=") + PropertyValue);
415                                 FirstToken = FALSE;
416                                 
417                         } else {
418                         
419                                 PropertyTokens.Append(wxT(";") + PropertyName + wxT("=") + PropertyValue);
420                                 
421                         }
422                         
423                 } 
424         
425         }
427         FullNamesList.insert(std::make_pair(*FNCount, PropertySeg2));
429         if (!PropertyTokens.IsEmpty()){
430         
431                 FullNamesListTokens.insert(std::make_pair(*FNCount, PropertyTokens));
432         
433         }
437 void ContactDataObject::ProcessN(wxString PropertySeg1, wxString PropertySeg2){
439         std::map<int, int> SplitPoints;
440         std::map<int, int> SplitLength;
442         int intPrevValue = 3;
443         int intPref = 0;                        
444         int intType = 0;
445         
446         SplitValues(&PropertySeg1, &SplitPoints, &SplitLength, intPrevValue);
447         
448         intPrevValue = 2;
449         
450         NameForename = PropertySeg2;
451         
452         wxString PropertyName;
453         wxString PropertyValue;
454         wxString PropertyData;
455         wxString PropertyTokens;
456         std::map<int,int>::iterator SLiter;
457         bool FirstToken = TRUE;
458         
459         for (std::map<int, int>::iterator intiter = SplitPoints.begin(); 
460         intiter != SplitPoints.end(); ++intiter){
461         
462                 SLiter = SplitLength.find(intiter->first);
463         
464                 PropertyData = PropertySeg1.Mid(intPrevValue, (SLiter->second));
465                 
466                 wxStringTokenizer PropertyElement (PropertyData, wxT("="));
467                 PropertyName = PropertyElement.GetNextToken();                          
468                 PropertyValue = PropertyElement.GetNextToken();
469                 
470                 intPrevValue = intiter->second;
471                 
472                 CaptureString(&PropertyValue, FALSE);
473                 
474                 if (PropertyName == wxT("ALTID")){
476                         NameAltID = PropertyValue;
477                 
478                 } else if (PropertyName == wxT("LANGUAGE")){
479                 
480                         NameLanguage = PropertyValue;
481                 
482                 }
483         
484         }
486
488 void SplitValues(wxString *PropertyLine, 
489         std::map<int,int> *SplitPoints, 
490         std::map<int,int> *SplitLength, 
491         int intSize){
492         
493         size_t intPropertyLen = PropertyLine->Len();
494         int intSplitsFound = 0;
495         int intSplitSize = 0;
496         int intSplitSeek = 0;
497         
498         for (int i = intSize; i <= intPropertyLen; i++){
500                 intSplitSize++;
501         
502                 if (PropertyLine->Mid(i, 1) == wxT(";") &&
503                     PropertyLine->Mid((i - 1), 1) != wxT("\\")){
504            
505                     if (intSplitsFound == 0){
506             
507                         SplitLength->insert(std::make_pair(intSplitsFound, (intSplitSize)));
508           
509                     } else {
510            
511                         SplitLength->insert(std::make_pair(intSplitsFound, (intSplitSize - 1)));
512             
513                     }
514             
515                     SplitPoints->insert(std::make_pair(intSplitsFound, (i + 1)));
516             
517                     intSplitsFound++;
518                     intSplitSeek = i;
519                     intSplitSize = 0;
520             
521                 }
523         }
525         if (intSplitsFound == 0){
527                 SplitPoints->insert(std::make_pair(intSplitsFound, (8 + 1)));
528                 SplitLength->insert(std::make_pair(intSplitsFound, intSplitSize));
530         } else {
532                 SplitPoints->insert(std::make_pair(intSplitsFound, (intSplitSeek + 1)));
533                 SplitLength->insert(std::make_pair(intSplitsFound, intSplitSize));
535         }
Xestia Software Development
Yn Maystri
© 2006 - 2019 Xestia Software Development
Software

Xestia Address Book
Xestia Calendar
Development

Xestia Gelforn
Everything else

About
News
Privacy Policy