Skip to content

Commit 945559d

Browse files
committed
fix vcardrestriction_check() and regression tests
1 parent d877cc5 commit 945559d

File tree

3 files changed

+143
-43
lines changed

3 files changed

+143
-43
lines changed

Diff for: src/libicalvcard/vcardrestriction.c.in

+15-17
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ static int _check_restriction(vcardcomponent *comp,
103103
if (restr == VCARD_RESTRICTION_ONEEXCLUSIVE ||
104104
restr == VCARD_RESTRICTION_ONEMUTUAL) {
105105

106-
/* First treat is as a 0/1 restriction */
106+
/* First treat it as a 0/1 restriction */
107107
restr = VCARD_RESTRICTION_ZEROORONE;
108108
}
109109

@@ -157,10 +157,10 @@ static int _check_restriction(vcardcomponent *comp,
157157
return compare;
158158
}
159159

160-
static int vcardrestriction_check_component(vcardproperty_version version,
161-
vcardcomponent *comp)
160+
static int vcardrestriction_check_component(vcardcomponent *comp)
162161
{
163162
vcardcomponent_kind comp_kind, inner_kind;
163+
vcardproperty_version version;
164164
vcardproperty_kind prop_kind;
165165
const vcardrestriction_record *start_record;
166166
vcardproperty *version_prop = NULL;
@@ -204,10 +204,10 @@ static int vcardrestriction_check_component(vcardproperty_version version,
204204

205205
/* Check all of the properties in this component */
206206

207-
start_record = vcardrestriction_get_restriction(NULL, version, comp_kind,
208-
VCARD_ANY_PROPERTY,
209-
VCARD_NO_COMPONENT);
210-
207+
start_record = vcardrestriction_get_restriction(NULL, VCARD_VERSION_NONE,
208+
comp_kind,
209+
VCARD_ANY_PROPERTY,
210+
VCARD_NO_COMPONENT);
211211
if (start_record != &null_restriction_record) {
212212

213213
for (prop_kind = VCARD_ANY_PROPERTY + 1;
@@ -227,14 +227,11 @@ static int vcardrestriction_check_component(vcardproperty_version version,
227227
valid = valid && compare;
228228
}
229229
}
230-
else {
231-
start_record = NULL;
232-
}
233230

234231
/* Now check the inner components */
235232

236-
start_record = vcardrestriction_get_restriction(start_record,
237-
version, comp_kind,
233+
start_record = vcardrestriction_get_restriction(NULL, VCARD_VERSION_NONE,
234+
comp_kind,
238235
VCARD_NO_PROPERTY,
239236
VCARD_ANY_COMPONENT);
240237

@@ -259,7 +256,7 @@ static int vcardrestriction_check_component(vcardproperty_version version,
259256
inner_comp != 0;
260257
inner_comp = vcardcomponent_get_next_component(comp, VCARD_ANY_COMPONENT)) {
261258

262-
compare = vcardrestriction_check_component(version, inner_comp);
259+
compare = vcardrestriction_check_component(inner_comp);
263260

264261
valid = valid && compare;
265262
}
@@ -276,13 +273,13 @@ int vcardrestriction_check(vcardcomponent *outer_comp)
276273

277274
comp_kind = vcardcomponent_isa(outer_comp);
278275

279-
if (comp_kind != VCARD_VCARD_COMPONENT && comp_kind != VCARD_XROOT_COMPONENT) {
276+
if (comp_kind != VCARD_VCARD_COMPONENT &&
277+
comp_kind != VCARD_XROOT_COMPONENT) {
280278
icalerror_set_errno(ICAL_BADARG_ERROR);
281279
return 0;
282280
}
283281

284-
/* Check the VCALENDAR wrapper */
285-
valid = vcardrestriction_check_component(VCARD_VERSION_NONE, outer_comp);
282+
valid = vcardrestriction_check_component(outer_comp);
286283

287284
return valid;
288285
}
@@ -302,7 +299,8 @@ static const vcardrestriction_record *vcardrestriction_get_restriction(
302299

303300
for (rec = start; rec && rec->restriction != VCARD_RESTRICTION_NONE; rec++) {
304301

305-
if (version == rec->version &&
302+
if ((version == VCARD_VERSION_NONE ||
303+
rec->version == VCARD_VERSION_NONE || version == rec->version) &&
306304
(component == VCARD_ANY_COMPONENT ||
307305
(component == rec->component &&
308306
(property == VCARD_ANY_PROPERTY || property == rec->property) &&

Diff for: src/test/libicalvcard/vcard_test.c

+127-25
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#include "vcard.h"
1717

18+
#include <assert.h>
1819
#include <stdio.h>
1920
#include <string.h>
2021
#include <sys/types.h>
@@ -26,6 +27,14 @@
2627
#include <unistd.h>
2728
#endif
2829

30+
#define assert_str_equals(want, have) \
31+
{ \
32+
const char *_w = (want); \
33+
const char *_h = (have); \
34+
int _v = strcmp(_w, _h); \
35+
if (_v) { fprintf(stderr, "line %d: string mismatch\n want=%s\n have=%s\n", __LINE__, _w, _h); assert(0); } \
36+
}
37+
2938
void strip_errors(vcardcomponent *comp)
3039
{
3140
vcardproperty *prop, *next;
@@ -38,49 +47,90 @@ void strip_errors(vcardcomponent *comp)
3847
}
3948
}
4049

41-
int main(int argc, const char **argv)
50+
static void test_parse_file(const char *fname)
4251
{
43-
int fd;
44-
const char *fname;
52+
int fd, r;
4553
struct stat sbuf;
4654
size_t filesize;
4755
void *data = NULL;
56+
vcardcomponent *card;
57+
const char *want =
58+
"BEGIN:VCARD\r\n"
59+
"VERSION:4.0\r\n"
60+
"FN:Simon Perreault\r\n"
61+
"N:Perreault;Simon;;;ing. jr,M.Sc.\r\n"
62+
"BDAY;VALUE=DATE:--0203\r\n"
63+
"BDAY;VALUE=DATE:--0203\r\n"
64+
"ANNIVERSARY;VALUE=TIMESTAMP:20090808T143000-0500\r\n"
65+
"GENDER:M;manly\r\n"
66+
"ADR;TYPE=WORK:;Suite D2-630;2875 Laurier;Quebec;QC;G1V 2M2;Canada\r\n"
67+
"TEL;VALUE=URI;TYPE=WORK,TEXT,VOICE,CELL,VIDEO,bar,foo:tel:\r\n"
68+
" +1-418-262-6501\r\n"
69+
"TEL;VALUE=URI:tel:+1-418-656-9254;ext=102\r\n"
70+
"EMAIL;TYPE=WORK:[email protected]\r\n"
71+
"LANG;PREF=2:en\r\n"
72+
"LANG;PREF=1:fr\r\n"
73+
"TZ;VALUE=TEXT:-0500\r\n"
74+
"GEO;TYPE=WORK:geo:46.772673,-71.282945\r\n"
75+
"ORG;TYPE=WORK:Viagenie;Foo\r\n"
76+
"CATEGORIES:bar,foo\r\n"
77+
"NOTE;LANGUAGE=en;PID=1.0,3:Test vCard\r\n"
78+
"URL;TYPE=HOME:http://nomis80.org\r\n"
79+
"KEY;VALUE=URI;TYPE=WORK:http://www.viagenie.ca/simon.perreault/simon.asc\r\n"
80+
"X-LIC-ERROR;X-LIC-ERRORTYPE=RESTRICTION-CHECK:Failed restrictions for \r\n"
81+
" BDAY property. Expected zero or one instances of the property and got 2\r\n"
82+
"END:VCARD\r\n"
83+
"BEGIN:VCARD\r\n"
84+
"FN:Mickey Mouse\r\n"
85+
"X-LIC-ERROR;X-LIC-ERRORTYPE=RESTRICTION-CHECK:Failed restrictions for N \r\n"
86+
" property. Expected 1 instances of the property and got 0\r\n"
87+
"X-LIC-ERROR;X-LIC-ERRORTYPE=RESTRICTION-CHECK:Failed restrictions for \r\n"
88+
" VERSION property. Expected 1 instances of the property and got 0\r\n"
89+
"END:VCARD\r\n";
4890

49-
if (argc != 2) {
50-
fprintf(stderr, "Usage: %s fname\n", argv[0]);
51-
exit(1);
52-
}
53-
54-
fname = argv[1];
5591
fd = open(fname, O_RDONLY);
5692
if (fd < 0) {
5793
fprintf(stderr, "Error: unable to open %s\n", fname);
58-
exit(1);
94+
assert(0);
5995
}
6096
fstat(fd, &sbuf);
6197
filesize = sbuf.st_size; //to make fortify compile happy
6298
data = malloc(filesize+1);
6399
memset(data, 0, filesize+1);
64-
if (read(fd, data, filesize) < 0) {
100+
101+
r = read(fd, data, filesize);
102+
close(fd);
103+
104+
if (r < 0) {
65105
fprintf(stderr, "Failed to read vCard\n");
66106
free(data);
67-
close(fd);
68-
return -1;
107+
assert(0);
69108
}
70109

71-
vcardcomponent *card = vcardparser_parse_string(data);
110+
card = vcardparser_parse_string(data);
72111
free(data);
73112

74113
if (card == NULL) {
75114
fprintf(stderr, "Failed to parse vCard\n");
76-
close(fd);
77-
return -1;
115+
assert(0);
78116
}
79117

80118
vcardrestriction_check(card);
81119
vcardcomponent_normalize(card);
82-
printf("%s\n", vcardcomponent_as_vcard_string(card));
120+
assert_str_equals(want, vcardcomponent_as_vcard_string(card));
83121
vcardcomponent_free(card);
122+
}
123+
124+
static vcardcomponent *test_comp_vanew(void)
125+
{
126+
vcardcomponent *card;
127+
const char *want =
128+
"BEGIN:VCARD\r\n"
129+
"VERSION:4.0\r\n"
130+
"X-LIC-ERROR;X-LIC-ERRORTYPE=RESTRICTION-CHECK:Failed restrictions for FN \r\n"
131+
" property. Expected one or more instances of the property and got 0\r\n"
132+
"END:VCARD\r\n";
133+
84134

85135
card = vcardcomponent_vanew(VCARD_VCARD_COMPONENT,
86136
vcardproperty_new_version(VCARD_VERSION_40),
@@ -89,14 +139,31 @@ int main(int argc, const char **argv)
89139

90140
if (card == NULL) {
91141
fprintf(stderr, "Failed to create vCard\n");
92-
close(fd);
93-
return -1;
142+
assert(0);
94143
}
95144

96145
vcardrestriction_check(card);
97-
printf("\n%s\n", vcardcomponent_as_vcard_string(card));
146+
vcardcomponent_normalize(card);
147+
assert_str_equals(want, vcardcomponent_as_vcard_string(card));
98148
strip_errors(card);
99149

150+
return card;
151+
}
152+
153+
static void test_add_props(vcardcomponent *card)
154+
{
155+
const char *want =
156+
"BEGIN:VCARD\r\n"
157+
"VERSION:4.0\r\n"
158+
"FN:Mickey Mouse\r\n"
159+
"N:Mouse;Mickey;;;;;\r\n"
160+
"BDAY;VALUE=DATE:19281118\r\n"
161+
"ADR:;;123 Main Street,Disney World;Orlando;FL;32836;USA;;;;;;;;;;;\r\n"
162+
"CATEGORIES:aaa,zzz\r\n"
163+
"group1.NOTE;LANGUAGE=en;PID=1,3;SORT-AS=bar,foo;TYPE=WORK:Test vCard\r\n"
164+
// "REV:20240424T143248Z\r\n"
165+
"END:VCARD\r\n";
166+
100167
/* Create and add NOTE property */
101168
vcardstrarray *sa = vcardstrarray_new(10);
102169
vcardstrarray_append(sa, "1");
@@ -173,25 +240,60 @@ int main(int argc, const char **argv)
173240
t.day = 18;
174241
prop = vcardproperty_new_bday(t);
175242
vcardcomponent_add_property(card, prop);
176-
243+
#if 0 // Can't easily compare
177244
/* Create and add REV property */
178245
t = vcardtime_current_utc_time();
179246
prop = vcardproperty_new_rev(t);
180247
vcardcomponent_add_property(card, prop);
181-
248+
#endif
182249
vcardrestriction_check(card);
183250
vcardcomponent_normalize(card);
184-
printf("\n%s\n", vcardcomponent_as_vcard_string(card));
251+
assert_str_equals(want, vcardcomponent_as_vcard_string(card));
252+
}
253+
254+
static void test_n_restriction(vcardcomponent *card)
255+
{
256+
vcardproperty *prop;
257+
const char *want =
258+
"BEGIN:VCARD\r\n"
259+
"VERSION:3.0\r\n"
260+
"FN:Mickey Mouse\r\n"
261+
"BDAY;VALUE=DATE:19281118\r\n"
262+
"ADR:;;123 Main Street,Disney World;Orlando;FL;32836;USA;;;;;;;;;;;\r\n"
263+
"CATEGORIES:aaa,zzz\r\n"
264+
"group1.NOTE;LANGUAGE=en;PID=1,3;SORT-AS=bar,foo;TYPE=WORK:Test vCard\r\n"
265+
"X-LIC-ERROR;X-LIC-ERRORTYPE=RESTRICTION-CHECK:Failed restrictions for N \r\n"
266+
" property. Expected 1 instances of the property and got 0\r\n"
267+
"END:VCARD\r\n";
185268

186269
/* Change VERSION from 4.0 to 3.0 */
187270
prop = vcardcomponent_get_first_property(card, VCARD_VERSION_PROPERTY);
188271
vcardproperty_set_version(prop, VCARD_VERSION_30);
189272

273+
/* Remove N property */
274+
prop = vcardcomponent_get_first_property(card, VCARD_N_PROPERTY);
275+
vcardcomponent_remove_property(card, prop);
276+
vcardproperty_free(prop);
277+
190278
vcardrestriction_check(card);
191-
printf("\n%s\n", vcardcomponent_as_vcard_string(card));
279+
assert_str_equals(want, vcardcomponent_as_vcard_string(card));
280+
}
281+
282+
int main(int argc, const char **argv)
283+
{
284+
vcardcomponent *card;
285+
286+
if (argc != 2) {
287+
fprintf(stderr, "Usage: %s fname\n", argv[0]);
288+
exit(1);
289+
}
290+
291+
test_parse_file(argv[1]);
292+
card = test_comp_vanew();
293+
test_add_props(card);
294+
test_n_restriction(card);
192295

193296
vcardcomponent_free(card);
194297

195-
close(fd);
196298
return 0;
197299
}

Diff for: test-data/test.vcf

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ VERSION: 4.0
33
FN:Simon Perreault
44
N:Perreault;Simon;;;ing. jr,M.Sc.
55
BDAY:--0203
6+
BDAY:--0203
67
ANNIVERSARY:20090808T1430-0500
78
GENDER:M;manly
89
LANG;PREF=1:fr
@@ -23,6 +24,5 @@ CATEGORIES:foo,bar
2324
END:VCARD
2425

2526
BEGIN:VCARD
26-
VERSION:5.0
2727
FN:Mickey Mouse
2828
END:VCARD

0 commit comments

Comments
 (0)