1 // ContactDataObject.cpp - Client Data Object.
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 "ContactDataObject.h"
21 ContactLoadStatus ContactDataObject::LoadFile(wxString Filename){
23 if (!wxFileExists(Filename)){
25 return CONTACTLOAD_FILEMISSING;
31 if (!ContactFile.Open(Filename, wxFile::read, wxS_DEFAULT)){
33 return CONTACTLOAD_FILEERROR;
37 // Check that the vCard is a valid vCard 4.0 file.
39 vCard vCard4FormatCheck;
41 vCard4FormatCheck.LoadFile(Filename);
43 if (vCard4FormatCheck.Get("VERSION") != wxT("4.0")){
45 return CONTACTLOAD_FILEINVALIDFORMAT;
49 // Check that the vCard meets the base specification.
51 if (!vCard4FormatCheck.MeetBaseSpecification()){
53 return CONTACTLOAD_FILEBASESPECFAIL;
57 wxStringTokenizer wSTContactFileLines(vCard4FormatCheck.WriteString(), wxT("\r\n"));
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));
71 wxString wxSPropertyNextLine;
73 bool ExtraLineSeek = TRUE;
74 bool QuoteMode = FALSE;
75 bool PropertyFind = TRUE;
76 bool KindProcessed = FALSE;
77 bool NameProcessed = FALSE;
78 bool GenderProcessed = FALSE;
79 bool BirthdayProcessed = FALSE;
80 bool AnniversaryProcessed = FALSE;
81 int ContactLineLen = 0;
82 int QuoteBreakPoint = 0;
85 int NicknameCount = 0;
86 int TimeZoneCount = 0;
89 wxString PropertyLine;
90 wxString PropertySeg1;
91 wxString PropertySeg2;
92 wxString PropertyNextLine;
95 for (std::map<int,wxString>::iterator iter = ContactFileLines.begin();
96 iter != ContactFileLines.end(); ++iter){
104 PropertyLine.Clear();
105 PropertySeg1.Clear();
106 PropertySeg2.Clear();
109 ContactLine = iter->second;
111 while (ExtraLineSeek == TRUE){
113 // Check if there is extra data on the next line
114 // (indicated by space or tab at the start) and add data.
118 if (iter == ContactFileLines.end()){
125 PropertyNextLine = iter->second;
127 if (PropertyNextLine.Mid(0, 1) == wxT(" ") || PropertyNextLine.Mid(0, 1) == wxT("\t")){
129 PropertyNextLine.Remove(0, 1);
130 ContactLine.Append(PropertyNextLine);
135 ExtraLineSeek = FALSE;
141 ContactLineLen = ContactLine.Len();
143 // Make sure we are not in quotation mode.
144 // Make sure colon does not have \ or \\ before it.
146 for (int i = 0; i <= ContactLineLen; i++){
148 if ((ContactLine.Mid(i, 1) == wxT(";") || ContactLine.Mid(i, 1) == wxT(":")) && PropertyFind == TRUE){
150 PropertyFind = FALSE;
152 } else if (PropertyFind == TRUE){
154 Property.Append(ContactLine.Mid(i, 1));
158 if (ContactLine.Mid(i, 1) == wxT("\"")){
160 if (QuoteMode == TRUE){
172 if (ContactLine.Mid(i, 1) == wxT(":") && ContactLine.Mid((i - 1), 1) != wxT("\\") && QuoteMode == FALSE){
181 // Split that line at the point into two variables (ignore the colon).
183 PropertySeg1 = ContactLine.Mid(0, QuoteBreakPoint);
184 PropertySeg2 = ContactLine.Mid((QuoteBreakPoint + 1));
186 if (Property == wxT("KIND") && KindProcessed == FALSE){
188 ProcessKind(PropertySeg2);
190 } else if (Property == wxT("MEMBER")){
192 ProcessMember(PropertySeg1, PropertySeg2, &GroupCount);
195 } else if (Property == wxT("FN")){
197 ProcessFN(PropertySeg1, PropertySeg2, &FNCount);
200 } else if (Property == wxT("N") && NameProcessed == FALSE){
202 ProcessN(PropertySeg1, PropertySeg2);
203 NameProcessed = TRUE;
205 } else if (Property == wxT("NICKNAME")){
207 ProcessNickname(PropertySeg1, PropertySeg2, &NicknameCount);
210 } else if (Property == wxT("GENDER") && GenderProcessed == FALSE){
212 ProcessGender(PropertySeg1, PropertySeg2);
213 GenderProcessed = TRUE;
215 } else if (Property == wxT("BDAY") && BirthdayProcessed == FALSE){
217 ProcessBirthday(PropertySeg1, PropertySeg2);
218 BirthdayProcessed = TRUE;
220 } else if (Property == wxT("ANNIVERSARY") && AnniversaryProcessed == FALSE){
222 ProcessAnniversary(PropertySeg1, PropertySeg2);
223 AnniversaryProcessed = TRUE;
225 } else if (Property == wxT("TZ")){
227 ProcessTimeZone(PropertySeg1, PropertySeg2, &TimeZoneCount);
230 } else if (Property == wxT("ADR")){
232 ProcessAddress(PropertySeg1, PropertySeg2, &AddressCount);
239 return CONTACTLOAD_OK;
243 void ContactDataObject::ProcessKind(wxString KindType){
245 if (KindType == wxT("individual")){
247 ContactKind = CONTACTKIND_INDIVIDUAL;
249 } else if (KindType == wxT("group")){
251 ContactKind = CONTACTKIND_GROUP;
253 } else if (KindType == wxT("org")){
255 ContactKind = CONTACTKIND_ORGANISATION;
257 } else if (KindType == wxT("location")){
259 ContactKind = CONTACTKIND_LOCATION;
263 ContactKind = CONTACTKIND_NONE;
268 void ContactDataObject::ProcessMember(wxString PropertySeg1, wxString PropertySeg2, int *GroupCount){
270 std::map<int, int> SplitPoints;
271 std::map<int, int> SplitLength;
273 int intPrevValue = 8;
277 SplitValues(&PropertySeg1, &SplitPoints, &SplitLength, intPrevValue);
281 wxString PropertyName;
282 wxString PropertyValue;
283 wxString PropertyData;
284 wxString PropertyTokens;
285 std::map<int,int>::iterator SLiter;
286 bool FirstToken = TRUE;
288 for (std::map<int, int>::iterator intiter = SplitPoints.begin();
289 intiter != SplitPoints.end(); ++intiter){
291 SLiter = SplitLength.find(intiter->first);
293 PropertyData = PropertySeg1.Mid(intPrevValue, (SLiter->second));
295 wxStringTokenizer PropertyElement (PropertyData, wxT("="));
296 PropertyName = PropertyElement.GetNextToken();
297 PropertyValue = PropertyElement.GetNextToken();
299 intPrevValue = intiter->second;
301 CaptureString(&PropertyValue, FALSE);
303 if (PropertyName == wxT("ALTID")){
305 GroupsListAltID.erase(*GroupCount);
306 GroupsListAltID.insert(std::make_pair(*GroupCount, PropertyValue));
308 } else if (PropertyName == wxT("PID")){
310 GroupsListPID.erase(*GroupCount);
311 GroupsListPID.insert(std::make_pair(*GroupCount, PropertyValue));
313 } else if (PropertyName == wxT("PREF")){
315 int PriorityNumber = 0;
316 bool ValidNumber = TRUE;
319 PriorityNumber = std::stoi(PropertyValue.ToStdString());
322 catch(std::invalid_argument &e){
326 if (ValidNumber == TRUE){
328 GroupsListPref.erase(*GroupCount);
329 GroupsListPref.insert(std::make_pair(*GroupCount, PriorityNumber));
333 } else if (PropertyName == wxT("MEDIATYPE")){
335 GroupsListMediaType.erase(*GroupCount);
336 GroupsListMediaType.insert(std::make_pair(*GroupCount, PropertyValue));
338 } else if (!PropertyName.IsEmpty() && !PropertyValue.IsEmpty()){
340 if (FirstToken == TRUE){
342 PropertyTokens.Append(PropertyName + wxT("=") + PropertyValue);
347 PropertyTokens.Append(wxT(";") + PropertyName + wxT("=") + PropertyValue);
355 GroupsList.insert(std::make_pair(*GroupCount, PropertySeg2));
357 if (!PropertyTokens.IsEmpty()){
359 GroupsListTokens.insert(std::make_pair(*GroupCount, PropertyTokens));
366 void ContactDataObject::ProcessFN(wxString PropertySeg1, wxString PropertySeg2, int *FNCount){
368 std::map<int, int> SplitPoints;
369 std::map<int, int> SplitLength;
371 int intPrevValue = 4;
375 SplitValues(&PropertySeg1, &SplitPoints, &SplitLength, intPrevValue);
379 wxString PropertyName;
380 wxString PropertyValue;
381 wxString PropertyData;
382 wxString PropertyTokens;
383 std::map<int,int>::iterator SLiter;
384 bool FirstToken = TRUE;
386 for (std::map<int, int>::iterator intiter = SplitPoints.begin();
387 intiter != SplitPoints.end(); ++intiter){
389 SLiter = SplitLength.find(intiter->first);
391 PropertyData = PropertySeg1.Mid(intPrevValue, (SLiter->second));
393 wxStringTokenizer PropertyElement (PropertyData, wxT("="));
394 PropertyName = PropertyElement.GetNextToken();
395 PropertyValue = PropertyElement.GetNextToken();
397 intPrevValue = intiter->second;
399 CaptureString(&PropertyValue, FALSE);
401 if (PropertyName == wxT("TYPE")){
403 if (!PropertyValue.IsEmpty() || PropertyValue == wxT("home") ||
404 PropertyValue == wxT("work") ){
406 FullNamesListType.erase(*FNCount);
407 FullNamesListType.insert(std::make_pair(*FNCount, PropertyValue));
411 } else if (PropertyName == wxT("LANGUAGE")){
413 FullNamesListLanguage.erase(*FNCount);
414 FullNamesListLanguage.insert(std::make_pair(*FNCount, PropertyValue));
416 } else if (PropertyName == wxT("ALTID")){
418 FullNamesListAltID.erase(*FNCount);
419 FullNamesListAltID.insert(std::make_pair(*FNCount, PropertyValue));
421 } else if (PropertyName == wxT("PID")){
423 FullNamesListPID.erase(*FNCount);
424 FullNamesListPID.insert(std::make_pair(*FNCount, PropertyValue));
426 } else if (PropertyName == wxT("PREF")){
428 int PriorityNumber = 0;
429 bool ValidNumber = TRUE;
432 PriorityNumber = std::stoi(PropertyValue.ToStdString());
435 catch(std::invalid_argument &e){
439 if (ValidNumber == TRUE){
441 FullNamesListPref.erase(*FNCount);
442 FullNamesListPref.insert(std::make_pair(*FNCount, PriorityNumber));
446 } else if (!PropertyName.IsEmpty() && !PropertyValue.IsEmpty()){
448 if (FirstToken == TRUE){
450 PropertyTokens.Append(PropertyName + wxT("=") + PropertyValue);
455 PropertyTokens.Append(wxT(";") + PropertyName + wxT("=") + PropertyValue);
463 FullNamesList.insert(std::make_pair(*FNCount, PropertySeg2));
465 if (!PropertyTokens.IsEmpty()){
467 FullNamesListTokens.insert(std::make_pair(*FNCount, PropertyTokens));
473 void ContactDataObject::ProcessN(wxString PropertySeg1, wxString PropertySeg2){
475 std::map<int, int> SplitPoints;
476 std::map<int, int> SplitLength;
478 int intPrevValue = 3;
482 SplitValues(&PropertySeg1, &SplitPoints, &SplitLength, intPrevValue);
486 wxString PropertyName;
487 wxString PropertyValue;
488 wxString PropertyData;
489 wxString PropertyTokens;
490 std::map<int,int>::iterator SLiter;
491 bool FirstToken = TRUE;
493 for (std::map<int, int>::iterator intiter = SplitPoints.begin();
494 intiter != SplitPoints.end(); ++intiter){
496 SLiter = SplitLength.find(intiter->first);
498 PropertyData = PropertySeg1.Mid(intPrevValue, (SLiter->second));
500 wxStringTokenizer PropertyElement (PropertyData, wxT("="));
501 PropertyName = PropertyElement.GetNextToken();
502 PropertyValue = PropertyElement.GetNextToken();
504 intPrevValue = intiter->second;
506 CaptureString(&PropertyValue, FALSE);
508 if (PropertyName == wxT("ALTID")){
510 NameAltID = PropertyValue;
512 } else if (PropertyName == wxT("LANGUAGE")){
514 NameLanguage = PropertyValue;
516 } else if (PropertyName == wxT("SORT-AS")){
518 if (PropertyValue.Left(1) == wxT("\"") && PropertyValue.Right(1) == wxT("\"") &&
519 PropertyValue.Len() >= 3){
520 NameDisplayAs = PropertyValue.Mid(1, (PropertyValue.Len() - 2));
523 } else if (!PropertyName.IsEmpty() && !PropertyValue.IsEmpty()){
525 if (FirstToken == TRUE){
527 PropertyTokens.Append(PropertyName + wxT("=") + PropertyValue);
532 PropertyTokens.Append(wxT(";") + PropertyName + wxT("=") + PropertyValue);
540 // Split the name data.
542 int intSplitSeek = 0;
543 int intSplitsFound = 0;
544 int intSplitSize = 0;
545 int intPropertyLen = PropertySeg2.Len();
547 std::map<int,wxString> NameValues;
550 for (int i = 0; i <= intPropertyLen; i++){
552 if (PropertySeg2.Mid(i, 1) == wxT(";") && PropertySeg2.Mid((i - 1), 1) != wxT("\\")){
554 NameValues.insert(std::make_pair(++intSplitsFound, PropertySeg2.Mid(intSplitSeek, intSplitSize)));
559 if (intSplitsFound == 4){
561 NameValues.insert(std::make_pair(++intSplitsFound, PropertySeg2.Mid(intSplitSeek, wxString::npos)));
575 // Split the data into several parts.
577 for (std::map<int, wxString>::iterator iter = NameValues.begin();
578 iter != NameValues.end(); ++iter){
580 if (iter->first == 1){
582 // Deal with family name.
584 NameSurname = iter->second;
586 } else if (iter->first == 2){
588 // Deal with given names.
590 NameForename = iter->second;
592 } else if (iter->first == 3){
594 // Deal with additional names.
596 NameOtherNames = iter->second;
598 } else if (iter->first == 4){
600 // Deal with honorifix prefixes and suffixes.
602 NameTitle = iter->second;
606 if (iter == NameValues.end()){
612 NameSuffix = iter->second;
618 // Add the name token data.
620 if (!PropertyTokens.IsEmpty()){
622 NameTokens = PropertyTokens;
628 void ContactDataObject::ProcessNickname(wxString PropertySeg1, wxString PropertySeg2, int *NicknameCount){
630 std::map<int, int> SplitPoints;
631 std::map<int, int> SplitLength;
633 int intPrevValue = 10;
636 SplitValues(&PropertySeg1, &SplitPoints, &SplitLength, intPrevValue);
640 PropertyType PropType;
642 // Look for type before continuing.
644 CheckType(&PropertySeg1, &SplitPoints, &SplitLength, &intPrevValue, &PropType);
648 std::map<int, wxString> *NicknamesList = NULL;
649 std::map<int, wxString> *NicknamesListType = NULL;
650 std::map<int, wxString> *NicknamesListLanguage = NULL;
651 std::map<int, wxString> *NicknamesListAltID = NULL;
652 std::map<int, wxString> *NicknamesListPID = NULL;
653 std::map<int, wxString> *NicknamesListTokens = NULL;
654 std::map<int, int> *NicknamesListPref = NULL;
658 NicknamesList = &GeneralNicknamesList;
659 NicknamesListType = &GeneralNicknamesListType;
660 NicknamesListLanguage = &GeneralNicknamesListLanguage;
661 NicknamesListAltID = &GeneralNicknamesListAltID;
662 NicknamesListPID = &GeneralNicknamesListPID;
663 NicknamesListTokens = &GeneralNicknamesListTokens;
664 NicknamesListPref = &GeneralNicknamesListPref;
667 NicknamesList = &HomeNicknamesList;
668 NicknamesListType = &HomeNicknamesListType;
669 NicknamesListLanguage = &HomeNicknamesListLanguage;
670 NicknamesListAltID = &HomeNicknamesListAltID;
671 NicknamesListPID = &HomeNicknamesListPID;
672 NicknamesListTokens = &HomeNicknamesListTokens;
673 NicknamesListPref = &HomeNicknamesListPref;
676 NicknamesList = &BusinessNicknamesList;
677 NicknamesListType = &BusinessNicknamesListType;
678 NicknamesListLanguage = &BusinessNicknamesListLanguage;
679 NicknamesListAltID = &BusinessNicknamesListAltID;
680 NicknamesListPID = &BusinessNicknamesListPID;
681 NicknamesListTokens = &BusinessNicknamesListTokens;
682 NicknamesListPref = &BusinessNicknamesListPref;
686 std::map<int, int>::iterator SLiter;
687 wxString PropertyData;
688 wxString PropertyName;
689 wxString PropertyValue;
690 wxString PropertyTokens;
691 bool FirstToken = TRUE;
693 for (std::map<int, int>::iterator intiter = SplitPoints.begin();
694 intiter != SplitPoints.end(); ++intiter){
696 SLiter = SplitLength.find(intiter->first);
698 PropertyData = PropertySeg1.Mid(intPrevValue, (SLiter->second));
700 wxStringTokenizer PropertyElement (PropertyData, wxT("="));
701 PropertyName = PropertyElement.GetNextToken();
702 PropertyValue = PropertyElement.GetNextToken();
704 intPrevValue = intiter->second;
706 CaptureString(&PropertyValue, FALSE);
708 if (PropertyName == wxT("ALTID")){
710 NicknamesListAltID->erase(*NicknameCount);
711 NicknamesListAltID->insert(std::make_pair(*NicknameCount, PropertyValue));
713 } else if (PropertyName == wxT("PID")){
715 NicknamesListPID->erase(*NicknameCount);
716 NicknamesListPID->insert(std::make_pair(*NicknameCount, PropertyValue));
718 } else if (PropertyName == wxT("PREF")){
720 int PriorityNumber = 0;
721 bool ValidNumber = TRUE;
724 PriorityNumber = std::stoi(PropertyValue.ToStdString());
727 catch(std::invalid_argument &e){
731 if (ValidNumber == TRUE){
733 NicknamesListPref->erase(*NicknameCount);
734 NicknamesListPref->insert(std::make_pair(*NicknameCount, PriorityNumber));
738 } else if (PropertyName == wxT("LANGUAGE")){
740 NicknamesListLanguage->erase(*NicknameCount);
741 NicknamesListLanguage->insert(std::make_pair(*NicknameCount, PropertyValue));
745 // Something else we don't know about so append
746 // to the tokens variable.
748 if (!PropertyName.IsEmpty() && !PropertyValue.IsEmpty() && PropertyName != wxT("TYPE")){
750 if (FirstToken == TRUE){
752 PropertyTokens.Append(PropertyName + wxT("=") + PropertyValue);
757 PropertyTokens.Append(wxT(";") + PropertyName + wxT("=") + PropertyValue);
767 NicknamesList->insert(std::make_pair(*NicknameCount, PropertySeg2));
769 // Add the name token data.
771 if (!PropertyTokens.IsEmpty()){
773 NicknamesListTokens->insert(std::make_pair(*NicknameCount, PropertyTokens));
779 void ContactDataObject::ProcessGender(wxString PropertySeg1, wxString PropertySeg2){
781 std::map<int, int> SplitPoints;
782 std::map<int, int> SplitLength;
783 std::map<int, int>::iterator SLiter;
784 wxString PropertyData;
785 wxString PropertyName;
786 wxString PropertyValue;
787 wxString PropertyTokens;
788 bool FirstToken = TRUE;
789 int intPrevValue = 8;
791 SplitValues(&PropertySeg1, &SplitPoints, &SplitLength, intPrevValue);
795 for (std::map<int, int>::iterator intiter = SplitPoints.begin();
796 intiter != SplitPoints.end(); ++intiter){
798 SLiter = SplitLength.find(intiter->first);
800 PropertyData = PropertySeg1.Mid(intPrevValue, (SLiter->second));
802 wxStringTokenizer PropertyElement (PropertyData, wxT("="));
803 PropertyName = PropertyElement.GetNextToken();
804 PropertyValue = PropertyElement.GetNextToken();
806 intPrevValue = intiter->second;
808 // Process properties.
810 size_t intPropertyValueLen = PropertyValue.Len();
812 if (PropertyValue.Mid((intPropertyValueLen - 1), 1) == wxT("\"")){
814 PropertyValue.Trim();
815 PropertyValue.RemoveLast();
819 if (PropertyValue.Mid(0, 1) == wxT("\"")){
821 PropertyValue.Remove(0, 1);
825 if (!PropertyName.IsEmpty() && !PropertyValue.IsEmpty()){
827 if (FirstToken == TRUE){
829 PropertyTokens.Append(PropertyName + wxT("=") + PropertyValue);
834 PropertyTokens.Append(wxT(";") + PropertyName + wxT("=") + PropertyValue);
842 wxStringTokenizer GenderData (PropertySeg2, wxT(";"));
844 wxString GenderComponent;
846 if (GenderData.CountTokens() >= 2){
848 Gender = GenderData.GetNextToken();
849 GenderDetails = GenderData.GetString();
851 CaptureString(&GenderDetails, FALSE);
855 Gender = GenderData.GetNextToken();
859 if (!PropertyTokens.IsEmpty()){
861 GenderTokens = PropertyTokens;
867 void ContactDataObject::ProcessBirthday(wxString PropertySeg1, wxString PropertySeg2){
869 // Process date. Preserve the remainder in the string.
871 std::map<int, int> SplitPoints;
872 std::map<int, int> SplitLength;
873 std::map<int, int>::iterator SLiter;
874 wxString PropertyData;
875 wxString PropertyName;
876 wxString PropertyValue;
877 wxString PropertyTokens;
878 bool BirthdayText = FALSE;
879 int intPrevValue = 6;
881 SplitValues(&PropertySeg1, &SplitPoints, &SplitLength, intPrevValue);
885 // Look for type before continuing.
887 for (std::map<int, int>::iterator intiter = SplitPoints.begin();
888 intiter != SplitPoints.end(); ++intiter){
890 SLiter = SplitLength.find(intiter->first);
892 PropertyData = PropertySeg1.Mid(intPrevValue, SLiter->second);
894 wxStringTokenizer PropertyElement (PropertyData, wxT("="));
895 PropertyName = PropertyElement.GetNextToken();
896 PropertyValue = PropertyElement.GetNextToken();
898 intPrevValue = intiter->second;
900 if (PropertyName == wxT("VALUE") && PropertyValue == wxT("text") && BirthdayText == FALSE){
902 CaptureString(&PropertySeg2, FALSE);
903 Birthday = PropertySeg2;
910 // Setup blank lines for later on.
913 bool FirstToken = TRUE;
915 for (std::map<int, int>::iterator intiter = SplitPoints.begin();
916 intiter != SplitPoints.end(); ++intiter){
918 SLiter = SplitLength.find(intiter->first);
920 PropertyData = PropertySeg1.Mid(intPrevValue, SLiter->second);
922 wxStringTokenizer PropertyElement (PropertyData, wxT("="));
923 PropertyName = PropertyElement.GetNextToken();
924 PropertyValue = PropertyElement.GetNextToken();
926 intPrevValue = intiter->second;
928 // Process properties.
930 CaptureString(&PropertyValue, FALSE);
932 if (PropertyValue.Mid((PropertyValue.Len() - 1), 1) == wxT("\"")){
934 PropertyValue.Trim();
935 PropertyValue.RemoveLast();
939 if (PropertyValue.Mid(0, 1) == wxT("\"")){
941 PropertyValue.Remove(0, 1);
945 if (PropertyName == wxT("ALTID")){
947 BirthdayAltID = PropertyValue;
949 } else if (PropertyName == wxT("CALSCALE")){
951 BirthdayCalScale = PropertyValue;
953 } else if (PropertyName != wxT("VALUE")) {
955 // Something else we don't know about so append
956 // to the tokens variable.
958 if (!PropertyName.IsEmpty() && !PropertyValue.IsEmpty()){
960 if (FirstToken == TRUE){
962 PropertyTokens.Append(PropertyName + wxT("=") + PropertyValue);
967 PropertyTokens.Append(wxT(";") + PropertyName + wxT("=") + PropertyValue);
977 // Add the data to the variables and form.
979 if (BirthdayText == FALSE){
981 Birthday = PropertySeg2;
985 if (!PropertyTokens.IsEmpty()){
987 BirthdayTokens = PropertyTokens;
993 void ContactDataObject::ProcessAnniversary(wxString PropertySeg1, wxString PropertySeg2){
995 // Process date. Preserve the remainder in the string.
997 std::map<int, int> SplitPoints;
998 std::map<int, int> SplitLength;
999 std::map<int, int>::iterator SLiter;
1000 wxString PropertyData;
1001 wxString PropertyName;
1002 wxString PropertyValue;
1003 wxString PropertyTokens;
1004 bool AnniversaryText = FALSE;
1005 int intPrevValue = 13;
1007 SplitValues(&PropertySeg1, &SplitPoints, &SplitLength, intPrevValue);
1011 // Look for type before continuing.
1013 for (std::map<int, int>::iterator intiter = SplitPoints.begin();
1014 intiter != SplitPoints.end(); ++intiter){
1016 SLiter = SplitLength.find(intiter->first);
1018 PropertyData = PropertySeg1.Mid(intPrevValue, SLiter->second);
1020 wxStringTokenizer PropertyElement (PropertyData, wxT("="));
1021 PropertyName = PropertyElement.GetNextToken();
1022 PropertyValue = PropertyElement.GetNextToken();
1024 intPrevValue = intiter->second;
1026 if (PropertyName == wxT("VALUE") && PropertyValue == wxT("text") && AnniversaryText == FALSE){
1028 CaptureString(&PropertySeg2, FALSE);
1029 Anniversary = PropertySeg2;
1030 AnniversaryText = TRUE;
1036 // Setup blank lines for later on.
1039 bool FirstToken = TRUE;
1041 for (std::map<int, int>::iterator intiter = SplitPoints.begin();
1042 intiter != SplitPoints.end(); ++intiter){
1044 SLiter = SplitLength.find(intiter->first);
1046 PropertyData = PropertySeg1.Mid(intPrevValue, SLiter->second);
1048 wxStringTokenizer PropertyElement (PropertyData, wxT("="));
1049 PropertyName = PropertyElement.GetNextToken();
1050 PropertyValue = PropertyElement.GetNextToken();
1052 intPrevValue = intiter->second;
1054 // Process properties.
1056 CaptureString(&PropertyValue, FALSE);
1058 if (PropertyValue.Mid((PropertyValue.Len() - 1), 1) == wxT("\"")){
1060 PropertyValue.Trim();
1061 PropertyValue.RemoveLast();
1065 if (PropertyValue.Mid(0, 1) == wxT("\"")){
1067 PropertyValue.Remove(0, 1);
1071 if (PropertyName == wxT("ALTID")){
1073 AnniversaryAltID = PropertyValue;
1075 } else if (PropertyName == wxT("CALSCALE")){
1077 AnniversaryCalScale = PropertyValue;
1079 } else if (PropertyName != wxT("VALUE")) {
1081 // Something else we don't know about so append
1082 // to the tokens variable.
1084 if (!PropertyName.IsEmpty() && !PropertyValue.IsEmpty()){
1086 if (FirstToken == TRUE){
1088 PropertyTokens.Append(PropertyName + wxT("=") + PropertyValue);
1093 PropertyTokens.Append(wxT(";") + PropertyName + wxT("=") + PropertyValue);
1103 // Add the data to the variables and form.
1105 if (AnniversaryText == FALSE){
1107 Anniversary = PropertySeg2;
1111 if (!PropertyTokens.IsEmpty()){
1113 AnniversaryTokens = PropertyTokens;
1119 void ContactDataObject::ProcessTimeZone(wxString PropertySeg1, wxString PropertySeg2, int *TimeZoneCount){
1121 std::map<int, int> SplitPoints;
1122 std::map<int, int> SplitLength;
1124 int intPrevValue = 4;
1127 SplitValues(&PropertySeg1, &SplitPoints, &SplitLength, intPrevValue);
1131 PropertyType PropType;
1133 // Look for type before continuing.
1135 CheckType(&PropertySeg1, &SplitPoints, &SplitLength, &intPrevValue, &PropType);
1139 std::map<int, wxString> *TZList = NULL;
1140 std::map<int, wxString> *TZListType = NULL;
1141 std::map<int, wxString> *TZListMediatype = NULL;
1142 std::map<int, wxString> *TZListAltID = NULL;
1143 std::map<int, wxString> *TZListPID = NULL;
1144 std::map<int, wxString> *TZListTokens = NULL;
1145 std::map<int, int> *TZListPref = NULL;
1149 TZList = &GeneralTZList;
1150 TZListType = &GeneralTZListType;
1151 TZListMediatype = &GeneralTZListMediatype;
1152 TZListAltID = &GeneralTZListAltID;
1153 TZListPID = &GeneralTZListPID;
1154 TZListTokens = &GeneralTZListTokens;
1155 TZListPref = &GeneralTZListPref;
1158 TZList = &HomeTZList;
1159 TZListType = &HomeTZListType;
1160 TZListMediatype = &HomeTZListMediatype;
1161 TZListAltID = &HomeTZListAltID;
1162 TZListPID = &HomeTZListPID;
1163 TZListTokens = &HomeTZListTokens;
1164 TZListPref = &HomeTZListPref;
1167 TZList = &BusinessTZList;
1168 TZListType = &BusinessTZListType;
1169 TZListMediatype = &BusinessTZListMediatype;
1170 TZListAltID = &BusinessTZListAltID;
1171 TZListPID = &BusinessTZListPID;
1172 TZListTokens = &BusinessTZListTokens;
1173 TZListPref = &BusinessTZListPref;
1177 std::map<int, int>::iterator SLiter;
1178 wxString PropertyData;
1179 wxString PropertyName;
1180 wxString PropertyValue;
1181 wxString PropertyTokens;
1182 bool FirstToken = TRUE;
1184 for (std::map<int, int>::iterator intiter = SplitPoints.begin();
1185 intiter != SplitPoints.end(); ++intiter){
1187 SLiter = SplitLength.find(intiter->first);
1189 PropertyData = PropertySeg1.Mid(intPrevValue, (SLiter->second));
1191 wxStringTokenizer PropertyElement (PropertyData, wxT("="));
1192 PropertyName = PropertyElement.GetNextToken();
1193 PropertyValue = PropertyElement.GetNextToken();
1195 intPrevValue = intiter->second;
1197 CaptureString(&PropertyValue, FALSE);
1199 if (PropertyName == wxT("ALTID")){
1201 TZListAltID->erase(*TimeZoneCount);
1202 TZListAltID->insert(std::make_pair(*TimeZoneCount, PropertyValue));
1204 } else if (PropertyName == wxT("PID")){
1206 TZListPID->erase(*TimeZoneCount);
1207 TZListPID->insert(std::make_pair(*TimeZoneCount, PropertyValue));
1209 } else if (PropertyName == wxT("PREF")){
1211 int PriorityNumber = 0;
1212 bool ValidNumber = TRUE;
1215 PriorityNumber = std::stoi(PropertyValue.ToStdString());
1218 catch(std::invalid_argument &e){
1219 ValidNumber = FALSE;
1222 if (ValidNumber == TRUE){
1224 TZListPref->erase(*TimeZoneCount);
1225 TZListPref->insert(std::make_pair(*TimeZoneCount, PriorityNumber));
1229 } else if (PropertyName == wxT("MEDIATYPE")){
1231 TZListMediatype->erase(*TimeZoneCount);
1232 TZListMediatype->insert(std::make_pair(*TimeZoneCount, PropertyValue));
1236 // Something else we don't know about so append
1237 // to the tokens variable.
1239 if (!PropertyName.IsEmpty() && !PropertyValue.IsEmpty() && PropertyName != wxT("TYPE")){
1241 if (FirstToken == TRUE){
1243 PropertyTokens.Append(PropertyName + wxT("=") + PropertyValue);
1248 PropertyTokens.Append(wxT(";") + PropertyName + wxT("=") + PropertyValue);
1258 TZList->insert(std::make_pair(*TimeZoneCount, PropertySeg2));
1260 // Add the name token data.
1262 if (!PropertyTokens.IsEmpty()){
1264 TZListTokens->insert(std::make_pair(*TimeZoneCount, PropertyTokens));
1271 void ContactDataObject::ProcessAddress(wxString PropertySeg1, wxString PropertySeg2, int *AddressCount){
1273 size_t intPropertyLen = PropertySeg1.Len();
1274 std::map<int, int> SplitPoints;
1275 std::map<int, int> SplitLength;
1276 std::map<int, int>::iterator SLiter;
1277 wxString PropertyData;
1278 wxString PropertyName;
1279 wxString PropertyValue;
1280 wxString PropertyTokens;
1281 wxString AddressLabel;
1282 wxString AddressLang;
1283 wxString AddressAltID;
1284 wxString AddressPID;
1285 wxString AddressTokens;
1286 wxString AddressGeo;
1287 wxString AddressTimezone;
1288 wxString AddressType;
1289 wxString AddressMediatype;
1290 wxString AddressPOBox;
1291 wxString AddressExtended;
1292 wxString AddressStreet;
1293 wxString AddressLocality;
1294 wxString AddressCity;
1295 wxString AddressRegion;
1296 wxString AddressPostalCode;
1297 wxString AddressCountry;
1298 bool FirstToken = TRUE;
1299 int intSplitsFound = 0;
1300 int intSplitSize = 0;
1301 int intPrevValue = 5;
1306 SplitValues(&PropertySeg1, &SplitPoints, &SplitLength, intPrevValue);
1310 PropertyType PropType;
1312 // Look for type before continuing.
1314 CheckType(&PropertySeg1, &SplitPoints, &SplitLength, &intPrevValue, &PropType);
1318 std::map<int, wxString> *AddressList = NULL;
1319 std::map<int, wxString> *AddressListTown = NULL;
1320 std::map<int, wxString> *AddressListCounty = NULL;
1321 std::map<int, wxString> *AddressListPostCode = NULL;
1322 std::map<int, wxString> *AddressListCountry = NULL;
1323 std::map<int, wxString> *AddressListLabel = NULL;
1324 std::map<int, wxString> *AddressListLang = NULL;
1325 std::map<int, wxString> *AddressListAltID = NULL;
1326 std::map<int, wxString> *AddressListPID = NULL;
1327 std::map<int, wxString> *AddressListTokens = NULL;
1328 std::map<int, wxString> *AddressListGeo = NULL;
1329 std::map<int, wxString> *AddressListTimezone = NULL;
1330 std::map<int, wxString> *AddressListType = NULL;
1331 std::map<int, wxString> *AddressListMediatype = NULL;
1332 std::map<int, int> *AddressListPref = NULL;
1336 AddressList = &GeneralAddressList;
1337 AddressListTown = &GeneralAddressListTown;
1338 AddressListCounty = &GeneralAddressListCounty;
1339 AddressListPostCode = &GeneralAddressListPostCode;
1340 AddressListCountry = &GeneralAddressListCountry;
1341 AddressListLabel = &GeneralAddressListLabel;
1342 AddressListLang = &GeneralAddressListLang;
1343 AddressListAltID = &GeneralAddressListAltID;
1344 AddressListPID = &GeneralAddressListPID;
1345 AddressListTokens = &GeneralAddressListTokens;
1346 AddressListGeo = &GeneralAddressListGeo;
1347 AddressListTimezone = &GeneralAddressListTimezone;
1348 AddressListType = &GeneralAddressListType;
1349 AddressListMediatype = &GeneralAddressListMediatype;
1350 AddressListPref = &GeneralAddressListPref;
1353 AddressList = &HomeAddressList;
1354 AddressListTown = &HomeAddressListTown;
1355 AddressListCounty = &HomeAddressListCounty;
1356 AddressListPostCode = &HomeAddressListPostCode;
1357 AddressListCountry = &HomeAddressListCountry;
1358 AddressListLabel = &HomeAddressListLabel;
1359 AddressListLang = &HomeAddressListLang;
1360 AddressListAltID = &HomeAddressListAltID;
1361 AddressListPID = &HomeAddressListPID;
1362 AddressListTokens = &HomeAddressListTokens;
1363 AddressListGeo = &HomeAddressListGeo;
1364 AddressListTimezone = &HomeAddressListTimezone;
1365 AddressListType = &HomeAddressListType;
1366 AddressListMediatype = &HomeAddressListMediatype;
1367 AddressListPref = &HomeAddressListPref;
1370 AddressList = &BusinessAddressList;
1371 AddressListTown = &BusinessAddressListTown;
1372 AddressListCounty = &BusinessAddressListCounty;
1373 AddressListPostCode = &BusinessAddressListPostCode;
1374 AddressListCountry = &BusinessAddressListCountry;
1375 AddressListLabel = &BusinessAddressListLabel;
1376 AddressListLang = &BusinessAddressListLang;
1377 AddressListAltID = &BusinessAddressListAltID;
1378 AddressListPID = &BusinessAddressListPID;
1379 AddressListTokens = &BusinessAddressListTokens;
1380 AddressListGeo = &BusinessAddressListGeo;
1381 AddressListTimezone = &BusinessAddressListTimezone;
1382 AddressListType = &BusinessAddressListType;
1383 AddressListMediatype = &BusinessAddressListMediatype;
1384 AddressListPref = &BusinessAddressListPref;
1390 for (std::map<int, int>::iterator intiter = SplitPoints.begin();
1391 intiter != SplitPoints.end(); ++intiter){
1393 SLiter = SplitLength.find(intiter->first);
1395 PropertyData = PropertySeg1.Mid(intPrevValue, (SLiter->second));
1397 wxStringTokenizer PropertyElement (PropertyData, wxT("="));
1398 PropertyName = PropertyElement.GetNextToken();
1399 PropertyValue = PropertyElement.GetNextToken();
1401 intPrevValue = intiter->second;
1403 CaptureString(&PropertyValue, FALSE);
1405 // Process properties.
1407 if (PropertyName == wxT("LABEL")){
1409 AddressListLabel->erase(*AddressCount);
1410 AddressListLabel->insert(std::make_pair(*AddressCount, PropertyValue));
1412 } else if (PropertyName == wxT("LANGUAGE")){
1414 AddressListLang->erase(*AddressCount);
1415 AddressListLang->insert(std::make_pair(*AddressCount, PropertyValue));
1417 } else if (PropertyName == wxT("ALTID")){
1419 AddressListAltID->erase(*AddressCount);
1420 AddressListAltID->insert(std::make_pair(*AddressCount, PropertyValue));
1422 } else if (PropertyName == wxT("PID")){
1424 AddressListPID->erase(*AddressCount);
1425 AddressListPID->insert(std::make_pair(*AddressCount, PropertyValue));
1427 } else if (PropertyName == wxT("GEO")){
1429 AddressListGeo->erase(*AddressCount);
1430 AddressListGeo->insert(std::make_pair(*AddressCount, PropertyValue));
1432 } else if (PropertyName == wxT("TZ")){
1434 AddressListTimezone->erase(*AddressCount);
1435 AddressListTimezone->insert(std::make_pair(*AddressCount, PropertyValue));
1437 } else if (PropertyName == wxT("MEDIATYPE")){
1439 AddressListMediatype->erase(*AddressCount);
1440 AddressListMediatype->insert(std::make_pair(*AddressCount, PropertyValue));
1442 } else if (PropertyName == wxT("PREF")){
1444 int PriorityNumber = 0;
1445 bool ValidNumber = TRUE;
1448 PriorityNumber = std::stoi(PropertyValue.ToStdString());
1451 catch(std::invalid_argument &e){
1452 ValidNumber = FALSE;
1455 if (ValidNumber == TRUE){
1457 AddressListPref->erase(*AddressCount);
1458 AddressListPref->insert(std::make_pair(*AddressCount, PriorityNumber));
1464 if (!PropertyName.IsEmpty() && !PropertyValue.IsEmpty() && PropertyName != wxT("TYPE")){
1466 if (FirstToken == TRUE){
1468 PropertyTokens.Append(PropertyName + wxT("=") + PropertyValue);
1473 PropertyTokens.Append(wxT(";") + PropertyName + wxT("=") + PropertyValue);
1483 // Split the address.
1485 //std::map<int, int>::iterator SLiter;
1486 intPropertyLen = PropertySeg2.Len();
1487 SplitPoints.clear();
1488 SplitLength.clear();
1493 for (int i = 0; i <= intPropertyLen; i++){
1497 if (PropertySeg2.Mid(i, 1) == wxT(";") && PropertySeg2.Mid((i - 1), 1) != wxT("\\")){
1500 SplitPoints.insert(std::make_pair(intSplitsFound, (i + 1)));
1502 if (intSplitsFound == 6){
1504 SplitLength.insert(std::make_pair(intSplitsFound, (intSplitSize - 1)));
1509 SplitLength.insert(std::make_pair(intSplitsFound, (intSplitSize - 1)));
1519 // Split the data into several parts.
1521 for (std::map<int, int>::iterator intiter = SplitPoints.begin();
1522 intiter != SplitPoints.end(); ++intiter){
1524 if (intiter->first == 1){
1526 // Deal with PO Box.
1528 SLiter = SplitLength.find(1);
1530 //txtSurname->SetValue(ContactData.Convert(wxSPropertySeg2.Mid(0, SLiter->second), TRUE));
1531 AddressPOBox = PropertySeg2.Mid(0, SLiter->second);
1532 intPrevValue = intiter->second;
1534 } else if (intiter->first == 2){
1536 // Deal with extended address.
1538 SLiter = SplitLength.find(2);
1540 AddressExtended = PropertySeg2.Mid(intPrevValue, SLiter->second);
1541 //txtForename->SetValue(ContactData.Convert(wxSPropertySeg2.Mid(intPrevValue, SLiter->second), TRUE));
1542 intPrevValue = intiter->second;
1544 } else if (intiter->first == 3){
1546 // Deal with street address.
1548 SLiter = SplitLength.find(3);
1550 AddressStreet = PropertySeg2.Mid(intPrevValue, SLiter->second);
1551 //txtOtherNames->SetValue(ContactData.Convert(wxSPropertySeg2.Mid(intPrevValue, SLiter->second), TRUE));
1552 intPrevValue = intiter->second;
1554 } else if (intiter->first == 4){
1556 // Deal with locality
1558 SLiter = SplitLength.find(4);
1560 AddressLocality = PropertySeg2.Mid(intPrevValue, SLiter->second);
1561 //txtTitle->SetValue(ContactData.Convert(wxSPropertySeg2.Mid(intPrevValue, SLiter->second), TRUE));
1562 intPrevValue = intiter->second;
1564 //txtSuffix->SetValue(ContactData.Convert(wxSPropertySeg2.Mid(intPrevValue), TRUE));
1566 } else if (intiter->first == 5){
1568 // Deal with region.
1570 SLiter = SplitLength.find(5);
1572 AddressRegion = PropertySeg2.Mid(intPrevValue, SLiter->second);
1573 //txtTitle->SetValue(ContactData.Convert(wxSPropertySeg2.Mid(intPrevValue, SLiter->second), TRUE));
1574 intPrevValue = intiter->second;
1576 //txtSuffix->SetValue(ContactData.Convert(wxSPropertySeg2.Mid(intPrevValue), TRUE));
1578 } else if (intiter->first == 6){
1580 // Deal with post code.
1582 SLiter = SplitLength.find(6);
1584 AddressPostalCode = PropertySeg2.Mid(intPrevValue, SLiter->second);
1585 //txtTitle->SetValue(ContactData.Convert(wxSPropertySeg2.Mid(intPrevValue, SLiter->second), TRUE));
1586 intPrevValue = intiter->second;
1588 // Deal with country.
1590 AddressCountry = PropertySeg2.Mid(intPrevValue, wxString::npos);
1591 //txtSuffix->SetValue(ContactData.Convert(wxSPropertySeg2.Mid(intPrevValue), TRUE));
1599 // Add the data to the General/Home/Work address variables.
1601 CaptureString(&AddressStreet, FALSE);
1602 CaptureString(&AddressLocality, FALSE);
1603 CaptureString(&AddressRegion, FALSE);
1604 CaptureString(&AddressPostalCode, FALSE);
1605 CaptureString(&AddressCountry, FALSE);
1607 if (!PropertyTokens.IsEmpty()){
1609 AddressListTokens->insert(std::make_pair(*AddressCount, PropertyTokens));
1613 AddressListCountry->insert(std::make_pair(*AddressCount, AddressCountry));
1614 AddressList->insert(std::make_pair(*AddressCount, AddressStreet));
1615 AddressListTown->insert(std::make_pair(*AddressCount, AddressLocality));
1616 AddressListCounty->insert(std::make_pair(*AddressCount, AddressRegion));
1617 AddressListPostCode->insert(std::make_pair(*AddressCount, AddressPostalCode));
1621 AddressListType->insert(std::make_pair(*AddressCount, wxT("")));
1624 AddressListType->insert(std::make_pair(*AddressCount, wxT("home")));
1627 AddressListType->insert(std::make_pair(*AddressCount, wxT("work")));
1631 AddressListTokens->insert(std::make_pair(*AddressCount, PropertyTokens));
1635 void SplitValues(wxString *PropertyLine,
1636 std::map<int,int> *SplitPoints,
1637 std::map<int,int> *SplitLength,
1640 size_t intPropertyLen = PropertyLine->Len();
1641 int intSplitsFound = 0;
1642 int intSplitSize = 0;
1643 int intSplitSeek = 0;
1645 for (int i = intSize; i <= intPropertyLen; i++){
1649 if (PropertyLine->Mid(i, 1) == wxT(";") &&
1650 PropertyLine->Mid((i - 1), 1) != wxT("\\")){
1652 if (intSplitsFound == 0){
1654 SplitLength->insert(std::make_pair(intSplitsFound, (intSplitSize)));
1658 SplitLength->insert(std::make_pair(intSplitsFound, (intSplitSize - 1)));
1662 SplitPoints->insert(std::make_pair(intSplitsFound, (i + 1)));
1672 if (intSplitsFound == 0){
1674 SplitPoints->insert(std::make_pair(intSplitsFound, (8 + 1)));
1675 SplitLength->insert(std::make_pair(intSplitsFound, intSplitSize));
1679 SplitPoints->insert(std::make_pair(intSplitsFound, (intSplitSeek + 1)));
1680 SplitLength->insert(std::make_pair(intSplitsFound, intSplitSize));
1686 void CheckType(wxString *PropertySeg1,
1687 std::map<int,int> *SplitPoints,
1688 std::map<int,int> *SplitLength,
1690 PropertyType *PropType){
1692 wxString PropertyData;
1693 wxString PropertyName;
1694 wxString PropertyValue;
1695 std::map<int,int>::iterator SLiter;
1697 for (std::map<int, int>::iterator intiter = SplitPoints->begin();
1698 intiter != SplitPoints->end(); ++intiter){
1700 SLiter = SplitLength->find(intiter->first);
1702 PropertyData = PropertySeg1->Mid(*intPrevValue, (SLiter->second));
1704 wxStringTokenizer PropertyElement (PropertyData, wxT("="));
1705 PropertyName = PropertyElement.GetNextToken();
1706 PropertyValue = PropertyElement.GetNextToken();
1708 *intPrevValue = intiter->second;
1710 if (PropertyName == wxT("TYPE")){
1712 if (PropertyValue == wxT("work")){
1714 *PropType = PROPERTY_WORK;
1716 } else if (PropertyValue == wxT("home")){
1718 *PropType = PROPERTY_HOME;
1722 *PropType = PROPERTY_NONE;