Switch to latest upstream go-webdav
* Use one, fixed path layout * New type `ConditionalMatch` for contents of `If-Match`/`If-None-Match` header
This commit is contained in:
parent
7f0f9fd365
commit
68de660456
4
go.mod
4
go.mod
@ -7,7 +7,7 @@ require (
|
|||||||
github.com/emersion/go-imap v1.2.0
|
github.com/emersion/go-imap v1.2.0
|
||||||
github.com/emersion/go-sasl v0.0.0-20211008083017-0b9dcfb154ac
|
github.com/emersion/go-sasl v0.0.0-20211008083017-0b9dcfb154ac
|
||||||
github.com/emersion/go-vcard v0.0.0-20210521075357-3445b9171995
|
github.com/emersion/go-vcard v0.0.0-20210521075357-3445b9171995
|
||||||
github.com/emersion/go-webdav v0.3.2-0.20220916070414-6f22a649ac4c
|
github.com/emersion/go-webdav v0.3.2-0.20221122105813-ac9af45270fb
|
||||||
github.com/go-chi/chi/v5 v5.0.7
|
github.com/go-chi/chi/v5 v5.0.7
|
||||||
github.com/msteinert/pam v1.0.0
|
github.com/msteinert/pam v1.0.0
|
||||||
)
|
)
|
||||||
@ -16,5 +16,3 @@ require (
|
|||||||
github.com/teambition/rrule-go v1.7.2 // indirect
|
github.com/teambition/rrule-go v1.7.2 // indirect
|
||||||
golang.org/x/text v0.3.7 // indirect
|
golang.org/x/text v0.3.7 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
replace github.com/emersion/go-webdav v0.3.2-0.20220916070414-6f22a649ac4c => github.com/bitfehler/go-webdav v0.3.2-0.20221031110527-fb914f2f6d18
|
|
||||||
|
4
go.sum
4
go.sum
@ -1,5 +1,3 @@
|
|||||||
github.com/bitfehler/go-webdav v0.3.2-0.20221031110527-fb914f2f6d18 h1:OCxO7C4E58C6GIhXDL1zQjsN5gq/xh7LhKKwg4/g8Co=
|
|
||||||
github.com/bitfehler/go-webdav v0.3.2-0.20221031110527-fb914f2f6d18/go.mod h1:lkPYZO/vsDNV9GPyVMBBsAUZzzxINL97bEVFykApo58=
|
|
||||||
github.com/emersion/go-ical v0.0.0-20220601085725-0864dccc089f h1:feGUUxxvOtWVOhTko8Cbmp33a+tU0IMZxMEmnkoAISQ=
|
github.com/emersion/go-ical v0.0.0-20220601085725-0864dccc089f h1:feGUUxxvOtWVOhTko8Cbmp33a+tU0IMZxMEmnkoAISQ=
|
||||||
github.com/emersion/go-ical v0.0.0-20220601085725-0864dccc089f/go.mod h1:2MKFUgfNMULRxqZkadG1Vh44we3y5gJAtTBlVsx1BKQ=
|
github.com/emersion/go-ical v0.0.0-20220601085725-0864dccc089f/go.mod h1:2MKFUgfNMULRxqZkadG1Vh44we3y5gJAtTBlVsx1BKQ=
|
||||||
github.com/emersion/go-imap v1.2.0 h1:lyUQ3+EVM21/qbWE/4Ya5UG9r5+usDxlg4yfp3TgHFA=
|
github.com/emersion/go-imap v1.2.0 h1:lyUQ3+EVM21/qbWE/4Ya5UG9r5+usDxlg4yfp3TgHFA=
|
||||||
@ -12,6 +10,8 @@ github.com/emersion/go-textwrapper v0.0.0-20200911093747-65d896831594/go.mod h1:
|
|||||||
github.com/emersion/go-vcard v0.0.0-20191221110513-5f81fa0d3cc7/go.mod h1:HMJKR5wlh/ziNp+sHEDV2ltblO4JD2+IdDOWtGcQBTM=
|
github.com/emersion/go-vcard v0.0.0-20191221110513-5f81fa0d3cc7/go.mod h1:HMJKR5wlh/ziNp+sHEDV2ltblO4JD2+IdDOWtGcQBTM=
|
||||||
github.com/emersion/go-vcard v0.0.0-20210521075357-3445b9171995 h1:DpVfmcoBs6o9VYcccNWbuKFQxuHCgt25/y4q9H8AUvc=
|
github.com/emersion/go-vcard v0.0.0-20210521075357-3445b9171995 h1:DpVfmcoBs6o9VYcccNWbuKFQxuHCgt25/y4q9H8AUvc=
|
||||||
github.com/emersion/go-vcard v0.0.0-20210521075357-3445b9171995/go.mod h1:HMJKR5wlh/ziNp+sHEDV2ltblO4JD2+IdDOWtGcQBTM=
|
github.com/emersion/go-vcard v0.0.0-20210521075357-3445b9171995/go.mod h1:HMJKR5wlh/ziNp+sHEDV2ltblO4JD2+IdDOWtGcQBTM=
|
||||||
|
github.com/emersion/go-webdav v0.3.2-0.20221122105813-ac9af45270fb h1:hf7lieMeu22uJuQ+TzglBMQ77C8R8h4OnHeLVHGDRQE=
|
||||||
|
github.com/emersion/go-webdav v0.3.2-0.20221122105813-ac9af45270fb/go.mod h1:lkPYZO/vsDNV9GPyVMBBsAUZzzxINL97bEVFykApo58=
|
||||||
github.com/go-chi/chi/v5 v5.0.7 h1:rDTPXLDHGATaeHvVlLcR4Qe0zftYethFucbjVQ1PxU8=
|
github.com/go-chi/chi/v5 v5.0.7 h1:rDTPXLDHGATaeHvVlLcR4Qe0zftYethFucbjVQ1PxU8=
|
||||||
github.com/go-chi/chi/v5 v5.0.7/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
github.com/go-chi/chi/v5 v5.0.7/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
||||||
github.com/msteinert/pam v1.0.0 h1:4XoXKtMCH3+e6GIkW41uxm6B37eYqci/DH3gzSq7ocg=
|
github.com/msteinert/pam v1.0.0 h1:4XoXKtMCH3+e6GIkW41uxm6B37eYqci/DH3gzSq7ocg=
|
||||||
|
@ -84,7 +84,7 @@ func ensureLocalDir(path string) error {
|
|||||||
|
|
||||||
// don't use this directly, use localCalDAVPath or localCardDAVPath instead.
|
// don't use this directly, use localCalDAVPath or localCardDAVPath instead.
|
||||||
func (b *filesystemBackend) safeLocalPath(homeSetPath string, urlPath string) (string, error) {
|
func (b *filesystemBackend) safeLocalPath(homeSetPath string, urlPath string) (string, error) {
|
||||||
localPath := filepath.Join(b.path, homeSetPath)
|
localPath := filepath.Join(b.path, homeSetPath, "default")
|
||||||
if err := ensureLocalDir(localPath); err != nil {
|
if err := ensureLocalDir(localPath); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@ -96,10 +96,10 @@ func (b *filesystemBackend) safeLocalPath(homeSetPath string, urlPath string) (s
|
|||||||
// We are mapping to local filesystem path, so be conservative about what to accept
|
// We are mapping to local filesystem path, so be conservative about what to accept
|
||||||
// TODO this changes once multiple addess books are supported
|
// TODO this changes once multiple addess books are supported
|
||||||
dir, file := path.Split(urlPath)
|
dir, file := path.Split(urlPath)
|
||||||
// only accept resources in prefix, no subdirs for now
|
// only accept resources in default calendar/adress book for now
|
||||||
if dir != homeSetPath {
|
if path.Clean(dir) != path.Join(homeSetPath, "default") {
|
||||||
if strings.HasPrefix(dir, homeSetPath+"/") {
|
if strings.HasPrefix(dir, homeSetPath) {
|
||||||
err := fmt.Errorf("invalid request path: %s", urlPath)
|
err := fmt.Errorf("invalid request path: %s (%s is not %s)", urlPath, dir, path.Join(homeSetPath, "default"))
|
||||||
return "", webdav.NewHTTPError(400, err)
|
return "", webdav.NewHTTPError(400, err)
|
||||||
} else {
|
} else {
|
||||||
err := fmt.Errorf("Access to resource outside of home set: %s", urlPath)
|
err := fmt.Errorf("Access to resource outside of home set: %s", urlPath)
|
||||||
@ -228,26 +228,27 @@ func createDefaultAddressBook(path, localPath string) error {
|
|||||||
|
|
||||||
func (b *filesystemBackend) AddressBook(ctx context.Context) (*carddav.AddressBook, error) {
|
func (b *filesystemBackend) AddressBook(ctx context.Context) (*carddav.AddressBook, error) {
|
||||||
debug.Printf("filesystem.AddressBook()")
|
debug.Printf("filesystem.AddressBook()")
|
||||||
path, err := b.localCardDAVPath(ctx, "")
|
localPath, err := b.localCardDAVPath(ctx, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
path = filepath.Join(path, "addressbook.json")
|
localPath = filepath.Join(localPath, "addressbook.json")
|
||||||
|
|
||||||
debug.Printf("loading addressbook from %s", path)
|
debug.Printf("loading addressbook from %s", localPath)
|
||||||
|
|
||||||
data, readErr := ioutil.ReadFile(path)
|
data, readErr := ioutil.ReadFile(localPath)
|
||||||
if os.IsNotExist(readErr) {
|
if os.IsNotExist(readErr) {
|
||||||
urlPath, err := b.AddressbookHomeSetPath(ctx)
|
urlPath, err := b.AddressbookHomeSetPath(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
debug.Printf("creating default addressbook (URL:path): %s:%s", urlPath, path)
|
urlPath = path.Join(urlPath, "default") + "/"
|
||||||
err = createDefaultAddressBook(urlPath, path)
|
debug.Printf("creating default addressbook (URL:path): %s:%s", urlPath, localPath)
|
||||||
|
err = createDefaultAddressBook(urlPath, localPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
data, readErr = ioutil.ReadFile(path)
|
data, readErr = ioutil.ReadFile(localPath)
|
||||||
}
|
}
|
||||||
if readErr != nil {
|
if readErr != nil {
|
||||||
return nil, fmt.Errorf("error opening address book: %s", readErr.Error())
|
return nil, fmt.Errorf("error opening address book: %s", readErr.Error())
|
||||||
@ -330,7 +331,7 @@ func (b *filesystemBackend) loadAllContacts(ctx context.Context, propFilter []st
|
|||||||
}
|
}
|
||||||
|
|
||||||
obj := carddav.AddressObject{
|
obj := carddav.AddressObject{
|
||||||
Path: path.Join(homeSetPath, filepath.Base(filename)),
|
Path: path.Join(homeSetPath, "default", filepath.Base(filename)),
|
||||||
ModTime: info.ModTime(),
|
ModTime: info.ModTime(),
|
||||||
ContentLength: info.Size(),
|
ContentLength: info.Size(),
|
||||||
ETag: etag,
|
ETag: etag,
|
||||||
@ -375,7 +376,7 @@ func (b *filesystemBackend) loadAllCalendars(ctx context.Context, propFilter []s
|
|||||||
}
|
}
|
||||||
|
|
||||||
obj := caldav.CalendarObject{
|
obj := caldav.CalendarObject{
|
||||||
Path: path.Join(homeSetPath, filepath.Base(filename)),
|
Path: path.Join(homeSetPath, "default", filepath.Base(filename)),
|
||||||
ModTime: info.ModTime(),
|
ModTime: info.ModTime(),
|
||||||
ContentLength: info.Size(),
|
ContentLength: info.Size(),
|
||||||
ETag: etag,
|
ETag: etag,
|
||||||
@ -427,17 +428,25 @@ func (b *filesystemBackend) PutAddressObject(ctx context.Context, objPath string
|
|||||||
}
|
}
|
||||||
|
|
||||||
flags := os.O_RDWR | os.O_CREATE | os.O_TRUNC
|
flags := os.O_RDWR | os.O_CREATE | os.O_TRUNC
|
||||||
if opts.IfNoneMatch {
|
// TODO handle IfNoneMatch == ETag
|
||||||
|
if opts.IfNoneMatch.IsWildcard() {
|
||||||
|
// Make sure we're not overwriting an existing file
|
||||||
flags |= os.O_EXCL
|
flags |= os.O_EXCL
|
||||||
} else if opts.IfMatch == "*" {
|
} else if opts.IfMatch.IsWildcard() {
|
||||||
|
// Make sure we _are_ overwriting an existing file
|
||||||
flags &= ^os.O_CREATE
|
flags &= ^os.O_CREATE
|
||||||
} else if opts.IfMatch != "" {
|
} else if opts.IfMatch.IsSet() {
|
||||||
|
// Make sure we overwrite the _right_ file
|
||||||
etag, err := etagForFile(localPath)
|
etag, err := etagForFile(localPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", webdav.NewHTTPError(http.StatusPreconditionFailed, err)
|
return "", webdav.NewHTTPError(http.StatusPreconditionFailed, err)
|
||||||
}
|
}
|
||||||
if opts.IfMatch != etag {
|
want, err := opts.IfMatch.ETag()
|
||||||
err = fmt.Errorf("If-Match does not match current ETag (%s/%s)", opts.IfMatch, etag)
|
if err != nil {
|
||||||
|
return "", webdav.NewHTTPError(http.StatusBadRequest, err)
|
||||||
|
}
|
||||||
|
if want != etag {
|
||||||
|
err = fmt.Errorf("If-Match does not match current ETag (%s/%s)", want, etag)
|
||||||
return "", webdav.NewHTTPError(http.StatusPreconditionFailed, err)
|
return "", webdav.NewHTTPError(http.StatusPreconditionFailed, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -495,26 +504,27 @@ func createDefaultCalendar(path, localPath string) error {
|
|||||||
func (b *filesystemBackend) Calendar(ctx context.Context) (*caldav.Calendar, error) {
|
func (b *filesystemBackend) Calendar(ctx context.Context) (*caldav.Calendar, error) {
|
||||||
debug.Printf("filesystem.Calendar()")
|
debug.Printf("filesystem.Calendar()")
|
||||||
|
|
||||||
path, err := b.localCalDAVPath(ctx, "")
|
localPath, err := b.localCalDAVPath(ctx, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
path = filepath.Join(path, "calendar.json")
|
localPath = filepath.Join(localPath, "calendar.json")
|
||||||
|
|
||||||
debug.Printf("loading calendar from %s", path)
|
debug.Printf("loading calendar from %s", localPath)
|
||||||
|
|
||||||
data, readErr := ioutil.ReadFile(path)
|
data, readErr := ioutil.ReadFile(localPath)
|
||||||
if os.IsNotExist(readErr) {
|
if os.IsNotExist(readErr) {
|
||||||
homeSetPath, err := b.CalendarHomeSetPath(ctx)
|
urlPath, err := b.CalendarHomeSetPath(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
debug.Printf("creating default calendar (URL:path): %s:%s", homeSetPath, path)
|
urlPath = path.Join(urlPath, "default") + "/"
|
||||||
err = createDefaultCalendar(homeSetPath, path)
|
debug.Printf("creating default calendar (URL:path): %s:%s", urlPath, localPath)
|
||||||
|
err = createDefaultCalendar(urlPath, localPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
data, readErr = ioutil.ReadFile(path)
|
data, readErr = ioutil.ReadFile(localPath)
|
||||||
}
|
}
|
||||||
if readErr != nil {
|
if readErr != nil {
|
||||||
return nil, fmt.Errorf("error opening calendar: %s", readErr.Error())
|
return nil, fmt.Errorf("error opening calendar: %s", readErr.Error())
|
||||||
@ -617,17 +627,25 @@ func (b *filesystemBackend) PutCalendarObject(ctx context.Context, objPath strin
|
|||||||
}
|
}
|
||||||
|
|
||||||
flags := os.O_RDWR | os.O_CREATE | os.O_TRUNC
|
flags := os.O_RDWR | os.O_CREATE | os.O_TRUNC
|
||||||
if opts.IfNoneMatch {
|
// TODO handle IfNoneMatch == ETag
|
||||||
|
if opts.IfNoneMatch.IsWildcard() {
|
||||||
|
// Make sure we're not overwriting an existing file
|
||||||
flags |= os.O_EXCL
|
flags |= os.O_EXCL
|
||||||
} else if opts.IfMatch == "*" {
|
} else if opts.IfMatch.IsWildcard() {
|
||||||
|
// Make sure we _are_ overwriting an existing file
|
||||||
flags &= ^os.O_CREATE
|
flags &= ^os.O_CREATE
|
||||||
} else if opts.IfMatch != "" {
|
} else if opts.IfMatch.IsSet() {
|
||||||
|
// Make sure we overwrite the _right_ file
|
||||||
etag, err := etagForFile(localPath)
|
etag, err := etagForFile(localPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", webdav.NewHTTPError(http.StatusPreconditionFailed, err)
|
return "", webdav.NewHTTPError(http.StatusPreconditionFailed, err)
|
||||||
}
|
}
|
||||||
if opts.IfMatch != etag {
|
want, err := opts.IfMatch.ETag()
|
||||||
err = fmt.Errorf("If-Match does not match current ETag (%s/%s)", opts.IfMatch, etag)
|
if err != nil {
|
||||||
|
return "", webdav.NewHTTPError(http.StatusBadRequest, err)
|
||||||
|
}
|
||||||
|
if want != etag {
|
||||||
|
err = fmt.Errorf("If-Match does not match current ETag (%s/%s)", want, etag)
|
||||||
return "", webdav.NewHTTPError(http.StatusPreconditionFailed, err)
|
return "", webdav.NewHTTPError(http.StatusPreconditionFailed, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user