From abadf534f49a3b6636029ca8b4f8306e05780235 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Thu, 27 Feb 2020 12:36:14 +0100 Subject: [PATCH] carddav: expose supported address data in client --- carddav/carddav.go | 26 ++++++++++++++++++++++---- carddav/client.go | 23 +++++++++++++++++++---- carddav/elements.go | 12 ++++++------ carddav/server.go | 4 ++-- 4 files changed, 49 insertions(+), 16 deletions(-) diff --git a/carddav/carddav.go b/carddav/carddav.go index 9a3dc8b..47c366f 100644 --- a/carddav/carddav.go +++ b/carddav/carddav.go @@ -9,11 +9,29 @@ import ( "github.com/emersion/go-vcard" ) +type AddressDataType struct { + ContentType string + Version string +} + type AddressBook struct { - Path string - Name string - Description string - MaxResourceSize int64 + Path string + Name string + Description string + MaxResourceSize int64 + SupportedAddressData []AddressDataType +} + +func (ab *AddressBook) SupportsAddressData(contentType, version string) bool { + if len(ab.SupportedAddressData) == 0 { + return contentType == "text/vcard" && version == "3.0" + } + for _, t := range ab.SupportedAddressData { + if t.ContentType == contentType && t.Version == version { + return true + } + } + return false } type AddressBookQuery struct { diff --git a/carddav/client.go b/carddav/client.go index d649aa4..53d8d97 100644 --- a/carddav/client.go +++ b/carddav/client.go @@ -94,12 +94,21 @@ func (c *Client) FindAddressBookHomeSet(principal string) (string, error) { return prop.Href.Path, nil } +func decodeSupportedAddressData(supported *supportedAddressData) []AddressDataType { + l := make([]AddressDataType, len(supported.Types)) + for i, t := range supported.Types { + l[i] = AddressDataType{t.ContentType, t.Version} + } + return l +} + func (c *Client) FindAddressBooks(addressBookHomeSet string) ([]AddressBook, error) { propfind := internal.NewPropNamePropfind( internal.ResourceTypeName, internal.DisplayNameName, addressBookDescriptionName, maxResourceSizeName, + supportedAddressDataName, ) ms, err := c.ic.Propfind(addressBookHomeSet, internal.DepthOne, propfind) if err != nil { @@ -139,11 +148,17 @@ func (c *Client) FindAddressBooks(addressBookHomeSet string) ([]AddressBook, err return nil, fmt.Errorf("carddav: max-resource-size must be a positive integer") } + var supported supportedAddressData + if err := resp.DecodeProp(&supported); err != nil && !internal.IsNotFound(err) { + return nil, err + } + l = append(l, AddressBook{ - Path: path, - Name: dispName.Name, - Description: desc.Description, - MaxResourceSize: maxResSize.Size, + Path: path, + Name: dispName.Name, + Description: desc.Description, + MaxResourceSize: maxResSize.Size, + SupportedAddressData: decodeSupportedAddressData(&supported), }) } diff --git a/carddav/elements.go b/carddav/elements.go index 6bc764a..fee3f16 100644 --- a/carddav/elements.go +++ b/carddav/elements.go @@ -12,10 +12,10 @@ const namespace = "urn:ietf:params:xml:ns:carddav" var ( addressBookHomeSetName = xml.Name{namespace, "addressbook-home-set"} - addressBookName = xml.Name{namespace, "addressbook"} - addressBookDescriptionName = xml.Name{namespace, "addressbook-description"} - addressBookSupportedAddressData = xml.Name{namespace, "addressbook-supported-address-data"} - maxResourceSizeName = xml.Name{namespace, "max-resource-size"} + addressBookName = xml.Name{namespace, "addressbook"} + addressBookDescriptionName = xml.Name{namespace, "addressbook-description"} + supportedAddressDataName = xml.Name{namespace, "supported-address-data"} + maxResourceSizeName = xml.Name{namespace, "max-resource-size"} addressBookQueryName = xml.Name{namespace, "addressbook-query"} addressBookMultigetName = xml.Name{namespace, "addressbook-multiget"} @@ -35,8 +35,8 @@ type addressbookDescription struct { } // https://tools.ietf.org/html/rfc6352#section-6.2.2 -type addressbookSupportedAddressData struct { - XMLName xml.Name `xml:"urn:ietf:params:xml:ns:carddav addressbook-supported-address-data"` +type supportedAddressData struct { + XMLName xml.Name `xml:"urn:ietf:params:xml:ns:carddav supported-address-data"` Types []addressDataType `xml:"address-data-type"` } diff --git a/carddav/server.go b/carddav/server.go index 07b525b..4f8995c 100644 --- a/carddav/server.go +++ b/carddav/server.go @@ -321,8 +321,8 @@ func (b *backend) propfindAddressBook(propfind *internal.Propfind, ab *AddressBo addressBookDescriptionName: func(*internal.RawXMLValue) (interface{}, error) { return &addressbookDescription{Description: ab.Description}, nil }, - addressBookSupportedAddressData: func(*internal.RawXMLValue) (interface{}, error) { - return &addressbookSupportedAddressData{ + supportedAddressDataName: func(*internal.RawXMLValue) (interface{}, error) { + return &supportedAddressData{ Types: []addressDataType{ {ContentType: vcard.MIMEType, Version: "3.0"}, {ContentType: vcard.MIMEType, Version: "4.0"},