Commit Graph

107 Commits

Author SHA1 Message Date
Conrad Hoffmann
ac9af45270 Dedicated type for conditional match header fields
The `If-Match` and `If-None-Match` conditional headers can have either a
wildcard or a (quoted) ETag as value. However, the ETag _could_ be a
literal `*`, so care must be taken to allow these cases to be
distinguished. The values of these headers have to be handled by the
backend, so export a type that facilitates working with these values.
2022-11-22 11:58:13 +01:00
Conrad Hoffmann
d4d56c2707 carddav: use custom type for context keys 2022-11-16 10:37:40 +01:00
Conrad Hoffmann
561012d30f carddav: switch to one static path layout
See #100 for details. Obsoletes #99.
2022-11-02 19:44:42 +01:00
Conrad Hoffmann
9adfd95fa9 carddav: run gofmt 2022-08-31 13:53:16 +02:00
Conrad Hoffmann
4a3cd0510f carddav: end-to-end test address book discovery
As the implementation evolves, it will be necessary to have more tests
to assert we don't break anything when making changes. This commit
introduces a test setup to test that server and client can handle the
address book discovery with various parameters. The test setup should be
easily extendable to cover even more ground as needed.
2022-07-13 08:45:11 +02:00
Simon Ser
987c9eef0b carddav: use "/.well-known/carddav/" as initial context path in Discover
See RFC 6764 section 6 item 3.
2022-07-13 08:43:40 +02:00
Conrad Hoffmann
db966a275c carddav: do property filtering in match.Filter()
With this commit, the list of AddressObjects returned by `Filter()` will
always be a correct response to the query argument passed to it, even if
the input list contained objects with arbitraty properties present.
2022-06-03 08:36:05 +02:00
Conrad Hoffmann
21aea26c70 carddav: don't filter properties in test queries
As is, the tests in `match_test.go` test wrong behavior. They request
"partial retrieval" (i.e. filtering of returned properties), but compare
the returned result to the original input. They essentially rely on the
fact that property filtering is currently not implemented.

To fix this, simply make all existing test queries request all
properties. If property filtering gets implemented (correctly), the
tests will then continue to work. New tests can be added for testing
the property filtering itself.
2022-06-03 08:36:05 +02:00
Simon Ser
d7891ce50c internal: fix XML element struct naming
We were sometimes using TitleCase, sometimes Lowercase. Let's align
on the idiomatic Go naming and pick TitleCase everywhere.
2022-05-31 23:04:42 +02:00
Simon Ser
97e0b10b4f carddav: add Discover TODO about "path" key in TXT record 2022-05-25 14:57:05 +02:00
Conrad Hoffmann
5d845721d8 carddav: add Content-Length support to client 2022-05-24 11:18:11 +02:00
Conrad Hoffmann
1e99b70a62 carddav: set content length header for HEAD/GET requests
Now that the backend can supply this value, use it for explicitly
setting the header in GET/HEAD responses if available.
2022-05-24 11:18:11 +02:00
Conrad Hoffmann
a3e56141d9 carddav: add support for getcontentlength property
Allow the backend to provide a value for the `getcontentlength` property
as described in [RFC 2518 section 13.4][1].

The implementation treats is as optional, allthough it is a required
property per RFC. Most clients do perfectly fine without it, though.

Properly setting this in the backend makes the CardDAV collection
listable with clients that do require it, e.g. cadaver.

[1]: https://datatracker.ietf.org/doc/html/rfc2518#section-13.4
2022-05-24 11:18:11 +02:00
Simon Ser
38a35d3545 carddav: improve Client.SyncCollection docs 2022-05-24 10:20:08 +02:00
Conrad Hoffmann
cabaf3268b 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.
2022-05-23 11:30:03 +02:00
Conrad Hoffmann
b0c59cdea1 carddav/caldav: use 308 for .well-known redirects
This makes it a little less ambiguous (and, in case of Go clients, a lot
easier) that clients should follow the redirect by sending the same
PROPFIND request, including body, to the new location.

