feat: implement caldav search
This commit is contained in:
7
vendor/github.com/dolanor/caldav-go/icalendar/values/cal_scale.go
generated
vendored
Normal file
7
vendor/github.com/dolanor/caldav-go/icalendar/values/cal_scale.go
generated
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
package values
|
||||
|
||||
type CalScale string
|
||||
|
||||
const (
|
||||
GregorianCalScale CalScale = "GREGORIAN"
|
||||
)
|
33
vendor/github.com/dolanor/caldav-go/icalendar/values/comment.go
generated
vendored
Normal file
33
vendor/github.com/dolanor/caldav-go/icalendar/values/comment.go
generated
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
package values
|
||||
|
||||
import (
|
||||
"github.com/dolanor/caldav-go/icalendar/properties"
|
||||
)
|
||||
|
||||
// specifies non-processing information intended to provide a comment to the calendar user.
|
||||
type Comment string
|
||||
|
||||
// encodes the comment value for the iCalendar specification
|
||||
func (c Comment) EncodeICalValue() (string, error) {
|
||||
return string(c), nil
|
||||
}
|
||||
|
||||
// decodes the comment value from the iCalendar specification
|
||||
func (c Comment) DecodeICalValue(value string) error {
|
||||
c = Comment(value)
|
||||
return nil
|
||||
}
|
||||
|
||||
// encodes the comment value for the iCalendar specification
|
||||
func (c Comment) EncodeICalName() (properties.PropertyName, error) {
|
||||
return properties.CommentPropertyName, nil
|
||||
}
|
||||
|
||||
// creates a list of comments from strings
|
||||
func NewComments(comments ...string) []Comment {
|
||||
var _comments []Comment
|
||||
for _, comment := range comments {
|
||||
_comments = append(_comments, Comment(comment))
|
||||
}
|
||||
return _comments
|
||||
}
|
139
vendor/github.com/dolanor/caldav-go/icalendar/values/contact.go
generated
vendored
Normal file
139
vendor/github.com/dolanor/caldav-go/icalendar/values/contact.go
generated
vendored
Normal file
@ -0,0 +1,139 @@
|
||||
package values
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/dolanor/caldav-go/icalendar/properties"
|
||||
"github.com/dolanor/caldav-go/utils"
|
||||
"log"
|
||||
"net/mail"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var _ = log.Print
|
||||
|
||||
// Specifies the organizer of a group scheduled calendar entity. The property is specified within the "VFREEBUSY"
|
||||
// calendar component to specify the calendar user requesting the free or busy time. When publishing a "VFREEBUSY"
|
||||
// calendar component, the property is used to specify the calendar that the published busy time came from.
|
||||
//
|
||||
// The property has the property parameters CN, for specifying the common or display name associated with the
|
||||
// "Organizer", DIR, for specifying a pointer to the directory information associated with the "Organizer",
|
||||
// SENT-BY, for specifying another calendar user that is acting on behalf of the "Organizer". The non-standard
|
||||
// parameters may also be specified on this property. If the LANGUAGE property parameter is specified, the identified
|
||||
// language applies to the CN parameter value.
|
||||
type Contact struct {
|
||||
Entry mail.Address
|
||||
}
|
||||
|
||||
type AttendeeContact Contact
|
||||
type OrganizerContact Contact
|
||||
|
||||
// creates a new icalendar attendee representation
|
||||
func NewAttendeeContact(name, email string) *AttendeeContact {
|
||||
return &AttendeeContact{Entry: mail.Address{Name: name, Address: email}}
|
||||
}
|
||||
|
||||
// creates a new icalendar organizer representation
|
||||
func NewOrganizerContact(name, email string) *OrganizerContact {
|
||||
return &OrganizerContact{Entry: mail.Address{Name: name, Address: email}}
|
||||
}
|
||||
|
||||
// validates the contact value for the iCalendar specification
|
||||
func (c *Contact) ValidateICalValue() error {
|
||||
email := c.Entry.String()
|
||||
if _, err := mail.ParseAddress(email); err != nil {
|
||||
msg := fmt.Sprintf("unable to validate address %s", email)
|
||||
return utils.NewError(c.ValidateICalValue, msg, c, err)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// encodes the contact value for the iCalendar specification
|
||||
func (c *Contact) EncodeICalValue() (string, error) {
|
||||
return fmt.Sprintf("MAILTO:%s", c.Entry.Address), nil
|
||||
}
|
||||
|
||||
// encodes the contact params for the iCalendar specification
|
||||
func (c *Contact) EncodeICalParams() (params properties.Params, err error) {
|
||||
if c.Entry.Name != "" {
|
||||
params = properties.Params{properties.CanonicalNameParameterName: c.Entry.Name}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// decodes the contact value from the iCalendar specification
|
||||
func (c *Contact) DecodeICalValue(value string) error {
|
||||
parts := strings.SplitN(value, ":", 2)
|
||||
if len(parts) > 1 {
|
||||
c.Entry.Address = parts[1]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// decodes the contact params from the iCalendar specification
|
||||
func (c *Contact) DecodeICalParams(params properties.Params) error {
|
||||
if name, found := params[properties.CanonicalNameParameterName]; found {
|
||||
c.Entry.Name = name
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// validates the contact value for the iCalendar specification
|
||||
func (c *OrganizerContact) ValidateICalValue() error {
|
||||
return (*Contact)(c).ValidateICalValue()
|
||||
}
|
||||
|
||||
// encodes the contact value for the iCalendar specification
|
||||
func (c *OrganizerContact) EncodeICalValue() (string, error) {
|
||||
return (*Contact)(c).EncodeICalValue()
|
||||
}
|
||||
|
||||
// encodes the contact params for the iCalendar specification
|
||||
func (c *OrganizerContact) EncodeICalParams() (params properties.Params, err error) {
|
||||
return (*Contact)(c).EncodeICalParams()
|
||||
}
|
||||
|
||||
// decodes the contact value from the iCalendar specification
|
||||
func (c *OrganizerContact) DecodeICalValue(value string) error {
|
||||
return (*Contact)(c).DecodeICalValue(value)
|
||||
}
|
||||
|
||||
// decodes the contact params from the iCalendar specification
|
||||
func (c *OrganizerContact) DecodeICalParams(params properties.Params) error {
|
||||
return (*Contact)(c).DecodeICalParams(params)
|
||||
}
|
||||
|
||||
// encodes the contact property name for the iCalendar specification
|
||||
func (o *OrganizerContact) EncodeICalName() (properties.PropertyName, error) {
|
||||
return properties.OrganizerPropertyName, nil
|
||||
}
|
||||
|
||||
// validates the contact value for the iCalendar specification
|
||||
func (c *AttendeeContact) ValidateICalValue() error {
|
||||
return (*Contact)(c).ValidateICalValue()
|
||||
}
|
||||
|
||||
// encodes the contact value for the iCalendar specification
|
||||
func (c *AttendeeContact) EncodeICalValue() (string, error) {
|
||||
return (*Contact)(c).EncodeICalValue()
|
||||
}
|
||||
|
||||
// encodes the contact params for the iCalendar specification
|
||||
func (c *AttendeeContact) EncodeICalParams() (params properties.Params, err error) {
|
||||
return (*Contact)(c).EncodeICalParams()
|
||||
}
|
||||
|
||||
// decodes the contact value from the iCalendar specification
|
||||
func (c *AttendeeContact) DecodeICalValue(value string) error {
|
||||
return (*Contact)(c).DecodeICalValue(value)
|
||||
}
|
||||
|
||||
// decodes the contact params from the iCalendar specification
|
||||
func (c *AttendeeContact) DecodeICalParams(params properties.Params) error {
|
||||
return (*Contact)(c).DecodeICalParams(params)
|
||||
}
|
||||
|
||||
// encodes the contact property name for the iCalendar specification
|
||||
func (o *AttendeeContact) EncodeICalName() (properties.PropertyName, error) {
|
||||
return properties.AttendeePropertyName, nil
|
||||
}
|
24
vendor/github.com/dolanor/caldav-go/icalendar/values/csv.go
generated
vendored
Normal file
24
vendor/github.com/dolanor/caldav-go/icalendar/values/csv.go
generated
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
package values
|
||||
|
||||
import (
|
||||
"log"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var _ = log.Print
|
||||
|
||||
type CSV []string
|
||||
|
||||
func (csv *CSV) EncodeICalValue() (string, error) {
|
||||
return strings.Join(*csv, ","), nil
|
||||
}
|
||||
|
||||
func (csv *CSV) DecodeICalValue(value string) error {
|
||||
value = strings.TrimSpace(value)
|
||||
*csv = CSV(strings.Split(value, ","))
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewCSV(items ...string) *CSV {
|
||||
return (*CSV)(&items)
|
||||
}
|
265
vendor/github.com/dolanor/caldav-go/icalendar/values/datetime.go
generated
vendored
Normal file
265
vendor/github.com/dolanor/caldav-go/icalendar/values/datetime.go
generated
vendored
Normal file
@ -0,0 +1,265 @@
|
||||
package values
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/dolanor/caldav-go/icalendar/properties"
|
||||
"github.com/dolanor/caldav-go/utils"
|
||||
"log"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
var _ = log.Print
|
||||
|
||||
const DateFormatString = "20060102"
|
||||
const DateTimeFormatString = "20060102T150405"
|
||||
const UTCDateTimeFormatString = "20060102T150405Z"
|
||||
|
||||
// a representation of a date and time for iCalendar
|
||||
type DateTime struct {
|
||||
t time.Time
|
||||
}
|
||||
|
||||
type DateTimes []*DateTime
|
||||
|
||||
// The exception dates, if specified, are used in computing the recurrence set. The recurrence set is the complete set
|
||||
// of recurrence instances for a calendar component. The recurrence set is generated by considering the initial
|
||||
// "DTSTART" property along with the "RRULE", "RDATE", "EXDATE" and "EXRULE" properties contained within the iCalendar
|
||||
// object. The "DTSTART" property defines the first instance in the recurrence set. Multiple instances of the "RRULE"
|
||||
// and "EXRULE" properties can also be specified to define more sophisticated recurrence sets. The final recurrence set
|
||||
// is generated by gathering all of the start date-times generated by any of the specified "RRULE" and "RDATE"
|
||||
// properties, and then excluding any start date and times which fall within the union of start date and times
|
||||
// generated by any specified "EXRULE" and "EXDATE" properties. This implies that start date and times within exclusion
|
||||
// related properties (i.e., "EXDATE" and "EXRULE") take precedence over those specified by inclusion properties
|
||||
// (i.e., "RDATE" and "RRULE"). Where duplicate instances are generated by the "RRULE" and "RDATE" properties, only
|
||||
// one recurrence is considered. Duplicate instances are ignored.
|
||||
//
|
||||
// The "EXDATE" property can be used to exclude the value specified in "DTSTART". However, in such cases the original
|
||||
// "DTSTART" date MUST still be maintained by the calendaring and scheduling system because the original "DTSTART"
|
||||
// value has inherent usage dependencies by other properties such as the "RECURRENCE-ID".
|
||||
type ExceptionDateTimes DateTimes
|
||||
|
||||
// The recurrence dates, if specified, are used in computing the recurrence set. The recurrence set is the complete set
|
||||
// of recurrence instances for a calendar component. The recurrence set is generated by considering the initial
|
||||
// "DTSTART" property along with the "RRULE", "RDATE", "EXDATE" and "EXRULE" properties contained within the iCalendar
|
||||
// object. The "DTSTART" property defines the first instance in the recurrence set. Multiple instances of the "RRULE"
|
||||
// and "EXRULE" properties can also be specified to define more sophisticated recurrence sets. The final recurrence set
|
||||
// is generated by gathering all of the start date-times generated by any of the specified "RRULE" and "RDATE"
|
||||
// properties, and then excluding any start date and times which fall within the union of start date and times
|
||||
// generated by any specified "EXRULE" and "EXDATE" properties. This implies that start date and times within exclusion
|
||||
// related properties (i.e., "EXDATE" and "EXRULE") take precedence over those specified by inclusion properties
|
||||
// (i.e., "RDATE" and "RRULE"). Where duplicate instances are generated by the "RRULE" and "RDATE" properties, only
|
||||
// one recurrence is considered. Duplicate instances are ignored.
|
||||
type RecurrenceDateTimes DateTimes
|
||||
|
||||
// creates a new icalendar datetime representation
|
||||
func NewDateTime(t time.Time) *DateTime {
|
||||
return &DateTime{t: t.Truncate(time.Second)}
|
||||
}
|
||||
|
||||
// creates a new icalendar datetime array representation
|
||||
func NewDateTimes(dates ...*DateTime) DateTimes {
|
||||
return DateTimes(dates)
|
||||
}
|
||||
|
||||
// creates a new icalendar datetime array representation
|
||||
func NewExceptionDateTimes(dates ...*DateTime) *ExceptionDateTimes {
|
||||
datetimes := NewDateTimes(dates...)
|
||||
return (*ExceptionDateTimes)(&datetimes)
|
||||
}
|
||||
|
||||
// creates a new icalendar datetime array representation
|
||||
func NewRecurrenceDateTimes(dates ...*DateTime) *RecurrenceDateTimes {
|
||||
datetimes := NewDateTimes(dates...)
|
||||
return (*RecurrenceDateTimes)(&datetimes)
|
||||
}
|
||||
|
||||
// checks to see if two datetimes are equal
|
||||
func (d *DateTime) Equals(test *DateTime) bool {
|
||||
return d.t.Equal(test.t)
|
||||
}
|
||||
|
||||
// returns the native time for the datetime object
|
||||
func (d *DateTime) NativeTime() time.Time {
|
||||
return d.t
|
||||
}
|
||||
|
||||
// encodes the datetime value for the iCalendar specification
|
||||
func (d *DateTime) EncodeICalValue() (string, error) {
|
||||
val := d.t.Format(DateTimeFormatString)
|
||||
loc := d.t.Location()
|
||||
if loc == time.UTC {
|
||||
val = fmt.Sprintf("%sZ", val)
|
||||
}
|
||||
return val, nil
|
||||
}
|
||||
|
||||
// decodes the datetime value from the iCalendar specification
|
||||
func (d *DateTime) DecodeICalValue(value string) error {
|
||||
layout := DateTimeFormatString
|
||||
if strings.HasSuffix(value, "Z") {
|
||||
layout = UTCDateTimeFormatString
|
||||
} else if len(value) == 8 {
|
||||
layout = DateFormatString
|
||||
}
|
||||
var err error
|
||||
d.t, err = time.ParseInLocation(layout, value, time.UTC)
|
||||
if err != nil {
|
||||
return utils.NewError(d.DecodeICalValue, "unable to parse datetime value", d, err)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// encodes the datetime params for the iCalendar specification
|
||||
func (d *DateTime) EncodeICalParams() (params properties.Params, err error) {
|
||||
loc := d.t.Location()
|
||||
if loc != time.UTC {
|
||||
params = properties.Params{properties.TimeZoneIdPropertyName: loc.String()}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// decodes the datetime params from the iCalendar specification
|
||||
func (d *DateTime) DecodeICalParams(params properties.Params) error {
|
||||
layout := DateTimeFormatString
|
||||
value := d.t.Format(layout)
|
||||
if name, found := params[properties.TimeZoneIdPropertyName]; !found {
|
||||
return nil
|
||||
} else if loc, err := time.LoadLocation(name); err != nil {
|
||||
return utils.NewError(d.DecodeICalValue, "unable to parse timezone", d, err)
|
||||
} else if t, err := time.ParseInLocation(layout, value, loc); err != nil {
|
||||
return utils.NewError(d.DecodeICalValue, "unable to parse datetime value", d, err)
|
||||
} else {
|
||||
d.t = t
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// validates the datetime value against the iCalendar specification
|
||||
func (d *DateTime) ValidateICalValue() error {
|
||||
|
||||
loc := d.t.Location()
|
||||
|
||||
if loc == time.Local {
|
||||
msg := "DateTime location may not Local, please use UTC or explicit Location"
|
||||
return utils.NewError(d.ValidateICalValue, msg, d, nil)
|
||||
}
|
||||
|
||||
if loc.String() == "" {
|
||||
msg := "DateTime location must have a valid name"
|
||||
return utils.NewError(d.ValidateICalValue, msg, d, nil)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// encodes the datetime value for the iCalendar specification
|
||||
func (d *DateTime) String() string {
|
||||
if s, err := d.EncodeICalValue(); err != nil {
|
||||
panic(err)
|
||||
} else {
|
||||
return s
|
||||
}
|
||||
}
|
||||
|
||||
// encodes a list of datetime values for the iCalendar specification
|
||||
func (ds *DateTimes) EncodeICalValue() (string, error) {
|
||||
var csv CSV
|
||||
for i, d := range *ds {
|
||||
if s, err := d.EncodeICalValue(); err != nil {
|
||||
msg := fmt.Sprintf("unable to encode datetime at index %d", i)
|
||||
return "", utils.NewError(ds.EncodeICalValue, msg, ds, err)
|
||||
} else {
|
||||
csv = append(csv, s)
|
||||
}
|
||||
}
|
||||
return csv.EncodeICalValue()
|
||||
}
|
||||
|
||||
// encodes a list of datetime params for the iCalendar specification
|
||||
func (ds *DateTimes) EncodeICalParams() (params properties.Params, err error) {
|
||||
if len(*ds) > 0 {
|
||||
params, err = (*ds)[0].EncodeICalParams()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// decodes a list of datetime params from the iCalendar specification
|
||||
func (ds *DateTimes) DecodeICalParams(params properties.Params) error {
|
||||
for i, d := range *ds {
|
||||
if err := d.DecodeICalParams(params); err != nil {
|
||||
msg := fmt.Sprintf("unable to decode datetime params for index %d", i)
|
||||
return utils.NewError(ds.DecodeICalValue, msg, ds, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// encodes a list of datetime values for the iCalendar specification
|
||||
func (ds *DateTimes) DecodeICalValue(value string) error {
|
||||
csv := new(CSV)
|
||||
if err := csv.DecodeICalValue(value); err != nil {
|
||||
return utils.NewError(ds.DecodeICalValue, "unable to decode datetime list as CSV", ds, err)
|
||||
}
|
||||
for i, value := range *csv {
|
||||
d := new(DateTime)
|
||||
if err := d.DecodeICalValue(value); err != nil {
|
||||
msg := fmt.Sprintf("unable to decode datetime at index %d", i)
|
||||
return utils.NewError(ds.DecodeICalValue, msg, ds, err)
|
||||
} else {
|
||||
*ds = append(*ds, d)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// encodes exception date times property name for icalendar
|
||||
func (e *ExceptionDateTimes) EncodeICalName() (properties.PropertyName, error) {
|
||||
return properties.ExceptionDateTimesPropertyName, nil
|
||||
}
|
||||
|
||||
// encodes recurrence date times property name for icalendar
|
||||
func (r *RecurrenceDateTimes) EncodeICalName() (properties.PropertyName, error) {
|
||||
return properties.RecurrenceDateTimesPropertyName, nil
|
||||
}
|
||||
|
||||
// encodes exception date times property value for icalendar
|
||||
func (e *ExceptionDateTimes) EncodeICalValue() (string, error) {
|
||||
return (*DateTimes)(e).EncodeICalValue()
|
||||
}
|
||||
|
||||
// encodes recurrence date times property value for icalendar
|
||||
func (r *RecurrenceDateTimes) EncodeICalValue() (string, error) {
|
||||
return (*DateTimes)(r).EncodeICalValue()
|
||||
}
|
||||
|
||||
// decodes exception date times property value for icalendar
|
||||
func (e *ExceptionDateTimes) DecodeICalValue(value string) error {
|
||||
return (*DateTimes)(e).DecodeICalValue(value)
|
||||
}
|
||||
|
||||
// decodes recurrence date times property value for icalendar
|
||||
func (r *RecurrenceDateTimes) DecodeICalValue(value string) error {
|
||||
return (*DateTimes)(r).DecodeICalValue(value)
|
||||
}
|
||||
|
||||
// encodes exception date times property params for icalendar
|
||||
func (e *ExceptionDateTimes) EncodeICalParams() (params properties.Params, err error) {
|
||||
return (*DateTimes)(e).EncodeICalParams()
|
||||
}
|
||||
|
||||
// encodes recurrence date times property params for icalendar
|
||||
func (r *RecurrenceDateTimes) EncodeICalParams() (params properties.Params, err error) {
|
||||
return (*DateTimes)(r).EncodeICalParams()
|
||||
}
|
||||
|
||||
// encodes exception date times property params for icalendar
|
||||
func (e *ExceptionDateTimes) DecodeICalParams(params properties.Params) error {
|
||||
return (*DateTimes)(e).DecodeICalParams(params)
|
||||
}
|
||||
|
||||
// encodes recurrence date times property params for icalendar
|
||||
func (r *RecurrenceDateTimes) DecodeICalParams(params properties.Params) error {
|
||||
return (*DateTimes)(r).DecodeICalParams(params)
|
||||
}
|
132
vendor/github.com/dolanor/caldav-go/icalendar/values/duration.go
generated
vendored
Normal file
132
vendor/github.com/dolanor/caldav-go/icalendar/values/duration.go
generated
vendored
Normal file
@ -0,0 +1,132 @@
|
||||
package values
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/dolanor/caldav-go/utils"
|
||||
"log"
|
||||
"math"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
var _ = log.Print
|
||||
|
||||
// a representation of duration for iCalendar
|
||||
type Duration struct {
|
||||
d time.Duration
|
||||
}
|
||||
|
||||
// breaks apart the duration into its component time parts
|
||||
func (d *Duration) Decompose() (weeks, days, hours, minutes, seconds int64) {
|
||||
|
||||
// chip away at this
|
||||
rem := time.Duration(math.Abs(float64(d.d)))
|
||||
|
||||
div := time.Hour * 24 * 7
|
||||
weeks = int64(rem / div)
|
||||
rem = rem % div
|
||||
div = div / 7
|
||||
days = int64(rem / div)
|
||||
rem = rem % div
|
||||
div = div / 24
|
||||
hours = int64(rem / div)
|
||||
rem = rem % div
|
||||
div = div / 60
|
||||
minutes = int64(rem / div)
|
||||
rem = rem % div
|
||||
div = div / 60
|
||||
seconds = int64(rem / div)
|
||||
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
// returns the native golang duration
|
||||
func (d *Duration) NativeDuration() time.Duration {
|
||||
return d.d
|
||||
}
|
||||
|
||||
// returns true if the duration is negative
|
||||
func (d *Duration) IsPast() bool {
|
||||
return d.d < 0
|
||||
}
|
||||
|
||||
// encodes the duration of time into iCalendar format
|
||||
func (d *Duration) EncodeICalValue() (string, error) {
|
||||
var parts []string
|
||||
weeks, days, hours, minutes, seconds := d.Decompose()
|
||||
if d.IsPast() {
|
||||
parts = append(parts, "-")
|
||||
}
|
||||
parts = append(parts, "P")
|
||||
if weeks > 0 {
|
||||
parts = append(parts, fmt.Sprintf("%dW", weeks))
|
||||
}
|
||||
if days > 0 {
|
||||
parts = append(parts, fmt.Sprintf("%dD", days))
|
||||
}
|
||||
if hours > 0 || minutes > 0 || seconds > 0 {
|
||||
parts = append(parts, "T")
|
||||
if hours > 0 {
|
||||
parts = append(parts, fmt.Sprintf("%dH", hours))
|
||||
}
|
||||
if minutes > 0 {
|
||||
parts = append(parts, fmt.Sprintf("%dM", minutes))
|
||||
}
|
||||
if seconds > 0 {
|
||||
parts = append(parts, fmt.Sprintf("%dS", seconds))
|
||||
}
|
||||
}
|
||||
return strings.Join(parts, ""), nil
|
||||
}
|
||||
|
||||
var durationRegEx = regexp.MustCompile("(\\d+)(\\w)")
|
||||
|
||||
// decodes the duration of time from iCalendar format
|
||||
func (d *Duration) DecodeICalValue(value string) error {
|
||||
var seconds int64
|
||||
var isPast = strings.HasPrefix(value, "-P")
|
||||
var matches = durationRegEx.FindAllStringSubmatch(value, -1)
|
||||
for _, match := range matches {
|
||||
var multiplier int64
|
||||
ivalue, err := strconv.ParseInt(match[1], 10, 64)
|
||||
if err != nil {
|
||||
return utils.NewError(d.DecodeICalValue, "unable to decode duration value "+match[1], d, nil)
|
||||
}
|
||||
switch match[2] {
|
||||
case "S":
|
||||
multiplier = 1
|
||||
case "M":
|
||||
multiplier = 60
|
||||
case "H":
|
||||
multiplier = 60 * 60
|
||||
case "D":
|
||||
multiplier = 60 * 60 * 24
|
||||
case "W":
|
||||
multiplier = 60 * 60 * 24 * 7
|
||||
default:
|
||||
return utils.NewError(d.DecodeICalValue, "unable to decode duration segment "+match[2], d, nil)
|
||||
}
|
||||
seconds = seconds + multiplier*ivalue
|
||||
}
|
||||
d.d = time.Duration(seconds) * time.Second
|
||||
if isPast {
|
||||
d.d = -d.d
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Duration) String() string {
|
||||
if s, err := d.EncodeICalValue(); err != nil {
|
||||
panic(err)
|
||||
} else {
|
||||
return s
|
||||
}
|
||||
}
|
||||
|
||||
// creates a new iCalendar duration representation
|
||||
func NewDuration(d time.Duration) *Duration {
|
||||
return &Duration{d: d}
|
||||
}
|
17
vendor/github.com/dolanor/caldav-go/icalendar/values/event_access_classification.go
generated
vendored
Normal file
17
vendor/github.com/dolanor/caldav-go/icalendar/values/event_access_classification.go
generated
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
package values
|
||||
|
||||
// An access classification is only one component of the general security system within a calendar application.
|
||||
// It provides a method of capturing the scope of the access the calendar owner intends for information within an
|
||||
// individual calendar entry. The access classification of an individual iCalendar component is useful when measured
|
||||
// along with the other security components of a calendar system (e.g., calendar user authentication, authorization,
|
||||
// access rights, access role, etc.). Hence, the semantics of the individual access classifications cannot be completely
|
||||
// defined by this memo alone. Additionally, due to the "blind" nature of most exchange processes using this memo, these
|
||||
// access classifications cannot serve as an enforcement statement for a system receiving an iCalendar object. Rather,
|
||||
// they provide a method for capturing the intention of the calendar owner for the access to the calendar component.
|
||||
type EventAccessClassification string
|
||||
|
||||
const (
|
||||
PublicEventAccessClassification EventAccessClassification = "PUBLIC"
|
||||
PrivateEventAccessClassification = "PRIVATE"
|
||||
ConfidentialEventAccessClassification = "CONFIDENTIAL"
|
||||
)
|
13
vendor/github.com/dolanor/caldav-go/icalendar/values/event_status.go
generated
vendored
Normal file
13
vendor/github.com/dolanor/caldav-go/icalendar/values/event_status.go
generated
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
package values
|
||||
|
||||
// In a group scheduled calendar component, the property is used by the "Organizer" to provide a confirmation of the
|
||||
// event to the "Attendees".
|
||||
// For example in an Event calendar component, the "Organizer" can indicate that a meeting is tentative, confirmed or
|
||||
// cancelled.
|
||||
type EventStatus string
|
||||
|
||||
const (
|
||||
TentativeEventStatus EventStatus = "TENTATIVE" // Indicates event is tentative.
|
||||
ConfirmedEventStatus = "CONFIRMED" // Indicates event is definite.
|
||||
CancelledEventStatus = "CANCELLED" // Indicates event is cancelled.
|
||||
)
|
69
vendor/github.com/dolanor/caldav-go/icalendar/values/geo.go
generated
vendored
Normal file
69
vendor/github.com/dolanor/caldav-go/icalendar/values/geo.go
generated
vendored
Normal file
@ -0,0 +1,69 @@
|
||||
package values
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/dolanor/caldav-go/utils"
|
||||
"log"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var _ = log.Print
|
||||
|
||||
// a representation of a geographical point for iCalendar
|
||||
type Geo struct {
|
||||
coords []float64
|
||||
}
|
||||
|
||||
// creates a new icalendar geo representation
|
||||
func NewGeo(lat, lng float64) *Geo {
|
||||
return &Geo{coords: []float64{lat, lng}}
|
||||
}
|
||||
|
||||
// returns the latitude encoded into the geo point
|
||||
func (g *Geo) Lat() float64 {
|
||||
return g.coords[0]
|
||||
}
|
||||
|
||||
// returns the longitude encoded into the geo point
|
||||
func (g *Geo) Lng() float64 {
|
||||
return g.coords[1]
|
||||
}
|
||||
|
||||
// validates the geo value against the iCalendar specification
|
||||
func (g *Geo) ValidateICalValue() error {
|
||||
|
||||
if len(g.coords) != 2 {
|
||||
return utils.NewError(g.ValidateICalValue, "geo value must have length of 2", g, nil)
|
||||
}
|
||||
|
||||
if g.Lat() < -90 || g.Lat() > 90 {
|
||||
return utils.NewError(g.ValidateICalValue, "geo latitude must be between -90 and 90 degrees", g, nil)
|
||||
}
|
||||
|
||||
if g.Lng() < -180 || g.Lng() > 180 {
|
||||
return utils.NewError(g.ValidateICalValue, "geo longitude must be between -180 and 180 degrees", g, nil)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
// encodes the geo value for the iCalendar specification
|
||||
func (g *Geo) EncodeICalValue() (string, error) {
|
||||
return fmt.Sprintf("%f %f", g.Lat(), g.Lng()), nil
|
||||
}
|
||||
|
||||
// decodes the geo value from the iCalendar specification
|
||||
func (g *Geo) DecodeICalValue(value string) error {
|
||||
if latlng := strings.Split(value, " "); len(latlng) < 2 {
|
||||
return utils.NewError(g.DecodeICalValue, "geo value must have both a latitude and longitude component", g, nil)
|
||||
} else if lat, err := strconv.ParseFloat(latlng[0], 64); err != nil {
|
||||
return utils.NewError(g.DecodeICalValue, "unable to decode latitude component", g, err)
|
||||
} else if lng, err := strconv.ParseFloat(latlng[1], 64); err != nil {
|
||||
return utils.NewError(g.DecodeICalValue, "unable to decode latitude component", g, err)
|
||||
} else {
|
||||
*g = Geo{coords: []float64{lat, lng}}
|
||||
return nil
|
||||
}
|
||||
}
|
78
vendor/github.com/dolanor/caldav-go/icalendar/values/location.go
generated
vendored
Normal file
78
vendor/github.com/dolanor/caldav-go/icalendar/values/location.go
generated
vendored
Normal file
@ -0,0 +1,78 @@
|
||||
package values
|
||||
|
||||
import (
|
||||
"github.com/dolanor/caldav-go/icalendar/properties"
|
||||
"github.com/dolanor/caldav-go/utils"
|
||||
"log"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
var _ = log.Print
|
||||
|
||||
// Specific venues such as conference or meeting rooms may be explicitly specified using this property. An alternate
|
||||
// representation may be specified that is a URI that points to directory information with more structured specification
|
||||
// of the location. For example, the alternate representation may specify either an LDAP URI pointing to an LDAP server
|
||||
// entry or a CID URI pointing to a MIME body part containing a vCard [RFC 2426] for the location.
|
||||
type Location struct {
|
||||
value string
|
||||
altrep *url.URL
|
||||
}
|
||||
|
||||
// creates a new icalendar location representation
|
||||
func NewLocation(value string, altrep ...*url.URL) *Location {
|
||||
loc := &Location{value: value}
|
||||
if len(altrep) > 0 {
|
||||
loc.altrep = altrep[0]
|
||||
}
|
||||
return loc
|
||||
}
|
||||
|
||||
// returns an alternate representation for the location
|
||||
// if one exists
|
||||
func (l *Location) AltRep() *url.URL {
|
||||
return l.altrep
|
||||
}
|
||||
|
||||
// encodes the location for the iCalendar specification
|
||||
func (l *Location) EncodeICalValue() (string, error) {
|
||||
return l.value, nil
|
||||
}
|
||||
|
||||
// decodes the location from the iCalendar specification
|
||||
func (l *Location) DecodeICalValue(value string) error {
|
||||
l.value = value
|
||||
return nil
|
||||
}
|
||||
|
||||
// encodes the location params for the iCalendar specification
|
||||
func (l *Location) EncodeICalParams() (params properties.Params, err error) {
|
||||
if l.altrep != nil {
|
||||
params = properties.Params{properties.AlternateRepresentationName: l.altrep.String()}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// decodes the location params from the iCalendar specification
|
||||
func (l *Location) DecodeICalParams(params properties.Params) error {
|
||||
if rep, found := params[properties.AlternateRepresentationName]; !found {
|
||||
return nil
|
||||
} else if altrep, err := url.Parse(rep); err != nil {
|
||||
return utils.NewError(l.DecodeICalValue, "unable to parse alternate representation", l, err)
|
||||
} else {
|
||||
l.altrep = altrep
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// validates the location against the iCalendar specification
|
||||
func (l *Location) ValidateICalValue() error {
|
||||
|
||||
if l.altrep != nil {
|
||||
if _, err := url.Parse(l.altrep.String()); err != nil {
|
||||
msg := "location alternate representation must be a valid url"
|
||||
return utils.NewError(l.ValidateICalValue, msg, l, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
7
vendor/github.com/dolanor/caldav-go/icalendar/values/method.go
generated
vendored
Normal file
7
vendor/github.com/dolanor/caldav-go/icalendar/values/method.go
generated
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
package values
|
||||
|
||||
type Method string
|
||||
|
||||
const (
|
||||
PublishMethod Method = "PUBLISH"
|
||||
)
|
434
vendor/github.com/dolanor/caldav-go/icalendar/values/recurrence_rule.go
generated
vendored
Normal file
434
vendor/github.com/dolanor/caldav-go/icalendar/values/recurrence_rule.go
generated
vendored
Normal file
@ -0,0 +1,434 @@
|
||||
package values
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/dolanor/caldav-go/icalendar/properties"
|
||||
"github.com/dolanor/caldav-go/utils"
|
||||
"log"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// The recurrence rule, if specified, is used in computing the recurrence set. The recurrence set is the complete set
|
||||
// of recurrence instances for a calendar component. The recurrence set is generated by considering the initial
|
||||
// "DTSTART" property along with the "RRULE", "RDATE", "EXDATE" and "EXRULE" properties contained within the iCalendar
|
||||
// object. The "DTSTART" property defines the first instance in the recurrence set. Multiple instances of the "RRULE"
|
||||
// and "EXRULE" properties can also be specified to define more sophisticated recurrence sets. The final recurrence
|
||||
// set is generated by gathering all of the start date/times generated by any of the specified "RRULE" and "RDATE"
|
||||
// properties, and excluding any start date/times which fall within the union of start date/times generated by any
|
||||
// specified "EXRULE" and "EXDATE" properties. This implies that start date/times within exclusion related properties
|
||||
// (i.e., "EXDATE" and "EXRULE") take precedence over those specified by inclusion properties
|
||||
// (i.e., "RDATE" and "RRULE"). Where duplicate instances are generated by the "RRULE" and "RDATE" properties, only
|
||||
// one recurrence is considered. Duplicate instances are ignored.
|
||||
|
||||
// The "DTSTART" and "DTEND" property pair or "DTSTART" and "DURATION" property pair, specified within the iCalendar
|
||||
// object defines the first instance of the recurrence. When used with a recurrence rule, the "DTSTART" and "DTEND"
|
||||
// properties MUST be specified in local time and the appropriate set of "VTIMEZONE" calendar components MUST be
|
||||
// included. For detail on the usage of the "VTIMEZONE" calendar component, see the "VTIMEZONE" calendar component
|
||||
// definition.
|
||||
|
||||
// Any duration associated with the iCalendar object applies to all members of the generated recurrence set. Any
|
||||
// modified duration for specific recurrences MUST be explicitly specified using the "RDATE" property.
|
||||
type RecurrenceRule struct {
|
||||
Frequency RecurrenceFrequency
|
||||
Until *DateTime
|
||||
Count int
|
||||
Interval int
|
||||
BySecond []int
|
||||
ByMinute []int
|
||||
ByHour []int
|
||||
ByDay []RecurrenceWeekday
|
||||
ByMonthDay []int
|
||||
ByYearDay []int
|
||||
ByWeekNumber []int
|
||||
ByMonth []int
|
||||
BySetPosition []int
|
||||
WeekStart RecurrenceWeekday
|
||||
}
|
||||
|
||||
var _ = log.Print
|
||||
|
||||
// the frequency an event recurs
|
||||
type RecurrenceFrequency string
|
||||
|
||||
const (
|
||||
SecondRecurrenceFrequency RecurrenceFrequency = "SECONDLY"
|
||||
MinuteRecurrenceFrequency = "MINUTELY"
|
||||
HourRecurrenceFrequency = "HOURLY"
|
||||
DayRecurrenceFrequency = "DAILY"
|
||||
WeekRecurrenceFrequency = "WEEKLY"
|
||||
MonthRecurrenceFrequency = "MONTHLY"
|
||||
YearRecurrenceFrequency = "YEARLY"
|
||||
)
|
||||
|
||||
// the frequency an event recurs
|
||||
type RecurrenceWeekday string
|
||||
|
||||
const (
|
||||
MondayRecurrenceWeekday RecurrenceWeekday = "MO"
|
||||
TuesdayRecurrenceWeekday = "TU"
|
||||
WednesdayRecurrenceWeekday = "WE"
|
||||
ThursdayRecurrenceWeekday = "TH"
|
||||
FridayRecurrenceWeekday = "FR"
|
||||
SaturdayRecurrenceWeekday = "SA"
|
||||
SundayRecurrenceWeekday = "SU"
|
||||
)
|
||||
|
||||
// creates a new recurrence rule object for iCalendar
|
||||
func NewRecurrenceRule(frequency RecurrenceFrequency) *RecurrenceRule {
|
||||
return &RecurrenceRule{Frequency: frequency}
|
||||
}
|
||||
|
||||
var weekdayRegExp = regexp.MustCompile("MO|TU|WE|TH|FR|SA|SU")
|
||||
|
||||
// returns true if weekday is a valid constant
|
||||
func (r RecurrenceWeekday) IsValidWeekDay() bool {
|
||||
return weekdayRegExp.MatchString(strings.ToUpper(string(r)))
|
||||
}
|
||||
|
||||
var frequencyRegExp = regexp.MustCompile("SECONDLY|MINUTELY|HOURLY|DAILY|WEEKLY|MONTHLY|YEARLY")
|
||||
|
||||
// returns true if weekday is a valid constant
|
||||
func (r RecurrenceFrequency) IsValidFrequency() bool {
|
||||
return frequencyRegExp.MatchString(strings.ToUpper(string(r)))
|
||||
}
|
||||
|
||||
// returns the recurrence rule name for the iCalendar specification
|
||||
func (r *RecurrenceRule) EncodeICalName() (properties.PropertyName, error) {
|
||||
return properties.RecurrenceRulePropertyName, nil
|
||||
}
|
||||
|
||||
// encodes the recurrence rule value for the iCalendar specification
|
||||
func (r *RecurrenceRule) EncodeICalValue() (string, error) {
|
||||
|
||||
out := []string{fmt.Sprintf("FREQ=%s", strings.ToUpper(string(r.Frequency)))}
|
||||
|
||||
if r.Until != nil {
|
||||
if encoded, err := r.Until.EncodeICalValue(); err != nil {
|
||||
return "", utils.NewError(r.EncodeICalValue, "unable to encode until date", r, err)
|
||||
} else {
|
||||
out = append(out, fmt.Sprintf("UNTIL=%s", encoded))
|
||||
}
|
||||
}
|
||||
|
||||
if r.Count > 0 {
|
||||
out = append(out, fmt.Sprintf("COUNT=%d", r.Count))
|
||||
}
|
||||
|
||||
if r.Interval > 0 {
|
||||
out = append(out, fmt.Sprintf("INTERVAL=%d", r.Interval))
|
||||
}
|
||||
|
||||
if len(r.BySecond) > 0 {
|
||||
if encoded, err := intsToCSV(r.BySecond); err != nil {
|
||||
return "", utils.NewError(r.EncodeICalValue, "unable to encode by second value", r, err)
|
||||
} else {
|
||||
out = append(out, fmt.Sprintf("BYSECOND=%s", encoded))
|
||||
}
|
||||
}
|
||||
|
||||
if len(r.ByMinute) > 0 {
|
||||
if encoded, err := intsToCSV(r.ByMinute); err != nil {
|
||||
return "", utils.NewError(r.EncodeICalValue, "unable to encode by minute value", r, err)
|
||||
} else {
|
||||
out = append(out, fmt.Sprintf("BYMINUTE=%s", encoded))
|
||||
}
|
||||
}
|
||||
|
||||
if len(r.ByHour) > 0 {
|
||||
if encoded, err := intsToCSV(r.ByHour); err != nil {
|
||||
return "", utils.NewError(r.EncodeICalValue, "unable to encode by hour value", r, err)
|
||||
} else {
|
||||
out = append(out, fmt.Sprintf("BYHOUR=%s", encoded))
|
||||
}
|
||||
}
|
||||
|
||||
if len(r.ByDay) > 0 {
|
||||
if encoded, err := daysToCSV(r.ByDay); err != nil {
|
||||
return "", utils.NewError(r.EncodeICalValue, "unable to encode by day value", r, err)
|
||||
} else {
|
||||
out = append(out, fmt.Sprintf("BYDAY=%s", encoded))
|
||||
}
|
||||
}
|
||||
|
||||
if len(r.ByMonthDay) > 0 {
|
||||
if encoded, err := intsToCSV(r.ByMonthDay); err != nil {
|
||||
return "", utils.NewError(r.EncodeICalValue, "unable to encode by month day value", r, err)
|
||||
} else {
|
||||
out = append(out, fmt.Sprintf("BYMONTHDAY=%s", encoded))
|
||||
}
|
||||
}
|
||||
|
||||
if len(r.ByYearDay) > 0 {
|
||||
if encoded, err := intsToCSV(r.ByYearDay); err != nil {
|
||||
return "", utils.NewError(r.EncodeICalValue, "unable to encode by year day value", r, err)
|
||||
} else {
|
||||
out = append(out, fmt.Sprintf("BYYEARDAY=%s", encoded))
|
||||
}
|
||||
}
|
||||
|
||||
if len(r.ByWeekNumber) > 0 {
|
||||
if encoded, err := intsToCSV(r.ByWeekNumber); err != nil {
|
||||
return "", utils.NewError(r.EncodeICalValue, "unable to encode by week number value", r, err)
|
||||
} else {
|
||||
out = append(out, fmt.Sprintf("BYWEEKNO=%s", encoded))
|
||||
}
|
||||
}
|
||||
|
||||
if len(r.ByMonth) > 0 {
|
||||
if encoded, err := intsToCSV(r.ByMonth); err != nil {
|
||||
return "", utils.NewError(r.EncodeICalValue, "unable to encode by month value", r, err)
|
||||
} else {
|
||||
out = append(out, fmt.Sprintf("BYMONTH=%s", encoded))
|
||||
}
|
||||
}
|
||||
|
||||
if len(r.BySetPosition) > 0 {
|
||||
if encoded, err := intsToCSV(r.BySetPosition); err != nil {
|
||||
return "", utils.NewError(r.EncodeICalValue, "unable to encode by set position value", r, err)
|
||||
} else {
|
||||
out = append(out, fmt.Sprintf("BYSETPOS=%s", encoded))
|
||||
}
|
||||
}
|
||||
|
||||
if r.WeekStart != "" {
|
||||
out = append(out, fmt.Sprintf("WKST=%s", r.WeekStart))
|
||||
}
|
||||
|
||||
return strings.Join(out, ";"), nil
|
||||
}
|
||||
|
||||
var rruleParamRegExp = regexp.MustCompile("(\\w+)\\s*=\\s*([^;]+)")
|
||||
|
||||
// decodes the recurrence rule value from the iCalendar specification
|
||||
func (r *RecurrenceRule) DecodeICalValue(value string) error {
|
||||
|
||||
matches := rruleParamRegExp.FindAllStringSubmatch(value, -1)
|
||||
if len(matches) <= 0 {
|
||||
return utils.NewError(r.DecodeICalValue, "no recurrence rules found", r, nil)
|
||||
}
|
||||
|
||||
for _, match := range matches {
|
||||
if err := r.decodeICalValue(match[1], match[2]); err != nil {
|
||||
msg := fmt.Sprintf("unable to decode %s value", match[1])
|
||||
return utils.NewError(r.DecodeICalValue, msg, r, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
func (r *RecurrenceRule) decodeICalValue(name string, value string) error {
|
||||
|
||||
switch name {
|
||||
case "FREQ":
|
||||
r.Frequency = RecurrenceFrequency(value)
|
||||
case "UNTIL":
|
||||
until := new(DateTime)
|
||||
if err := until.DecodeICalValue(value); err != nil {
|
||||
return utils.NewError(r.decodeICalValue, "invalid until value "+value, r, err)
|
||||
} else {
|
||||
r.Until = until
|
||||
}
|
||||
case "COUNT":
|
||||
if count, err := strconv.ParseInt(value, 10, 64); err != nil {
|
||||
return utils.NewError(r.decodeICalValue, "invalid count value "+value, r, err)
|
||||
} else {
|
||||
r.Count = int(count)
|
||||
}
|
||||
case "INTERVAL":
|
||||
if interval, err := strconv.ParseInt(value, 10, 64); err != nil {
|
||||
return utils.NewError(r.decodeICalValue, "invalid interval value "+value, r, err)
|
||||
} else {
|
||||
r.Interval = int(interval)
|
||||
}
|
||||
case "BYSECOND":
|
||||
if ints, err := csvToInts(value); err != nil {
|
||||
return utils.NewError(r.decodeICalValue, "invalid by second value "+value, r, err)
|
||||
} else {
|
||||
r.BySecond = ints
|
||||
}
|
||||
case "BYMINUTE":
|
||||
if ints, err := csvToInts(value); err != nil {
|
||||
return utils.NewError(r.decodeICalValue, "invalid by minute value "+value, r, err)
|
||||
} else {
|
||||
r.ByMinute = ints
|
||||
}
|
||||
case "BYHOUR":
|
||||
if ints, err := csvToInts(value); err != nil {
|
||||
return utils.NewError(r.decodeICalValue, "invalid by hour value "+value, r, err)
|
||||
} else {
|
||||
r.ByHour = ints
|
||||
}
|
||||
case "BYDAY":
|
||||
if days, err := csvToDays(value); err != nil {
|
||||
return utils.NewError(r.decodeICalValue, "invalid by day value "+value, r, err)
|
||||
} else {
|
||||
r.ByDay = days
|
||||
}
|
||||
case "BYMONTHDAY":
|
||||
if ints, err := csvToInts(value); err != nil {
|
||||
return utils.NewError(r.decodeICalValue, "invalid by month day value "+value, r, err)
|
||||
} else {
|
||||
r.ByMonthDay = ints
|
||||
}
|
||||
case "BYYEARDAY":
|
||||
if ints, err := csvToInts(value); err != nil {
|
||||
return utils.NewError(r.decodeICalValue, "invalid by year day value "+value, r, err)
|
||||
} else {
|
||||
r.ByYearDay = ints
|
||||
}
|
||||
case "BYWEEKNO":
|
||||
if ints, err := csvToInts(value); err != nil {
|
||||
return utils.NewError(r.decodeICalValue, "invalid by week number value "+value, r, err)
|
||||
} else {
|
||||
r.ByWeekNumber = ints
|
||||
}
|
||||
case "BYMONTH":
|
||||
if ints, err := csvToInts(value); err != nil {
|
||||
return utils.NewError(r.decodeICalValue, "unable to encode by month value "+value, r, err)
|
||||
} else {
|
||||
r.ByMonth = ints
|
||||
}
|
||||
case "BYSETPOS":
|
||||
if ints, err := csvToInts(value); err != nil {
|
||||
return utils.NewError(r.decodeICalValue, "unable to encode by set position value "+value, r, err)
|
||||
} else {
|
||||
r.BySetPosition = ints
|
||||
}
|
||||
case "WKST":
|
||||
r.WeekStart = RecurrenceWeekday(value)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
// validates the recurrence rule value against the iCalendar specification
|
||||
func (r *RecurrenceRule) ValidateICalValue() error {
|
||||
if !r.Frequency.IsValidFrequency() {
|
||||
return utils.NewError(r.ValidateICalValue, "a frequency is required in all recurrence rules", r, nil)
|
||||
} else if r.Until != nil && r.Count > 0 {
|
||||
return utils.NewError(r.ValidateICalValue, "until and count values are mutually exclusive", r, nil)
|
||||
} else if found, fine := intsInRange(r.BySecond, 59); !fine {
|
||||
msg := fmt.Sprintf("by second value of %d is out of bounds", found)
|
||||
return utils.NewError(r.ValidateICalValue, msg, r, nil)
|
||||
} else if found, fine := intsInRange(r.ByMinute, 59); !fine {
|
||||
msg := fmt.Sprintf("by minute value of %d is out of bounds", found)
|
||||
return utils.NewError(r.ValidateICalValue, msg, r, nil)
|
||||
} else if found, fine := intsInRange(r.ByHour, 23); !fine {
|
||||
msg := fmt.Sprintf("by hour value of %d is out of bounds", found)
|
||||
return utils.NewError(r.ValidateICalValue, msg, r, nil)
|
||||
} else if err := daysInRange(r.ByDay); err != nil {
|
||||
return utils.NewError(r.ValidateICalValue, "by day value not in range", r, err)
|
||||
} else if found, fine := intsInRange(r.ByMonthDay, 31); !fine {
|
||||
msg := fmt.Sprintf("by month day value of %d is out of bounds", found)
|
||||
return utils.NewError(r.ValidateICalValue, msg, r, nil)
|
||||
} else if found, fine := intsInRange(r.ByYearDay, 366); !fine {
|
||||
msg := fmt.Sprintf("by year day value of %d is out of bounds", found)
|
||||
return utils.NewError(r.ValidateICalValue, msg, r, nil)
|
||||
} else if found, fine := intsInRange(r.ByMonth, 12); !fine {
|
||||
msg := fmt.Sprintf("by month value of %d is out of bounds", found)
|
||||
return utils.NewError(r.ValidateICalValue, msg, r, nil)
|
||||
} else if found, fine := intsInRange(r.BySetPosition, 366); !fine {
|
||||
msg := fmt.Sprintf("by month value of %d is out of bounds", found)
|
||||
return utils.NewError(r.ValidateICalValue, msg, r, nil)
|
||||
} else if err := dayInRange(r.WeekStart); r.WeekStart != "" && err != nil {
|
||||
return utils.NewError(r.ValidateICalValue, "week start value not in range", r, err)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func intsToCSV(ints []int) (string, error) {
|
||||
csv := new(CSV)
|
||||
for _, i := range ints {
|
||||
*csv = append(*csv, fmt.Sprintf("%d", i))
|
||||
}
|
||||
return csv.EncodeICalValue()
|
||||
}
|
||||
|
||||
func csvToInts(value string) (ints []int, err error) {
|
||||
csv := new(CSV)
|
||||
if ierr := csv.DecodeICalValue(value); err != nil {
|
||||
err = utils.NewError(csvToInts, "unable to decode CSV value", value, ierr)
|
||||
return
|
||||
}
|
||||
for _, v := range *csv {
|
||||
if i, ierr := strconv.ParseInt(v, 10, 64); err != nil {
|
||||
err = utils.NewError(csvToInts, "unable to parse int value "+v, value, ierr)
|
||||
return
|
||||
} else {
|
||||
ints = append(ints, int(i))
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func intsInRange(ints []int, max int) (int, bool) {
|
||||
for _, i := range ints {
|
||||
if i < -max || i > max {
|
||||
return i, false
|
||||
}
|
||||
}
|
||||
return 0, true
|
||||
}
|
||||
|
||||
func daysInRange(days []RecurrenceWeekday) error {
|
||||
for _, day := range days {
|
||||
if err := dayInRange(day); err != nil {
|
||||
msg := fmt.Sprintf("day value %s is not in range", day)
|
||||
return utils.NewError(dayInRange, msg, days, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var dayRegExp = regexp.MustCompile("(\\d{1,2})?(\\w{2})")
|
||||
|
||||
func dayInRange(day RecurrenceWeekday) error {
|
||||
var ordinal, weekday string
|
||||
if matches := dayRegExp.FindAllStringSubmatch(string(day), -1); len(matches) <= 0 {
|
||||
msg := fmt.Sprintf("weekday value %s is not in valid format", day)
|
||||
return utils.NewError(dayInRange, msg, day, nil)
|
||||
} else if len(matches[0]) > 2 {
|
||||
ordinal = matches[0][1]
|
||||
weekday = matches[0][2]
|
||||
} else {
|
||||
weekday = matches[0][1]
|
||||
}
|
||||
if !RecurrenceWeekday(weekday).IsValidWeekDay() {
|
||||
msg := fmt.Sprintf("weekday value %s is not valid", weekday)
|
||||
return utils.NewError(dayInRange, msg, day, nil)
|
||||
} else if i, err := strconv.ParseInt(ordinal, 10, 64); ordinal != "" && err != nil {
|
||||
msg := fmt.Sprintf("weekday ordinal value %d is not valid", i)
|
||||
return utils.NewError(dayInRange, msg, day, err)
|
||||
} else if i < -53 || i > 53 {
|
||||
msg := fmt.Sprintf("weekday ordinal value %d is not in range", i)
|
||||
return utils.NewError(dayInRange, msg, day, nil)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func daysToCSV(days []RecurrenceWeekday) (string, error) {
|
||||
csv := new(CSV)
|
||||
for _, day := range days {
|
||||
*csv = append(*csv, strings.ToUpper(string(day)))
|
||||
}
|
||||
return csv.EncodeICalValue()
|
||||
}
|
||||
|
||||
func csvToDays(value string) (days []RecurrenceWeekday, err error) {
|
||||
csv := new(CSV)
|
||||
if ierr := csv.DecodeICalValue(value); err != nil {
|
||||
err = utils.NewError(csvToInts, "unable to decode CSV value", value, ierr)
|
||||
return
|
||||
}
|
||||
for _, v := range *csv {
|
||||
days = append(days, RecurrenceWeekday(v))
|
||||
}
|
||||
return
|
||||
}
|
12
vendor/github.com/dolanor/caldav-go/icalendar/values/time_transparency.go
generated
vendored
Normal file
12
vendor/github.com/dolanor/caldav-go/icalendar/values/time_transparency.go
generated
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
package values
|
||||
|
||||
// Time Transparency is the characteristic of an event that determines whether it appears to consume time on a calendar.
|
||||
// Events that consume actual time for the individual or resource associated with the calendar SHOULD be recorded as
|
||||
// OPAQUE, allowing them to be detected by free-busy time searches. Other events, which do not take up the individual's
|
||||
// (or resource's) time SHOULD be recorded as TRANSPARENT, making them invisible to free-busy time searches.
|
||||
type TimeTransparency string
|
||||
|
||||
const (
|
||||
OpaqueTimeTransparency TimeTransparency = "OPAQUE" // Blocks or opaque on busy time searches. DEFAULT
|
||||
TransparentTimeTransparency = "TRANSPARENT" // Transparent on busy time searches.
|
||||
)
|
49
vendor/github.com/dolanor/caldav-go/icalendar/values/url.go
generated
vendored
Normal file
49
vendor/github.com/dolanor/caldav-go/icalendar/values/url.go
generated
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
package values
|
||||
|
||||
import (
|
||||
"github.com/dolanor/caldav-go/icalendar/properties"
|
||||
"github.com/dolanor/caldav-go/utils"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
// a representation of duration for iCalendar
|
||||
type Url struct {
|
||||
u url.URL
|
||||
}
|
||||
|
||||
// encodes the URL into iCalendar format
|
||||
func (u *Url) EncodeICalValue() (string, error) {
|
||||
return u.u.String(), nil
|
||||
}
|
||||
|
||||
// encodes the url params for the iCalendar specification
|
||||
func (u *Url) EncodeICalParams() (params properties.Params, err error) {
|
||||
params = properties.Params{
|
||||
properties.ValuePropertyName: "URI",
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// decodes the URL from iCalendar format
|
||||
func (u *Url) DecodeICalValue(value string) error {
|
||||
if parsed, err := url.Parse(value); err != nil {
|
||||
return utils.NewError(u.ValidateICalValue, "unable to parse url", u, err)
|
||||
} else {
|
||||
u.u = *parsed
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// validates the URL for iCalendar format
|
||||
func (u *Url) ValidateICalValue() error {
|
||||
if _, err := url.Parse(u.u.String()); err != nil {
|
||||
return utils.NewError(u.ValidateICalValue, "invalid URL object", u, err)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// creates a new iCalendar duration representation
|
||||
func NewUrl(u url.URL) *Url {
|
||||
return &Url{u: u}
|
||||
}
|
Reference in New Issue
Block a user