Skip to content

Commit

Permalink
jmap_contact.c: unknown component kind/property results in JSPROP for…
Browse files Browse the repository at this point in the history
… components
  • Loading branch information
ksmurchison committed Jul 20, 2023
1 parent b66c13a commit f631aed
Show file tree
Hide file tree
Showing 4 changed files with 246 additions and 21 deletions.
66 changes: 66 additions & 0 deletions cassandane/tiny-tests/JMAPContacts/card-set-create-name-bad-type
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#!perl
use Cassandane::Tiny;

sub test_card_set_create_name_bad_type
:min_version_3_9 :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 $href = "Default/$id.vcf";

my $res = $jmap->CallMethods([
['Card/set', {
create => {
"1" => {
'@type' => 'Card',
version => '1.0',
uid => $id,
name => {
isOrdered => JSON::true,
components => [
{
kind => 'given',
value => 'Robert'
},
{
kind => 'given2',
value => 'Pau'
},
{
kind => 'surname',
value => 'Shou'
},
{
'@type' => 'Foo',
kind => 'surname2',
value => 'Chang'
}
],
sortAs => {
surname => 'Pau Shou Chang',
given => 'Robert'
}
}
}
}
}, 'R1']
]);

$self->assert_not_null($res->[0][1]{notCreated}{1});
$self->assert_equals("name/components[3]/\@type",
$res->[0][1]{notCreated}{1}{properties}[0]);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#!perl
use Cassandane::Tiny;

sub test_card_set_create_name_unknown_kind
:min_version_3_9 :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 $href = "Default/$id.vcf";

my $res = $jmap->CallMethods([
['Card/set', {
create => {
"1" => {
'@type' => 'Card',
version => '1.0',
uid => $id,
name => {
isOrdered => JSON::true,
components => [
{
kind => 'given',
value => 'Robert'
},
{
kind => 'middle',
value => 'Pau'
},
{
kind => 'surname',
value => 'Shou'
},
{
'@type' => 'Name',
kind => 'surname2',
value => 'Chang'
}
],
sortAs => {
surname => 'Pau Shou Chang',
given => 'Robert'
}
}
}
}
}, 'R1']
]);

$self->assert_not_null($res->[0][1]{created}{1});

$res = $carddav->Request('GET', $href, '',
'Accept' => 'text/vcard; version=4.0');

my $card = $res->{content};
$card =~ s/\r?\n[ \t]+//gs; # unfold long properties
$card =~ s/\\,/,/gs; # unescape commas

$self->assert_matches(qr|JSPROP;JSPTR=name/components:|, $card);
$self->assert_matches(qr/FN:No Name/, $card);
$self->assert_does_not_match(qr/N;/, $card);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#!perl
use Cassandane::Tiny;

sub test_card_set_create_name_unknown_prop
:min_version_3_9 :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 $href = "Default/$id.vcf";

my $res = $jmap->CallMethods([
['Card/set', {
create => {
"1" => {
'@type' => 'Card',
version => '1.0',
uid => $id,
name => {
isOrdered => JSON::true,
components => [
{
kind => 'given',
value => 'Robert',
foo => bar
},
{
kind => 'given2',
value => 'Pau'
},
{
kind => 'surname',
value => 'Shou'
},
{
'@type' => 'Name',
kind => 'surname2',
value => 'Chang'
}
],
sortAs => {
surname => 'Pau Shou Chang',
given => 'Robert'
}
}
}
}
}, 'R1']
]);

$self->assert_not_null($res->[0][1]{created}{1});

$res = $carddav->Request('GET', $href, '',
'Accept' => 'text/vcard; version=4.0');

my $card = $res->{content};
$card =~ s/\r?\n[ \t]+//gs; # unfold long properties
$card =~ s/\\,/,/gs; # unescape commas

$self->assert_matches(qr|JSPROP;JSPTR=name/components:|, $card);
$self->assert_matches(qr/FN:No Name/, $card);
$self->assert_does_not_match(qr/N;/, $card);
}
50 changes: 29 additions & 21 deletions imap/jmap_contact.c
Original file line number Diff line number Diff line change
Expand Up @@ -8653,26 +8653,41 @@ static int _jscomps_to_vcard(struct jmap_parser *parser, json_t *obj,

for (i = 0; i < size; i++) {
json_t *comp = json_array_get(comps, i);
const char *key, *val;
const char *key, *kind = NULL, *val = NULL;
json_t *jsubprop;

jmap_parser_push_index(parser, "components", i, NULL);

jsubprop = json_object_get(comp, "@type");
if (jsubprop &&
strcmpsafe(comp_type, json_string_value(jsubprop))) {
jmap_parser_invalid(parser, "@type");
break;
json_object_foreach(comp, key, jsubprop) {
if (!strcmp("@type", key)) {
if (strcmpsafe(comp_type, json_string_value(jsubprop))) {
jmap_parser_invalid(parser, "@type");
break;
}
}
else if (!strcmp("kind", key)) {
kind = json_string_value(jsubprop);
}
else if (!strcmp("value", key)) {
val = json_string_value(jsubprop);
}
else {
jmap_parser_pop(parser);
_jsunknown_to_vcard(parser, "components", comps, card);
goto fail;
}
}

val = json_string_value(json_object_get(comp, "value"));
if (!val) {
jmap_parser_invalid(parser, "value");
break;
}

key = json_string_value(json_object_get(comp, "kind"));
if (!strcmp(key, "separator")) {
if (!kind) {
jmap_parser_invalid(parser, "kind");
break;
}
else if (!strcmp(kind, "separator")) {
if (isordered) {
/* Add separator entry to JSCOMPS */
sep = val;
Expand All @@ -8690,12 +8705,14 @@ static int _jscomps_to_vcard(struct jmap_parser *parser, json_t *obj,
}
}
else {
const struct comp_kind *ckind = _field_name_to_kind(key, comp_kinds);
const struct comp_kind *ckind =
_field_name_to_kind(kind, comp_kinds);
vcardstrarray **field;

if (!ckind) {
jmap_parser_invalid(parser, "kind");
break;
jmap_parser_pop(parser);
_jsunknown_to_vcard(parser, "components", comps, card);
goto fail;
}

/* Add value to proper field */
Expand Down Expand Up @@ -8732,15 +8749,6 @@ static int _jscomps_to_vcard(struct jmap_parser *parser, json_t *obj,
}
}

json_object_del(comp, "@type");
json_object_del(comp, "kind");
json_object_del(comp, "value");

/* Add unknown properties */
json_object_foreach(comp, key, jsubprop) {
_jsunknown_to_vcard(parser, key, jsubprop, card);
}

jmap_parser_pop(parser);
}

Expand Down

0 comments on commit f631aed

Please sign in to comment.