See also the documentation of [http.Client.Do()][1] and the comments in
[http.redirectBehavior()][2].

Confirmed to not make a difference for Evolution and Thunderbird
clients.

[1]: https://pkg.go.dev/net/http#Client.Do
[2]: https://cs.opensource.google/go/go/+/refs/tags/go1.18.2:src/net/http/client.go;drc=d8762b2f4532cc2e5ec539670b88bbc469a13938;l=502
2022-05-23 09:54:10 +02:00
Simon Ser
bc3faca3a0 carddav: only call CurrentUserPrincipal when necessary 2022-05-13 15:29:55 +02:00
Conrad Hoffmann
6887b6b812 Support custom user principal and home set paths
Currently, the user principal path and the home set path are both
hardcoded to "/", for both CalDAV and CardDAV. This poses a challenge if
one wishes to run a CardDAV and CalDAV server in the same server.

This commit introduces the concept of a UserPrincipalBackend. This
backend must provide the path of the current user's principal URL from
the given request context.

The CalDAV and CardDAV backends are extended to also function as
UserPrincipalBackend. In addition, they are required to supply the path
of the respective home set (`calendar-home-set` and
`addressbook-home-set`). The CardDAV and CalDAV servers act accordingly.

The individual servers will continue to work as before (including the
option of keeping everything at "/"). If one wishes to run CardDAV and
CalDAV in parallel, the new `webdav.ServeUserPrincipal()` can be used as
a convenience function to serve a common user principal URL for both
servers. The input for this function can be easily computed by the
application by getting the home set paths from the backends and using
`caldav.NewCalendarHomeSet()` and `carddav.NewAddressbookHomeSet()` to
create the home sets.

Note that the storage backend will have to know about these paths as
well. For any non-trivial use case, a storage backend should probably
have access to the same UserPrincipalBackend. That is, however, an
implementation detail and doesn't have to be reflected in the
interfaces.
2022-05-11 11:12:04 +02:00
Conrad Hoffmann
95a4ae783b carddav: use AddressBook.Path in PROPFIND response 2022-05-02 20:58:00 +02:00
Simon Ser
8cc6542f1c carddav: use partial error response on multiget failure
Instead of making the whole HTTP request fail when a single address
object cannot be fetched, return a partial error response.
2022-05-02 15:43:43 +02:00
Simon Ser
4e8c5effe3 Replace DAVError with HTTPError + Error
That way we can avoid having different ways of representing the
same error value.
2022-05-02 15:43:43 +02:00
Conrad Hoffmann
c4206ba616 carddav: pass If-(None-)Match to backend
This simply extends the interfaces to pass on the values if they were
used, relying on the backend to handle things accordingly.
2022-03-22 09:28:24 +01:00
Conrad Hoffmann
85d2b222bb Add error type representing DAV/XML errors
Backends will need some way to signal that a precondition error occurred
(and specifying which one) without causing the server to return a 500.
This commit adds an exported function to create a specific error for
this. The existing error handling routine is slightly adapted to handle
this error in such a way that it returns the desired result.

Usage would be something like:

```
return "", carddav.NewPreconditionError(carddav.PreconditionNoUIDConflict)
```

which triggers the following HTTP response:

```
HTTP/1.1 409 Conflict.
Content-Type: text/xml; charset=utf-8.
Date: Thu, 10 Mar 2022 10:28:56 GMT.
Content-Length: 141.
Connection: close.

<?xml version="1.0" encoding="UTF-8"?>
<error xmlns="DAV:"><no-uid-conflict
xmlns="urn:ietf:params:xml:ns:carddav"></no-uid-conflict></error>
```

This response gets correctly recognized by e.g. Evolution (though it's
handling is not great).

The added error type is generic enough to be used for other stuff also.
As it is not exported (internal package), new functions for creating
such errors would have to be added.
2022-03-10 16:48:11 +01:00
Sebastien Binet
6d59672ed4 carddav: add filtering and matching helper functions
Updates emersion/hydroxide#159.

