carddav: add AddressObject.{ModTime,ETag}

This commit is contained in:
Simon Ser 2020-01-22 15:35:36 +01:00
parent 2eb6e89979
commit 0a251a8dfb
No known key found for this signature in database
GPG Key ID: 0FDE7BE0E88F5E48
3 changed files with 56 additions and 15 deletions

View File

@ -4,6 +4,8 @@
package carddav package carddav
import ( import (
"time"
"github.com/emersion/go-vcard" "github.com/emersion/go-vcard"
) )
@ -25,5 +27,7 @@ type AddressBookMultiGet struct {
type AddressObject struct { type AddressObject struct {
Path string Path string
ModTime time.Time
ETag string
Card vcard.Card Card vcard.Card
} }

View File

@ -6,7 +6,9 @@ import (
"net" "net"
"net/http" "net/http"
"net/url" "net/url"
"strconv"
"strings" "strings"
"time"
"github.com/emersion/go-vcard" "github.com/emersion/go-vcard"
"github.com/emersion/go-webdav" "github.com/emersion/go-webdav"
@ -140,6 +142,17 @@ func (c *Client) FindAddressBooks(addressBookHomeSet string) ([]AddressBook, err
return l, nil return l, nil
} }
func encodeAddressPropReq(props []string) (*internal.Prop, error) {
var addrDataReq addressDataReq
for _, name := range props {
addrDataReq.Props = append(addrDataReq.Props, prop{Name: name})
}
getLastModReq := internal.NewRawXMLElement(internal.GetLastModifiedName, nil, nil)
getETagReq := internal.NewRawXMLElement(internal.GetETagName, nil, nil)
return internal.EncodeProp(&addrDataReq, getLastModReq, getETagReq)
}
func decodeAddressList(ms *internal.Multistatus) ([]AddressObject, error) { func decodeAddressList(ms *internal.Multistatus) ([]AddressObject, error) {
addrs := make([]AddressObject, 0, len(ms.Responses)) addrs := make([]AddressObject, 0, len(ms.Responses))
for _, resp := range ms.Responses { for _, resp := range ms.Responses {
@ -153,6 +166,20 @@ func decodeAddressList(ms *internal.Multistatus) ([]AddressObject, error) {
return nil, err return nil, err
} }
var getLastMod internal.GetLastModified
if err := resp.DecodeProp(&getLastMod); err != nil && !internal.IsNotFound(err) {
return nil, err
}
var getETag internal.GetETag
if err := resp.DecodeProp(&getETag); err != nil && !internal.IsNotFound(err) {
return nil, err
}
etag, err := strconv.Unquote(getETag.ETag)
if err != nil {
return nil, fmt.Errorf("carddav: failed to unquote ETag: %v", err)
}
r := bytes.NewReader(addrData.Data) r := bytes.NewReader(addrData.Data)
card, err := vcard.NewDecoder(r).Decode() card, err := vcard.NewDecoder(r).Decode()
if err != nil { if err != nil {
@ -161,6 +188,8 @@ func decodeAddressList(ms *internal.Multistatus) ([]AddressObject, error) {
addrs = append(addrs, AddressObject{ addrs = append(addrs, AddressObject{
Path: path, Path: path,
ModTime: time.Time(getLastMod.LastModified),
ETag: etag,
Card: card, Card: card,
}) })
} }
@ -169,14 +198,12 @@ func decodeAddressList(ms *internal.Multistatus) ([]AddressObject, error) {
} }
func (c *Client) QueryAddressBook(addressBook string, query *AddressBookQuery) ([]AddressObject, error) { func (c *Client) QueryAddressBook(addressBook string, query *AddressBookQuery) ([]AddressObject, error) {
var addrDataReq addressDataReq var props []string
if query != nil { if query != nil {
for _, name := range query.Props { props = query.Props
addrDataReq.Props = append(addrDataReq.Props, prop{Name: name})
}
} }
propReq, err := internal.EncodeProp(&addrDataReq) propReq, err := encodeAddressPropReq(props)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -199,14 +226,12 @@ func (c *Client) QueryAddressBook(addressBook string, query *AddressBookQuery) (
} }
func (c *Client) MultiGetAddressBook(path string, multiGet *AddressBookMultiGet) ([]AddressObject, error) { func (c *Client) MultiGetAddressBook(path string, multiGet *AddressBookMultiGet) ([]AddressObject, error) {
var addrDataReq addressDataReq var props []string
if multiGet != nil { if multiGet != nil {
for _, name := range multiGet.Props { props = multiGet.Props
addrDataReq.Props = append(addrDataReq.Props, prop{Name: name})
}
} }
propReq, err := internal.EncodeProp(&addrDataReq) propReq, err := encodeAddressPropReq(props)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -3,6 +3,7 @@ package carddav
import ( import (
"bytes" "bytes"
"encoding/xml" "encoding/xml"
"fmt"
"mime" "mime"
"net/http" "net/http"
@ -259,7 +260,18 @@ func (b *backend) propfindAddressObject(propfind *internal.Propfind, ao *Address
return &addressDataResp{Data: buf.Bytes()}, nil return &addressDataResp{Data: buf.Bytes()}, nil
}, },
// TODO: getlastmodified, getetag }
if !ao.ModTime.IsZero() {
props[internal.GetLastModifiedName] = func(*internal.RawXMLValue) (interface{}, error) {
return &internal.GetLastModified{LastModified: internal.Time(ao.ModTime)}, nil
}
}
if ao.ETag != "" {
props[internal.GetETagName] = func(*internal.RawXMLValue) (interface{}, error) {
return &internal.GetETag{ETag: fmt.Sprintf("%q", ao.ETag)}, nil
}
} }
return internal.NewPropfindResponse(ao.Path, propfind, props) return internal.NewPropfindResponse(ao.Path, propfind, props)