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;
88 wxString PropertyLine;
89 wxString PropertySeg1;
90 wxString PropertySeg2;
91 wxString PropertyNextLine;
94 for (std::map<int,wxString>::iterator iter = ContactFileLines.begin();
95 iter != ContactFileLines.end(); ++iter){
103 PropertyLine.Clear();
104 PropertySeg1.Clear();
105 PropertySeg2.Clear();
108 ContactLine = iter->second;
110 while (ExtraLineSeek == TRUE){
112 // Check if there is extra data on the next line
113 // (indicated by space or tab at the start) and add data.
117 if (iter == ContactFileLines.end()){
124 PropertyNextLine = iter->second;
126 if (PropertyNextLine.Mid(0, 1) == wxT(" ") || PropertyNextLine.Mid(0, 1) == wxT("\t")){
128 PropertyNextLine.Remove(0, 1);
129 ContactLine.Append(PropertyNextLine);
134 ExtraLineSeek = FALSE;
140 ContactLineLen = ContactLine.Len();
142 // Make sure we are not in quotation mode.
143 // Make sure colon does not have \ or \\ before it.
145 for (int i = 0; i <= ContactLineLen; i++){
147 if ((ContactLine.Mid(i, 1) == wxT(";") || ContactLine.Mid(i, 1) == wxT(":")) && PropertyFind == TRUE){
149 PropertyFind = FALSE;
151 } else if (PropertyFind == TRUE){
153 Property.Append(ContactLine.Mid(i, 1));
157 if (ContactLine.Mid(i, 1) == wxT("\"")){
159 if (QuoteMode == TRUE){
171 if (ContactLine.Mid(i, 1) == wxT(":") && ContactLine.Mid((i - 1), 1) != wxT("\\") && QuoteMode == FALSE){
180 // Split that line at the point into two variables (ignore the colon).
182 PropertySeg1 = ContactLine.Mid(0, QuoteBreakPoint);
183 PropertySeg2 = ContactLine.Mid((QuoteBreakPoint + 1));
185 if (Property == wxT("KIND") && KindProcessed == FALSE){
187 ProcessKind(PropertySeg2);
189 } else if (Property == wxT("MEMBER")){
191 ProcessMember(PropertySeg1, PropertySeg2, &GroupCount);
194 } else if (Property == wxT("FN")){
196 ProcessFN(PropertySeg1, PropertySeg2, &FNCount);
199 } else if (Property == wxT("N") && NameProcessed == FALSE){
201 ProcessN(PropertySeg1, PropertySeg2);
202 NameProcessed = TRUE;
204 } else if (Property == wxT("NICKNAME")){
206 ProcessNickname(PropertySeg1, PropertySeg2, &NicknameCount);
209 } else if (Property == wxT("GENDER") && GenderProcessed == FALSE){
211 ProcessGender(PropertySeg1, PropertySeg2);
212 GenderProcessed = TRUE;
214 } else if (Property == wxT("BDAY") && BirthdayProcessed == FALSE){
216 ProcessBirthday(PropertySeg1, PropertySeg2);
217 BirthdayProcessed = TRUE;
219 } else if (Property == wxT("ANNIVERSARY") && AnniversaryProcessed == FALSE){
221 ProcessAnniversary(PropertySeg1, PropertySeg2);
222 AnniversaryProcessed = TRUE;
224 } else if (Property == wxT("TZ")){
226 ProcessTimeZone(PropertySeg1, PropertySeg2, &TimeZoneCount);
233 return CONTACTLOAD_OK;
237 void ContactDataObject::ProcessKind(wxString KindType){
239 if (KindType == wxT("individual")){
241 ContactKind = CONTACTKIND_INDIVIDUAL;
243 } else if (KindType == wxT("group")){
245 ContactKind = CONTACTKIND_GROUP;
247 } else if (KindType == wxT("org")){
249 ContactKind = CONTACTKIND_ORGANISATION;
251 } else if (KindType == wxT("location")){
253 ContactKind = CONTACTKIND_LOCATION;
257 ContactKind = CONTACTKIND_NONE;
262 void ContactDataObject::ProcessMember(wxString PropertySeg1, wxString PropertySeg2, int *GroupCount){
264 std::map<int, int> SplitPoints;
265 std::map<int, int> SplitLength;
267 int intPrevValue = 8;
271 SplitValues(&PropertySeg1, &SplitPoints, &SplitLength, intPrevValue);
275 wxString PropertyName;
276 wxString PropertyValue;
277 wxString PropertyData;
278 wxString PropertyTokens;
279 std::map<int,int>::iterator SLiter;
280 bool FirstToken = TRUE;
282 for (std::map<int, int>::iterator intiter = SplitPoints.begin();
283 intiter != SplitPoints.end(); ++intiter){
285 SLiter = SplitLength.find(intiter->first);
287 PropertyData = PropertySeg1.Mid(intPrevValue, (SLiter->second));
289 wxStringTokenizer PropertyElement (PropertyData, wxT("="));
290 PropertyName = PropertyElement.GetNextToken();
291 PropertyValue = PropertyElement.GetNextToken();
293 intPrevValue = intiter->second;
295 CaptureString(&PropertyValue, FALSE);
297 if (PropertyName == wxT("ALTID")){
299 GroupsListAltID.erase(*GroupCount);
300 GroupsListAltID.insert(std::make_pair(*GroupCount, PropertyValue));
302 } else if (PropertyName == wxT("PID")){
304 GroupsListPID.erase(*GroupCount);
305 GroupsListPID.insert(std::make_pair(*GroupCount, PropertyValue));
307 } else if (PropertyName == wxT("PREF")){
309 int PriorityNumber = 0;
310 bool ValidNumber = TRUE;
313 PriorityNumber = std::stoi(PropertyValue.ToStdString());
316 catch(std::invalid_argument &e){
320 if (ValidNumber == TRUE){
322 GroupsListPref.erase(*GroupCount);
323 GroupsListPref.insert(std::make_pair(*GroupCount, PriorityNumber));
327 } else if (PropertyName == wxT("MEDIATYPE")){
329 GroupsListMediaType.erase(*GroupCount);
330 GroupsListMediaType.insert(std::make_pair(*GroupCount, PropertyValue));
332 } else if (!PropertyName.IsEmpty() && !PropertyValue.IsEmpty()){
334 if (FirstToken == TRUE){
336 PropertyTokens.Append(PropertyName + wxT("=") + PropertyValue);
341 PropertyTokens.Append(wxT(";") + PropertyName + wxT("=") + PropertyValue);
349 GroupsList.insert(std::make_pair(*GroupCount, PropertySeg2));
351 if (!PropertyTokens.IsEmpty()){
353 GroupsListTokens.insert(std::make_pair(*GroupCount, PropertyTokens));
360 void ContactDataObject::ProcessFN(wxString PropertySeg1, wxString PropertySeg2, int *FNCount){
362 std::map<int, int> SplitPoints;
363 std::map<int, int> SplitLength;
365 int intPrevValue = 4;
369 SplitValues(&PropertySeg1, &SplitPoints, &SplitLength, intPrevValue);
373 wxString PropertyName;
374 wxString PropertyValue;
375 wxString PropertyData;
376 wxString PropertyTokens;
377 std::map<int,int>::iterator SLiter;
378 bool FirstToken = TRUE;
380 for (std::map<int, int>::iterator intiter = SplitPoints.begin();
381 intiter != SplitPoints.end(); ++intiter){
383 SLiter = SplitLength.find(intiter->first);
385 PropertyData = PropertySeg1.Mid(intPrevValue, (SLiter->second));
387 wxStringTokenizer PropertyElement (PropertyData, wxT("="));
388 PropertyName = PropertyElement.GetNextToken();
389 PropertyValue = PropertyElement.GetNextToken();
391 intPrevValue = intiter->second;
393 CaptureString(&PropertyValue, FALSE);
395 if (PropertyName == wxT("TYPE")){
397 if (!PropertyValue.IsEmpty() || PropertyValue == wxT("home") ||
398 PropertyValue == wxT("work") ){
400 FullNamesListType.erase(*FNCount);
401 FullNamesListType.insert(std::make_pair(*FNCount, PropertyValue));
405 } else if (PropertyName == wxT("LANGUAGE")){
407 FullNamesListLanguage.erase(*FNCount);
408 FullNamesListLanguage.insert(std::make_pair(*FNCount, PropertyValue));
410 } else if (PropertyName == wxT("ALTID")){
412 FullNamesListAltID.erase(*FNCount);
413 FullNamesListAltID.insert(std::make_pair(*FNCount, PropertyValue));
415 } else if (PropertyName == wxT("PID")){
417 FullNamesListPID.erase(*FNCount);
418 FullNamesListPID.insert(std::make_pair(*FNCount, PropertyValue));
420 } else if (PropertyName == wxT("PREF")){
422 int PriorityNumber = 0;
423 bool ValidNumber = TRUE;
426 PriorityNumber = std::stoi(PropertyValue.ToStdString());
429 catch(std::invalid_argument &e){
433 if (ValidNumber == TRUE){
435 FullNamesListPref.erase(*FNCount);
436 FullNamesListPref.insert(std::make_pair(*FNCount, PriorityNumber));
440 } else if (!PropertyName.IsEmpty() && !PropertyValue.IsEmpty()){
442 if (FirstToken == TRUE){
444 PropertyTokens.Append(PropertyName + wxT("=") + PropertyValue);
449 PropertyTokens.Append(wxT(";") + PropertyName + wxT("=") + PropertyValue);
457 FullNamesList.insert(std::make_pair(*FNCount, PropertySeg2));
459 if (!PropertyTokens.IsEmpty()){
461 FullNamesListTokens.insert(std::make_pair(*FNCount, PropertyTokens));
467 void ContactDataObject::ProcessN(wxString PropertySeg1, wxString PropertySeg2){
469 std::map<int, int> SplitPoints;
470 std::map<int, int> SplitLength;
472 int intPrevValue = 3;
476 SplitValues(&PropertySeg1, &SplitPoints, &SplitLength, intPrevValue);
480 wxString PropertyName;
481 wxString PropertyValue;
482 wxString PropertyData;
483 wxString PropertyTokens;
484 std::map<int,int>::iterator SLiter;
485 bool FirstToken = TRUE;
487 for (std::map<int, int>::iterator intiter = SplitPoints.begin();
488 intiter != SplitPoints.end(); ++intiter){
490 SLiter = SplitLength.find(intiter->first);
492 PropertyData = PropertySeg1.Mid(intPrevValue, (SLiter->second));
494 wxStringTokenizer PropertyElement (PropertyData, wxT("="));
495 PropertyName = PropertyElement.GetNextToken();
496 PropertyValue = PropertyElement.GetNextToken();
498 intPrevValue = intiter->second;
500 CaptureString(&PropertyValue, FALSE);
502 if (PropertyName == wxT("ALTID")){
504 NameAltID = PropertyValue;
506 } else if (PropertyName == wxT("LANGUAGE")){
508 NameLanguage = PropertyValue;
510 } else if (PropertyName == wxT("SORT-AS")){
512 if (PropertyValue.Left(1) == wxT("\"") && PropertyValue.Right(1) == wxT("\"") &&
513 PropertyValue.Len() >= 3){
514 NameDisplayAs = PropertyValue.Mid(1, (PropertyValue.Len() - 2));
517 } else if (!PropertyName.IsEmpty() && !PropertyValue.IsEmpty()){
519 if (FirstToken == TRUE){
521 PropertyTokens.Append(PropertyName + wxT("=") + PropertyValue);
526 PropertyTokens.Append(wxT(";") + PropertyName + wxT("=") + PropertyValue);
534 // Split the name data.
536 int intSplitSeek = 0;
537 int intSplitsFound = 0;
538 int intSplitSize = 0;
539 int intPropertyLen = PropertySeg2.Len();
541 std::map<int,wxString> NameValues;
544 for (int i = 0; i <= intPropertyLen; i++){
546 if (PropertySeg2.Mid(i, 1) == wxT(";") && PropertySeg2.Mid((i - 1), 1) != wxT("\\")){
548 NameValues.insert(std::make_pair(++intSplitsFound, PropertySeg2.Mid(intSplitSeek, intSplitSize)));
553 if (intSplitsFound == 4){
555 NameValues.insert(std::make_pair(++intSplitsFound, PropertySeg2.Mid(intSplitSeek, wxString::npos)));
569 // Split the data into several parts.
571 for (std::map<int, wxString>::iterator iter = NameValues.begin();
572 iter != NameValues.end(); ++iter){
574 if (iter->first == 1){
576 // Deal with family name.
578 NameSurname = iter->second;
580 } else if (iter->first == 2){
582 // Deal with given names.
584 NameForename = iter->second;
586 } else if (iter->first == 3){
588 // Deal with additional names.
590 NameOtherNames = iter->second;
592 } else if (iter->first == 4){
594 // Deal with honorifix prefixes and suffixes.
596 NameTitle = iter->second;
600 if (iter == NameValues.end()){
606 NameSuffix = iter->second;
612 // Add the name token data.
614 if (!PropertyTokens.IsEmpty()){
616 NameTokens = PropertyTokens;
622 void ContactDataObject::ProcessNickname(wxString PropertySeg1, wxString PropertySeg2, int *NicknameCount){
624 std::map<int, int> SplitPoints;
625 std::map<int, int> SplitLength;
627 int intPrevValue = 10;
630 SplitValues(&PropertySeg1, &SplitPoints, &SplitLength, intPrevValue);
634 PropertyType PropType;
636 // Look for type before continuing.
638 CheckType(&PropertySeg1, &SplitPoints, &SplitLength, &intPrevValue, &PropType);
642 std::map<int, wxString> *NicknamesList = NULL;
643 std::map<int, wxString> *NicknamesListType = NULL;
644 std::map<int, wxString> *NicknamesListLanguage = NULL;
645 std::map<int, wxString> *NicknamesListAltID = NULL;
646 std::map<int, wxString> *NicknamesListPID = NULL;
647 std::map<int, wxString> *NicknamesListTokens = NULL;
648 std::map<int, int> *NicknamesListPref = NULL;
652 NicknamesList = &GeneralNicknamesList;
653 NicknamesListType = &GeneralNicknamesListType;
654 NicknamesListLanguage = &GeneralNicknamesListLanguage;
655 NicknamesListAltID = &GeneralNicknamesListAltID;
656 NicknamesListPID = &GeneralNicknamesListPID;
657 NicknamesListTokens = &GeneralNicknamesListTokens;
658 NicknamesListPref = &GeneralNicknamesListPref;
661 NicknamesList = &HomeNicknamesList;
662 NicknamesListType = &HomeNicknamesListType;
663 NicknamesListLanguage = &HomeNicknamesListLanguage;
664 NicknamesListAltID = &HomeNicknamesListAltID;
665 NicknamesListPID = &HomeNicknamesListPID;
666 NicknamesListTokens = &HomeNicknamesListTokens;
667 NicknamesListPref = &HomeNicknamesListPref;
670 NicknamesList = &BusinessNicknamesList;
671 NicknamesListType = &BusinessNicknamesListType;
672 NicknamesListLanguage = &BusinessNicknamesListLanguage;
673 NicknamesListAltID = &BusinessNicknamesListAltID;
674 NicknamesListPID = &BusinessNicknamesListPID;
675 NicknamesListTokens = &BusinessNicknamesListTokens;
676 NicknamesListPref = &BusinessNicknamesListPref;
680 std::map<int, int>::iterator SLiter;
681 wxString PropertyData;
682 wxString PropertyName;
683 wxString PropertyValue;
684 wxString PropertyTokens;
685 bool FirstToken = TRUE;
687 for (std::map<int, int>::iterator intiter = SplitPoints.begin();
688 intiter != SplitPoints.end(); ++intiter){
690 SLiter = SplitLength.find(intiter->first);
692 PropertyData = PropertySeg1.Mid(intPrevValue, (SLiter->second));
694 wxStringTokenizer PropertyElement (PropertyData, wxT("="));
695 PropertyName = PropertyElement.GetNextToken();
696 PropertyValue = PropertyElement.GetNextToken();
698 intPrevValue = intiter->second;
700 CaptureString(&PropertyValue, FALSE);
702 if (PropertyName == wxT("ALTID")){
704 NicknamesListAltID->erase(*NicknameCount);
705 NicknamesListAltID->insert(std::make_pair(*NicknameCount, PropertyValue));
707 } else if (PropertyName == wxT("PID")){
709 NicknamesListPID->erase(*NicknameCount);
710 NicknamesListPID->insert(std::make_pair(*NicknameCount, PropertyValue));
712 } else if (PropertyName == wxT("PREF")){
714 int PriorityNumber = 0;
715 bool ValidNumber = TRUE;
718 PriorityNumber = std::stoi(PropertyValue.ToStdString());
721 catch(std::invalid_argument &e){
725 if (ValidNumber == TRUE){
727 NicknamesListPref->erase(*NicknameCount);
728 NicknamesListPref->insert(std::make_pair(*NicknameCount, PriorityNumber));
732 } else if (PropertyName == wxT("LANGUAGE")){
734 NicknamesListLanguage->erase(*NicknameCount);
735 NicknamesListLanguage->insert(std::make_pair(*NicknameCount, PropertyValue));
739 // Something else we don't know about so append
740 // to the tokens variable.
742 if (!PropertyName.IsEmpty() && !PropertyValue.IsEmpty() && PropertyName != wxT("TYPE")){
744 if (FirstToken == TRUE){
746 PropertyTokens.Append(PropertyName + wxT("=") + PropertyValue);
751 PropertyTokens.Append(wxT(";") + PropertyName + wxT("=") + PropertyValue);
761 NicknamesList->insert(std::make_pair(*NicknameCount, PropertySeg2));
763 // Add the name token data.
765 if (!PropertyTokens.IsEmpty()){
767 NicknamesListTokens->insert(std::make_pair(*NicknameCount, PropertyTokens));
773 void ContactDataObject::ProcessGender(wxString PropertySeg1, wxString PropertySeg2){
775 std::map<int, int> SplitPoints;
776 std::map<int, int> SplitLength;
777 std::map<int, int>::iterator SLiter;
778 wxString PropertyData;
779 wxString PropertyName;
780 wxString PropertyValue;
781 wxString PropertyTokens;
782 bool FirstToken = TRUE;
783 int intPrevValue = 8;
785 SplitValues(&PropertySeg1, &SplitPoints, &SplitLength, intPrevValue);
789 for (std::map<int, int>::iterator intiter = SplitPoints.begin();
790 intiter != SplitPoints.end(); ++intiter){
792 SLiter = SplitLength.find(intiter->first);
794 PropertyData = PropertySeg1.Mid(intPrevValue, (SLiter->second));
796 wxStringTokenizer PropertyElement (PropertyData, wxT("="));
797 PropertyName = PropertyElement.GetNextToken();
798 PropertyValue = PropertyElement.GetNextToken();
800 intPrevValue = intiter->second;
802 // Process properties.
804 size_t intPropertyValueLen = PropertyValue.Len();
806 if (PropertyValue.Mid((intPropertyValueLen - 1), 1) == wxT("\"")){
808 PropertyValue.Trim();
809 PropertyValue.RemoveLast();
813 if (PropertyValue.Mid(0, 1) == wxT("\"")){
815 PropertyValue.Remove(0, 1);
819 if (!PropertyName.IsEmpty() && !PropertyValue.IsEmpty()){
821 if (FirstToken == TRUE){
823 PropertyTokens.Append(PropertyName + wxT("=") + PropertyValue);
828 PropertyTokens.Append(wxT(";") + PropertyName + wxT("=") + PropertyValue);
836 wxStringTokenizer GenderData (PropertySeg2, wxT(";"));
838 wxString GenderComponent;
840 if (GenderData.CountTokens() >= 2){
842 Gender = GenderData.GetNextToken();
843 GenderDetails = GenderData.GetString();
845 CaptureString(&GenderDetails, FALSE);
849 Gender = GenderData.GetNextToken();
853 if (!PropertyTokens.IsEmpty()){
855 GenderTokens = PropertyTokens;
861 void ContactDataObject::ProcessBirthday(wxString PropertySeg1, wxString PropertySeg2){
863 // Process date. Preserve the remainder in the string.
865 std::map<int, int> SplitPoints;
866 std::map<int, int> SplitLength;
867 std::map<int, int>::iterator SLiter;
868 wxString PropertyData;
869 wxString PropertyName;
870 wxString PropertyValue;
871 wxString PropertyTokens;
872 bool BirthdayText = FALSE;
873 int intPrevValue = 6;
875 SplitValues(&PropertySeg1, &SplitPoints, &SplitLength, intPrevValue);
879 // Look for type before continuing.
881 for (std::map<int, int>::iterator intiter = SplitPoints.begin();
882 intiter != SplitPoints.end(); ++intiter){
884 SLiter = SplitLength.find(intiter->first);
886 PropertyData = PropertySeg1.Mid(intPrevValue, SLiter->second);
888 wxStringTokenizer PropertyElement (PropertyData, wxT("="));
889 PropertyName = PropertyElement.GetNextToken();
890 PropertyValue = PropertyElement.GetNextToken();
892 intPrevValue = intiter->second;
894 if (PropertyName == wxT("VALUE") && PropertyValue == wxT("text") && BirthdayText == FALSE){
896 CaptureString(&PropertySeg2, FALSE);
897 Birthday = PropertySeg2;
904 // Setup blank lines for later on.
907 bool FirstToken = TRUE;
909 for (std::map<int, int>::iterator intiter = SplitPoints.begin();
910 intiter != SplitPoints.end(); ++intiter){
912 SLiter = SplitLength.find(intiter->first);
914 PropertyData = PropertySeg1.Mid(intPrevValue, SLiter->second);
916 wxStringTokenizer PropertyElement (PropertyData, wxT("="));
917 PropertyName = PropertyElement.GetNextToken();
918 PropertyValue = PropertyElement.GetNextToken();
920 intPrevValue = intiter->second;
922 // Process properties.
924 CaptureString(&PropertyValue, FALSE);
926 if (PropertyValue.Mid((PropertyValue.Len() - 1), 1) == wxT("\"")){
928 PropertyValue.Trim();
929 PropertyValue.RemoveLast();
933 if (PropertyValue.Mid(0, 1) == wxT("\"")){
935 PropertyValue.Remove(0, 1);
939 if (PropertyName == wxT("ALTID")){
941 BirthdayAltID = PropertyValue;
943 } else if (PropertyName == wxT("CALSCALE")){
945 BirthdayCalScale = PropertyValue;
947 } else if (PropertyName != wxT("VALUE")) {
949 // Something else we don't know about so append
950 // to the tokens variable.
952 if (!PropertyName.IsEmpty() && !PropertyValue.IsEmpty()){
954 if (FirstToken == TRUE){
956 PropertyTokens.Append(PropertyName + wxT("=") + PropertyValue);
961 PropertyTokens.Append(wxT(";") + PropertyName + wxT("=") + PropertyValue);
971 // Add the data to the variables and form.
973 if (BirthdayText == FALSE){
975 Birthday = PropertySeg2;
979 if (!PropertyTokens.IsEmpty()){
981 BirthdayTokens = PropertyTokens;
987 void ContactDataObject::ProcessAnniversary(wxString PropertySeg1, wxString PropertySeg2){
989 // Process date. Preserve the remainder in the string.
991 std::map<int, int> SplitPoints;
992 std::map<int, int> SplitLength;
993 std::map<int, int>::iterator SLiter;
994 wxString PropertyData;
995 wxString PropertyName;
996 wxString PropertyValue;
997 wxString PropertyTokens;
998 bool AnniversaryText = FALSE;
999 int intPrevValue = 13;
1001 SplitValues(&PropertySeg1, &SplitPoints, &SplitLength, intPrevValue);
1005 // Look for type before continuing.
1007 for (std::map<int, int>::iterator intiter = SplitPoints.begin();
1008 intiter != SplitPoints.end(); ++intiter){
1010 SLiter = SplitLength.find(intiter->first);
1012 PropertyData = PropertySeg1.Mid(intPrevValue, SLiter->second);
1014 wxStringTokenizer PropertyElement (PropertyData, wxT("="));
1015 PropertyName = PropertyElement.GetNextToken();
1016 PropertyValue = PropertyElement.GetNextToken();
1018 intPrevValue = intiter->second;
1020 if (PropertyName == wxT("VALUE") && PropertyValue == wxT("text") && AnniversaryText == FALSE){
1022 CaptureString(&PropertySeg2, FALSE);
1023 Anniversary = PropertySeg2;
1024 AnniversaryText = TRUE;
1030 // Setup blank lines for later on.
1033 bool FirstToken = TRUE;
1035 for (std::map<int, int>::iterator intiter = SplitPoints.begin();
1036 intiter != SplitPoints.end(); ++intiter){
1038 SLiter = SplitLength.find(intiter->first);
1040 PropertyData = PropertySeg1.Mid(intPrevValue, SLiter->second);
1042 wxStringTokenizer PropertyElement (PropertyData, wxT("="));
1043 PropertyName = PropertyElement.GetNextToken();
1044 PropertyValue = PropertyElement.GetNextToken();
1046 intPrevValue = intiter->second;
1048 // Process properties.
1050 CaptureString(&PropertyValue, FALSE);
1052 if (PropertyValue.Mid((PropertyValue.Len() - 1), 1) == wxT("\"")){
1054 PropertyValue.Trim();
1055 PropertyValue.RemoveLast();
1059 if (PropertyValue.Mid(0, 1) == wxT("\"")){
1061 PropertyValue.Remove(0, 1);
1065 if (PropertyName == wxT("ALTID")){
1067 AnniversaryAltID = PropertyValue;
1069 } else if (PropertyName == wxT("CALSCALE")){
1071 AnniversaryCalScale = PropertyValue;
1073 } else if (PropertyName != wxT("VALUE")) {
1075 // Something else we don't know about so append
1076 // to the tokens variable.
1078 if (!PropertyName.IsEmpty() && !PropertyValue.IsEmpty()){
1080 if (FirstToken == TRUE){
1082 PropertyTokens.Append(PropertyName + wxT("=") + PropertyValue);
1087 PropertyTokens.Append(wxT(";") + PropertyName + wxT("=") + PropertyValue);
1097 // Add the data to the variables and form.
1099 if (AnniversaryText == FALSE){
1101 Anniversary = PropertySeg2;
1105 if (!PropertyTokens.IsEmpty()){
1107 AnniversaryTokens = PropertyTokens;
1113 void ContactDataObject::ProcessTimeZone(wxString PropertySeg1, wxString PropertySeg2, int *TimeZoneCount){
1115 std::map<int, int> SplitPoints;
1116 std::map<int, int> SplitLength;
1118 int intPrevValue = 4;
1121 SplitValues(&PropertySeg1, &SplitPoints, &SplitLength, intPrevValue);
1125 PropertyType PropType;
1127 // Look for type before continuing.
1129 CheckType(&PropertySeg1, &SplitPoints, &SplitLength, &intPrevValue, &PropType);
1133 std::map<int, wxString> *TZList = NULL;
1134 std::map<int, wxString> *TZListType = NULL;
1135 std::map<int, wxString> *TZListMediatype = NULL;
1136 std::map<int, wxString> *TZListAltID = NULL;
1137 std::map<int, wxString> *TZListPID = NULL;
1138 std::map<int, wxString> *TZListTokens = NULL;
1139 std::map<int, int> *TZListPref = NULL;
1143 TZList = &GeneralTZList;
1144 TZListType = &GeneralTZListType;
1145 TZListMediatype = &GeneralTZListMediatype;
1146 TZListAltID = &GeneralTZListAltID;
1147 TZListPID = &GeneralTZListPID;
1148 TZListTokens = &GeneralTZListTokens;
1149 TZListPref = &GeneralTZListPref;
1152 TZList = &HomeTZList;
1153 TZListType = &HomeTZListType;
1154 TZListMediatype = &HomeTZListMediatype;
1155 TZListAltID = &HomeTZListAltID;
1156 TZListPID = &HomeTZListPID;
1157 TZListTokens = &HomeTZListTokens;
1158 TZListPref = &HomeTZListPref;
1161 TZList = &BusinessTZList;
1162 TZListType = &BusinessTZListType;
1163 TZListMediatype = &BusinessTZListMediatype;
1164 TZListAltID = &BusinessTZListAltID;
1165 TZListPID = &BusinessTZListPID;
1166 TZListTokens = &BusinessTZListTokens;
1167 TZListPref = &BusinessTZListPref;
1171 std::map<int, int>::iterator SLiter;
1172 wxString PropertyData;
1173 wxString PropertyName;
1174 wxString PropertyValue;
1175 wxString PropertyTokens;
1176 bool FirstToken = TRUE;
1178 for (std::map<int, int>::iterator intiter = SplitPoints.begin();
1179 intiter != SplitPoints.end(); ++intiter){
1181 SLiter = SplitLength.find(intiter->first);
1183 PropertyData = PropertySeg1.Mid(intPrevValue, (SLiter->second));
1185 wxStringTokenizer PropertyElement (PropertyData, wxT("="));
1186 PropertyName = PropertyElement.GetNextToken();
1187 PropertyValue = PropertyElement.GetNextToken();
1189 intPrevValue = intiter->second;
1191 CaptureString(&PropertyValue, FALSE);
1193 if (PropertyName == wxT("ALTID")){
1195 TZListAltID->erase(*TimeZoneCount);
1196 TZListAltID->insert(std::make_pair(*TimeZoneCount, PropertyValue));
1198 } else if (PropertyName == wxT("PID")){
1200 TZListPID->erase(*TimeZoneCount);
1201 TZListPID->insert(std::make_pair(*TimeZoneCount, PropertyValue));
1203 } else if (PropertyName == wxT("PREF")){
1205 int PriorityNumber = 0;
1206 bool ValidNumber = TRUE;
1209 PriorityNumber = std::stoi(PropertyValue.ToStdString());
1212 catch(std::invalid_argument &e){
1213 ValidNumber = FALSE;
1216 if (ValidNumber == TRUE){
1218 TZListPref->erase(*TimeZoneCount);
1219 TZListPref->insert(std::make_pair(*TimeZoneCount, PriorityNumber));
1223 } else if (PropertyName == wxT("MEDIATYPE")){
1225 TZListMediatype->erase(*TimeZoneCount);
1226 TZListMediatype->insert(std::make_pair(*TimeZoneCount, PropertyValue));
1230 // Something else we don't know about so append
1231 // to the tokens variable.
1233 if (!PropertyName.IsEmpty() && !PropertyValue.IsEmpty() && PropertyName != wxT("TYPE")){
1235 if (FirstToken == TRUE){
1237 PropertyTokens.Append(PropertyName + wxT("=") + PropertyValue);
1242 PropertyTokens.Append(wxT(";") + PropertyName + wxT("=") + PropertyValue);
1252 TZList->insert(std::make_pair(*TimeZoneCount, PropertySeg2));
1254 // Add the name token data.
1256 if (!PropertyTokens.IsEmpty()){
1258 TZListTokens->insert(std::make_pair(*TimeZoneCount, PropertyTokens));
1265 void SplitValues(wxString *PropertyLine,
1266 std::map<int,int> *SplitPoints,
1267 std::map<int,int> *SplitLength,
1270 size_t intPropertyLen = PropertyLine->Len();
1271 int intSplitsFound = 0;
1272 int intSplitSize = 0;
1273 int intSplitSeek = 0;
1275 for (int i = intSize; i <= intPropertyLen; i++){
1279 if (PropertyLine->Mid(i, 1) == wxT(";") &&
1280 PropertyLine->Mid((i - 1), 1) != wxT("\\")){
1282 if (intSplitsFound == 0){
1284 SplitLength->insert(std::make_pair(intSplitsFound, (intSplitSize)));
1288 SplitLength->insert(std::make_pair(intSplitsFound, (intSplitSize - 1)));
1292 SplitPoints->insert(std::make_pair(intSplitsFound, (i + 1)));
1302 if (intSplitsFound == 0){
1304 SplitPoints->insert(std::make_pair(intSplitsFound, (8 + 1)));
1305 SplitLength->insert(std::make_pair(intSplitsFound, intSplitSize));
1309 SplitPoints->insert(std::make_pair(intSplitsFound, (intSplitSeek + 1)));
1310 SplitLength->insert(std::make_pair(intSplitsFound, intSplitSize));
1316 void CheckType(wxString *PropertySeg1,
1317 std::map<int,int> *SplitPoints,
1318 std::map<int,int> *SplitLength,
1320 PropertyType *PropType){
1322 wxString PropertyData;
1323 wxString PropertyName;
1324 wxString PropertyValue;
1325 std::map<int,int>::iterator SLiter;
1327 for (std::map<int, int>::iterator intiter = SplitPoints->begin();
1328 intiter != SplitPoints->end(); ++intiter){
1330 SLiter = SplitLength->find(intiter->first);
1332 PropertyData = PropertySeg1->Mid(*intPrevValue, (SLiter->second));
1334 wxStringTokenizer PropertyElement (PropertyData, wxT("="));
1335 PropertyName = PropertyElement.GetNextToken();
1336 PropertyValue = PropertyElement.GetNextToken();
1338 *intPrevValue = intiter->second;
1340 if (PropertyName == wxT("TYPE")){
1342 if (PropertyValue == wxT("work")){
1344 *PropType = PROPERTY_WORK;
1346 } else if (PropertyValue == wxT("home")){
1348 *PropType = PROPERTY_HOME;
1352 *PropType = PROPERTY_NONE;