mirror of
https://github.com/1f349/go-webdav.git
synced 2024-12-22 16:24:14 +00:00
carddav: honor address-data in addressbook-query
This commit is contained in:
parent
29cccc7ef9
commit
1f509de404
@ -17,8 +17,7 @@ type AddressBook struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type AddressBookQuery struct {
|
type AddressBookQuery struct {
|
||||||
Props []string
|
DataRequest AddressDataRequest
|
||||||
AllProp bool
|
|
||||||
|
|
||||||
PropFilters []PropFilter
|
PropFilters []PropFilter
|
||||||
FilterTest FilterTest // defaults to FilterAnyOf
|
FilterTest FilterTest // defaults to FilterAnyOf
|
||||||
@ -26,6 +25,11 @@ type AddressBookQuery struct {
|
|||||||
Limit int // <= 0 means unlimited
|
Limit int // <= 0 means unlimited
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AddressDataRequest struct {
|
||||||
|
Props []string
|
||||||
|
AllProp bool
|
||||||
|
}
|
||||||
|
|
||||||
type PropFilter struct {
|
type PropFilter struct {
|
||||||
Name string
|
Name string
|
||||||
Test FilterTest // defaults to FilterAnyOf
|
Test FilterTest // defaults to FilterAnyOf
|
||||||
@ -68,9 +72,7 @@ const (
|
|||||||
|
|
||||||
type AddressBookMultiGet struct {
|
type AddressBookMultiGet struct {
|
||||||
Paths []string
|
Paths []string
|
||||||
|
DataRequest AddressDataRequest
|
||||||
Props []string
|
|
||||||
AllProp bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type AddressObject struct {
|
type AddressObject struct {
|
||||||
|
@ -142,12 +142,12 @@ func (c *Client) FindAddressBooks(addressBookHomeSet string) ([]AddressBook, err
|
|||||||
return l, nil
|
return l, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func encodeAddressPropReq(props []string, allProp bool) (*internal.Prop, error) {
|
func encodeAddressPropReq(req *AddressDataRequest) (*internal.Prop, error) {
|
||||||
var addrDataReq addressDataReq
|
var addrDataReq addressDataReq
|
||||||
if allProp {
|
if req.AllProp {
|
||||||
addrDataReq.Allprop = &struct{}{}
|
addrDataReq.Allprop = &struct{}{}
|
||||||
} else {
|
} else {
|
||||||
for _, name := range props {
|
for _, name := range req.Props {
|
||||||
addrDataReq.Props = append(addrDataReq.Props, prop{Name: name})
|
addrDataReq.Props = append(addrDataReq.Props, prop{Name: name})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -245,14 +245,7 @@ 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 props []string
|
propReq, err := encodeAddressPropReq(&query.DataRequest)
|
||||||
var allProp bool
|
|
||||||
if query != nil {
|
|
||||||
props = query.Props
|
|
||||||
allProp = query.AllProp
|
|
||||||
}
|
|
||||||
|
|
||||||
propReq, err := encodeAddressPropReq(props, allProp)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -286,14 +279,7 @@ 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 props []string
|
propReq, err := encodeAddressPropReq(&multiGet.DataRequest)
|
||||||
var allProp bool
|
|
||||||
if multiGet != nil {
|
|
||||||
props = multiGet.Props
|
|
||||||
allProp = multiGet.AllProp
|
|
||||||
}
|
|
||||||
|
|
||||||
propReq, err := encodeAddressPropReq(props, allProp)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -16,8 +16,8 @@ import (
|
|||||||
// Backend is a CardDAV server backend.
|
// Backend is a CardDAV server backend.
|
||||||
type Backend interface {
|
type Backend interface {
|
||||||
AddressBook() (*AddressBook, error)
|
AddressBook() (*AddressBook, error)
|
||||||
GetAddressObject(path string) (*AddressObject, error)
|
GetAddressObject(path string, req *AddressDataRequest) (*AddressObject, error)
|
||||||
ListAddressObjects() ([]AddressObject, error)
|
ListAddressObjects(req *AddressDataRequest) ([]AddressObject, error)
|
||||||
QueryAddressObjects(query *AddressBookQuery) ([]AddressObject, error)
|
QueryAddressObjects(query *AddressBookQuery) ([]AddressObject, error)
|
||||||
PutAddressObject(path string, card vcard.Card) error
|
PutAddressObject(path string, card vcard.Card) error
|
||||||
DeleteAddressObject(path string) error
|
DeleteAddressObject(path string) error
|
||||||
@ -108,6 +108,18 @@ func decodeTextMatch(tm *textMatch) *TextMatch {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func decodeAddressDataReq(addressData *addressDataReq) (*AddressDataRequest, error) {
|
||||||
|
if addressData.Allprop != nil && len(addressData.Props) > 0 {
|
||||||
|
return nil, internal.HTTPErrorf(http.StatusBadRequest, "carddav: only one of allprop or prop can be specified in address-data")
|
||||||
|
}
|
||||||
|
|
||||||
|
req := &AddressDataRequest{AllProp: addressData.Allprop != nil}
|
||||||
|
for _, p := range addressData.Props {
|
||||||
|
req.Props = append(req.Props, p.Name)
|
||||||
|
}
|
||||||
|
return req, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (h *Handler) handleQuery(w http.ResponseWriter, query *addressbookQuery) error {
|
func (h *Handler) handleQuery(w http.ResponseWriter, query *addressbookQuery) error {
|
||||||
var q AddressBookQuery
|
var q AddressBookQuery
|
||||||
if query.Prop != nil {
|
if query.Prop != nil {
|
||||||
@ -115,13 +127,11 @@ func (h *Handler) handleQuery(w http.ResponseWriter, query *addressbookQuery) er
|
|||||||
if err := query.Prop.Decode(&addressData); err != nil && !internal.IsMissingProp(err) {
|
if err := query.Prop.Decode(&addressData); err != nil && !internal.IsMissingProp(err) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if addressData.Allprop != nil && len(addressData.Props) > 0 {
|
req, err := decodeAddressDataReq(&addressData)
|
||||||
return internal.HTTPErrorf(http.StatusBadRequest, "carddav: only one of allprop or prop can be specified in address-data")
|
if err != nil {
|
||||||
}
|
return err
|
||||||
q.AllProp = addressData.Allprop != nil
|
|
||||||
for _, p := range addressData.Props {
|
|
||||||
q.Props = append(q.Props, p.Name)
|
|
||||||
}
|
}
|
||||||
|
q.DataRequest = *req
|
||||||
}
|
}
|
||||||
q.FilterTest = FilterTest(query.Filter.Test)
|
q.FilterTest = FilterTest(query.Filter.Test)
|
||||||
for _, el := range query.Filter.Props {
|
for _, el := range query.Filter.Props {
|
||||||
@ -163,11 +173,22 @@ func (h *Handler) handleQuery(w http.ResponseWriter, query *addressbookQuery) er
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handler) handleMultiget(w http.ResponseWriter, multiget *addressbookMultiget) error {
|
func (h *Handler) handleMultiget(w http.ResponseWriter, multiget *addressbookMultiget) error {
|
||||||
|
var dataReq AddressDataRequest
|
||||||
|
if multiget.Prop != nil {
|
||||||
|
var addressData addressDataReq
|
||||||
|
if err := multiget.Prop.Decode(&addressData); err != nil && !internal.IsMissingProp(err) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
decoded, err := decodeAddressDataReq(&addressData)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
dataReq = *decoded
|
||||||
|
}
|
||||||
|
|
||||||
var resps []internal.Response
|
var resps []internal.Response
|
||||||
for _, href := range multiget.Hrefs {
|
for _, href := range multiget.Hrefs {
|
||||||
// TODO: only get a subset of the vCard fields, depending on the
|
ao, err := h.Backend.GetAddressObject(href.Path, &dataReq)
|
||||||
// multiget query
|
|
||||||
ao, err := h.Backend.GetAddressObject(href.Path)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err // TODO: create internal.Response with error
|
return err // TODO: create internal.Response with error
|
||||||
}
|
}
|
||||||
@ -200,7 +221,8 @@ func (b *backend) Options(r *http.Request) ([]string, error) {
|
|||||||
return []string{http.MethodOptions, "PROPFIND"}, nil
|
return []string{http.MethodOptions, "PROPFIND"}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := b.Backend.GetAddressObject(r.URL.Path)
|
var dataReq AddressDataRequest
|
||||||
|
_, err := b.Backend.GetAddressObject(r.URL.Path, &dataReq)
|
||||||
if httpErr, ok := err.(*internal.HTTPError); ok && httpErr.Code == http.StatusNotFound {
|
if httpErr, ok := err.(*internal.HTTPError); ok && httpErr.Code == http.StatusNotFound {
|
||||||
return []string{http.MethodOptions}, nil
|
return []string{http.MethodOptions}, nil
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
@ -215,7 +237,11 @@ func (b *backend) HeadGet(w http.ResponseWriter, r *http.Request) error {
|
|||||||
return &internal.HTTPError{Code: http.StatusMethodNotAllowed}
|
return &internal.HTTPError{Code: http.StatusMethodNotAllowed}
|
||||||
}
|
}
|
||||||
|
|
||||||
ao, err := b.Backend.GetAddressObject(r.URL.Path)
|
var dataReq AddressDataRequest
|
||||||
|
if r.Method != http.MethodHead {
|
||||||
|
dataReq.AllProp = true
|
||||||
|
}
|
||||||
|
ao, err := b.Backend.GetAddressObject(r.URL.Path, &dataReq)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -230,6 +256,8 @@ func (b *backend) HeadGet(w http.ResponseWriter, r *http.Request) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *backend) Propfind(r *http.Request, propfind *internal.Propfind, depth internal.Depth) (*internal.Multistatus, error) {
|
func (b *backend) Propfind(r *http.Request, propfind *internal.Propfind, depth internal.Depth) (*internal.Multistatus, error) {
|
||||||
|
var dataReq AddressDataRequest
|
||||||
|
|
||||||
var resps []internal.Response
|
var resps []internal.Response
|
||||||
if r.URL.Path == "/" {
|
if r.URL.Path == "/" {
|
||||||
ab, err := b.Backend.AddressBook()
|
ab, err := b.Backend.AddressBook()
|
||||||
@ -244,7 +272,7 @@ func (b *backend) Propfind(r *http.Request, propfind *internal.Propfind, depth i
|
|||||||
resps = append(resps, *resp)
|
resps = append(resps, *resp)
|
||||||
|
|
||||||
if depth != internal.DepthZero {
|
if depth != internal.DepthZero {
|
||||||
aos, err := b.Backend.ListAddressObjects()
|
aos, err := b.Backend.ListAddressObjects(&dataReq)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -258,7 +286,7 @@ func (b *backend) Propfind(r *http.Request, propfind *internal.Propfind, depth i
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ao, err := b.Backend.GetAddressObject(r.URL.Path)
|
ao, err := b.Backend.GetAddressObject(r.URL.Path, &dataReq)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user