mirror of
https://github.com/1f349/go-webdav.git
synced 2024-12-22 08:14:15 +00:00
caldav: add Client.QueryCalendar
This commit is contained in:
parent
dd1527b97e
commit
ca51e9427a
@ -3,9 +3,34 @@
|
||||
// CalDAV is defined in RFC 4791.
|
||||
package caldav
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type Calendar struct {
|
||||
Path string
|
||||
Name string
|
||||
Description string
|
||||
MaxResourceSize int64
|
||||
}
|
||||
|
||||
type CalendarCompRequest struct {
|
||||
Name string
|
||||
|
||||
AllProps bool
|
||||
Props []string
|
||||
|
||||
AllComps bool
|
||||
Comps []CalendarCompRequest
|
||||
}
|
||||
|
||||
type CalendarQuery struct {
|
||||
Comp CalendarCompRequest
|
||||
}
|
||||
|
||||
type CalendarObject struct {
|
||||
Path string
|
||||
ModTime time.Time
|
||||
ETag string
|
||||
Data []byte
|
||||
}
|
||||
|
@ -3,6 +3,8 @@ package caldav
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/emersion/go-webdav"
|
||||
"github.com/emersion/go-webdav/internal"
|
||||
@ -102,3 +104,98 @@ func (c *Client) FindCalendars(calendarHomeSet string) ([]Calendar, error) {
|
||||
|
||||
return l, nil
|
||||
}
|
||||
|
||||
func encodeCalendarCompReq(c *CalendarCompRequest) (*comp, error) {
|
||||
encoded := comp{Name: c.Name}
|
||||
|
||||
if c.AllProps {
|
||||
encoded.Allprop = &struct{}{}
|
||||
}
|
||||
for _, name := range c.Props {
|
||||
encoded.Prop = append(encoded.Prop, prop{Name: name})
|
||||
}
|
||||
|
||||
if c.AllComps {
|
||||
encoded.Allcomp = &struct{}{}
|
||||
}
|
||||
for _, child := range c.Comps {
|
||||
encodedChild, err := encodeCalendarCompReq(&child)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
encoded.Comp = append(encoded.Comp, *encodedChild)
|
||||
}
|
||||
|
||||
return &encoded, nil
|
||||
}
|
||||
|
||||
func encodeCalendarReq(c *CalendarCompRequest) (*internal.Prop, error) {
|
||||
compReq, err := encodeCalendarCompReq(c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
calDataReq := calendarDataReq{Comp: compReq}
|
||||
|
||||
getLastModReq := internal.NewRawXMLElement(internal.GetLastModifiedName, nil, nil)
|
||||
getETagReq := internal.NewRawXMLElement(internal.GetETagName, nil, nil)
|
||||
return internal.EncodeProp(&calDataReq, getLastModReq, getETagReq)
|
||||
}
|
||||
|
||||
func decodeCalendarObjectList(ms *internal.Multistatus) ([]CalendarObject, error) {
|
||||
addrs := make([]CalendarObject, 0, len(ms.Responses))
|
||||
for _, resp := range ms.Responses {
|
||||
path, err := resp.Path()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var calData calendarDataResp
|
||||
if err := resp.DecodeProp(&calData); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var getLastMod internal.GetLastModified
|
||||
if err := resp.DecodeProp(&getLastMod); err != nil && !internal.IsNotFound(err) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var getETag internal.GetETag
|
||||
if err := resp.DecodeProp(&getETag); err != nil && !internal.IsNotFound(err) {
|
||||
return nil, err
|
||||
}
|
||||
etag, err := strconv.Unquote(getETag.ETag)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("carddav: failed to unquote ETag: %v", err)
|
||||
}
|
||||
|
||||
addrs = append(addrs, CalendarObject{
|
||||
Path: path,
|
||||
ModTime: time.Time(getLastMod.LastModified),
|
||||
ETag: etag,
|
||||
Data: calData.Data,
|
||||
})
|
||||
}
|
||||
|
||||
return addrs, nil
|
||||
}
|
||||
|
||||
func (c *Client) QueryCalendar(calendar string, query *CalendarQuery) ([]CalendarObject, error) {
|
||||
propReq, err := encodeCalendarReq(&query.Comp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
calendarQuery := calendarQuery{Prop: propReq}
|
||||
req, err := c.ic.NewXMLRequest("REPORT", calendar, &calendarQuery)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ms, err := c.ic.DoMultiStatus(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return decodeCalendarObjectList(ms)
|
||||
}
|
||||
|
@ -85,7 +85,7 @@ type prop struct {
|
||||
}
|
||||
|
||||
// Response variant of https://tools.ietf.org/html/rfc4791#section-9.6
|
||||
type calendarData struct {
|
||||
type calendarDataResp struct {
|
||||
XMLName xml.Name `xml:"urn:ietf:params:xml:ns:caldav calendar-data"`
|
||||
Data []byte `xml:",chardata"`
|
||||
}
|
||||
|
@ -109,6 +109,7 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
if href != nil {
|
||||
w.Header().Set("Location", (*url.URL)(href).String())
|
||||
}
|
||||
// TODO: http.StatusNoContent if the resource already existed
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
}
|
||||
case http.MethodDelete:
|
||||
|
Loading…
Reference in New Issue
Block a user