Signed-off-by: Sebastien Binet <binet@cern.ch>
Co-authored-by: Conrad Hoffmann <ch@bitfehler.net>
2022-03-01 10:06:11 +01:00
Conrad Hoffmann
dc57b81662
carddav/server: set ETag and Last-Modified if available
Some clients (e.g. Evolution) will not work properly without this. It is
up to the underlying backend to actually provide this data, the headers
will only be set if it is available.
2022-02-24 12:41:56 +01:00
Conrad Hoffmann
0f6744ede8 Pass request context to storage interface
This way the storage implementation can communicate with any potentially
used middleware (e.g. authentication) or for example abort requests.
2022-02-23 12:01:13 +01:00
Heiko Carrasco
4316bbcd93
caldav: add server handling for well-known URLs 2020-10-09 15:10:33 +02:00
AlmogBaku
9e23289610 sync-collection for client 2020-05-25 18:28:24 +02:00
AlmogBaku
1b725cb0b9 fixes #33, remove missingPropError error 2020-04-02 16:48:13 +02:00
Simon Ser
abadf534f4
carddav: expose supported address data in client 2020-02-27 12:36:14 +01:00
Simon Ser
7d2b6a3902
carddav: make Discover fail when target is empty 2020-02-19 16:32:35 +01:00
Simon Ser
4b24edf624
carddav: fix Discover with default HTTPS port 2020-02-19 16:31:03 +01:00
Simon Ser
ddf2a85958
Introduce HTTPClient, remove Client.SetBasicAuth 2020-02-19 16:02:49 +01:00
Simon Ser
c52097fefb
carddav: add Client.GetAddressObject 2020-02-12 21:38:55 +01:00
Simon Ser
236dc07837
carddav: fix Client.PutAddressObject failing with Radicale
This is workaround for a Radicale issue.

References: https://github.com/Kozea/Radicale/issues/1016
2020-02-12 21:10:52 +01:00
Simon Ser
842acb3647
carddav: add Client.PutAddressObject 2020-02-12 19:47:16 +01:00
Simon Ser
a892cc58df
internal: only handle relative paths in Client.ResolveHref
Don't prepend the endpoint path in front of absolute paths.
2020-02-12 17:13:12 +01:00
Simon Ser
f9d728aaeb
carddav: add Client.HasSupport 2020-02-05 16:08:15 +01:00
Simon Ser
25678476db
internal: add ETag 2020-02-03 21:48:31 +01:00
Simon Ser
dd1527b97e
carddav: allow created address book objects to have a different path
Closes: https://github.com/emersion/go-webdav/issues/32
2020-01-30 15:20:10 +01:00
Simon Ser
6aea0eda2d
caldav: add Client boilerplate 2020-01-30 13:18:05 +01:00
Simon Ser
feea39c898
carddav: fix server appearing as read-only in Evolution 2020-01-30 00:43:23 +01:00
Simon Ser
8937358ac1
Allow servers to return DAV capabilities in OPTIONS 2020-01-29 18:03:47 +01:00
Simon Ser
5f03e421d3
carddav: fix addressbook-home-set>href namespace 2020-01-29 17:41:28 +01:00
Simon Ser
1f509de404
carddav: honor address-data in addressbook-query 2020-01-27 10:30:19 +01:00
Simon Ser
29cccc7ef9
carddav: add query filter support in server
Closes: https://github.com/emersion/go-webdav/issues/18
2020-01-24 16:34:57 +01:00
Simon Ser
73b67b62b1
carddav: add client support for query filter
References: https://github.com/emersion/go-webdav/issues/18
2020-01-24 12:24:35 +01:00
Simon Ser
5ada08f6ab
carddav: add full query AST 2020-01-24 11:25:58 +01:00
Simon Ser
e56ab47c43
carddav: add negateCondition 2020-01-23 19:32:10 +01:00
Simon Ser
30977aac83
carddav: add matchType 2020-01-23 19:27:31 +01:00