Implement query and property filters

The property filters are also used for other operations.
This commit is contained in:
Conrad Hoffmann 2022-02-28 19:50:36 +01:00
parent 9b0d3b87ad
commit 18a9f9bf77

View File

@ -7,7 +7,6 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"log"
"os" "os"
"path/filepath" "path/filepath"
@ -67,7 +66,28 @@ func etagForFile(path string) (string, error) {
return base64.StdEncoding.EncodeToString(csum[:]), nil 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) f, err := os.Open(path)
if err != nil { if err != nil {
return nil, err return nil, err
@ -80,7 +100,7 @@ func vcardFromFile(path string) (*vcard.Card, error) {
return nil, err return nil, err
} }
return &card, nil return vcardPropFilter(&card, propFilter), nil
} }
func createDefaultAddressBook(path string) error { func createDefaultAddressBook(path string) error {
@ -144,7 +164,12 @@ func (b *filesystemBackend) GetAddressObject(ctx context.Context, path string, r
return nil, err 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 { if err != nil {
return nil, err return nil, err
} }
@ -163,7 +188,7 @@ func (b *filesystemBackend) GetAddressObject(ctx context.Context, path string, r
return &obj, nil 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{} result := []carddav.AddressObject{}
path, err := b.pathForContext(ctx) 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 { err = filepath.Walk(path, func(filename string, info os.FileInfo, err error) error {
// TODO this heuristic will not work for all clients // Skip address book meta data files
if filepath.Ext(filename) != ".vcf" { if !info.Mode().IsRegular() || filepath.Ext(filename) == ".json" {
return nil return nil
} }
card, err := vcardFromFile(filename) card, err := vcardFromFile(filename, propFilter)
if err != nil { if err != nil {
return err return err
} }
@ -196,17 +221,31 @@ func (b *filesystemBackend) ListAddressObjects(ctx context.Context, req *carddav
result = append(result, obj) result = append(result, obj)
return nil return nil
}) })
return result, err
}
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 { if err != nil {
panic(err) return result, err
} }
return result, nil return carddav.Filter(query, result)
}
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) PutAddressObject(ctx context.Context, path string, card vcard.Card) (loc string, err error) { func (b *filesystemBackend) PutAddressObject(ctx context.Context, path string, card vcard.Card) (loc string, err error) {