Skip to content

Commit

Permalink
Merge pull request libical#720 from libical/datetime_timestamp_restri…
Browse files Browse the repository at this point in the history
…ctions

vcardrestrictions.c.in: add _validate_[datetime|timestamp]_value()
  • Loading branch information
ksmurchison authored Jul 1, 2024
2 parents a899918 + 16f3e63 commit 6d09bc8
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 9 deletions.
10 changes: 5 additions & 5 deletions design-data/vcard-restrictions.csv
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# Version, Target component, Property, Sub-component, Restriction

NONE,VCARD,VERSION,NONE,ONE
NONE,VCARD,ANNIVERSARY,NONE,ZEROORONE
NONE,VCARD,BDAY,NONE,ZEROORONE
NONE,VCARD,ANNIVERSARY,NONE,ZEROORONE,validate_datetime_value
NONE,VCARD,BDAY,NONE,ZEROORONE,validate_datetime_value
NONE,VCARD,GENDER,NONE,ZEROORONE
NONE,VCARD,KIND,NONE,ZEROORONE
NONE,VCARD,PRODID,NONE,ZEROORONE
NONE,VCARD,REV,NONE,ZEROORONE
NONE,VCARD,REV,NONE,ZEROORONE,validate_timestamp_value
NONE,VCARD,UID,NONE,ZEROORONE
NONE,VCARD,NONE,X,ZEROPLUS

Expand All @@ -21,8 +21,8 @@ NONE,VCARD,NONE,X,ZEROPLUS
# Birth/Death Extensions (RFC 6474)
NONE,VCARD,BIRTHPLACE,NONE,ZEROORONE
NONE,VCARD,DEATHPLACE,NONE,ZEROORONE
NONE,VCARD,DEATHDATE,NONE,ZEROORONE
NONE,VCARD,DEATHDATE,NONE,ZEROORONE,validate_datetime_value

# JSContact Extensions (RFC 9554)
NONE,VCARD,CREATED,NONE,ZEROORONE
NONE,VCARD,CREATED,NONE,ZEROORONE,validate_timestamp_value
NONE,VCARD,LANGUAGE,NONE,ZEROORONE
47 changes: 47 additions & 0 deletions src/libicalvcard/vcardcomponent.c
Original file line number Diff line number Diff line change
Expand Up @@ -875,6 +875,28 @@ static void comp_to_v4(vcardcomponent *impl)
vcardproperty_set_version(prop, VCARD_VERSION_40);
break;

case VCARD_BDAY_PROPERTY:
case VCARD_DEATHDATE_PROPERTY:
case VCARD_ANNIVERSARY_PROPERTY:
for (param = vcardproperty_get_first_parameter(prop,
VCARD_X_PARAMETER);
param;
param = vcardproperty_get_next_parameter(prop,
VCARD_X_PARAMETER)) {
const char *name = vcardparameter_get_xname(param);

/* This appears in the wild for v3 date with missing year */
if (name && !strcasecmp(name, "X-APPLE-OMIT-YEAR")) {
vcardtimetype dt = vcardproperty_get_bday(prop);

dt.year = -1;
vcardproperty_set_bday(prop, dt);
vcardproperty_remove_parameter_by_ref(prop, param);
break;
}
}
break;

