From e220477a5a380886f66ab21e5567b2d3eff0939b Mon Sep 17 00:00:00 2001 From: Ken Murchison Date: Tue, 1 Aug 2023 19:04:17 -0400 Subject: [PATCH] jmap_contact.c: add support for phonetics --- .../JMAPContacts/card-get-phonetics | 89 +++++++++++++++++++ imap/jmap_contact.c | 42 +++++++-- 2 files changed, 126 insertions(+), 5 deletions(-) create mode 100644 cassandane/tiny-tests/JMAPContacts/card-get-phonetics diff --git a/cassandane/tiny-tests/JMAPContacts/card-get-phonetics b/cassandane/tiny-tests/JMAPContacts/card-get-phonetics new file mode 100644 index 00000000000..58c2f0f59cc --- /dev/null +++ b/cassandane/tiny-tests/JMAPContacts/card-get-phonetics @@ -0,0 +1,89 @@ +#!perl +use Cassandane::Tiny; +use utf8; + +sub test_card_get_phonetics + :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 $card = <Request('PUT', $href, $card, 'Content-Type' => 'text/vcard'); + + my $res = $jmap->CallMethods([ + ['ContactCard/get', { + }, 'R1'] + ]); + + my $want_jscard = { + '@type' => 'Card', + version => '1.0', + addressBookId => 'Default', + 'cyrusimap.org:href' => $carddav->fullpath() . $href, + id => $id, + uid => $id, + language => 'zho-Hant', + vCardProps => [ + [ 'version', {}, 'text', '4.0' ] + ], + name => { + full => '孫中山文逸仙', + components => [ + { kind => 'surname', value => '孫' }, + { kind => 'given', value => '中山' }, + { kind => 'given2', value => '文' }, + { kind => 'given2', value => '逸仙' } + ] + }, + localizations => { + yue => { + "name/phoneticSystem" => "jyut", + "name/phoneticScript" => "Latn", + "name/components/0/phonetic" => "syun1", + "name/components/1/phonetic" => "zung1saan1", + "name/components/2/phonetic" => "man4", + "name/components/3/phonetic" => "jat6sin1" + } + } + }; + + my $have_jscard = $res->[0][1]{list}[0]; + + # Delete generated fields + delete $have_jscard->{blobId}; + delete $have_jscard->{'cyrusimap.org:blobId'}; + delete $have_jscard->{'cyrusimap.org:size'}; + + # Normalize and compare cards + normalize_jscard($want_jscard); + normalize_jscard($have_jscard); + + $self->assert_deep_equals($want_jscard, $have_jscard); +} diff --git a/imap/jmap_contact.c b/imap/jmap_contact.c index 374162c0243..4b7095272ef 100644 --- a/imap/jmap_contact.c +++ b/imap/jmap_contact.c @@ -6226,12 +6226,43 @@ static void jscomps_from_vcard(json_t *obj, vcardproperty *prop, vcardstructuredtype *st, const struct comp_kind *comp_kinds) { - vcardparameter *param = - vcardproperty_get_first_parameter(prop, VCARD_JSCOMPS_PARAMETER); + vcardparameter *param; vcardstrarray *sa; - const char *val; + const char *val, *val_prop_name = "value"; size_t i; + param = vcardproperty_get_first_parameter(prop, VCARD_PHONETIC_PARAMETER); + if (param) { + vcardparameter_phonetic phonetic = vcardparameter_get_phonetic(param); + struct buf buf = BUF_INITIALIZER; + + if (phonetic == VCARD_PHONETIC_X) { + buf_setcstr(&buf, vcardparameter_get_xvalue(param)); + } + else { + buf_setcstr(&buf, vcardparameter_enum_to_string(phonetic)); + buf_lcase(&buf); + } + json_object_set_new(obj, "phoneticSystem", + json_string(buf_cstring(&buf))); + buf_free(&buf); + + val_prop_name = "phonetic"; + + /* Remove PHONETIC parameter */ + vcardproperty_remove_parameter_by_ref(prop, param); + } + + param = vcardproperty_get_first_parameter(prop, VCARD_SCRIPT_PARAMETER); + if (param) { + json_object_set_new(obj, "phoneticScript", + json_string(vcardparameter_get_script(param))); + + /* Remove SCRIPT parameter */ + vcardproperty_remove_parameter_by_ref(prop, param); + } + + param = vcardproperty_get_first_parameter(prop, VCARD_JSCOMPS_PARAMETER); if (param) { /* Order components per JSCOMPS */ vcardstructuredtype *jscomps = vcardparameter_get_jscomps(param); @@ -6275,7 +6306,8 @@ static void jscomps_from_vcard(json_t *obj, vcardproperty *prop, "components", "[]"), json_pack("{s:s s:o}", "kind", kind, - "value", jmap_utf8string(val))); + val_prop_name, + jmap_utf8string(val))); } } @@ -6304,7 +6336,7 @@ static void jscomps_from_vcard(json_t *obj, vcardproperty *prop, "components", "[]"), json_pack("{s:s s:o}", "kind", ckind->name, - "value", + val_prop_name, jmap_utf8string(val))); } }