Liu Song’s Projects


~/Projects/webdav-go

git clone https://code.lsong.org/webdav-go

Commit

Commit
f9d728aaeb1cb603019bb5e1ec301f17b9c7a163
Author
Simon Ser <[email protected]>
Date
2020-02-05 16:08:15 +0100 +0100
Diffstat
 carddav/client.go | 12 ++++++++++++
 internal/client.go | 41 +++++++++++++++++++++++++++++++++++++++++

carddav: add Client.HasSupport


diff --git a/carddav/client.go b/carddav/client.go
index b9397605c5f5df34d62856e753dec6ff61ac43b1..2c6b00fe9ceeb16c77e3abba079fecd150055526 100644
--- a/carddav/client.go
+++ b/carddav/client.go
@@ -70,6 +70,18 @@ 	c.Client.SetBasicAuth(username, password)
 	c.ic.SetBasicAuth(username, password)
 }
 
+func (c *Client) HasSupport() error {
+	classes, _, err := c.ic.Options("/")
+	if err != nil {
+		return err
+	}
+
+	if !classes["addressbook"] {
+		return fmt.Errorf("carddav: server doesn't support the DAV addressbook class")
+	}
+	return nil
+}
+
 func (c *Client) FindAddressBookHomeSet(principal string) (string, error) {
 	propfind := internal.NewPropNamePropfind(addressBookHomeSetName)
 	resp, err := c.ic.PropfindFlat(principal, propfind)




diff --git a/internal/client.go b/internal/client.go
index 17f84f0b108267297cdf483ec74d02950092d748..78da9a2597404ba23ffc7308a89dc99413aaba3a 100644
--- a/internal/client.go
+++ b/internal/client.go
@@ -8,6 +8,8 @@ 	"io"
 	"net/http"
 	"net/url"
 	"path"
+	"unicode"
+	"strings"
 )
 
 type Client struct {
@@ -119,3 +121,42 @@ 	}
 
 	return ms.Get(path)
 }
+
+func parseCommaSeparatedSet(values []string, upper bool) map[string]bool {
+	m := make(map[string]bool)
+	for _, v := range values {
+		fields := strings.FieldsFunc(v, func(r rune) bool {
+			return unicode.IsSpace(r) || r == ','
+		})
+		for _, f := range fields {
+			if upper {
+				f = strings.ToUpper(f)
+			} else {
+				f = strings.ToLower(f)
+			}
+			m[f] = true
+		}
+	}
+	return m
+}
+
+func (c *Client) Options(path string) (classes map[string]bool, methods map[string]bool, err error) {
+	req, err := c.NewRequest(http.MethodOptions, path, nil)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	resp, err := c.Do(req)
+	if err != nil {
+		return nil, nil, err
+	}
+	resp.Body.Close()
+
+	classes = parseCommaSeparatedSet(resp.Header["Dav"], false)
+	if !classes["1"] {
+		return nil, nil, fmt.Errorf("webdav: server doesn't support DAV class 1")
+	}
+
+	methods = parseCommaSeparatedSet(resp.Header["Allow"], true)
+	return classes, methods, nil
+}