diff --git a/caldav/server.go b/caldav/server.go index d3e83b8..7ddfffc 100644 --- a/caldav/server.go +++ b/caldav/server.go @@ -465,12 +465,10 @@ func (b *backend) propFindRoot(ctx context.Context, propfind *internal.PropFind) } props := map[xml.Name]internal.PropFindFunc{ - internal.CurrentUserPrincipalName: func(*internal.RawXMLValue) (interface{}, error) { - return &internal.CurrentUserPrincipal{Href: internal.Href{Path: principalPath}}, nil - }, - internal.ResourceTypeName: func(*internal.RawXMLValue) (interface{}, error) { - return internal.NewResourceType(internal.CollectionName), nil - }, + internal.CurrentUserPrincipalName: internal.PropFindValue(&internal.CurrentUserPrincipal{ + Href: internal.Href{Path: principalPath}, + }), + internal.ResourceTypeName: internal.PropFindValue(internal.NewResourceType(internal.CollectionName)), } return internal.NewPropFindResponse(principalPath, propfind, props) } @@ -486,15 +484,13 @@ func (b *backend) propFindUserPrincipal(ctx context.Context, propfind *internal. } props := map[xml.Name]internal.PropFindFunc{ - internal.CurrentUserPrincipalName: func(*internal.RawXMLValue) (interface{}, error) { - return &internal.CurrentUserPrincipal{Href: internal.Href{Path: principalPath}}, nil - }, - calendarHomeSetName: func(*internal.RawXMLValue) (interface{}, error) { - return &calendarHomeSet{Href: internal.Href{Path: homeSetPath}}, nil - }, - internal.ResourceTypeName: func(*internal.RawXMLValue) (interface{}, error) { - return internal.NewResourceType(internal.CollectionName), nil - }, + internal.CurrentUserPrincipalName: internal.PropFindValue(&internal.CurrentUserPrincipal{ + Href: internal.Href{Path: principalPath}, + }), + calendarHomeSetName: internal.PropFindValue(&calendarHomeSet{ + Href: internal.Href{Path: homeSetPath}, + }), + internal.ResourceTypeName: internal.PropFindValue(internal.NewResourceType(internal.CollectionName)), } return internal.NewPropFindResponse(principalPath, propfind, props) } @@ -511,12 +507,10 @@ func (b *backend) propFindHomeSet(ctx context.Context, propfind *internal.PropFi // TODO anything else to return here? props := map[xml.Name]internal.PropFindFunc{ - internal.CurrentUserPrincipalName: func(*internal.RawXMLValue) (interface{}, error) { - return &internal.CurrentUserPrincipal{Href: internal.Href{Path: principalPath}}, nil - }, - internal.ResourceTypeName: func(*internal.RawXMLValue) (interface{}, error) { - return internal.NewResourceType(internal.CollectionName), nil - }, + internal.CurrentUserPrincipalName: internal.PropFindValue(&internal.CurrentUserPrincipal{ + Href: internal.Href{Path: principalPath}, + }), + internal.ResourceTypeName: internal.PropFindValue(internal.NewResourceType(internal.CollectionName)), } return internal.NewPropFindResponse(homeSetPath, propfind, props) } @@ -530,19 +524,15 @@ func (b *backend) propFindCalendar(ctx context.Context, propfind *internal.PropF } return &internal.CurrentUserPrincipal{Href: internal.Href{Path: path}}, nil }, - internal.ResourceTypeName: func(*internal.RawXMLValue) (interface{}, error) { - return internal.NewResourceType(internal.CollectionName, calendarName), nil - }, - calendarDescriptionName: func(*internal.RawXMLValue) (interface{}, error) { - return &calendarDescription{Description: cal.Description}, nil - }, - supportedCalendarDataName: func(*internal.RawXMLValue) (interface{}, error) { - return &supportedCalendarData{ - Types: []calendarDataType{ - {ContentType: ical.MIMEType, Version: "2.0"}, - }, - }, nil - }, + internal.ResourceTypeName: internal.PropFindValue(internal.NewResourceType(internal.CollectionName, calendarName)), + calendarDescriptionName: internal.PropFindValue(&calendarDescription{ + Description: cal.Description, + }), + supportedCalendarDataName: internal.PropFindValue(&supportedCalendarData{ + Types: []calendarDataType{ + {ContentType: ical.MIMEType, Version: "2.0"}, + }, + }), supportedCalendarComponentSetName: func(*internal.RawXMLValue) (interface{}, error) { components := []comp{} if cal.SupportedComponentSet != nil { @@ -559,19 +549,19 @@ func (b *backend) propFindCalendar(ctx context.Context, propfind *internal.PropF } if cal.Name != "" { - props[internal.DisplayNameName] = func(*internal.RawXMLValue) (interface{}, error) { - return &internal.DisplayName{Name: cal.Name}, nil - } + props[internal.DisplayNameName] = internal.PropFindValue(&internal.DisplayName{ + Name: cal.Name, + }) } if cal.Description != "" { - props[calendarDescriptionName] = func(*internal.RawXMLValue) (interface{}, error) { - return &calendarDescription{Description: cal.Description}, nil - } + props[calendarDescriptionName] = internal.PropFindValue(&calendarDescription{ + Description: cal.Description, + }) } if cal.MaxResourceSize > 0 { - props[maxResourceSizeName] = func(*internal.RawXMLValue) (interface{}, error) { - return &maxResourceSize{Size: cal.MaxResourceSize}, nil - } + props[maxResourceSizeName] = internal.PropFindValue(&maxResourceSize{ + Size: cal.MaxResourceSize, + }) } // TODO: CALDAV:calendar-timezone, CALDAV:supported-calendar-component-set, CALDAV:min-date-time, CALDAV:max-date-time, CALDAV:max-instances, CALDAV:max-attendees-per-instance @@ -612,9 +602,9 @@ func (b *backend) propFindCalendarObject(ctx context.Context, propfind *internal } return &internal.CurrentUserPrincipal{Href: internal.Href{Path: path}}, nil }, - internal.GetContentTypeName: func(*internal.RawXMLValue) (interface{}, error) { - return &internal.GetContentType{Type: ical.MIMEType}, nil - }, + internal.GetContentTypeName: internal.PropFindValue(&internal.GetContentType{ + Type: ical.MIMEType, + }), // TODO: calendar-data can only be used in REPORT requests calendarDataName: func(*internal.RawXMLValue) (interface{}, error) { var buf bytes.Buffer @@ -627,20 +617,20 @@ func (b *backend) propFindCalendarObject(ctx context.Context, propfind *internal } if co.ContentLength > 0 { - props[internal.GetContentLengthName] = func(*internal.RawXMLValue) (interface{}, error) { - return &internal.GetContentLength{Length: co.ContentLength}, nil - } + props[internal.GetContentLengthName] = internal.PropFindValue(&internal.GetContentLength{ + Length: co.ContentLength, + }) } if !co.ModTime.IsZero() { - props[internal.GetLastModifiedName] = func(*internal.RawXMLValue) (interface{}, error) { - return &internal.GetLastModified{LastModified: internal.Time(co.ModTime)}, nil - } + props[internal.GetLastModifiedName] = internal.PropFindValue(&internal.GetLastModified{ + LastModified: internal.Time(co.ModTime), + }) } if co.ETag != "" { - props[internal.GetETagName] = func(*internal.RawXMLValue) (interface{}, error) { - return &internal.GetETag{ETag: internal.ETag(co.ETag)}, nil - } + props[internal.GetETagName] = internal.PropFindValue(&internal.GetETag{ + ETag: internal.ETag(co.ETag), + }) } return internal.NewPropFindResponse(co.Path, propfind, props) diff --git a/carddav/server.go b/carddav/server.go index 915c49e..8e96ed0 100644 --- a/carddav/server.go +++ b/carddav/server.go @@ -431,12 +431,10 @@ func (b *backend) propFindRoot(ctx context.Context, propfind *internal.PropFind) } props := map[xml.Name]internal.PropFindFunc{ - internal.CurrentUserPrincipalName: func(*internal.RawXMLValue) (interface{}, error) { - return &internal.CurrentUserPrincipal{Href: internal.Href{Path: principalPath}}, nil - }, - internal.ResourceTypeName: func(*internal.RawXMLValue) (interface{}, error) { - return internal.NewResourceType(internal.CollectionName), nil - }, + internal.CurrentUserPrincipalName: internal.PropFindValue(&internal.CurrentUserPrincipal{ + Href: internal.Href{Path: principalPath}, + }), + internal.ResourceTypeName: internal.PropFindValue(internal.NewResourceType(internal.CollectionName)), } return internal.NewPropFindResponse(principalPath, propfind, props) } @@ -446,30 +444,24 @@ func (b *backend) propFindUserPrincipal(ctx context.Context, propfind *internal. if err != nil { return nil, err } - homeSetPath, err := b.Backend.AddressBookHomeSetPath(ctx) - if err != nil { - return nil, err - } props := map[xml.Name]internal.PropFindFunc{ - internal.CurrentUserPrincipalName: func(*internal.RawXMLValue) (interface{}, error) { - return &internal.CurrentUserPrincipal{Href: internal.Href{Path: principalPath}}, nil - }, + internal.CurrentUserPrincipalName: internal.PropFindValue(&internal.CurrentUserPrincipal{ + Href: internal.Href{Path: principalPath}, + }), addressBookHomeSetName: func(*internal.RawXMLValue) (interface{}, error) { + homeSetPath, err := b.Backend.AddressBookHomeSetPath(ctx) + if err != nil { + return nil, err + } return &addressbookHomeSet{Href: internal.Href{Path: homeSetPath}}, nil }, - internal.ResourceTypeName: func(*internal.RawXMLValue) (interface{}, error) { - return internal.NewResourceType(internal.CollectionName), nil - }, + internal.ResourceTypeName: internal.PropFindValue(internal.NewResourceType(internal.CollectionName)), } return internal.NewPropFindResponse(principalPath, propfind, props) } func (b *backend) propFindHomeSet(ctx context.Context, propfind *internal.PropFind) (*internal.Response, error) { - principalPath, err := b.Backend.CurrentUserPrincipal(ctx) - if err != nil { - return nil, err - } homeSetPath, err := b.Backend.AddressBookHomeSetPath(ctx) if err != nil { return nil, err @@ -478,11 +470,13 @@ func (b *backend) propFindHomeSet(ctx context.Context, propfind *internal.PropFi // TODO anything else to return here? props := map[xml.Name]internal.PropFindFunc{ internal.CurrentUserPrincipalName: func(*internal.RawXMLValue) (interface{}, error) { + principalPath, err := b.Backend.CurrentUserPrincipal(ctx) + if err != nil { + return nil, err + } return &internal.CurrentUserPrincipal{Href: internal.Href{Path: principalPath}}, nil }, - internal.ResourceTypeName: func(*internal.RawXMLValue) (interface{}, error) { - return internal.NewResourceType(internal.CollectionName), nil - }, + internal.ResourceTypeName: internal.PropFindValue(internal.NewResourceType(internal.CollectionName)), } return internal.NewPropFindResponse(homeSetPath, propfind, props) } @@ -496,33 +490,29 @@ func (b *backend) propFindAddressBook(ctx context.Context, propfind *internal.Pr } return &internal.CurrentUserPrincipal{Href: internal.Href{Path: path}}, nil }, - internal.ResourceTypeName: func(*internal.RawXMLValue) (interface{}, error) { - return internal.NewResourceType(internal.CollectionName, addressBookName), nil - }, - supportedAddressDataName: func(*internal.RawXMLValue) (interface{}, error) { - return &supportedAddressData{ - Types: []addressDataType{ - {ContentType: vcard.MIMEType, Version: "3.0"}, - {ContentType: vcard.MIMEType, Version: "4.0"}, - }, - }, nil - }, + internal.ResourceTypeName: internal.PropFindValue(internal.NewResourceType(internal.CollectionName, addressBookName)), + supportedAddressDataName: internal.PropFindValue(&supportedAddressData{ + Types: []addressDataType{ + {ContentType: vcard.MIMEType, Version: "3.0"}, + {ContentType: vcard.MIMEType, Version: "4.0"}, + }, + }), } if ab.Name != "" { - props[internal.DisplayNameName] = func(*internal.RawXMLValue) (interface{}, error) { - return &internal.DisplayName{Name: ab.Name}, nil - } + props[internal.DisplayNameName] = internal.PropFindValue(&internal.DisplayName{ + Name: ab.Name, + }) } if ab.Description != "" { - props[addressBookDescriptionName] = func(*internal.RawXMLValue) (interface{}, error) { - return &addressbookDescription{Description: ab.Description}, nil - } + props[addressBookDescriptionName] = internal.PropFindValue(&addressbookDescription{ + Description: ab.Description, + }) } if ab.MaxResourceSize > 0 { - props[maxResourceSizeName] = func(*internal.RawXMLValue) (interface{}, error) { - return &maxResourceSize{Size: ab.MaxResourceSize}, nil - } + props[maxResourceSizeName] = internal.PropFindValue(&maxResourceSize{ + Size: ab.MaxResourceSize, + }) } return internal.NewPropFindResponse(ab.Path, propfind, props) @@ -561,9 +551,9 @@ func (b *backend) propFindAddressObject(ctx context.Context, propfind *internal. } return &internal.CurrentUserPrincipal{Href: internal.Href{Path: path}}, nil }, - internal.GetContentTypeName: func(*internal.RawXMLValue) (interface{}, error) { - return &internal.GetContentType{Type: vcard.MIMEType}, nil - }, + internal.GetContentTypeName: internal.PropFindValue(&internal.GetContentType{ + Type: vcard.MIMEType, + }), // TODO: address-data can only be used in REPORT requests addressDataName: func(*internal.RawXMLValue) (interface{}, error) { var buf bytes.Buffer @@ -576,20 +566,20 @@ func (b *backend) propFindAddressObject(ctx context.Context, propfind *internal. } if ao.ContentLength > 0 { - props[internal.GetContentLengthName] = func(*internal.RawXMLValue) (interface{}, error) { - return &internal.GetContentLength{Length: ao.ContentLength}, nil - } + props[internal.GetContentLengthName] = internal.PropFindValue(&internal.GetContentLength{ + Length: ao.ContentLength, + }) } if !ao.ModTime.IsZero() { - props[internal.GetLastModifiedName] = func(*internal.RawXMLValue) (interface{}, error) { - return &internal.GetLastModified{LastModified: internal.Time(ao.ModTime)}, nil - } + props[internal.GetLastModifiedName] = internal.PropFindValue(&internal.GetLastModified{ + LastModified: internal.Time(ao.ModTime), + }) } if ao.ETag != "" { - props[internal.GetETagName] = func(*internal.RawXMLValue) (interface{}, error) { - return &internal.GetETag{ETag: internal.ETag(ao.ETag)}, nil - } + props[internal.GetETagName] = internal.PropFindValue(&internal.GetETag{ + ETag: internal.ETag(ao.ETag), + }) } return internal.NewPropFindResponse(ao.Path, propfind, props) diff --git a/internal/server.go b/internal/server.go index a27e771..b76443d 100644 --- a/internal/server.go +++ b/internal/server.go @@ -162,13 +162,17 @@ func (h *Handler) handlePropfind(w http.ResponseWriter, r *http.Request) error { type PropFindFunc func(raw *RawXMLValue) (interface{}, error) +func PropFindValue(value interface{}) PropFindFunc { + return func(raw *RawXMLValue) (interface{}, error) { + return value, nil + } +} + func NewPropFindResponse(path string, propfind *PropFind, props map[xml.Name]PropFindFunc) (*Response, error) { resp := &Response{Hrefs: []Href{Href{Path: path}}} if _, ok := props[ResourceTypeName]; !ok { - props[ResourceTypeName] = func(*RawXMLValue) (interface{}, error) { - return NewResourceType(), nil - } + props[ResourceTypeName] = PropFindValue(NewResourceType()) } if propfind.PropName != nil { diff --git a/server.go b/server.go index 5175159..3d2fcc8 100644 --- a/server.go +++ b/server.go @@ -162,26 +162,26 @@ func (b *backend) propFindFile(propfind *internal.PropFind, fi *FileInfo) (*inte } if !fi.IsDir { - props[internal.GetContentLengthName] = func(*internal.RawXMLValue) (interface{}, error) { - return &internal.GetContentLength{Length: fi.Size}, nil - } + props[internal.GetContentLengthName] = internal.PropFindValue(&internal.GetContentLength{ + Length: fi.Size, + }) if !fi.ModTime.IsZero() { - props[internal.GetLastModifiedName] = func(*internal.RawXMLValue) (interface{}, error) { - return &internal.GetLastModified{LastModified: internal.Time(fi.ModTime)}, nil - } + props[internal.GetLastModifiedName] = internal.PropFindValue(&internal.GetLastModified{ + LastModified: internal.Time(fi.ModTime), + }) } if fi.MIMEType != "" { - props[internal.GetContentTypeName] = func(*internal.RawXMLValue) (interface{}, error) { - return &internal.GetContentType{Type: fi.MIMEType}, nil - } + props[internal.GetContentTypeName] = internal.PropFindValue(&internal.GetContentType{ + Type: fi.MIMEType, + }) } if fi.ETag != "" { - props[internal.GetETagName] = func(*internal.RawXMLValue) (interface{}, error) { - return &internal.GetETag{ETag: internal.ETag(fi.ETag)}, nil - } + props[internal.GetETagName] = internal.PropFindValue(&internal.GetETag{ + ETag: internal.ETag(fi.ETag), + }) } }