Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

caldav: add support for more props on MKCOL and PROPFIND #150

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions caldav/caldav.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,10 @@ type Calendar struct {
Path string
Name string
Description string
Color string
MaxResourceSize int64
SupportedComponentSet []string
Timezone string
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably be a parsed *ical.Calendar?

We should probably check that the parsed value contains exactly one VTIMEZONE component?

}

type CalendarCompRequest struct {
Expand Down
33 changes: 27 additions & 6 deletions caldav/elements.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,16 @@ var (
calendarQueryName = xml.Name{namespace, "calendar-query"}
calendarMultigetName = xml.Name{namespace, "calendar-multiget"}

calendarName = xml.Name{namespace, "calendar"}
calendarDataName = xml.Name{namespace, "calendar-data"}
calendarName = xml.Name{namespace, "calendar"}
calendarDataName = xml.Name{namespace, "calendar-data"}
calendarColorName = xml.Name{
Space: "http://apple.com/ns/ical/",
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The standard way to set the color of a calendar is: https://datatracker.ietf.org/doc/html/rfc7986#section-5.9

This is a non-standard, Apple-specfic property. I'm not sure I want to support it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I never saw this one in real life. But happy to add this as well.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just adding my 2 cents: I have indeed also observed the proliferation of this pseudo-standard (apple.com/ns/ical) into many open-source clients (e.g. DavX5 sets it on MKCOL). On the other hand, from my experience, after initial calendar creation, this is treated as a pure client-side property by pretty much all clients (i.e. it never gets updated again), so not sure how necessary it really is...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so not sure how necessary it really is...

agreed - this is for sure a pretty low feature.
Never the less if the color is stored server side it will be "synced" once opening the calendar with another client which has some benefits of recognizing calendars.

e.g. on the owncloud 10 codebase (php+sabredav) colors are the same on all clients (owncloud calendar app in web, DAVx and iOS)

Copy link
Owner

@emersion emersion Apr 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, actually it doesn't seem like there is any standard way to fetch a VCALENDAR for the calendar itself in CalDAV. So RFC 7986 is only useful to set the calendar color when exporting a whole calendar as .ics.

Oh well, let's just do like everybody else then…

Local: "calendar-color",
}
calendarTimezoneName = xml.Name{
Space: namespace,
Local: "calendar-timezone",
}
)

// https://tools.ietf.org/html/rfc4791#section-6.2.1
Expand All @@ -41,6 +49,16 @@ type calendarDescription struct {
Description string `xml:",chardata"`
}

type calendarColor struct {
XMLName xml.Name `xml:"http://apple.com/ns/ical/ calendar-color"`
Color string `xml:",chardata"`
}

type calendarTimezone struct {
XMLName xml.Name `xml:"urn:ietf:params:xml:ns:caldav calendar-timezone"`
Timezone string `xml:",chardata"`
}

// https://tools.ietf.org/html/rfc4791#section-5.2.4
type supportedCalendarData struct {
XMLName xml.Name `xml:"urn:ietf:params:xml:ns:caldav supported-calendar-data"`
Expand Down Expand Up @@ -230,8 +248,11 @@ func (r *reportReq) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
}

type mkcolReq struct {
XMLName xml.Name `xml:"DAV: mkcol"`
ResourceType internal.ResourceType `xml:"set>prop>resourcetype"`
DisplayName string `xml:"set>prop>displayname"`
// TODO this could theoretically contain all addressbook properties?
XMLName xml.Name `xml:"DAV: mkcol"`
ResourceType internal.ResourceType `xml:"set>prop>resourcetype"`
DisplayName string `xml:"set>prop>displayname"`
Description string `xml:"set>prop>calendar-description"`
CalendarColor string `xml:"set>prop>calendar-color"`
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably specify the http://apple.com/ns/ical/ namespace for this prop?

CalendarTimeZone string `xml:"set>prop>calendar-timezone"`
SupportedCalendarComponentSet supportedCalendarComponentSet `xml:"set>prop>supported-calendar-component-set"`
}
23 changes: 22 additions & 1 deletion caldav/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,20 @@ func (b *backend) propFindCalendar(ctx context.Context, propfind *internal.PropF
return &calendarDescription{Description: cal.Description}, nil
}
}
if cal.Color != "" {
props[calendarColorName] = func(*internal.RawXMLValue) (interface{}, error) {
return &calendarColor{
Color: cal.Color,
}, nil
}
}
if cal.Timezone != "" {
props[calendarTimezoneName] = func(*internal.RawXMLValue) (interface{}, error) {
return &calendarTimezone{
Timezone: cal.Timezone,
}, nil
}
}
if cal.MaxResourceSize > 0 {
props[maxResourceSizeName] = func(*internal.RawXMLValue) (interface{}, error) {
return &maxResourceSize{Size: cal.MaxResourceSize}, nil
Expand Down Expand Up @@ -737,7 +751,14 @@ func (b *backend) Mkcol(r *http.Request) error {
return internal.HTTPErrorf(http.StatusBadRequest, "carddav: unexpected resource type")
}
cal.Name = m.DisplayName
// TODO ...
cal.Description = m.Description
cal.Color = strings.TrimSpace(m.CalendarColor)
cal.Timezone = strings.TrimSpace(m.CalendarTimeZone)

cal.SupportedComponentSet = make([]string, len(m.SupportedCalendarComponentSet.Comp))
for i, v := range m.SupportedCalendarComponentSet.Comp {
cal.SupportedComponentSet[i] = v.Name
}
}

return b.Backend.CreateCalendar(r.Context(), &cal)
Expand Down
Loading