From 989b17dad6769b6c0da75a2ce1d8f7604908b8bc Mon Sep 17 00:00:00 2001 From: Ken Murchison Date: Mon, 1 Jul 2024 08:20:37 -0400 Subject: [PATCH] vcard_support.c: properly handle X-APPLE-OMIT-YEAR parameter --- cassandane/tiny-tests/Carddav/put_bday_noyear | 69 +++++++++++++++++++ .../JMAPContacts/card_set_create_bday_noyear | 65 +++++++++++++++++ .../contact_set_create_bday_noyear | 48 +++++++++++++ 3 files changed, 182 insertions(+) create mode 100644 cassandane/tiny-tests/Carddav/put_bday_noyear create mode 100644 cassandane/tiny-tests/JMAPContacts/card_set_create_bday_noyear create mode 100644 cassandane/tiny-tests/JMAPContacts/contact_set_create_bday_noyear diff --git a/cassandane/tiny-tests/Carddav/put_bday_noyear b/cassandane/tiny-tests/Carddav/put_bday_noyear new file mode 100644 index 0000000000..25fc7c4e27 --- /dev/null +++ b/cassandane/tiny-tests/Carddav/put_bday_noyear @@ -0,0 +1,69 @@ +#!perl +use Cassandane::Tiny; + +sub test_put_bday_noyear + :needs_component_httpd +{ + my ($self) = @_; + + my $CardDAV = $self->{carddav}; + my $Id = $CardDAV->NewAddressBook('foo'); + $self->assert_not_null($Id); + $self->assert_str_equals($Id, 'foo'); + my $href = "$Id/bar.vcf"; + + my $id = 'ae2640cc-234a-4dd9-95cc-3106258445b9'; + my $card = < 'text/vcard', + 'Authorization' => $CardDAV->auth_header(), + ); + + xlog $self, "PUT vCard v3 with no-year BDAY -- should fail"; + my $Response = $CardDAV->{ua}->request('PUT', $CardDAV->request_url($href), { + content => $card, + headers => \%Headers, + }); + $self->assert_num_equals(403, $Response->{status}); + + xlog $self, "PUT vCard v4 with no-year BDAY"; + $card =~ s/3.0/4.0/; + $Response = $CardDAV->{ua}->request('PUT', $CardDAV->request_url($href), { + content => $card, + headers => \%Headers, + }); + $self->assert_num_equals(201, $Response->{status}); + + my $res = $CardDAV->Request('GET', $href, '', + 'Accept' => 'text/vcard; version=3.0'); + + $card = $res->{content}; + $card =~ s/\r?\n[ \t]+//gs; # unfold long properties + + $self->assert_matches(qr|BDAY;X-APPLE-OMIT-YEAR=1604:1604(-)?04(-)?15|, + $card); + + xlog $self, "PUT vCard v3 with omit-year BDAY"; + $Response = $CardDAV->{ua}->request('PUT', $CardDAV->request_url($href), { + content => $card, + headers => \%Headers, + }); + $self->assert_num_equals(204, $Response->{status}); + + $res = $CardDAV->Request('GET', $href, '', + 'Accept' => 'text/vcard; version=4.0'); + + $card = $res->{content}; + $card =~ s/\r?\n[ \t]+//gs; # unfold long properties + + $self->assert_matches(qr|BDAY:--0415|, $card); +} diff --git a/cassandane/tiny-tests/JMAPContacts/card_set_create_bday_noyear b/cassandane/tiny-tests/JMAPContacts/card_set_create_bday_noyear new file mode 100644 index 0000000000..285df4a85c --- /dev/null +++ b/cassandane/tiny-tests/JMAPContacts/card_set_create_bday_noyear @@ -0,0 +1,65 @@ +#!perl +use Cassandane::Tiny; + +sub test_card_set_create_bday_noyear + :needs_component_jmap :needs_dependency_icalvcard +{ + my ($self) = @_; + my $jmap = $self->{jmap}; + + my $service = $self->{instance}->get_service("http"); + $ENV{DEBUGDAV} = 1; + my $carddav = Net::CardDAVTalk->new( + user => 'cassandane', + password => 'pass', + host => $service->host(), + port => $service->port(), + scheme => 'http', + url => '/', + expandurl => 1, + ); + + my $id = 'ae2640cc-234a-4dd9-95cc-3106258445b9'; + + my $res = $jmap->CallMethods([ + ['ContactCard/set', { + create => { + "1" => { + '@type' => 'Card', + version => '1.0', + uid => $id, + name => { full => 'Jane Doe' }, + anniversaries => { + k8 => { + '@type' => 'Anniversary', + kind => 'birth', + date => { + month => 4, + day => 15 + } + } + } + } + } + }, 'R1'] + ]); + + $self->assert_not_null($res->[0][1]{created}{1}); + + my $href = $res->[0][1]{created}{1}{'cyrusimap.org:href'}; + $res = $carddav->Request('GET', $href, '', + 'Accept' => 'text/vcard; version=4.0'); + + my $card = $res->{content}; + $card =~ s/\r?\n[ \t]+//gs; # unfold long properties + + $self->assert_matches(qr|BDAY(;VALUE=DATE)?;PROP-ID=k8:--0415|, $card); + + $res = $carddav->Request('GET', $href, '', + 'Accept' => 'text/vcard; version=3.0'); + + $card = $res->{content}; + $card =~ s/\r?\n[ \t]+//gs; # unfold long properties + + $self->assert_matches(qr|BDAY(;VALUE=DATE)?;PROP-ID=k8;X-APPLE-OMIT-YEAR=1604:1604(-)?04(-)?15|, $card); +} diff --git a/cassandane/tiny-tests/JMAPContacts/contact_set_create_bday_noyear b/cassandane/tiny-tests/JMAPContacts/contact_set_create_bday_noyear new file mode 100644 index 0000000000..07a8e385a2 --- /dev/null +++ b/cassandane/tiny-tests/JMAPContacts/contact_set_create_bday_noyear @@ -0,0 +1,48 @@ +#!perl +use Cassandane::Tiny; + +sub test_contact_set_create_bday_noyear + :needs_component_jmap +{ + my ($self) = @_; + my $jmap = $self->{jmap}; + + my $service = $self->{instance}->get_service("http"); + $ENV{DEBUGDAV} = 1; + my $carddav = Net::CardDAVTalk->new( + user => 'cassandane', + password => 'pass', + host => $service->host(), + port => $service->port(), + scheme => 'http', + url => '/', + expandurl => 1, + ); + + my $id = 'ae2640cc-234a-4dd9-95cc-3106258445b9'; + + my $res = $jmap->CallMethods([ + ['Contact/set', { + create => { + "1" => { + uid => $id, + firstName => 'Jane', + lastName => 'Doe', + birthday => '0000-04-15' + } + } + }, 'R1'], + ['Contact/get', { ids => [ "#1" ] }, 'R2'] + ]); + + $self->assert_not_null($res->[0][1]{created}{1}); + + my $href = $res->[1][1]{list}[0]{'x-href'}; + $res = $carddav->Request('GET', $href, '', + 'Accept' => 'text/vcard; version=4.0'); + + my $card = $res->{content}; + $card =~ s/\r?\n[ \t]+//gs; # unfold long properties + + $self->assert_matches(qr|BDAY(;VALUE=DATE)?:--0415|, $card); +}