From cabaf3268bd3a32dbd445485388942dbe196ac62 Mon Sep 17 00:00:00 2001 From: Conrad Hoffmann Date: Wed, 18 May 2022 11:37:25 +0200 Subject: [PATCH] carddav: return multistatus response on PROPPATCH This does not implement any actual PROPPATCH logic, but makes the server return a proper multistatus response with errors for each property instead of a generic HTTP error. It also adds the distinction between requests to the address book and those to other resources. In CardDAV, only the address book itself has properties that make sense to change via PROPPATCH. Those are responded to with a 501, indicating that this needs further implementation. Requests to other resources return 405 for each property, indicating that the resources do not support PROPPATCH at all. --- carddav/server.go | 40 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/carddav/server.go b/carddav/server.go index 81ae875..ea474d6 100644 --- a/carddav/server.go +++ b/carddav/server.go @@ -457,9 +457,43 @@ func (b *backend) propfindAddressObject(ctx context.Context, propfind *internal. } func (b *backend) Proppatch(r *http.Request, update *internal.Propertyupdate) (*internal.Response, error) { - // TODO: return a failed Response instead - // TODO: support PROPPATCH for address books - return nil, internal.HTTPErrorf(http.StatusForbidden, "carddav: PROPPATCH is unsupported") + homeSetPath, err := b.Backend.AddressbookHomeSetPath(r.Context()) + if err != nil { + return nil, err + } + + resp := internal.NewOKResponse(r.URL.Path) + + if r.URL.Path == homeSetPath { + // TODO: support PROPPATCH for address books + for _, prop := range update.Remove { + emptyVal := internal.NewRawXMLElement(prop.Prop.XMLName, nil, nil) + if err := resp.EncodeProp(http.StatusNotImplemented, emptyVal); err != nil { + return nil, err + } + } + for _, prop := range update.Set { + emptyVal := internal.NewRawXMLElement(prop.Prop.XMLName, nil, nil) + if err := resp.EncodeProp(http.StatusNotImplemented, emptyVal); err != nil { + return nil, err + } + } + } else { + for _, prop := range update.Remove { + emptyVal := internal.NewRawXMLElement(prop.Prop.XMLName, nil, nil) + if err := resp.EncodeProp(http.StatusMethodNotAllowed, emptyVal); err != nil { + return nil, err + } + } + for _, prop := range update.Set { + emptyVal := internal.NewRawXMLElement(prop.Prop.XMLName, nil, nil) + if err := resp.EncodeProp(http.StatusMethodNotAllowed, emptyVal); err != nil { + return nil, err + } + } + } + + return resp, nil } func (b *backend) Put(r *http.Request) (*internal.Href, error) {