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