|
@@ -14,12 +14,12 @@ import (
|
|
|
"net/http"
|
|
"net/http"
|
|
|
"time"
|
|
"time"
|
|
|
|
|
|
|
|
- "golang.org/x/net/webdav/internal/xml"
|
|
|
|
|
|
|
+ ixml "golang.org/x/net/webdav/internal/xml"
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
// http://www.webdav.org/specs/rfc4918.html#ELEMENT_lockinfo
|
|
// http://www.webdav.org/specs/rfc4918.html#ELEMENT_lockinfo
|
|
|
type lockInfo struct {
|
|
type lockInfo struct {
|
|
|
- XMLName xml.Name `xml:"lockinfo"`
|
|
|
|
|
|
|
+ XMLName ixml.Name `xml:"lockinfo"`
|
|
|
Exclusive *struct{} `xml:"lockscope>exclusive"`
|
|
Exclusive *struct{} `xml:"lockscope>exclusive"`
|
|
|
Shared *struct{} `xml:"lockscope>shared"`
|
|
Shared *struct{} `xml:"lockscope>shared"`
|
|
|
Write *struct{} `xml:"locktype>write"`
|
|
Write *struct{} `xml:"locktype>write"`
|
|
@@ -33,7 +33,7 @@ type owner struct {
|
|
|
|
|
|
|
|
func readLockInfo(r io.Reader) (li lockInfo, status int, err error) {
|
|
func readLockInfo(r io.Reader) (li lockInfo, status int, err error) {
|
|
|
c := &countingReader{r: r}
|
|
c := &countingReader{r: r}
|
|
|
- if err = xml.NewDecoder(c).Decode(&li); err != nil {
|
|
|
|
|
|
|
+ if err = ixml.NewDecoder(c).Decode(&li); err != nil {
|
|
|
if err == io.EOF {
|
|
if err == io.EOF {
|
|
|
if c.n == 0 {
|
|
if c.n == 0 {
|
|
|
// An empty body means to refresh the lock.
|
|
// An empty body means to refresh the lock.
|
|
@@ -88,7 +88,7 @@ func escape(s string) string {
|
|
|
switch s[i] {
|
|
switch s[i] {
|
|
|
case '"', '&', '\'', '<', '>':
|
|
case '"', '&', '\'', '<', '>':
|
|
|
b := bytes.NewBuffer(nil)
|
|
b := bytes.NewBuffer(nil)
|
|
|
- xml.EscapeText(b, []byte(s))
|
|
|
|
|
|
|
+ ixml.EscapeText(b, []byte(s))
|
|
|
return b.String()
|
|
return b.String()
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -100,14 +100,14 @@ func escape(s string) string {
|
|
|
// and directives.
|
|
// and directives.
|
|
|
// http://www.webdav.org/specs/rfc4918.html#property_values
|
|
// http://www.webdav.org/specs/rfc4918.html#property_values
|
|
|
// http://www.webdav.org/specs/rfc4918.html#xml-extensibility
|
|
// http://www.webdav.org/specs/rfc4918.html#xml-extensibility
|
|
|
-func next(d *xml.Decoder) (xml.Token, error) {
|
|
|
|
|
|
|
+func next(d *ixml.Decoder) (ixml.Token, error) {
|
|
|
for {
|
|
for {
|
|
|
t, err := d.Token()
|
|
t, err := d.Token()
|
|
|
if err != nil {
|
|
if err != nil {
|
|
|
return t, err
|
|
return t, err
|
|
|
}
|
|
}
|
|
|
switch t.(type) {
|
|
switch t.(type) {
|
|
|
- case xml.Comment, xml.Directive, xml.ProcInst:
|
|
|
|
|
|
|
+ case ixml.Comment, ixml.Directive, ixml.ProcInst:
|
|
|
continue
|
|
continue
|
|
|
default:
|
|
default:
|
|
|
return t, nil
|
|
return t, nil
|
|
@@ -116,31 +116,31 @@ func next(d *xml.Decoder) (xml.Token, error) {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// http://www.webdav.org/specs/rfc4918.html#ELEMENT_prop (for propfind)
|
|
// http://www.webdav.org/specs/rfc4918.html#ELEMENT_prop (for propfind)
|
|
|
-type propfindProps []xml.Name
|
|
|
|
|
|
|
+type propfindProps []ixml.Name
|
|
|
|
|
|
|
|
// UnmarshalXML appends the property names enclosed within start to pn.
|
|
// UnmarshalXML appends the property names enclosed within start to pn.
|
|
|
//
|
|
//
|
|
|
// It returns an error if start does not contain any properties or if
|
|
// It returns an error if start does not contain any properties or if
|
|
|
// properties contain values. Character data between properties is ignored.
|
|
// properties contain values. Character data between properties is ignored.
|
|
|
-func (pn *propfindProps) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
|
|
|
|
|
|
+func (pn *propfindProps) UnmarshalXML(d *ixml.Decoder, start ixml.StartElement) error {
|
|
|
for {
|
|
for {
|
|
|
t, err := next(d)
|
|
t, err := next(d)
|
|
|
if err != nil {
|
|
if err != nil {
|
|
|
return err
|
|
return err
|
|
|
}
|
|
}
|
|
|
switch t.(type) {
|
|
switch t.(type) {
|
|
|
- case xml.EndElement:
|
|
|
|
|
|
|
+ case ixml.EndElement:
|
|
|
if len(*pn) == 0 {
|
|
if len(*pn) == 0 {
|
|
|
return fmt.Errorf("%s must not be empty", start.Name.Local)
|
|
return fmt.Errorf("%s must not be empty", start.Name.Local)
|
|
|
}
|
|
}
|
|
|
return nil
|
|
return nil
|
|
|
- case xml.StartElement:
|
|
|
|
|
- name := t.(xml.StartElement).Name
|
|
|
|
|
|
|
+ case ixml.StartElement:
|
|
|
|
|
+ name := t.(ixml.StartElement).Name
|
|
|
t, err = next(d)
|
|
t, err = next(d)
|
|
|
if err != nil {
|
|
if err != nil {
|
|
|
return err
|
|
return err
|
|
|
}
|
|
}
|
|
|
- if _, ok := t.(xml.EndElement); !ok {
|
|
|
|
|
|
|
+ if _, ok := t.(ixml.EndElement); !ok {
|
|
|
return fmt.Errorf("unexpected token %T", t)
|
|
return fmt.Errorf("unexpected token %T", t)
|
|
|
}
|
|
}
|
|
|
*pn = append(*pn, name)
|
|
*pn = append(*pn, name)
|
|
@@ -150,7 +150,7 @@ func (pn *propfindProps) UnmarshalXML(d *xml.Decoder, start xml.StartElement) er
|
|
|
|
|
|
|
|
// http://www.webdav.org/specs/rfc4918.html#ELEMENT_propfind
|
|
// http://www.webdav.org/specs/rfc4918.html#ELEMENT_propfind
|
|
|
type propfind struct {
|
|
type propfind struct {
|
|
|
- XMLName xml.Name `xml:"DAV: propfind"`
|
|
|
|
|
|
|
+ XMLName ixml.Name `xml:"DAV: propfind"`
|
|
|
Allprop *struct{} `xml:"DAV: allprop"`
|
|
Allprop *struct{} `xml:"DAV: allprop"`
|
|
|
Propname *struct{} `xml:"DAV: propname"`
|
|
Propname *struct{} `xml:"DAV: propname"`
|
|
|
Prop propfindProps `xml:"DAV: prop"`
|
|
Prop propfindProps `xml:"DAV: prop"`
|
|
@@ -159,7 +159,7 @@ type propfind struct {
|
|
|
|
|
|
|
|
func readPropfind(r io.Reader) (pf propfind, status int, err error) {
|
|
func readPropfind(r io.Reader) (pf propfind, status int, err error) {
|
|
|
c := countingReader{r: r}
|
|
c := countingReader{r: r}
|
|
|
- if err = xml.NewDecoder(&c).Decode(&pf); err != nil {
|
|
|
|
|
|
|
+ if err = ixml.NewDecoder(&c).Decode(&pf); err != nil {
|
|
|
if err == io.EOF {
|
|
if err == io.EOF {
|
|
|
if c.n == 0 {
|
|
if c.n == 0 {
|
|
|
// An empty body means to propfind allprop.
|
|
// An empty body means to propfind allprop.
|
|
@@ -190,7 +190,7 @@ func readPropfind(r io.Reader) (pf propfind, status int, err error) {
|
|
|
// See http://www.webdav.org/specs/rfc4918.html#data.model.for.resource.properties
|
|
// See http://www.webdav.org/specs/rfc4918.html#data.model.for.resource.properties
|
|
|
type Property struct {
|
|
type Property struct {
|
|
|
// XMLName is the fully qualified name that identifies this property.
|
|
// XMLName is the fully qualified name that identifies this property.
|
|
|
- XMLName xml.Name
|
|
|
|
|
|
|
+ XMLName ixml.Name
|
|
|
|
|
|
|
|
// Lang is an optional xml:lang attribute.
|
|
// Lang is an optional xml:lang attribute.
|
|
|
Lang string `xml:"xml:lang,attr,omitempty"`
|
|
Lang string `xml:"xml:lang,attr,omitempty"`
|
|
@@ -209,8 +209,8 @@ type Property struct {
|
|
|
// http://www.webdav.org/specs/rfc4918.html#ELEMENT_error
|
|
// http://www.webdav.org/specs/rfc4918.html#ELEMENT_error
|
|
|
// See multistatusWriter for the "D:" namespace prefix.
|
|
// See multistatusWriter for the "D:" namespace prefix.
|
|
|
type xmlError struct {
|
|
type xmlError struct {
|
|
|
- XMLName xml.Name `xml:"D:error"`
|
|
|
|
|
- InnerXML []byte `xml:",innerxml"`
|
|
|
|
|
|
|
+ XMLName ixml.Name `xml:"D:error"`
|
|
|
|
|
+ InnerXML []byte `xml:",innerxml"`
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// http://www.webdav.org/specs/rfc4918.html#ELEMENT_propstat
|
|
// http://www.webdav.org/specs/rfc4918.html#ELEMENT_propstat
|
|
@@ -224,10 +224,10 @@ type propstat struct {
|
|
|
|
|
|
|
|
// MarshalXML prepends the "D:" namespace prefix on properties in the DAV: namespace
|
|
// MarshalXML prepends the "D:" namespace prefix on properties in the DAV: namespace
|
|
|
// before encoding. See multistatusWriter.
|
|
// before encoding. See multistatusWriter.
|
|
|
-func (ps propstat) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
|
|
|
|
|
|
|
+func (ps propstat) MarshalXML(e *ixml.Encoder, start ixml.StartElement) error {
|
|
|
for k, prop := range ps.Prop {
|
|
for k, prop := range ps.Prop {
|
|
|
if prop.XMLName.Space == "DAV:" {
|
|
if prop.XMLName.Space == "DAV:" {
|
|
|
- prop.XMLName = xml.Name{Space: "", Local: "D:" + prop.XMLName.Local}
|
|
|
|
|
|
|
+ prop.XMLName = ixml.Name{Space: "", Local: "D:" + prop.XMLName.Local}
|
|
|
ps.Prop[k] = prop
|
|
ps.Prop[k] = prop
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -239,7 +239,7 @@ func (ps propstat) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
|
|
|
// http://www.webdav.org/specs/rfc4918.html#ELEMENT_response
|
|
// http://www.webdav.org/specs/rfc4918.html#ELEMENT_response
|
|
|
// See multistatusWriter for the "D:" namespace prefix.
|
|
// See multistatusWriter for the "D:" namespace prefix.
|
|
|
type response struct {
|
|
type response struct {
|
|
|
- XMLName xml.Name `xml:"D:response"`
|
|
|
|
|
|
|
+ XMLName ixml.Name `xml:"D:response"`
|
|
|
Href []string `xml:"D:href"`
|
|
Href []string `xml:"D:href"`
|
|
|
Propstat []propstat `xml:"D:propstat"`
|
|
Propstat []propstat `xml:"D:propstat"`
|
|
|
Status string `xml:"D:status,omitempty"`
|
|
Status string `xml:"D:status,omitempty"`
|
|
@@ -264,7 +264,7 @@ type multistatusWriter struct {
|
|
|
responseDescription string
|
|
responseDescription string
|
|
|
|
|
|
|
|
w http.ResponseWriter
|
|
w http.ResponseWriter
|
|
|
- enc *xml.Encoder
|
|
|
|
|
|
|
+ enc *ixml.Encoder
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Write validates and emits a DAV response as part of a multistatus response
|
|
// Write validates and emits a DAV response as part of a multistatus response
|
|
@@ -308,14 +308,14 @@ func (w *multistatusWriter) writeHeader() error {
|
|
|
if err != nil {
|
|
if err != nil {
|
|
|
return err
|
|
return err
|
|
|
}
|
|
}
|
|
|
- w.enc = xml.NewEncoder(w.w)
|
|
|
|
|
- return w.enc.EncodeToken(xml.StartElement{
|
|
|
|
|
- Name: xml.Name{
|
|
|
|
|
|
|
+ w.enc = ixml.NewEncoder(w.w)
|
|
|
|
|
+ return w.enc.EncodeToken(ixml.StartElement{
|
|
|
|
|
+ Name: ixml.Name{
|
|
|
Space: "DAV:",
|
|
Space: "DAV:",
|
|
|
Local: "multistatus",
|
|
Local: "multistatus",
|
|
|
},
|
|
},
|
|
|
- Attr: []xml.Attr{{
|
|
|
|
|
- Name: xml.Name{Space: "xmlns", Local: "D"},
|
|
|
|
|
|
|
+ Attr: []ixml.Attr{{
|
|
|
|
|
+ Name: ixml.Name{Space: "xmlns", Local: "D"},
|
|
|
Value: "DAV:",
|
|
Value: "DAV:",
|
|
|
}},
|
|
}},
|
|
|
})
|
|
})
|
|
@@ -329,17 +329,17 @@ func (w *multistatusWriter) close() error {
|
|
|
if w.enc == nil {
|
|
if w.enc == nil {
|
|
|
return nil
|
|
return nil
|
|
|
}
|
|
}
|
|
|
- var end []xml.Token
|
|
|
|
|
|
|
+ var end []ixml.Token
|
|
|
if w.responseDescription != "" {
|
|
if w.responseDescription != "" {
|
|
|
- name := xml.Name{Space: "DAV:", Local: "responsedescription"}
|
|
|
|
|
|
|
+ name := ixml.Name{Space: "DAV:", Local: "responsedescription"}
|
|
|
end = append(end,
|
|
end = append(end,
|
|
|
- xml.StartElement{Name: name},
|
|
|
|
|
- xml.CharData(w.responseDescription),
|
|
|
|
|
- xml.EndElement{Name: name},
|
|
|
|
|
|
|
+ ixml.StartElement{Name: name},
|
|
|
|
|
+ ixml.CharData(w.responseDescription),
|
|
|
|
|
+ ixml.EndElement{Name: name},
|
|
|
)
|
|
)
|
|
|
}
|
|
}
|
|
|
- end = append(end, xml.EndElement{
|
|
|
|
|
- Name: xml.Name{Space: "DAV:", Local: "multistatus"},
|
|
|
|
|
|
|
+ end = append(end, ixml.EndElement{
|
|
|
|
|
+ Name: ixml.Name{Space: "DAV:", Local: "multistatus"},
|
|
|
})
|
|
})
|
|
|
for _, t := range end {
|
|
for _, t := range end {
|
|
|
err := w.enc.EncodeToken(t)
|
|
err := w.enc.EncodeToken(t)
|
|
@@ -353,9 +353,9 @@ func (w *multistatusWriter) close() error {
|
|
|
// http://www.webdav.org/specs/rfc4918.html#ELEMENT_prop (for proppatch)
|
|
// http://www.webdav.org/specs/rfc4918.html#ELEMENT_prop (for proppatch)
|
|
|
type proppatchProps []Property
|
|
type proppatchProps []Property
|
|
|
|
|
|
|
|
-var xmlLangName = xml.Name{Space: "http://www.w3.org/XML/1998/namespace", Local: "lang"}
|
|
|
|
|
|
|
+var xmlLangName = ixml.Name{Space: "http://www.w3.org/XML/1998/namespace", Local: "lang"}
|
|
|
|
|
|
|
|
-func xmlLang(s xml.StartElement, d string) string {
|
|
|
|
|
|
|
+func xmlLang(s ixml.StartElement, d string) string {
|
|
|
for _, attr := range s.Attr {
|
|
for _, attr := range s.Attr {
|
|
|
if attr.Name == xmlLangName {
|
|
if attr.Name == xmlLangName {
|
|
|
return attr.Value
|
|
return attr.Value
|
|
@@ -366,19 +366,19 @@ func xmlLang(s xml.StartElement, d string) string {
|
|
|
|
|
|
|
|
type xmlValue []byte
|
|
type xmlValue []byte
|
|
|
|
|
|
|
|
-func (v *xmlValue) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
|
|
|
|
|
|
+func (v *xmlValue) UnmarshalXML(d *ixml.Decoder, start ixml.StartElement) error {
|
|
|
// The XML value of a property can be arbitrary, mixed-content XML.
|
|
// The XML value of a property can be arbitrary, mixed-content XML.
|
|
|
// To make sure that the unmarshalled value contains all required
|
|
// To make sure that the unmarshalled value contains all required
|
|
|
// namespaces, we encode all the property value XML tokens into a
|
|
// namespaces, we encode all the property value XML tokens into a
|
|
|
// buffer. This forces the encoder to redeclare any used namespaces.
|
|
// buffer. This forces the encoder to redeclare any used namespaces.
|
|
|
var b bytes.Buffer
|
|
var b bytes.Buffer
|
|
|
- e := xml.NewEncoder(&b)
|
|
|
|
|
|
|
+ e := ixml.NewEncoder(&b)
|
|
|
for {
|
|
for {
|
|
|
t, err := next(d)
|
|
t, err := next(d)
|
|
|
if err != nil {
|
|
if err != nil {
|
|
|
return err
|
|
return err
|
|
|
}
|
|
}
|
|
|
- if e, ok := t.(xml.EndElement); ok && e.Name == start.Name {
|
|
|
|
|
|
|
+ if e, ok := t.(ixml.EndElement); ok && e.Name == start.Name {
|
|
|
break
|
|
break
|
|
|
}
|
|
}
|
|
|
if err = e.EncodeToken(t); err != nil {
|
|
if err = e.EncodeToken(t); err != nil {
|
|
@@ -401,7 +401,7 @@ func (v *xmlValue) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
|
|
//
|
|
//
|
|
|
// UnmarshalXML returns an error if start does not contain any properties or if
|
|
// UnmarshalXML returns an error if start does not contain any properties or if
|
|
|
// property values contain syntactically incorrect XML.
|
|
// property values contain syntactically incorrect XML.
|
|
|
-func (ps *proppatchProps) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
|
|
|
|
|
|
+func (ps *proppatchProps) UnmarshalXML(d *ixml.Decoder, start ixml.StartElement) error {
|
|
|
lang := xmlLang(start, "")
|
|
lang := xmlLang(start, "")
|
|
|
for {
|
|
for {
|
|
|
t, err := next(d)
|
|
t, err := next(d)
|
|
@@ -409,15 +409,15 @@ func (ps *proppatchProps) UnmarshalXML(d *xml.Decoder, start xml.StartElement) e
|
|
|
return err
|
|
return err
|
|
|
}
|
|
}
|
|
|
switch elem := t.(type) {
|
|
switch elem := t.(type) {
|
|
|
- case xml.EndElement:
|
|
|
|
|
|
|
+ case ixml.EndElement:
|
|
|
if len(*ps) == 0 {
|
|
if len(*ps) == 0 {
|
|
|
return fmt.Errorf("%s must not be empty", start.Name.Local)
|
|
return fmt.Errorf("%s must not be empty", start.Name.Local)
|
|
|
}
|
|
}
|
|
|
return nil
|
|
return nil
|
|
|
- case xml.StartElement:
|
|
|
|
|
|
|
+ case ixml.StartElement:
|
|
|
p := Property{
|
|
p := Property{
|
|
|
- XMLName: t.(xml.StartElement).Name,
|
|
|
|
|
- Lang: xmlLang(t.(xml.StartElement), lang),
|
|
|
|
|
|
|
+ XMLName: t.(ixml.StartElement).Name,
|
|
|
|
|
+ Lang: xmlLang(t.(ixml.StartElement), lang),
|
|
|
}
|
|
}
|
|
|
err = d.DecodeElement(((*xmlValue)(&p.InnerXML)), &elem)
|
|
err = d.DecodeElement(((*xmlValue)(&p.InnerXML)), &elem)
|
|
|
if err != nil {
|
|
if err != nil {
|
|
@@ -431,29 +431,29 @@ func (ps *proppatchProps) UnmarshalXML(d *xml.Decoder, start xml.StartElement) e
|
|
|
// http://www.webdav.org/specs/rfc4918.html#ELEMENT_set
|
|
// http://www.webdav.org/specs/rfc4918.html#ELEMENT_set
|
|
|
// http://www.webdav.org/specs/rfc4918.html#ELEMENT_remove
|
|
// http://www.webdav.org/specs/rfc4918.html#ELEMENT_remove
|
|
|
type setRemove struct {
|
|
type setRemove struct {
|
|
|
- XMLName xml.Name
|
|
|
|
|
|
|
+ XMLName ixml.Name
|
|
|
Lang string `xml:"xml:lang,attr,omitempty"`
|
|
Lang string `xml:"xml:lang,attr,omitempty"`
|
|
|
Prop proppatchProps `xml:"DAV: prop"`
|
|
Prop proppatchProps `xml:"DAV: prop"`
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// http://www.webdav.org/specs/rfc4918.html#ELEMENT_propertyupdate
|
|
// http://www.webdav.org/specs/rfc4918.html#ELEMENT_propertyupdate
|
|
|
type propertyupdate struct {
|
|
type propertyupdate struct {
|
|
|
- XMLName xml.Name `xml:"DAV: propertyupdate"`
|
|
|
|
|
|
|
+ XMLName ixml.Name `xml:"DAV: propertyupdate"`
|
|
|
Lang string `xml:"xml:lang,attr,omitempty"`
|
|
Lang string `xml:"xml:lang,attr,omitempty"`
|
|
|
SetRemove []setRemove `xml:",any"`
|
|
SetRemove []setRemove `xml:",any"`
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
func readProppatch(r io.Reader) (patches []Proppatch, status int, err error) {
|
|
func readProppatch(r io.Reader) (patches []Proppatch, status int, err error) {
|
|
|
var pu propertyupdate
|
|
var pu propertyupdate
|
|
|
- if err = xml.NewDecoder(r).Decode(&pu); err != nil {
|
|
|
|
|
|
|
+ if err = ixml.NewDecoder(r).Decode(&pu); err != nil {
|
|
|
return nil, http.StatusBadRequest, err
|
|
return nil, http.StatusBadRequest, err
|
|
|
}
|
|
}
|
|
|
for _, op := range pu.SetRemove {
|
|
for _, op := range pu.SetRemove {
|
|
|
remove := false
|
|
remove := false
|
|
|
switch op.XMLName {
|
|
switch op.XMLName {
|
|
|
- case xml.Name{Space: "DAV:", Local: "set"}:
|
|
|
|
|
|
|
+ case ixml.Name{Space: "DAV:", Local: "set"}:
|
|
|
// No-op.
|
|
// No-op.
|
|
|
- case xml.Name{Space: "DAV:", Local: "remove"}:
|
|
|
|
|
|
|
+ case ixml.Name{Space: "DAV:", Local: "remove"}:
|
|
|
for _, p := range op.Prop {
|
|
for _, p := range op.Prop {
|
|
|
if len(p.InnerXML) > 0 {
|
|
if len(p.InnerXML) > 0 {
|
|
|
return nil, http.StatusBadRequest, errInvalidProppatch
|
|
return nil, http.StatusBadRequest, errInvalidProppatch
|