Home | News | Projects | Releases
Bugs | RFE | Repositories | Help
Added comments to describe functions in vcard/vcard.cpp
[xestiaab/.git] / source / vcard / vcard.cpp
1 // vcard.cpp - vCard 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 "vcard.h"
20 #include <wx/file.h>
21 #include <wx/ffile.h>
22 #include <wx/tokenzr.h>
23 #include <cmath>
25 // vcard.cpp - Deals with vCard 4.0 formatted files meeting the
26 // RFC 6350 specification.
28 vCard::vCard(){
29         
30         // Setup the vCard object.
31         
32         vCardBegin = FALSE;
33         vCardEnd = FALSE;
34         vCardFN = FALSE;
35         vCardVersion = 0.0;
36         SettingCount = 0;
37         
38 }
40 void vCard::Add(wxString SettingName, wxString SettingValue, bool ReplaceMode){  
41     
42         // Add data to vCard object.
43         
44         // Check for backslashes used for commas, newlines and
45         // backslashes used for values.
46     
47         if (ReplaceMode == TRUE){
48     
49                 SettingValue.Replace(wxT("\\n"), wxT("\n"));
50                 SettingValue.Replace(wxT("\\,"), wxT(","));
51                 SettingValue.Replace(wxT("\\:"), wxT(":"));
52                 SettingValue.Replace(wxT("\\\\"), wxT("\\"));
53     
54         } else {
56                 SettingValue.Replace(wxT("\\"), wxT("\\\\"));
57                 SettingValue.Replace(wxT("\n"), wxT("\\n"));
58                 SettingValue.Replace(wxT(","), wxT("\\,"));
59                 SettingValue.Replace(wxT(":"), wxT("\\:"));
60                 SettingValue = SettingValue + wxT("\n");
61     
62         }
63   
64         // Check data to make sure that it meets the required
65         // vCard 4.0 specifications.
66     
67         if (SettingName == wxT("BEGIN") && SettingValue == wxT("VCARD")){
68                 vCardBegin = TRUE;
69         }
70     
71         if (SettingName == wxT("END") && SettingValue == wxT("VCARD")){
72                 vCardEnd = TRUE;
73         }
75         if (SettingName.Mid(0,2) == wxT("FN")){
76                 vCardFN = TRUE;
77         }
78     
79         if (SettingName == wxT("VERSION") && SettingValue == wxT("4.0")){
80                 vCardVersion = 4.0;
81         }
82     
83         if (SettingName == wxT("VERSION") && SettingValue == wxT("3.0")){
84                 vCardVersion = 3.0;
85         }
86     
87         if (SettingName == wxT("VERSION") && SettingValue == wxT("3.0")){
88                 vCardVersion = 2.0;
89         }
90     
91         SettingValue.Trim();    
92     
93         if (SettingValue.Right(2) != wxT("\r\n")){
94     
95                 SettingValue.Append(wxT("\r\n"));
96     
97         }
98     
99         SettingNames.Add(SettingName, 1);
100         SettingValues.Add(SettingValue, 1);      
101     
102         ++SettingCount;
103         
106 void vCard::AddRaw(wxString SettingName, wxString SettingValue){  
107   
108         // Add data to the vCard in raw mode.
110         // Check data to make sure that it meets the required
111         // vCard 4.0 specifications.
112         
113         if (SettingName == wxT("BEGIN") && SettingValue == wxT("VCARD")){
114                 vCardBegin = TRUE;
115         }
116     
117         if (SettingName == wxT("END") && SettingValue == wxT("VCARD")){
118                 vCardEnd = TRUE;
119         }
120     
121         if (SettingName.Mid(0,2) == wxT("FN")){
122                 vCardFN = TRUE;
123         }
124     
125         if (SettingName == wxT("VERSION") && SettingValue == wxT("4.0")){   
126                 vCardVersion = 4.0;
127         }
129         if (SettingName == wxT("VERSION") && SettingValue == wxT("3.0")){   
130                 vCardVersion = 3.0;
131         }
132     
133         if (SettingName == wxT("VERSION") && SettingValue == wxT("3.0")){   
134                 vCardVersion = 2.0;
135         }
136     
137         SettingValue.Trim();
138     
139         if (SettingValue.Right(2) != wxT("\r\n")){
140     
141                 SettingValue.Append(wxT("\r\n"));
142     
143         }
144         
145         SettingNames.Add(SettingName, 1);
146         SettingValues.Add(SettingValue, 1);      
147     
148         ++SettingCount;
149         
152 wxString vCard::Get(wxString SettingName){
153   
154         // Get values from the vCard object.
155         
156         wxString SettingValue;
157     
158         // Look for the setting name.
160         for (int i = 0; i < SettingCount; i++){
161       
162                 if (SettingNames[i] == SettingName){
163         
164                         SettingValue = SettingValues[i];
165                         SettingValue.Trim(TRUE);
166                     
167                         while (SettingValues[(i + 1)].Mid(0, 1) == wxT(" ") || SettingValues[(i + 1)].Mid(0, 1) == wxT("\t")){
168                 
169                                 SettingValue.Trim();
170                                 SettingValue.Append(SettingValues[(i + 1)]);
171                 
172                                 i++;
173                         
174                         }
175             
176                         return SettingValue;
177                 
178                 }
179         
180         }
182         return wxEmptyString;
186 vCardName vCard::GetName(){
188         // Get the name from the vCard object.
189         
190         vCardName NameData;
191         ArrayvCardOutData NameArray = this->GetByPartial(wxT("N"));
192         //wxString NameDataGet = NameArray.PropValues[0];
193         wxString NameDataGet = NameArray.PropValues[0];
194         std::map<int, int> SplitPoints;
195         std::map<int, int> SplitLength;
196         std::map<int, int>::iterator SLiter;
197         
198         // Process the name data to get the required information.
199         
200         int intPropertyLen = NameDataGet.Len();
201         int intSplitSeek = 0;
202         int intSplitsFound = 0;
203         int intSplitSize = 0;
204         int intPrevValue = 0;                                   
205         
206         for (int i = 0; i <= intPropertyLen; i++){
208                 intSplitSize++;
209         
210                 if (NameDataGet.Mid(i, 1) == wxT(";") && NameDataGet.Mid((i - 1), 1) != wxT("\\")){
211         
212                         intSplitsFound++;
213                         SplitPoints.insert(std::make_pair(intSplitsFound, (i + 1)));
214                         
215                         if (intSplitsFound == 4){ 
216                         
217                                 SplitLength.insert(std::make_pair(intSplitsFound, (intSplitSize - 1)));
218                                 break; 
219                                 
220                         } else {
221                         
222                                 SplitLength.insert(std::make_pair(intSplitsFound, (intSplitSize - 1)));
223                         
224                         }
225                         
226                         intSplitSize = 0;                                       
227         
228                 }
230         }
231         
232         for (std::map<int, int>::iterator intiter = SplitPoints.begin(); 
233         intiter != SplitPoints.end(); ++intiter){
234         
235                 if (intiter->first == 1){
236                 
237                         // Deal with family name.
238                         
239                         SLiter = SplitLength.find(1);
241                         NameData.Surname = NameDataGet.Mid(0, SLiter->second);                          
242                         intPrevValue = intiter->second;
243                 
244                 } else if (intiter->first == 2){
245                 
246                         // Deal with given names.
247                         
248                         SLiter = SplitLength.find(2);
250                         NameData.Forename = NameDataGet.Mid(intPrevValue, SLiter->second);                      
251                         intPrevValue = intiter->second;
253                 
254                 } else if (intiter->first == 3){
255                 
256                         // Deal with additional names.
257                         
258                         SLiter = SplitLength.find(3);
260                         NameData.OtherNames = NameDataGet.Mid(intPrevValue, SLiter->second);
261                         intPrevValue = intiter->second;
262                 
263                 } else if (intiter->first == 4){
264                 
265                         // Deal with honorifix prefixes and suffixes.
266                         SLiter = SplitLength.find(4);
268                         NameData.Title = NameDataGet.Mid(intPrevValue, SLiter->second);                 
269                         intPrevValue = intiter->second;
270                         NameData.Suffix = NameDataGet.Mid(intPrevValue);
271                 
272                 }
273         
274         }
275         
276         return NameData;
277         
281 ArrayvCardOutData vCard::GetByPartial(wxString SettingName){
283         // Get data from the vCard object based on a partial match.
284         
285         ArrayvCardOutData vCardOutData;
286         wxArrayString SettingList;
287         wxString SettingValueCurrent;
288         wxString SettingValue;
289         int SettingNameLen;
290         int SettingNameSeek;
291         bool FirstToken = TRUE;
292     
293         SettingNameLen = SettingName.Len();
294         
295         for (int i = 0; i < SettingCount; i++){
296     
297                 if (SettingNames[i].Mid(0, SettingNameLen) == SettingName){
298             
299                         SettingValue = SettingValues[i];
300                         SettingNameSeek = i;        
301             
302                 while (SettingValues[(i + 1)].Mid(0, 1) == wxT(" ") || SettingValues[(i + 1)].Mid(0, 1) == wxT("\t")){
303                 
304                         if (FirstToken == TRUE){
305                 
306                                 SettingValue.Trim(FALSE);
307                                 SettingValue.Trim(TRUE);                                
308                                 FirstToken = FALSE;
309                 
310                         }
311                 
312                         SettingValueCurrent = SettingValues[(i + 1)];
313                         SettingValueCurrent.Trim(FALSE);
314                         SettingValueCurrent.Trim(TRUE);         
315                 
316                         SettingValue.Append(SettingValueCurrent);
317                 
318                         i++;
319                 
320                 }
321             
322                 //SettingList.Add(SettingNames[SettingNameSeek] + wxT(":") + SettingValue);
323                 vCardOutData.PropData.Add(SettingNames[SettingNameSeek]);
324                 vCardOutData.PropValues.Add(SettingValue);
325                 vCardOutData.PropCount++;
326             
327                 }
328         }
329     
330     /*for (int i = 0; i < SettingCount; i++){
331         if (SettingNames[i].Mid(0, SettingNameLen) == SettingName){
332             
333             SettingValue = SettingValues[i];
334             SettingNameSeek = i;            
335             
336             while (SettingValues[(i + 1)].Mid(0, 1) == wxT(" ") || SettingValues[(i + 1)].Mid(0, 1) == wxT("\t")){
337                 
338                 SettingValueCurrent = SettingValues[(i + 1)];
339                 SettingValueCurrent.Trim(FALSE);
340                 SettingValueCurrent.Trim(TRUE);         
341                 
342                 SettingValue.Append(SettingValueCurrent);
343                 
344                 i++;
345                 
346             }
347             
348             //SettingList.Add(SettingNames[SettingNameSeek] + wxT(":") + SettingValue);
349             vCardOutData.PropData.Add(SettingName);
350             vCardOutData.PropData.Add(SettingValue);
351             
352         }
353     }*/
354     
355         return vCardOutData;
359 wxString vCard::GetById(int id){
360         
361         // Get data from the vCard object based on ID.
362         
363         // Unimplemented.
364         return wxT("");
365         
368 int vCard::WriteFile(wxString WriteFilename){
370         // Write the vCard to a file using the WriteFilename given.
371         
372         // Open the file and begin writing data into the file.
373     
374         wxString SettingName;
375         wxString SettingValue;
376         wxString SettingLine;
377     
378         SettingCount = SettingNames.GetCount();
379     
380         wxFile ContactFile;
381         if (ContactFile.Create(WriteFilename, TRUE, wxS_DEFAULT) == FALSE){
382                 return 1;
383         }
384     
385         for (int i = 0; i < SettingCount; i++){
386     
387                 SettingLine = SettingNames[i] + wxT(":") + SettingValues[i];
388     
389                 int SettingLineLen = SettingLine.Len();
390                 int intDivider = 74;
391                 int intTimes = floor((SettingLine.Len() / intDivider));
392                 int intSeek = 0;
393                 int intLineSeek = 0;
394                 int intPrevLine;
395                 bool FirstLine = TRUE;
396     
397                 // Remember to round down the calculation.
399                 while (intSeek < SettingLineLen){
400         
401                         if ((intLineSeek == intDivider && FirstLine == TRUE) ||
402                                 (intLineSeek == (intDivider - 1) && FirstLine == FALSE)){
403                 
404                                 SettingLine.insert(intSeek, wxT("\r\n "));
405                                 intSeek = intSeek + 3;
406                                 SettingLineLen = SettingLineLen + 3;
407                                 intLineSeek = 0;
408                                 intPrevLine = intSeek;
409                                 FirstLine = FALSE;
410                 
411                         }
412         
413                         intSeek++;
414                         intLineSeek++;
415         
416                 }
418         /*
420         for (int x = 0; x < intTimes; x++){     
421         
422             if (x == 0){
423                 SettingLine.insert((intDivider - 1), wxT("\r\n "));
424             } else if (x == intTimes){
425             
426             } else {
427                 if (x < intDivider){
428                         SettingLine.insert((intDivider * (x+1)) + (x * 3), wxT("\r\n "));
429                 }
430             }
431             
432             intTimes = floor(SettingLine.Len() / intDivider);
433         
434         }
435         
436         */
437         
438                 ContactFile.Write(SettingLine);
439         
440         }
441     
442         ContactFile.Close();
444         return 0;
448 int vCard::LoadFile(wxString LoadFilename){
450         // Load data from a file using the LoadFilename given.
451         
452         wxFFile ContactFile;
453   
454         wxString wxSContactString;
455   
456         vCardFilename = LoadFilename;
457         
458         // Check if we are using wxWidgets version 2.8 or less and
459         // execute the required command accordingly.
460     
461 #if wxABI_VERSION < 20900
462         ContactFile.Open(LoadFilename.c_str(), wxT("r"));
463 #else
464         ContactFile.Open(LoadFilename, wxT("r"));
465 #endif  
466         
467         if (ContactFile.IsOpened() == FALSE){
468         
469                 return 1;
470         
471         }
472         
473         ContactFile.ReadAll(&wxSContactString, wxConvAuto());
474     
475         ContactFile.Close();
476     
477         ProcessString(&wxSContactString);
479         return 0;
483 int vCard::LoadString(wxString ContactData){
485         // Load data from a wxString.
486         
487         ProcessString(&ContactData);
489         return 0;
493 void vCard::ProcessString(wxString *ContactDataInc){
495         // Process data from a wxString pointer.
496         
497         // Split the vCards (if there are more than one vCard in the file).
499         wxString ContactLine;
501         int ContactLineLen;
502         bool ExtraLineSeek = FALSE;
503         int QuoteBreakPoint = 0;
504     
505         bool PropertyFind = FALSE;
506         bool QuoteMode = FALSE;
507    
508         wxString wxSPropertyNextLine;
509         wxString wxSProperty;
510         wxString wxSPropertySeg1;
511         wxString wxSPropertySeg2;
512     
513         bool FoundBegin = FALSE;
514         bool FoundEnd = FALSE;
515         bool FirstContact = TRUE;
516         wxString FirstContactData;
517         wxString ContactData;
518         int ContactCount = 0;
519     
520         wxStringTokenizer wSTContactFileLines(*ContactDataInc, wxT("\r\n"));
521     
522         while(wSTContactFileLines.HasMoreTokens() == TRUE){
523     
524                 ContactLine = wSTContactFileLines.GetNextToken();
525         
526                 if (ContactLine == wxT("BEGIN:VCARD")){
527                 
528                         if (FoundBegin == TRUE){
529                 
530                                 // No END:VCARD was found so discard current data.
531                         
532                                 ContactData.Clear();
533                 
534                                 if (FirstContact == TRUE){
535                         
536                                         FirstContactData.Clear();
537                         
538                                 }
539                 
540                         }
541                 
542                         FoundBegin = TRUE;
543                 
544                         FirstContactData.Append(ContactLine + wxT("\r\n"));
545                         ContactData.Append(ContactLine + wxT("\r\n"));
546                 
547                 } else if (ContactLine == wxT("END:VCARD") && FoundBegin == TRUE){
548         
549                         if (FirstContact == TRUE){
550                 
551                                 FirstContact = FALSE;
552                                 FirstContactData.Append(ContactLine + wxT("\r\n"));
553                 
554                         }
555                 
556                         ContactData.Append(ContactLine + wxT("\r\n"));
557                                 
558                         Cards.insert(std::make_pair(ContactCount, ContactData));
559         
560                         ContactCount++;
561         
562                 } else if (FoundBegin == TRUE){
563         
564                         if (FirstContact == TRUE){
565                 
566                                 FirstContactData.Append(ContactLine + wxT("\r\n"));
567                 
568                         }
569                 
570                         ContactData.Append(ContactLine + wxT("\r\n"));
571         
572                 }
573     
574         }
576         ContactLine.Clear();
577     
578         // Split the lines.
579         
580         std::map<int, wxString> ContactFileLines;
581         std::map<int, wxString>::iterator striter;
582         
583         wxStringTokenizer wSTFirstContactLines(FirstContactData, wxT("\r\n"));
585         int ContactLineSeek = 0;
587         while (wSTFirstContactLines.HasMoreTokens() == TRUE){
589                 ContactLine = wSTFirstContactLines.GetNextToken();
590                 ContactFileLines.insert(std::make_pair(ContactLineSeek, ContactLine));
591                 ContactLineSeek++;              
592         
593         }
594     
595         for (std::map<int,wxString>::iterator iter = ContactFileLines.begin(); 
596                 iter != ContactFileLines.end(); ++iter){
598                 // Find the colon which splits the start bit from the data part.
599         
600                 ContactLine = iter->second;
601         
602                 while (ExtraLineSeek == TRUE){
603         
604                         // Check if there is extra data on the next line 
605                         // (indicated by space or tab at the start) and add data.
606         
607                         iter++;
608                 
609                         if (iter == ContactFileLines.end()){
610                 
611                                 iter--;
612                                 break;
613                 
614                         }
615         
616                         wxSPropertyNextLine = iter->second;
617                 
618                         if (wxSPropertyNextLine.Mid(0, 1) == wxT(" ") || wxSPropertyNextLine.Mid(0, 1) == wxT("\t")){
619                 
620                                 wxSPropertyNextLine.Remove(0, 1);
621                                 //wxSPropertyNextLine.Trim(FALSE);
622                                 //ContactLine.Trim();
623                                 ContactLine.Append(wxSPropertyNextLine);
624         
625                         } else {
626                 
627                                 iter--;
628                                 ExtraLineSeek = FALSE;
629                 
630                         }
631         
632                 }
634                 ContactLineLen = ContactLine.Len();
635         
636                 // Make sure we are not in quotation mode.
637                 // Make sure colon does not have \ or \\ before it.
638         
639                 for (int i = 0; i <= ContactLineLen; i++){
640         
641                         if ((ContactLine.Mid(i, 1) == wxT(";") || ContactLine.Mid(i, 1) == wxT(":")) && PropertyFind == TRUE){
642                 
643                                 PropertyFind = FALSE;
644                 
645                         } else if (PropertyFind == TRUE){
646                 
647                                 wxSProperty.Append(ContactLine.Mid(i, 1));
648                 
649                         }               
650         
651                         if (ContactLine.Mid(i, 1) == wxT("\"")){
652                 
653                                 if (QuoteMode == TRUE){
654                         
655                                         QuoteMode = FALSE;
656                         
657                                 } else {
658                 
659                                         QuoteMode = TRUE;
660                                 
661                                 }
662                 
663                         }
664                 
665                         if (ContactLine.Mid(i, 1) == wxT(":") && ContactLine.Mid((i - 1), 1) != wxT("\\") && QuoteMode == FALSE){
666                 
667                                 QuoteBreakPoint = i;
668                                 break;
669                 
670                         }
671         
672                 }
673         
674                 // Split that line at the point into two variables (ignore the colon).
675         
676                 wxSPropertySeg1 = ContactLine.Mid(0, QuoteBreakPoint);
677                 wxSPropertySeg2 = ContactLine.Mid((QuoteBreakPoint + 1));
678         
679                 // Insert both into the vCard data file.
680         
681                 AddRaw(wxSPropertySeg1, wxSPropertySeg2);
682         
683                 QuoteMode = FALSE;
684                 PropertyFind = TRUE;
685                 ExtraLineSeek = TRUE;
686                 ContactLineLen = 0;
687                 QuoteBreakPoint = 0;
688                 ContactLine.Clear();
689                 wxSProperty.Clear();
690         
691         }
696 wxString vCard::WriteString(){
698         // Write the vCard file into a wxString.
699         
700         // Open the file and begin writing data into the file.
701     
702         wxString SettingName;
703         wxString SettingValue;
704         wxString SettingLine;
705         wxString SettingFinal;
706     
707         SettingCount = SettingNames.GetCount();
708     
709         for (int i = 0; i < SettingCount; i++){
710     
711                 SettingLine = SettingNames[i] + wxT(":") + SettingValues[i];
712     
713                 int SettingLineLen = SettingLine.Len();
714                 int intDivider = 74;
715                 int intTimes = floor((SettingLine.Len() / intDivider));
716                 int intSeek = 0;
717                 int intLineSeek = 0;
718                 int intPrevLine;
719                 bool FirstLine = TRUE;
720     
721                 // Remember to round down the calculation.
723                 while (intSeek < SettingLineLen){
724         
725                         if ((intLineSeek == intDivider && FirstLine == TRUE) ||
726                         (intLineSeek == (intDivider - 1) && FirstLine == FALSE)){
727                 
728                                 SettingLine.insert(intSeek, wxT("\r\n "));
729                                 intSeek = intSeek + 3;
730                                 SettingLineLen = SettingLineLen + 3;
731                                 intLineSeek = 0;
732                                 intPrevLine = intSeek;
733                                 FirstLine = FALSE;
734                 
735                         }
736         
737                         intSeek++;
738                         intLineSeek++;
739         
740                 }
741         
742                 SettingFinal.Append(SettingLine);
743         
744         }
745     
746         return SettingFinal;
750 bool vCard::MeetBaseSpecification(){
751         
752         // Check and see if the vCard object meets the base specification
753         // of vCard 4.0.
754     
755         if (vCardBegin == TRUE && vCardEnd == TRUE && vCardFN == TRUE &&
756                 vCardVersion == 4.0){
758                 return TRUE;
760         } else {
762                 return FALSE;
764         }
765     
768 wxString vCard::Convert(wxString SettingValue, bool ReplaceMode){  
769     
770         // Check for backslashes used for commas, newlines and
771         // backslashes used for values.
772     
773         if (ReplaceMode == TRUE){
774     
775                 SettingValue.Replace(wxT("\\n"), wxT("\n"));
776                 SettingValue.Replace(wxT("\\,"), wxT(","));
777                 SettingValue.Replace(wxT("\\;"), wxT(";"));
778                 SettingValue.Replace(wxT("\\\\"), wxT("\\"));
779     
780         } else {
782                 SettingValue.Replace(wxT("\\"), wxT("\\\\"));
783                 SettingValue.Replace(wxT("\n"), wxT("\\n"));
784                 SettingValue.Replace(wxT(","), wxT("\\,"));
785                 SettingValue.Replace(wxT(";"), wxT("\\;"));
786                 SettingValue = SettingValue + wxT("\n");
787     
788         }
789     
790         return SettingValue;
791     
794 wxString vCard::GetFilename(){
796         // Get the filename associated with the vCard object.
797         
798         return vCardFilename;
802 std::map<int,wxString>* vCard::GetAllCards(){
804         // Get all of vCards within the vCard object.
805         
806         return &Cards;
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