Home | News | Projects | Releases
Bugs | RFE | Repositories | Help
bc9cd81509706a4a8661cdc23dff3526e7a24818
[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 intSplitsFound = 0;
202         int intSplitSize = 0;
203         int intPrevValue = 0;                                   
204         
205         for (int i = 0; i <= intPropertyLen; i++){
207                 intSplitSize++;
208         
209                 if (NameDataGet.Mid(i, 1) == wxT(";") && NameDataGet.Mid((i - 1), 1) != wxT("\\")){
210         
211                         intSplitsFound++;
212                         SplitPoints.insert(std::make_pair(intSplitsFound, (i + 1)));
213                         
214                         if (intSplitsFound == 4){ 
215                         
216                                 SplitLength.insert(std::make_pair(intSplitsFound, (intSplitSize - 1)));
217                                 break; 
218                                 
219                         } else {
220                         
221                                 SplitLength.insert(std::make_pair(intSplitsFound, (intSplitSize - 1)));
222                         
223                         }
224                         
225                         intSplitSize = 0;                                       
226         
227                 }
229         }
230         
231         for (std::map<int, int>::iterator intiter = SplitPoints.begin(); 
232         intiter != SplitPoints.end(); ++intiter){
233         
234                 if (intiter->first == 1){
235                 
236                         // Deal with family name.
237                         
238                         SLiter = SplitLength.find(1);
240                         NameData.Surname = NameDataGet.Mid(0, SLiter->second);                          
241                         intPrevValue = intiter->second;
242                 
243                 } else if (intiter->first == 2){
244                 
245                         // Deal with given names.
246                         
247                         SLiter = SplitLength.find(2);
249                         NameData.Forename = NameDataGet.Mid(intPrevValue, SLiter->second);                      
250                         intPrevValue = intiter->second;
252                 
253                 } else if (intiter->first == 3){
254                 
255                         // Deal with additional names.
256                         
257                         SLiter = SplitLength.find(3);
259                         NameData.OtherNames = NameDataGet.Mid(intPrevValue, SLiter->second);
260                         intPrevValue = intiter->second;
261                 
262                 } else if (intiter->first == 4){
263                 
264                         // Deal with honorifix prefixes and suffixes.
265                         SLiter = SplitLength.find(4);
267                         NameData.Title = NameDataGet.Mid(intPrevValue, SLiter->second);                 
268                         intPrevValue = intiter->second;
269                         NameData.Suffix = NameDataGet.Mid(intPrevValue);
270                 
271                 }
272         
273         }
274         
275         return NameData;
276         
280 ArrayvCardOutData vCard::GetByPartial(wxString SettingName){
282         // Get data from the vCard object based on a partial match.
283         
284         ArrayvCardOutData vCardOutData;
285         wxArrayString SettingList;
286         wxString SettingValueCurrent;
287         wxString SettingValue;
288         int SettingNameLen;
289         int SettingNameSeek;
290         bool FirstToken = TRUE;
291     
292         SettingNameLen = SettingName.Len();
293         
294         for (int i = 0; i < SettingCount; i++){
295     
296                 if (SettingNames[i].Mid(0, SettingNameLen) == SettingName){
297             
298                         SettingValue = SettingValues[i];
299                         SettingNameSeek = i;        
300             
301                 while (SettingValues[(i + 1)].Mid(0, 1) == wxT(" ") || SettingValues[(i + 1)].Mid(0, 1) == wxT("\t")){
302                 
303                         if (FirstToken == TRUE){
304                 
305                                 SettingValue.Trim(FALSE);
306                                 SettingValue.Trim(TRUE);                                
307                                 FirstToken = FALSE;
308                 
309                         }
310                 
311                         SettingValueCurrent = SettingValues[(i + 1)];
312                         SettingValueCurrent.Trim(FALSE);
313                         SettingValueCurrent.Trim(TRUE);         
314                 
315                         SettingValue.Append(SettingValueCurrent);
316                 
317                         i++;
318                 
319                 }
320             
321                 //SettingList.Add(SettingNames[SettingNameSeek] + wxT(":") + SettingValue);
322                 vCardOutData.PropData.Add(SettingNames[SettingNameSeek]);
323                 vCardOutData.PropValues.Add(SettingValue);
324                 vCardOutData.PropCount++;
325             
326                 }
327         }
328     
329     /*for (int i = 0; i < SettingCount; i++){
330         if (SettingNames[i].Mid(0, SettingNameLen) == SettingName){
331             
332             SettingValue = SettingValues[i];
333             SettingNameSeek = i;            
334             
335             while (SettingValues[(i + 1)].Mid(0, 1) == wxT(" ") || SettingValues[(i + 1)].Mid(0, 1) == wxT("\t")){
336                 
337                 SettingValueCurrent = SettingValues[(i + 1)];
338                 SettingValueCurrent.Trim(FALSE);
339                 SettingValueCurrent.Trim(TRUE);         
340                 
341                 SettingValue.Append(SettingValueCurrent);
342                 
343                 i++;
344                 
345             }
346             
347             //SettingList.Add(SettingNames[SettingNameSeek] + wxT(":") + SettingValue);
348             vCardOutData.PropData.Add(SettingName);
349             vCardOutData.PropData.Add(SettingValue);
350             
351         }
352     }*/
353     
354         return vCardOutData;
358 wxString vCard::GetById(int id){
359         
360         // Get data from the vCard object based on ID.
361         
362         // Unimplemented.
363         return wxT("");
364         
367 int vCard::WriteFile(wxString WriteFilename){
369         // Write the vCard to a file using the WriteFilename given.
370         
371         // Open the file and begin writing data into the file.
372     
373         wxString SettingName;
374         wxString SettingValue;
375         wxString SettingLine;
376     
377         SettingCount = SettingNames.GetCount();
378     
379         wxFile ContactFile;
380         if (ContactFile.Create(WriteFilename, TRUE, wxS_DEFAULT) == FALSE){
381                 return 1;
382         }
383     
384         for (int i = 0; i < SettingCount; i++){
385     
386                 SettingLine = SettingNames[i] + wxT(":") + SettingValues[i];
387     
388                 int SettingLineLen = SettingLine.Len();
389                 int intDivider = 74;
390                 int intSeek = 0;
391                 int intLineSeek = 0;
392                 bool FirstLine = TRUE;
393     
394                 // Remember to round down the calculation.
396                 while (intSeek < SettingLineLen){
397         
398                         if ((intLineSeek == intDivider && FirstLine == TRUE) ||
399                                 (intLineSeek == (intDivider - 1) && FirstLine == FALSE)){
400                 
401                                 SettingLine.insert(intSeek, wxT("\r\n "));
402                                 intSeek = intSeek + 3;
403                                 SettingLineLen = SettingLineLen + 3;
404                                 intLineSeek = 0;
405                                 FirstLine = FALSE;
406                 
407                         }
408         
409                         intSeek++;
410                         intLineSeek++;
411         
412                 }
413         
414                 ContactFile.Write(SettingLine);
415         
416         }
417     
418         ContactFile.Close();
420         return 0;
424 int vCard::LoadFile(wxString LoadFilename){
426         // Load data from a file using the LoadFilename given.
427         
428         wxFFile ContactFile;
429   
430         wxString wxSContactString;
431   
432         vCardFilename = LoadFilename;
433         
434         // Check if we are using wxWidgets version 2.8 or less and
435         // execute the required command accordingly.
436     
437 #if wxABI_VERSION < 20900
438         ContactFile.Open(LoadFilename.c_str(), wxT("r"));
439 #else
440         ContactFile.Open(LoadFilename, wxT("r"));
441 #endif  
442         
443         if (ContactFile.IsOpened() == FALSE){
444         
445                 return 1;
446         
447         }
448         
449         ContactFile.ReadAll(&wxSContactString, wxConvAuto());
450     
451         ContactFile.Close();
452     
453         ProcessString(&wxSContactString);
455         return 0;
459 int vCard::LoadString(wxString ContactData){
461         // Load data from a wxString.
462         
463         ProcessString(&ContactData);
465         return 0;
469 void vCard::ProcessString(wxString *ContactDataInc){
471         // Process data from a wxString pointer.
472         
473         // Split the vCards (if there are more than one vCard in the file).
475         wxString ContactLine;
477         int ContactLineLen;
478         bool ExtraLineSeek = FALSE;
479         int QuoteBreakPoint = 0;
480     
481         bool PropertyFind = FALSE;
482         bool QuoteMode = FALSE;
483    
484         wxString wxSPropertyNextLine;
485         wxString wxSProperty;
486         wxString wxSPropertySeg1;
487         wxString wxSPropertySeg2;
488     
489         bool FoundBegin = FALSE;
490         bool FirstContact = TRUE;
491         wxString FirstContactData;
492         wxString ContactData;
493         int ContactCount = 0;
494     
495         wxStringTokenizer wSTContactFileLines(*ContactDataInc, wxT("\r\n"));
496     
497         while(wSTContactFileLines.HasMoreTokens() == TRUE){
498     
499                 ContactLine = wSTContactFileLines.GetNextToken();
500         
501                 if (ContactLine == wxT("BEGIN:VCARD")){
502                 
503                         if (FoundBegin == TRUE){
504                 
505                                 // No END:VCARD was found so discard current data.
506                         
507                                 ContactData.Clear();
508                 
509                                 if (FirstContact == TRUE){
510                         
511                                         FirstContactData.Clear();
512                         
513                                 }
514                 
515                         }
516                 
517                         FoundBegin = TRUE;
518                 
519                         FirstContactData.Append(ContactLine + wxT("\r\n"));
520                         ContactData.Append(ContactLine + wxT("\r\n"));
521                 
522                 } else if (ContactLine == wxT("END:VCARD") && FoundBegin == TRUE){
523         
524                         if (FirstContact == TRUE){
525                 
526                                 FirstContact = FALSE;
527                                 FirstContactData.Append(ContactLine + wxT("\r\n"));
528                 
529                         }
530                 
531                         ContactData.Append(ContactLine + wxT("\r\n"));
532                                 
533                         Cards.insert(std::make_pair(ContactCount, ContactData));
534         
535                         ContactCount++;
536         
537                 } else if (FoundBegin == TRUE){
538         
539                         if (FirstContact == TRUE){
540                 
541                                 FirstContactData.Append(ContactLine + wxT("\r\n"));
542                 
543                         }
544                 
545                         ContactData.Append(ContactLine + wxT("\r\n"));
546         
547                 }
548     
549         }
551         ContactLine.Clear();
552     
553         // Split the lines.
554         
555         std::map<int, wxString> ContactFileLines;
556         std::map<int, wxString>::iterator striter;
557         
558         wxStringTokenizer wSTFirstContactLines(FirstContactData, wxT("\r\n"));
560         int ContactLineSeek = 0;
562         while (wSTFirstContactLines.HasMoreTokens() == TRUE){
564                 ContactLine = wSTFirstContactLines.GetNextToken();
565                 ContactFileLines.insert(std::make_pair(ContactLineSeek, ContactLine));
566                 ContactLineSeek++;              
567         
568         }
569     
570         for (std::map<int,wxString>::iterator iter = ContactFileLines.begin(); 
571                 iter != ContactFileLines.end(); ++iter){
573                 // Find the colon which splits the start bit from the data part.
574         
575                 ContactLine = iter->second;
576         
577                 while (ExtraLineSeek == TRUE){
578         
579                         // Check if there is extra data on the next line 
580                         // (indicated by space or tab at the start) and add data.
581         
582                         iter++;
583                 
584                         if (iter == ContactFileLines.end()){
585                 
586                                 iter--;
587                                 break;
588                 
589                         }
590         
591                         wxSPropertyNextLine = iter->second;
592                 
593                         if (wxSPropertyNextLine.Mid(0, 1) == wxT(" ") || wxSPropertyNextLine.Mid(0, 1) == wxT("\t")){
594                 
595                                 wxSPropertyNextLine.Remove(0, 1);
596                                 //wxSPropertyNextLine.Trim(FALSE);
597                                 //ContactLine.Trim();
598                                 ContactLine.Append(wxSPropertyNextLine);
599         
600                         } else {
601                 
602                                 iter--;
603                                 ExtraLineSeek = FALSE;
604                 
605                         }
606         
607                 }
609                 ContactLineLen = ContactLine.Len();
610         
611                 // Make sure we are not in quotation mode.
612                 // Make sure colon does not have \ or \\ before it.
613         
614                 for (int i = 0; i <= ContactLineLen; i++){
615         
616                         if ((ContactLine.Mid(i, 1) == wxT(";") || ContactLine.Mid(i, 1) == wxT(":")) && PropertyFind == TRUE){
617                 
618                                 PropertyFind = FALSE;
619                 
620                         } else if (PropertyFind == TRUE){
621                 
622                                 wxSProperty.Append(ContactLine.Mid(i, 1));
623                 
624                         }               
625         
626                         if (ContactLine.Mid(i, 1) == wxT("\"")){
627                 
628                                 if (QuoteMode == TRUE){
629                         
630                                         QuoteMode = FALSE;
631                         
632                                 } else {
633                 
634                                         QuoteMode = TRUE;
635                                 
636                                 }
637                 
638                         }
639                 
640                         if (ContactLine.Mid(i, 1) == wxT(":") && ContactLine.Mid((i - 1), 1) != wxT("\\") && QuoteMode == FALSE){
641                 
642                                 QuoteBreakPoint = i;
643                                 break;
644                 
645                         }
646         
647                 }
648         
649                 // Split that line at the point into two variables (ignore the colon).
650         
651                 wxSPropertySeg1 = ContactLine.Mid(0, QuoteBreakPoint);
652                 wxSPropertySeg2 = ContactLine.Mid((QuoteBreakPoint + 1));
653         
654                 // Insert both into the vCard data file.
655         
656                 AddRaw(wxSPropertySeg1, wxSPropertySeg2);
657         
658                 QuoteMode = FALSE;
659                 PropertyFind = TRUE;
660                 ExtraLineSeek = TRUE;
661                 ContactLineLen = 0;
662                 QuoteBreakPoint = 0;
663                 ContactLine.Clear();
664                 wxSProperty.Clear();
665         
666         }
671 wxString vCard::WriteString(){
673         // Write the vCard file into a wxString.
674         
675         // Open the file and begin writing data into the file.
676     
677         wxString SettingName;
678         wxString SettingValue;
679         wxString SettingLine;
680         wxString SettingFinal;
681     
682         SettingCount = SettingNames.GetCount();
683     
684         for (int i = 0; i < SettingCount; i++){
685     
686                 SettingLine = SettingNames[i] + wxT(":") + SettingValues[i];
687     
688                 int SettingLineLen = SettingLine.Len();
689                 int intDivider = 74;
690                 int intSeek = 0;
691                 int intLineSeek = 0;
692                 bool FirstLine = TRUE;
693     
694                 // Remember to round down the calculation.
696                 while (intSeek < SettingLineLen){
697         
698                         if ((intLineSeek == intDivider && FirstLine == TRUE) ||
699                         (intLineSeek == (intDivider - 1) && FirstLine == FALSE)){
700                 
701                                 SettingLine.insert(intSeek, wxT("\r\n "));
702                                 intSeek = intSeek + 3;
703                                 SettingLineLen = SettingLineLen + 3;
704                                 intLineSeek = 0;
705                                 FirstLine = FALSE;
706                 
707                         }
708         
709                         intSeek++;
710                         intLineSeek++;
711         
712                 }
713         
714                 SettingFinal.Append(SettingLine);
715         
716         }
717     
718         return SettingFinal;
722 bool vCard::MeetBaseSpecification(){
723         
724         // Check and see if the vCard object meets the base specification
725         // of vCard 4.0.
726     
727         if (vCardBegin == TRUE && vCardEnd == TRUE && vCardFN == TRUE &&
728                 vCardVersion == 4.0){
730                 return TRUE;
732         } else {
734                 return FALSE;
736         }
737     
740 wxString vCard::Convert(wxString SettingValue, bool ReplaceMode){  
741     
742         // Check for backslashes used for commas, newlines and
743         // backslashes used for values.
744     
745         if (ReplaceMode == TRUE){
746     
747                 SettingValue.Replace(wxT("\\n"), wxT("\n"));
748                 SettingValue.Replace(wxT("\\,"), wxT(","));
749                 SettingValue.Replace(wxT("\\;"), wxT(";"));
750                 SettingValue.Replace(wxT("\\\\"), wxT("\\"));
751     
752         } else {
754                 SettingValue.Replace(wxT("\\"), wxT("\\\\"));
755                 SettingValue.Replace(wxT("\n"), wxT("\\n"));
756                 SettingValue.Replace(wxT(","), wxT("\\,"));
757                 SettingValue.Replace(wxT(";"), wxT("\\;"));
758                 SettingValue = SettingValue + wxT("\n");
759     
760         }
761     
762         return SettingValue;
763     
766 wxString vCard::GetFilename(){
768         // Get the filename associated with the vCard object.
769         
770         return vCardFilename;
774 std::map<int,wxString>* vCard::GetAllCards(){
776         // Get all of vCards within the vCard object.
777         
778         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