mirror of
https://github.com/1f349/go-webdav.git
synced 2024-12-22 16:24:14 +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.
|
// CalDAV is defined in RFC 4791.
|
||||||
package caldav
|
package caldav
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
type Calendar struct {
|
type Calendar struct {
|
||||||
Path string
|
Path string
|
||||||
Name string
|
Name string
|
||||||
Description string
|
Description string
|
||||||
MaxResourceSize int64
|
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 (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/emersion/go-webdav"
|
"github.com/emersion/go-webdav"
|
||||||
"github.com/emersion/go-webdav/internal"
|
"github.com/emersion/go-webdav/internal"
|
||||||
@ -102,3 +104,98 @@ func (c *Client) FindCalendars(calendarHomeSet string) ([]Calendar, error) {
|
|||||||
|
|
||||||
return l, nil
|
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
|
// 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"`
|
XMLName xml.Name `xml:"urn:ietf:params:xml:ns:caldav calendar-data"`
|
||||||
Data []byte `xml:",chardata"`
|
Data []byte `xml:",chardata"`
|
||||||
}
|
}
|
||||||
|
@ -109,6 +109,7 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
if href != nil {
|
if href != nil {
|
||||||
w.Header().Set("Location", (*url.URL)(href).String())
|
w.Header().Set("Location", (*url.URL)(href).String())
|
||||||
}
|
}
|
||||||
|
// TODO: http.StatusNoContent if the resource already existed
|
||||||
w.WriteHeader(http.StatusCreated)
|
w.WriteHeader(http.StatusCreated)
|
||||||
}
|
}
|
||||||
case http.MethodDelete:
|
case http.MethodDelete:
|
||||||
|
Loading…
Reference in New Issue
Block a user