import "code.pfad.fr/gopim/webdav/carddav"
func NewAddressBookResource(ab AddressBook) libdav.Resource
WellKnown returns a handler for the /.well-known/carddav endpoint. The target function should return the path to a resource providing an AddressbookHomeSet (usually the principals url). If an empty string is returned, an unauthenticated response will be returned.
type AddressBook interface { // Get provides details for the addressbook Get(ctx context.Context, prefix, name string) (AddressBookDetails, error) // GetVCards implementation should skip any not-found names GetVCards(ctx context.Context, vreq VCardRequest, names ...string) ([]VCard, error) // QueryVCards usually asks for the vcard names (see vreq) QueryVCards(ctx context.Context, vreq VCardRequest, query Query) iter.Seq2[VCard, error] }
type AddressBookWriter interface { AddressBook MaxResourceSize() int64 // max size for uploads in bytes, 0 means no limit PutVCard(ctx context.Context, prefix, name string, vup VCardUpload) (VCard, error) DeleteVCard(ctx context.Context, prefix, name string) error }
func NewInMemoryAddressBook(details AddressBookDetails, cards ...VCard) AddressBookWriter
type Query struct { Limit uint // 0 means unlimited AnyFilter bool // if true, ANY filter must match; otherwise ALL must match (empty slice means no filtering) Filters []QueryProperty }
MatchCard is an helper function to check if a card matches the filters. Ideally the cards should be filtered when requesting them upstream.
type QueryParam struct { Name string // name of the parameter IsNotDefined bool // if set, only the existence of the parameter should be checked (the filters below must be ignored) ValueFilter QueryText }
QueryParam filters specific VCard parameters (attached to properties)
type QueryProperty struct { Name string // Name of the vcard prop to filter (eventually with group prefix) IsNotDefined bool // if set, only the existence of the property should be checked (the filters below must be ignored) AnyFilter bool // if true, ANY (value/param) filter must match; otherwise ALL must match ValueFilters []QueryText ParamFilters []QueryParam }
QueryProperty filters specific VCard properties
type QueryText struct { Text string Collation string // ignored (always compares unicode case-insensitive) NegateCondition bool // invert the result of the match MatchType QueryTextMatch // defaults to MatchContains if empty }
QueryText check if a given texts matches a provided match
Match the given string with the expected value (case-insensitive) Collation is ignored
const ( QueryTextEquals QueryTextMatch = "equals" QueryTextContains QueryTextMatch = "contains" QueryTextStartsWith QueryTextMatch = "starts-with" QueryTextEndsWith QueryTextMatch = "ends-with" )
type VCard interface { Name() string // base name of the card (e.g. 123.vcf) ModTime() time.Time // modification time ETag() []byte // etag updated on any data change (required by some clients) Data() (io.ReadSeeker, error) // encoded vcard }
NewMemVCard is mainly for debugging, implemetations should re-implement the VCard interface.
type VCardRequest struct { ModTime bool ETag bool DataAll bool // the whole data object is requested DataNames []string // when only specific vCard fields are requested (e.g. FN, ADR, EMAIL) Prefix string // base path of the addressbook, provided for generic AddressBook implementations to distinguish between AddressBooks }
VCardRequest indicates the requested fields, to optimize implementation (Name is always needed).
type VCardUpload struct { Body io.ReadCloser IfNoneMatch bool // if true, the client wants to create a new resource (and not overwrite an existing one) IfMatchAnyEtag [][]byte // if not empty, overwrite the resource only if the existing etag matches one provided. }
addressbook.go addressobject.go interface.go memaddressbook.go query.go