case VCARD_GEO_PROPERTY:
if (vkind != VCARD_X_VALUE) {
vcardgeotype geo = vcardvalue_get_geo(value);
Expand Down Expand Up @@ -1085,6 +1107,31 @@ static void comp_to_v3(vcardcomponent *impl)
vcardproperty_set_version(prop, VCARD_VERSION_30);
break;

case VCARD_BDAY_PROPERTY:
case VCARD_DEATHDATE_PROPERTY:
case VCARD_ANNIVERSARY_PROPERTY: {
vcardtimetype dt = vcardproperty_get_bday(prop);

if (dt.year == -1) {
/* This appears in the wild for v3 date with missing year */
dt.year = 1604;
vcardproperty_set_parameter_from_string(prop,
"X-APPLE-OMIT-YEAR",
"1604");
}
if (dt.hour != -1) {
if (dt.second == -1) {
dt.second = 0;
if (dt.minute == -1) {
dt.minute = 0;
}
}
}

vcardproperty_set_bday(prop, dt);
break;
}

case VCARD_GEO_PROPERTY:
if (vkind != VCARD_X_VALUE) {
vcardgeotype geo = vcardvalue_get_geo(value);
Expand Down
64 changes: 63 additions & 1 deletion src/libicalvcard/vcardrestriction.c.in
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,69 @@ int vcardrestriction_compare(vcardrestriction_kind restr, int count)
return compare_map[restr][count];
}

/* Special case routines */

#define TMP_BUF_SIZE 1024

static const char *vcardrestriction_validate_datetime_value(
const vcardrestriction_record *rec,
vcardcomponent *comp, vcardproperty *prop)
{
vcardtimetype t = vcardproperty_get_bday(prop);
static char buf[TMP_BUF_SIZE];

if (vcardtime_is_null_datetime(t))
return 0;

if (comp && vcardcomponent_get_version(comp) != VCARD_VERSION_40) {
unsigned missing_time_parts =
(t.hour < 0) + (t.minute < 0) + (t.second < 0);

if (t.year < 0 || t.month < 0 || t.day < 0 ||
(missing_time_parts && missing_time_parts != 3)) {

snprintf(buf, TMP_BUF_SIZE,
"Failed restrictions for %s property. "
"The value must be a full date or date-time",
vcardproperty_kind_to_string(rec->property));
return buf;
}
}

if (!vcardtime_is_valid_time(t)) {
snprintf(buf, TMP_BUF_SIZE,
"Failed restrictions for %s property. "
"The value is an invalid date-and-or-time",
vcardproperty_kind_to_string(rec->property));
return buf;
}

return 0;
}

static const char *vcardrestriction_validate_timestamp_value(
const vcardrestriction_record *rec,
vcardcomponent *comp, vcardproperty *prop)
{
_unused(comp);

vcardtimetype t = vcardproperty_get_rev(prop);
static char buf[TMP_BUF_SIZE];

if (vcardtime_is_null_datetime(t))
return 0;

if (!vcardtime_is_timestamp(t) || !vcardtime_is_valid_time(t)) {
snprintf(buf, TMP_BUF_SIZE,
"Failed restrictions for %s property. "
"The value is an invalid timestamp",
vcardproperty_kind_to_string(rec->property));
return buf;
}

return 0;
}

static int _check_restriction(vcardcomponent *comp,
const vcardrestriction_record *record,
int count, vcardproperty *prop)
Expand All @@ -112,7 +175,6 @@ static int _check_restriction(vcardcomponent *comp,
assert(compare != -1);

if (compare == 0) {
#define TMP_BUF_SIZE 1024
char temp[TMP_BUF_SIZE];
vcardproperty *errProp;
vcardparameter *errParam;
Expand Down
3 changes: 2 additions & 1 deletion src/libicalvcard/vcardtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ int vcardtime_is_datetime(const vcardtimetype t)
int vcardtime_is_timestamp(const vcardtimetype t)
{
return (t.year != -1 && t.month != -1 && t.day != -1 &&
t.hour != -1 && t.minute != -1 && t.second != -1);
t.hour != -1 && t.minute != -1 && t.second != -1 &&
t.utcoffset != -1);
}

int vcardtime_is_utc(const vcardtimetype t)
Expand Down
4 changes: 2 additions & 2 deletions src/test/libicalvcard/vcard_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ static void test_n_restriction(vcardcomponent *card)
"VERSION:3.0\r\n"
"FN:Mickey Mouse\r\n"
"PHOTO;ENCODING=B;TYPE=JPEG:ABCDEF\r\n"
"BDAY:00001118T030000\r\n"
"BDAY;X-APPLE-OMIT-YEAR=1604:16041118T030000\r\n"
"ADR:;;123 Main Street,Disney World;Orlando;FL;32836;USA;;;;;;;;;;;\r\n"
"TEL:+1-888-555-1212\r\n"
"LANG;PREF=1;TYPE=PREF:en\r\n"
Expand Down Expand Up @@ -354,7 +354,7 @@ static void test_v3_to_v4(vcardcomponent *card)
"VERSION:4.0\r\n"
"FN:Mickey Mouse\r\n"
"PHOTO:data:image/jpeg;base64,ABCDEF\r\n"
"BDAY:--1118T03\r\n"
"BDAY:--1118T030000\r\n"
"ADR:;;123 Main Street,Disney World;Orlando;FL;32836;USA;;;;;;;;;;;\r\n"
"TEL:+1-888-555-1212\r\n"
"LANG;PREF=1:en\r\n"
Expand Down

0 comments on commit 6d09bc8

Please sign in to comment.