5
5
6
6
#include <ctype.h>
7
7
#include <stdio.h>
8
+ #include <stdarg.h>
8
9
#include <stdlib.h>
9
10
#include <string.h>
10
11
@@ -40,6 +41,7 @@ enum parse_error {
40
41
PE_QSTRING_EOF ,
41
42
PE_QSTRING_EOL ,
42
43
PE_QSTRING_EOV ,
44
+ PE_VALUE_INVALID ,
43
45
PE_ILLEGAL_CHAR ,
44
46
PE_NUMERR /* last */
45
47
};
@@ -53,6 +55,7 @@ struct buf {
53
55
54
56
struct vcardparser_state {
55
57
struct buf buf ;
58
+ struct buf errbuf ;
56
59
const char * base ;
57
60
const char * itemstart ;
58
61
const char * p ;
@@ -75,13 +78,20 @@ struct vcardparser_errorpos {
75
78
int errorchar ;
76
79
};
77
80
81
+ #define BUF_GROW 128
82
+
78
83
void buf_init (struct buf * buf , size_t size )
79
84
{
80
85
buf -> len = 0 ;
81
86
buf -> alloc = size ;
82
87
buf -> s = icalmemory_new_buffer (buf -> alloc );
83
88
}
84
89
90
+ static size_t buf_len (struct buf * buf )
91
+ {
92
+ return buf -> len ;
93
+ }
94
+
85
95
static void buf_reset (struct buf * buf )
86
96
{
87
97
buf -> len = 0 ;
@@ -133,6 +143,30 @@ static void buf_trim(struct buf *buf)
133
143
}
134
144
}
135
145
146
+ static void buf_vprintf (struct buf * buf , const char * fmt , va_list args )
147
+ {
148
+ va_list ap ;
149
+ size_t size , n ;
150
+
151
+ /* Copy args in case we have to try again */
152
+ va_copy (ap , args );
153
+
154
+ size = buf -> alloc - buf -> len ;
155
+ n = vsnprintf (buf -> s + buf -> len , size , fmt , args );
156
+
157
+ if (n >= size ) {
158
+ /* Grow the buffer and try again */
159
+ size = n + BUF_GROW ;
160
+ buf -> alloc += size ;
161
+ buf -> s = icalmemory_resize_buffer (buf -> s , buf -> alloc );
162
+
163
+ n = vsnprintf (buf -> s + buf -> len , size , fmt , ap );
164
+ }
165
+ va_end (ap );
166
+
167
+ buf -> len += n ;
168
+ }
169
+
136
170
#define NOTESTART () state->itemstart = state->p
137
171
#define MAKE (X , Y ) X = icalmemory_new_buffer(sizeof(struct Y))
138
172
#define PUTC (C ) buf_putc(&state->buf, C)
@@ -438,8 +472,31 @@ static int _parse_param_value(struct vcardparser_state *state)
438
472
return PE_PARAMVALUE_EOF ;
439
473
}
440
474
475
+ static void _parse_error (struct vcardparser_state * state ,
476
+ enum vcardparameter_xlicerrortype type ,
477
+ const char * fmt , ...)
478
+ {
479
+ va_list ap ;
480
+
481
+ va_start (ap , fmt );
482
+ buf_reset (& state -> errbuf );
483
+ buf_vprintf (& state -> errbuf , fmt , ap );
484
+ va_end (ap );
485
+
486
+ if (state -> prop ) vcardproperty_free (state -> prop );
487
+
488
+ state -> prop =
489
+ vcardproperty_vanew_xlicerror (buf_cstring (& state -> errbuf ),
490
+ vcardparameter_new_xlicerrortype (type ),
491
+ (void * ) 0 );
492
+ buf_reset (& state -> buf );
493
+ }
494
+
441
495
static int _parse_prop_params (struct vcardparser_state * state )
442
496
{
497
+ vcardproperty_kind prop_kind = vcardproperty_isa (state -> prop );
498
+ const char * group = vcardproperty_get_group (state -> prop );
499
+
443
500
do {
444
501
int r ;
445
502
@@ -449,13 +506,32 @@ static int _parse_prop_params(struct vcardparser_state *state)
449
506
450
507
/* get the name */
451
508
r = _parse_param_name (state );
452
- if (r ) return r ;
509
+ if (r ) {
510
+ _parse_error (state ,
511
+ VCARD_XLICERRORTYPE_PARAMETERNAMEPARSEERROR ,
512
+ "%s '%s' in %s%s%s property. Removing entire property" ,
513
+ vcardparser_errstr (r ), buf_cstring (& state -> buf ),
514
+ group ? group : "" , group ? "." : "" ,
515
+ vcardproperty_kind_to_string (prop_kind ));
516
+ return r ;
517
+ }
518
+
519
+ vcardproperty_add_parameter (state -> prop , state -> param );
453
520
454
521
/* now get the value */
455
522
r = _parse_param_value (state );
456
- if (r ) return r ;
457
-
458
- vcardproperty_add_parameter (state -> prop , state -> param );
523
+ if (r ) {
524
+ vcardparameter_kind param_kind = vcardparameter_isa (state -> param );
525
+
526
+ _parse_error (state ,
527
+ VCARD_XLICERRORTYPE_PARAMETERVALUEPARSEERROR ,
528
+ "%s for %s in %s%s%s property. Removing entire property" ,
529
+ vcardparser_errstr (r ),
530
+ vcardparameter_kind_to_string (param_kind ),
531
+ group ? group : "" , group ? "." : "" ,
532
+ vcardproperty_kind_to_string (prop_kind ));
533
+ return r ;
534
+ }
459
535
460
536
} while (* state -> p == ';' ); /* another parameter to parse */
461
537
@@ -467,6 +543,7 @@ static int _parse_prop_name(struct vcardparser_state *state)
467
543
const char * name ;
468
544
char * group = NULL ;
469
545
vcardproperty_kind kind ;
546
+ int r = 0 ;
470
547
471
548
NOTESTART ();
472
549
@@ -510,12 +587,19 @@ static int _parse_prop_name(struct vcardparser_state *state)
510
587
buf_reset (& state -> buf );
511
588
512
589
/* no INC - we need to see this char up a layer */
513
- return 0 ;
590
+ return r ;
514
591
515
592
case '.' :
516
- if (group )
517
- return PE_PROP_MULTIGROUP ;
518
- group = icalmemory_tmp_copy (buf_cstring (& state -> buf ));
593
+ if (group ) {
594
+ char * tmp =
595
+ icalmemory_tmp_buffer (strlen (group ) + buf_len (& state -> buf ) + 2 );
596
+ sprintf (tmp , "%s.%s" , group , buf_cstring (& state -> buf ));
597
+ group = tmp ;
598
+ r = PE_PROP_MULTIGROUP ;
599
+ }
600
+ else {
601
+ group = icalmemory_tmp_copy (buf_cstring (& state -> buf ));
602
+ }
519
603
buf_reset (& state -> buf );
520
604
INC (1 );
521
605
break ;
@@ -664,26 +748,102 @@ static int _parse_prop_value(struct vcardparser_state *state)
664
748
buf_cstring (& state -> buf ));
665
749
}
666
750
667
- if (!value ) return PE_ILLEGAL_CHAR ;
751
+ if (!value ) return PE_VALUE_INVALID ;
668
752
669
753
vcardproperty_set_value (state -> prop , value );
670
754
buf_reset (& state -> buf );
671
755
672
756
return 0 ;
673
757
}
674
758
675
- static int _parse_prop (struct vcardparser_state * state )
759
+ static void _parse_eatline (struct vcardparser_state * state )
760
+ {
761
+ while (* state -> p ) {
762
+
763
+ /* Handle control characters and break for NUL char */
764
+ HANDLECTRL (state );
765
+
766
+ switch (* state -> p ) {
767
+ case '\n' :
768
+ if (state -> p [1 ] == ' ' || state -> p [1 ] == '\t' ) {/* wrapped line */
769
+ INC (2 );
770
+ break ;
771
+ }
772
+ /* otherwise it's the end of the line */
773
+ INC (1 );
774
+ return ;
775
+
776
+ default :
777
+ INC (1 );
778
+ break ;
779
+ }
780
+ }
781
+ }
782
+
783
+ static void _parse_prop (struct vcardparser_state * state )
676
784
{
677
785
int r = _parse_prop_name (state );
678
- if (r ) return r ;
786
+ if (r ) {
787
+ if (r == PE_PROP_MULTIGROUP ) {
788
+ vcardproperty_kind prop_kind = vcardproperty_isa (state -> prop );
789
+
790
+ _parse_error (state ,
791
+ VCARD_XLICERRORTYPE_PROPERTYPARSEERROR ,
792
+ "%s '%s.%s'. Removing entire property" ,
793
+ vcardparser_errstr (r ),
794
+ vcardproperty_get_group (state -> prop ),
795
+ vcardproperty_kind_to_string (prop_kind ));
796
+ _parse_eatline (state );
797
+ }
798
+ else if (r == PE_NAME_INVALID ) {
799
+ _parse_error (state ,
800
+ VCARD_XLICERRORTYPE_PROPERTYPARSEERROR ,
801
+ "%s '%s'. Removing entire property" ,
802
+ vcardparser_errstr (r ), buf_cstring (& state -> buf ));
803
+ _parse_eatline (state );
804
+ }
805
+ else {
806
+ _parse_error (state ,
807
+ VCARD_XLICERRORTYPE_PROPERTYPARSEERROR ,
808
+ "%s '%s'. Ignoring property" ,
809
+ vcardparser_errstr (r ), buf_cstring (& state -> buf ));
810
+ }
811
+ return ;
812
+ }
679
813
680
814
if (* state -> p == ';' ) {
681
815
r = _parse_prop_params (state );
682
- if (r ) return r ;
816
+ if (r ) {
817
+ /* errors handled in _parse_prop_params() */
818
+ return ;
819
+ }
683
820
}
684
821
685
822
INC (1 ); /* skip ':' */
686
- return _parse_prop_value (state );
823
+ r = _parse_prop_value (state );
824
+ if (r ) {
825
+ vcardproperty_kind prop_kind = vcardproperty_isa (state -> prop );
826
+ const char * group = vcardproperty_get_group (state -> prop );
827
+
828
+ if (r == PE_VALUE_INVALID ) {
829
+ _parse_error (state ,
830
+ VCARD_XLICERRORTYPE_VALUEPARSEERROR ,
831
+ "Error parsing '%s' as %s value in %s%s%s property."
832
+ " Removing entire property" ,
833
+ buf_cstring (& state -> buf ),
834
+ vcardvalue_kind_to_string (state -> value_kind ),
835
+ group ? group : "" , group ? "." : "" ,
836
+ vcardproperty_kind_to_string (prop_kind ));
837
+ }
838
+ else {
839
+ _parse_error (state ,
840
+ VCARD_XLICERRORTYPE_VALUEPARSEERROR ,
841
+ "%s in %s%s%s property. Removing entire property" ,
842
+ vcardparser_errstr (r ),
843
+ group ? group : "" , group ? "." : "" ,
844
+ vcardproperty_kind_to_string (prop_kind ));
845
+ }
846
+ }
687
847
}
688
848
689
849
static int _parse_vcard (struct vcardparser_state * state ,
@@ -701,8 +861,7 @@ static int _parse_vcard(struct vcardparser_state *state,
701
861
continue ;
702
862
}
703
863
704
- r = _parse_prop (state );
705
- if (r ) break ;
864
+ _parse_prop (state );
706
865
707
866
if (vcardproperty_isa (state -> prop ) == VCARD_BEGIN_PROPERTY ) {
708
867
const char * val =
@@ -767,7 +926,7 @@ static int vcardparser_parse(struct vcardparser_state *state, int only_one)
767
926
768
927
state -> p = state -> base ;
769
928
770
- buf_init (& state -> buf , 100 );
929
+ buf_init (& state -> buf , BUF_GROW );
771
930
772
931
/* don't parse trailing non-whitespace */
773
932
return _parse_vcard (state , state -> root , only_one );
@@ -778,6 +937,8 @@ static int vcardparser_parse(struct vcardparser_state *state, int only_one)
778
937
static void _free_state (struct vcardparser_state * state )
779
938
{
780
939
buf_free (& state -> buf );
940
+ buf_free (& state -> errbuf );
941
+
781
942
if (state -> root ) vcardcomponent_free (state -> root );
782
943
783
944
memset (state , 0 , sizeof (struct vcardparser_state ));
@@ -787,36 +948,8 @@ static void vcardparser_free(struct vcardparser_state *state)
787
948
{
788
949
_free_state (state );
789
950
}
790
- #if 0
791
- void vcardparser_fillpos (struct vcardparser_state * state ,
792
- struct vcardparser_errorpos * pos )
793
- {
794
- int l = 1 ;
795
- int c = 0 ;
796
- const char * p ;
797
-
798
- memset (pos , 0 , sizeof (struct vcardparser_errorpos ));
799
-
800
- pos -> errorpos = state -> p - state -> base ;
801
- pos -> startpos = state -> itemstart - state -> base ;
802
951
803
- for (p = state -> base ; p < state -> p ; p ++ ) {
804
- if (* p == '\n' ) {
805
- l ++ ;
806
- c = 0 ;
807
- }
808
- else {
809
- c ++ ;
810
- }
811
- if (p == state -> itemstart ) {
812
- pos -> startline = l ;
813
- pos -> startchar = c ;
814
- }
815
- }
816
-
817
- pos -> errorline = l ;
818
- pos -> errorchar = c ;
819
- }
952
+ /* PUBLIC API */
820
953
821
954
const char * vcardparser_errstr (int err )
822
955
{
@@ -839,6 +972,8 @@ const char *vcardparser_errstr(int err)
839
972
return "End of data while parsing property name" ;
840
973
case PE_NAME_EOL :
841
974
return "End of line while parsing property name" ;
975
+ case PE_NAME_INVALID :
976
+ return "Invalid property name" ;
842
977
case PE_PARAMVALUE_EOF :
843
978
return "End of data while parsing parameter value" ;
844
979
case PE_PARAMVALUE_EOL :
@@ -847,13 +982,13 @@ const char *vcardparser_errstr(int err)
847
982
return "End of data while parsing quoted value" ;
848
983
case PE_QSTRING_EOL :
849
984
return "End of line while parsing quoted value" ;
985
+ case PE_VALUE_INVALID :
986
+ return "Invalid value for property" ;
850
987
case PE_ILLEGAL_CHAR :
851
988
return "Illegal character in vCard" ;
852
989
}
853
990
return "Unknown error" ;
854
991
}
855
- #endif
856
- /* PUBLIC API */
857
992
858
993
vcardcomponent * vcardparser_parse_string (const char * str )
859
994
{
0 commit comments