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