diff --git a/carddav/carddav.go b/carddav/carddav.go index 4fe61a9..846bce7 100644 --- a/carddav/carddav.go +++ b/carddav/carddav.go @@ -19,6 +19,11 @@ type AddressBookQuery struct { Props []string } +type AddressBookMultiGet struct { + Hrefs []string + Props []string +} + type Address struct { Href string Card vcard.Card diff --git a/carddav/client.go b/carddav/client.go index bb905cc..555dbed 100644 --- a/carddav/client.go +++ b/carddav/client.go @@ -91,31 +91,7 @@ func (c *Client) FindAddressBooks(addressBookHomeSet string) ([]AddressBook, err return l, nil } -func (c *Client) QueryAddressBook(addressBook string, query *AddressBookQuery) ([]Address, error) { - var addrDataReq addressDataReq - for _, name := range query.Props { - addrDataReq.Props = append(addrDataReq.Props, prop{Name: name}) - } - - propReq, err := internal.EncodeProp(&addrDataReq) - if err != nil { - return nil, err - } - - addressbookQuery := addressbookQuery{Prop: propReq} - - req, err := c.ic.NewXMLRequest("REPORT", addressBook, &addressbookQuery) - if err != nil { - return nil, err - } - - req.Header.Add("Depth", "1") - - ms, err := c.ic.DoMultiStatus(req) - if err != nil { - return nil, err - } - +func decodeAddressList(ms *internal.Multistatus) ([]Address, error) { addrs := make([]Address, 0, len(ms.Responses)) for _, resp := range ms.Responses { href, err := resp.Href() @@ -142,3 +118,69 @@ func (c *Client) QueryAddressBook(addressBook string, query *AddressBookQuery) ( return addrs, nil } + +func (c *Client) QueryAddressBook(addressBook string, query *AddressBookQuery) ([]Address, error) { + var addrDataReq addressDataReq + if query != nil { + for _, name := range query.Props { + addrDataReq.Props = append(addrDataReq.Props, prop{Name: name}) + } + } + + propReq, err := internal.EncodeProp(&addrDataReq) + if err != nil { + return nil, err + } + + addressbookQuery := addressbookQuery{Prop: propReq} + + req, err := c.ic.NewXMLRequest("REPORT", addressBook, &addressbookQuery) + if err != nil { + return nil, err + } + + req.Header.Add("Depth", "1") + + ms, err := c.ic.DoMultiStatus(req) + if err != nil { + return nil, err + } + + return decodeAddressList(ms) +} + +func (c *Client) MultiGetAddressBook(href string, multiGet *AddressBookMultiGet) ([]Address, error) { + var addrDataReq addressDataReq + if multiGet != nil { + for _, name := range multiGet.Props { + addrDataReq.Props = append(addrDataReq.Props, prop{Name: name}) + } + } + + propReq, err := internal.EncodeProp(&addrDataReq) + if err != nil { + return nil, err + } + + addressbookMultiget := addressbookMultiget{Prop: propReq} + + if multiGet == nil || len(multiGet.Hrefs) == 0 { + addressbookMultiget.Hrefs = []string{href} + } else { + addressbookMultiget.Hrefs = multiGet.Hrefs + } + + req, err := c.ic.NewXMLRequest("REPORT", href, &addressbookMultiget) + if err != nil { + return nil, err + } + + req.Header.Add("Depth", "1") + + ms, err := c.ic.DoMultiStatus(req) + if err != nil { + return nil, err + } + + return decodeAddressList(ms) +} diff --git a/carddav/elements.go b/carddav/elements.go index 75f22d6..78ebd21 100644 --- a/carddav/elements.go +++ b/carddav/elements.go @@ -24,6 +24,14 @@ type addressbookQuery struct { // TODO: filter, limit? } +// https://tools.ietf.org/html/rfc6352#section-8.7 +type addressbookMultiget struct { + XMLName xml.Name `xml:"urn:ietf:params:xml:ns:carddav addressbook-multiget"` + Hrefs []string `xml:"DAV: href"` + Prop *internal.Prop `xml:"DAV: prop,omitempty"` + // TODO: DAV:allprop | DAV:propname +} + func newProp(name string, noValue bool) *internal.RawXMLValue { attrs := []xml.Attr{{Name: xml.Name{namespace, "name"}, Value: name}} if noValue {