116 lines
4.0 KiB
Go
116 lines
4.0 KiB
Go
// Copyright 2015 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package dav
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/xml"
|
|
)
|
|
|
|
// Proppatch describes a property update instruction as defined in RFC 4918.
|
|
// See http://www.webdav.org/specs/rfc4918.html#METHOD_PROPPATCH
|
|
type Proppatch struct {
|
|
// Remove specifies whether this patch removes properties. If it does not
|
|
// remove them, it sets them.
|
|
Remove bool
|
|
// Props contains the properties to be set or removed.
|
|
Props []Property
|
|
}
|
|
|
|
// Propstat describes a XML propstat element as defined in RFC 4918.
|
|
// See http://www.webdav.org/specs/rfc4918.html#ELEMENT_propstat
|
|
type Propstat struct {
|
|
// Props contains the properties for which Status applies.
|
|
Props []Property
|
|
|
|
// Status defines the HTTP status code of the properties in Prop.
|
|
// Allowed values include, but are not limited to the WebDAV status
|
|
// code extensions for HTTP/1.1.
|
|
// http://www.webdav.org/specs/rfc4918.html#status.code.extensions.to.http11
|
|
Status int
|
|
|
|
// XMLError contains the XML representation of the optional error element.
|
|
// XML content within this field must not rely on any predefined
|
|
// namespace declarations or prefixes. If empty, the XML error element
|
|
// is omitted.
|
|
XMLError string
|
|
|
|
// ResponseDescription contains the contents of the optional
|
|
// responsedescription field. If empty, the XML element is omitted.
|
|
ResponseDescription string
|
|
}
|
|
|
|
|
|
// DeadPropsHolder holds the dead properties of a resource.
|
|
//
|
|
// Dead properties are those properties that are explicitly defined. In
|
|
// comparison, live properties, such as DAV:getcontentlength, are implicitly
|
|
// defined by the underlying resource, and cannot be explicitly overridden or
|
|
// removed. See the Terminology section of
|
|
// http://www.webdav.org/specs/rfc4918.html#rfc.section.3
|
|
//
|
|
// There is a whitelist of the names of live properties. This package handles
|
|
// all live properties, and will only pass non-whitelisted names to the Patch
|
|
// method of DeadPropsHolder implementations.
|
|
type DeadPropsHolder interface {
|
|
// DeadProps returns a copy of the dead properties held.
|
|
DeadProps() (map[xml.Name]Property, error)
|
|
|
|
// Patch patches the dead properties held.
|
|
//
|
|
// Patching is atomic; either all or no patches succeed. It returns (nil,
|
|
// non-nil) if an internal server error occurred, otherwise the Propstats
|
|
// collectively contain one Property for each proposed patch Property. If
|
|
// all patches succeed, Patch returns a slice of length one and a Propstat
|
|
// element with a 200 OK HTTP status code. If none succeed, for reasons
|
|
// other than an internal server error, no Propstat has status 200 OK.
|
|
//
|
|
// For more details on when various HTTP status codes apply, see
|
|
// http://www.webdav.org/specs/rfc4918.html#PROPPATCH-status
|
|
Patch([]Proppatch) ([]Propstat, error)
|
|
}
|
|
|
|
|
|
func EscapeXML(s string) string {
|
|
for i := 0; i < len(s); i++ {
|
|
// As an optimization, if s contains only ASCII letters, digits or a
|
|
// few special characters, the escaped value is s itself and we don't
|
|
// need to allocate a buffer and convert between string and []byte.
|
|
switch c := s[i]; {
|
|
case c == ' ' || c == '_' ||
|
|
('+' <= c && c <= '9') || // Digits as well as + , - . and /
|
|
('A' <= c && c <= 'Z') ||
|
|
('a' <= c && c <= 'z'):
|
|
continue
|
|
}
|
|
// Otherwise, go through the full escaping process.
|
|
var buf bytes.Buffer
|
|
xml.EscapeText(&buf, []byte(s))
|
|
return buf.String()
|
|
}
|
|
return s
|
|
}
|
|
|
|
|
|
|
|
// ContentTyper is an optional interface for the os.FileInfo
|
|
// objects returned by the FileSystem.
|
|
//
|
|
// If this interface is defined then it will be used to read the
|
|
// content type from the object.
|
|
//
|
|
// If this interface is not defined the file will be opened and the
|
|
// content type will be guessed from the initial contents of the file.
|
|
type ContentTyper interface {
|
|
// ContentType returns the content type for the file.
|
|
//
|
|
// If this returns error ErrNotImplemented then the error will
|
|
// be ignored and the base implementation will be used
|
|
// instead.
|
|
ContentType(ctx context.Context) (string, error)
|
|
}
|
|
|