From 18a9f9bf773f0ec667c0ed089d89ffc87c4d2b12 Mon Sep 17 00:00:00 2001 From: Conrad Hoffmann Date: Mon, 28 Feb 2022 19:50:36 +0100 Subject: [PATCH] Implement query and property filters The property filters are also used for other operations. --- storage/filesystem.go | 71 +++++++++++++++++++++++++++++++++---------- 1 file changed, 55 insertions(+), 16 deletions(-) diff --git a/storage/filesystem.go b/storage/filesystem.go index 081253e..b8a3e0d 100644 --- a/storage/filesystem.go +++ b/storage/filesystem.go @@ -7,7 +7,6 @@ import ( "encoding/json" "fmt" "io/ioutil" - "log" "os" "path/filepath" @@ -67,7 +66,28 @@ func etagForFile(path string) (string, error) { return base64.StdEncoding.EncodeToString(csum[:]), nil } -func vcardFromFile(path string) (*vcard.Card, error) { +func vcardPropFilter(card *vcard.Card, props []string) *vcard.Card { + if card == nil { + return nil + } + + if len(props) == 0 { + return card + } + + result := make(vcard.Card) + result["VERSION"] = (*card)["VERSION"] + for _, prop := range props { + value, ok := (*card)[prop] + if ok { + result[prop] = value + } + } + + return &result +} + +func vcardFromFile(path string, propFilter []string) (*vcard.Card, error) { f, err := os.Open(path) if err != nil { return nil, err @@ -80,7 +100,7 @@ func vcardFromFile(path string) (*vcard.Card, error) { return nil, err } - return &card, nil + return vcardPropFilter(&card, propFilter), nil } func createDefaultAddressBook(path string) error { @@ -144,7 +164,12 @@ func (b *filesystemBackend) GetAddressObject(ctx context.Context, path string, r return nil, err } - card, err := vcardFromFile(path) + propFilter := []string{} + if req != nil && !req.AllProp { + propFilter = req.Props + } + + card, err := vcardFromFile(path, propFilter) if err != nil { return nil, err } @@ -163,7 +188,7 @@ func (b *filesystemBackend) GetAddressObject(ctx context.Context, path string, r return &obj, nil } -func (b *filesystemBackend) ListAddressObjects(ctx context.Context, req *carddav.AddressDataRequest) ([]carddav.AddressObject, error) { +func (b *filesystemBackend) loadAll(ctx context.Context, propFilter []string) ([]carddav.AddressObject, error) { result := []carddav.AddressObject{} path, err := b.pathForContext(ctx) @@ -172,12 +197,12 @@ func (b *filesystemBackend) ListAddressObjects(ctx context.Context, req *carddav } err = filepath.Walk(path, func(filename string, info os.FileInfo, err error) error { - // TODO this heuristic will not work for all clients - if filepath.Ext(filename) != ".vcf" { + // Skip address book meta data files + if !info.Mode().IsRegular() || filepath.Ext(filename) == ".json" { return nil } - card, err := vcardFromFile(filename) + card, err := vcardFromFile(filename, propFilter) if err != nil { return err } @@ -196,17 +221,31 @@ func (b *filesystemBackend) ListAddressObjects(ctx context.Context, req *carddav result = append(result, obj) return nil }) - if err != nil { - panic(err) - } - return result, nil + return result, err } -func (*filesystemBackend) QueryAddressObjects(ctx context.Context, query *carddav.AddressBookQuery) ([]carddav.AddressObject, error) { - // TODO - log.Println("QueryAddressObjects called, not implemented") - return []carddav.AddressObject{}, nil +func (b *filesystemBackend) ListAddressObjects(ctx context.Context, req *carddav.AddressDataRequest) ([]carddav.AddressObject, error) { + propFilter := []string{} + if req != nil && !req.AllProp { + propFilter = req.Props + } + + return b.loadAll(ctx, propFilter) +} + +func (b *filesystemBackend) QueryAddressObjects(ctx context.Context, query *carddav.AddressBookQuery) ([]carddav.AddressObject, error) { + propFilter := []string{} + if query != nil && !query.DataRequest.AllProp { + propFilter = query.DataRequest.Props + } + + result, err := b.loadAll(ctx, propFilter) + if err != nil { + return result, err + } + + return carddav.Filter(query, result) } func (b *filesystemBackend) PutAddressObject(ctx context.Context, path string, card vcard.Card) (loc string, err error) {