4 #include <wx/tokenzr.h>
7 // vcard.cpp - Deals with vCard 4.0 formatted files meeting the
8 // RFC 6350 specification.
18 void vCard::Add(wxString SettingName, wxString SettingValue, bool ReplaceMode){
20 // Check for backslashes used for commas, newlines and
21 // backslashes used for values.
23 if (ReplaceMode == TRUE){
25 SettingValue.Replace(wxT("\\n"), wxT("\n"));
26 SettingValue.Replace(wxT("\\,"), wxT(","));
27 SettingValue.Replace(wxT("\\:"), wxT(":"));
28 SettingValue.Replace(wxT("\\\\"), wxT("\\"));
32 SettingValue.Replace(wxT("\\"), wxT("\\\\"));
33 SettingValue.Replace(wxT("\n"), wxT("\\n"));
34 SettingValue.Replace(wxT(","), wxT("\\,"));
35 SettingValue.Replace(wxT(":"), wxT("\\:"));
36 SettingValue = SettingValue + wxT("\n");
40 // Check data to make sure that it meets the required
41 // vCard 4.0 specifications.
43 if (SettingName == wxT("BEGIN") && SettingValue == wxT("VCARD")){
47 if (SettingName == wxT("END") && SettingValue == wxT("VCARD")){
51 if (SettingName == wxT("FN")){
55 if (SettingName == wxT("VERSION") && SettingValue == wxT("4.0")){
59 if (SettingName == wxT("VERSION") && SettingValue == wxT("3.0")){
63 if (SettingName == wxT("VERSION") && SettingValue == wxT("3.0")){
69 if (SettingValue.Right(2) != wxT("\r\n")){
71 SettingValue.Append(wxT("\r\n"));
75 SettingNames.Add(SettingName, 1);
76 SettingValues.Add(SettingValue, 1);
81 void vCard::AddRaw(wxString SettingName, wxString SettingValue){
83 // Check data to make sure that it meets the required
84 // vCard 4.0 specifications.
86 if (SettingName == wxT("BEGIN") && SettingValue == wxT("VCARD")){
90 if (SettingName == wxT("END") && SettingValue == wxT("VCARD")){
94 if (SettingName == wxT("FN")){
98 if (SettingName == wxT("VERSION") && SettingValue == wxT("4.0")){
102 if (SettingName == wxT("VERSION") && SettingValue == wxT("3.0")){
106 if (SettingName == wxT("VERSION") && SettingValue == wxT("3.0")){
112 if (SettingValue.Right(2) != wxT("\r\n")){
114 SettingValue.Append(wxT("\r\n"));
118 SettingNames.Add(SettingName, 1);
119 SettingValues.Add(SettingValue, 1);
124 wxString vCard::Get(wxString SettingName){
126 wxString SettingValue;
128 // Look for the setting name.
130 for (int i = 0; i < SettingCount; i++){
132 if (SettingNames[i] == SettingName){
134 SettingValue = SettingValues[i];
135 SettingValue.Trim(TRUE);
137 while (SettingValues[(i + 1)].Mid(0, 1) == wxT(" ") || SettingValues[(i + 1)].Mid(0, 1) == wxT("\t")){
140 SettingValue.Append(SettingValues[(i + 1)]);
149 return wxEmptyString;
153 vCardName vCard::GetName(){
156 ArrayvCardOutData NameArray = this->GetByPartial(wxT("N"));
157 //wxString NameDataGet = NameArray.PropValues[0];
158 wxString NameDataGet = NameArray.PropValues[0];
159 std::map<int, int> SplitPoints;
160 std::map<int, int> SplitLength;
161 std::map<int, int>::iterator SLiter;
163 // Process the name data to get the required information.
165 int intPropertyLen = NameDataGet.Len();
166 int intSplitSeek = 0;
167 int intSplitsFound = 0;
168 int intSplitSize = 0;
169 int intPrevValue = 0;
171 for (int i = 0; i <= intPropertyLen; i++){
175 if (NameDataGet.Mid(i, 1) == wxT(";") && NameDataGet.Mid((i - 1), 1) != wxT("\\")){
178 SplitPoints.insert(std::make_pair(intSplitsFound, (i + 1)));
180 if (intSplitsFound == 4){
182 SplitLength.insert(std::make_pair(intSplitsFound, (intSplitSize - 1)));
187 SplitLength.insert(std::make_pair(intSplitsFound, (intSplitSize - 1)));
197 for (std::map<int, int>::iterator intiter = SplitPoints.begin();
198 intiter != SplitPoints.end(); ++intiter){
200 if (intiter->first == 1){
202 // Deal with family name.
204 SLiter = SplitLength.find(1);
206 NameData.Surname = NameDataGet.Mid(0, SLiter->second);
207 intPrevValue = intiter->second;
209 } else if (intiter->first == 2){
211 // Deal with given names.
213 SLiter = SplitLength.find(2);
215 NameData.Forename = NameDataGet.Mid(intPrevValue, SLiter->second);
216 intPrevValue = intiter->second;
219 } else if (intiter->first == 3){
221 // Deal with additional names.
223 SLiter = SplitLength.find(3);
225 NameData.OtherNames = NameDataGet.Mid(intPrevValue, SLiter->second);
226 intPrevValue = intiter->second;
228 } else if (intiter->first == 4){
230 // Deal with honorifix prefixes and suffixes.
231 SLiter = SplitLength.find(4);
233 NameData.Title = NameDataGet.Mid(intPrevValue, SLiter->second);
234 intPrevValue = intiter->second;
235 NameData.Suffix = NameDataGet.Mid(intPrevValue);
246 ArrayvCardOutData vCard::GetByPartial(wxString SettingName){
248 ArrayvCardOutData vCardOutData;
249 wxArrayString SettingList;
250 wxString SettingValueCurrent;
251 wxString SettingValue;
254 bool FirstToken = TRUE;
256 SettingNameLen = SettingName.Len();
258 for (int i = 0; i < SettingCount; i++){
260 if (SettingNames[i].Mid(0, SettingNameLen) == SettingName){
262 SettingValue = SettingValues[i];
265 while (SettingValues[(i + 1)].Mid(0, 1) == wxT(" ") || SettingValues[(i + 1)].Mid(0, 1) == wxT("\t")){
267 if (FirstToken == TRUE){
269 SettingValue.Trim(FALSE);
270 SettingValue.Trim(TRUE);
275 SettingValueCurrent = SettingValues[(i + 1)];
276 SettingValueCurrent.Trim(FALSE);
277 SettingValueCurrent.Trim(TRUE);
279 SettingValue.Append(SettingValueCurrent);
285 //SettingList.Add(SettingNames[SettingNameSeek] + wxT(":") + SettingValue);
286 vCardOutData.PropData.Add(SettingNames[SettingNameSeek]);
287 vCardOutData.PropValues.Add(SettingValue);
288 vCardOutData.PropCount++;
293 /*for (int i = 0; i < SettingCount; i++){
294 if (SettingNames[i].Mid(0, SettingNameLen) == SettingName){
296 SettingValue = SettingValues[i];
299 while (SettingValues[(i + 1)].Mid(0, 1) == wxT(" ") || SettingValues[(i + 1)].Mid(0, 1) == wxT("\t")){
301 SettingValueCurrent = SettingValues[(i + 1)];
302 SettingValueCurrent.Trim(FALSE);
303 SettingValueCurrent.Trim(TRUE);
305 SettingValue.Append(SettingValueCurrent);
311 //SettingList.Add(SettingNames[SettingNameSeek] + wxT(":") + SettingValue);
312 vCardOutData.PropData.Add(SettingName);
313 vCardOutData.PropData.Add(SettingValue);
322 wxString vCard::GetById(int id){
327 int vCard::WriteFile(wxString WriteFilename){
329 // Open the file and begin writing data into the file.
331 wxString SettingName;
332 wxString SettingValue;
333 wxString SettingLine;
335 SettingCount = SettingNames.GetCount();
338 if (ContactFile.Create(WriteFilename, TRUE, wxS_DEFAULT) == FALSE){
342 for (int i = 0; i < SettingCount; i++){
344 SettingLine = SettingNames[i] + wxT(":") + SettingValues[i];
346 int SettingLineLen = SettingLine.Len();
348 int intTimes = floor((SettingLine.Len() / intDivider));
352 bool FirstLine = TRUE;
354 // Remember to round down the calculation.
356 while (intSeek < SettingLineLen){
358 if ((intLineSeek == intDivider && FirstLine == TRUE) ||
359 (intLineSeek == (intDivider - 1) && FirstLine == FALSE)){
361 SettingLine.insert(intSeek, wxT("\r\n "));
362 intSeek = intSeek + 3;
363 SettingLineLen = SettingLineLen + 3;
365 intPrevLine = intSeek;
377 for (int x = 0; x < intTimes; x++){
380 SettingLine.insert((intDivider - 1), wxT("\r\n "));
381 } else if (x == intTimes){
385 SettingLine.insert((intDivider * (x+1)) + (x * 3), wxT("\r\n "));
389 intTimes = floor(SettingLine.Len() / intDivider);
395 ContactFile.Write(SettingLine);
405 int vCard::LoadFile(wxString LoadFilename){
409 wxString wxSContactString;
411 vCardFilename = LoadFilename;
413 // Check if we are using wxWidgets version 2.8 or less and
414 // execute the required command accordingly.
416 #if wxABI_VERSION < 20900
417 ContactFile.Open(LoadFilename.c_str(), wxT("r"));
419 ContactFile.Open(LoadFilename, wxT("r"));
422 if (ContactFile.IsOpened() == FALSE){
428 ContactFile.ReadAll(&wxSContactString, wxConvAuto());
432 ProcessString(&wxSContactString);
438 int vCard::LoadString(wxString ContactData){
440 ProcessString(&ContactData);
446 void vCard::ProcessString(wxString *ContactDataInc){
448 // Split the vCards (if there are more than one vCard in the file).
450 wxString ContactLine;
453 bool ExtraLineSeek = FALSE;
454 int QuoteBreakPoint = 0;
456 bool PropertyFind = FALSE;
457 bool QuoteMode = FALSE;
459 wxString wxSPropertyNextLine;
460 wxString wxSProperty;
461 wxString wxSPropertySeg1;
462 wxString wxSPropertySeg2;
464 bool FoundBegin = FALSE;
465 bool FoundEnd = FALSE;
466 bool FirstContact = TRUE;
467 wxString FirstContactData;
468 wxString ContactData;
469 int ContactCount = 0;
471 wxStringTokenizer wSTContactFileLines(*ContactDataInc, wxT("\r\n"));
473 while(wSTContactFileLines.HasMoreTokens() == TRUE){
475 ContactLine = wSTContactFileLines.GetNextToken();
477 if (ContactLine == wxT("BEGIN:VCARD")){
479 if (FoundBegin == TRUE){
481 // No END:VCARD was found so discard current data.
485 if (FirstContact == TRUE){
487 FirstContactData.Clear();
495 FirstContactData.Append(ContactLine + wxT("\r\n"));
496 ContactData.Append(ContactLine + wxT("\r\n"));
498 } else if (ContactLine == wxT("END:VCARD") && FoundBegin == TRUE){
500 if (FirstContact == TRUE){
502 FirstContact = FALSE;
503 FirstContactData.Append(ContactLine + wxT("\r\n"));
507 ContactData.Append(ContactLine + wxT("\r\n"));
509 Cards.insert(std::make_pair(ContactCount, ContactData));
513 } else if (FoundBegin == TRUE){
515 if (FirstContact == TRUE){
517 FirstContactData.Append(ContactLine + wxT("\r\n"));
521 ContactData.Append(ContactLine + wxT("\r\n"));
531 std::map<int, wxString> ContactFileLines;
532 std::map<int, wxString>::iterator striter;
534 wxStringTokenizer wSTFirstContactLines(FirstContactData, wxT("\r\n"));
536 int ContactLineSeek = 0;
538 while (wSTFirstContactLines.HasMoreTokens() == TRUE){
540 ContactLine = wSTFirstContactLines.GetNextToken();
541 ContactFileLines.insert(std::make_pair(ContactLineSeek, ContactLine));
546 for (std::map<int,wxString>::iterator iter = ContactFileLines.begin();
547 iter != ContactFileLines.end(); ++iter){
549 // Find the colon which splits the start bit from the data part.
551 ContactLine = iter->second;
553 while (ExtraLineSeek == TRUE){
555 // Check if there is extra data on the next line
556 // (indicated by space or tab at the start) and add data.
560 if (iter == ContactFileLines.end()){
567 wxSPropertyNextLine = iter->second;
570 if (wxSPropertyNextLine.Mid(0, 1) == wxT(" ") || wxSPropertyNextLine.Mid(0, 1) == wxT("\t")){
572 wxSPropertyNextLine.Remove(0, 1);
573 //wxSPropertyNextLine.Trim(FALSE);
574 //ContactLine.Trim();
575 ContactLine.Append(wxSPropertyNextLine);
580 ExtraLineSeek = FALSE;
586 ContactLineLen = ContactLine.Len();
588 // Make sure we are not in quotation mode.
589 // Make sure colon does not have \ or \\ before it.
591 for (int i = 0; i <= ContactLineLen; i++){
593 if ((ContactLine.Mid(i, 1) == wxT(";") || ContactLine.Mid(i, 1) == wxT(":")) && PropertyFind == TRUE){
595 PropertyFind = FALSE;
597 } else if (PropertyFind == TRUE){
599 wxSProperty.Append(ContactLine.Mid(i, 1));
603 if (ContactLine.Mid(i, 1) == wxT("\"")){
605 if (QuoteMode == TRUE){
617 if (ContactLine.Mid(i, 1) == wxT(":") && ContactLine.Mid((i - 1), 1) != wxT("\\") && QuoteMode == FALSE){
626 // Split that line at the point into two variables (ignore the colon).
628 wxSPropertySeg1 = ContactLine.Mid(0, QuoteBreakPoint);
629 wxSPropertySeg2 = ContactLine.Mid((QuoteBreakPoint + 1));
631 // Insert both into the vCard data file.
633 AddRaw(wxSPropertySeg1, wxSPropertySeg2);
637 ExtraLineSeek = TRUE;
648 wxString vCard::WriteString(){
650 // Open the file and begin writing data into the file.
652 wxString SettingName;
653 wxString SettingValue;
654 wxString SettingLine;
655 wxString SettingFinal;
657 SettingCount = SettingNames.GetCount();
659 for (int i = 0; i < SettingCount; i++){
661 SettingLine = SettingNames[i] + wxT(":") + SettingValues[i];
663 int SettingLineLen = SettingLine.Len();
665 int intTimes = floor((SettingLine.Len() / intDivider));
669 bool FirstLine = TRUE;
671 // Remember to round down the calculation.
673 while (intSeek < SettingLineLen){
675 if ((intLineSeek == intDivider && FirstLine == TRUE) ||
676 (intLineSeek == (intDivider - 1) && FirstLine == FALSE)){
678 SettingLine.insert(intSeek, wxT("\r\n "));
679 intSeek = intSeek + 3;
680 SettingLineLen = SettingLineLen + 3;
682 intPrevLine = intSeek;
692 SettingFinal.Append(SettingLine);
700 bool vCard::MeetBaseSpecification(){
701 // Check and see if the vCard object meets the base specification
704 if (vCardBegin == TRUE && vCardEnd == TRUE && vCardFN == TRUE &&
705 vCardVersion == 4.0){
713 wxString vCard::Convert(wxString SettingValue, bool ReplaceMode){
715 // Check for backslashes used for commas, newlines and
716 // backslashes used for values.
718 if (ReplaceMode == TRUE){
720 SettingValue.Replace(wxT("\\n"), wxT("\n"));
721 SettingValue.Replace(wxT("\\,"), wxT(","));
722 SettingValue.Replace(wxT("\\;"), wxT(";"));
723 SettingValue.Replace(wxT("\\\\"), wxT("\\"));
727 SettingValue.Replace(wxT("\\"), wxT("\\\\"));
728 SettingValue.Replace(wxT("\n"), wxT("\\n"));
729 SettingValue.Replace(wxT(","), wxT("\\,"));
730 SettingValue.Replace(wxT(";"), wxT("\\;"));
731 SettingValue = SettingValue + wxT("\n");
739 wxString vCard::GetFilename(){
741 return vCardFilename;
745 std::map<int,wxString>* vCard::GetAllCards(){