Patch title: Release 91 bulk changes
Abstract:
File: /protocol/http/webdav.pli
Key:
    Removed line
    Added line
module "/pliant/language/unsafe.pli"
module "/pliant/language/stream.pli"
module "/pliant/util/encoding/date.pli"
module "/pliant/util/encoding/http.pli"
module "/pliant/protocol/http/server.pli"

constant strictly_conforming false

(gvar TraceSlot webdav_log) configure "WebDav"


method r webdav_depth -> d
  arg HttpRequest r ; arg Int d
  d := undefined
  var Pointer:Arrow c :> r:query_log first
  while c<>null
    var Pointer:Str s :> c map Str
    if (s parse acword:"Depth" ":" (var Int i))
      d := i
    c :> r:query_log next c


method page webdav_propfind info dir
  arg_rw HtmlPage page ; arg FileInfo info ; arg Array:FileInfo dir
  var Link:HttpRequest request :> page http_request
  page reset_http_answer
  if info=undefined
    request send_header "status [dq]404 Not found[dq] size 0 static"
    request send_footer
    return
  var List:Str props :=  var List:Str empty_list ; var List:Str prop_ns :=  var List:Str empty_list
  var (Dictionary Str Str) namespaces := var (Dictionary Str Str) empty_dict
  var CBool prop := false
  var Link:Stream query :> request query_stream
  while not query:atend
    var Str l := query readline
    webdav_log trace l
    while (l parse "<" any:(var Str tag) ">" any:(var Str remain))
      if (tag parse any:(var Str base) _ any:(var Str options))
        tag := base
      else
        options := ""
      if (tag parse any:(var Str base) "/")
        tag := base
      if (tag parse "/" any ":" any:(var Str base))
        tag := "/"+base
      eif (tag parse any ":" any:(var Str base))
        tag := base
      if tag="/prop"
        prop := false
      var Str ns := options option "xmlns=" Str
      if not exists:(namespaces first ns)
        namespaces insert ns "ns"+(string namespaces:size)
      if prop
        props += tag ; prop_ns += ns
      if tag="prop"
        prop := true
      l := remain
  webdav_log trace ""
  if not (exists props:first)
    props += "resourcetype" ; prop_ns += ""
    props += "getlastmodified" ; prop_ns += ""
    props += "getcontentlength" ; prop_ns += ""
  request send_header "status [dq]207 Multi-Status[dq] mime [dq]text/xml; charset=[lb]dq[rb]utf-8[lb]dq[rb][dq] static compressed"
  request send_header "status [dq]207 Multi-Status[dq] mime [dq]text/xml; charset=[lb]dq[rb]utf-8[lb]dq[rb][dq] compressed static"
  var Link:Stream answer :> request answer_stream
  answer writeline "<?xml version=[dq]1.0[dq] encoding=[dq]utf-8[dq] ?>"
  webdav_log trace "<?xml version=[dq]1.0[dq] encoding=[dq]utf-8[dq] ?>"
  var Str l := "<D:multistatus xmlns:D=[dq]DAV:[dq]"
  each pns namespaces
    l += " xmlns:"+pns+"=[dq]"+(shunt (namespaces key pns)<>"" (namespaces key pns) "DAV:")+"[dq]"
  l += ">"
  answer writeline l
  webdav_log trace l
  for (var Int i) -1 dir:size-1
    var Str href ; var Pointer:FileInfo f
    if i=(-1)
      href := request encoded_path
      f :> info
    else
      href := request:encoded_path
      href := request encoded_path
      if (href href:len-1)<>"/"
        href += "/"
      href += http_encode dir:i:name
      f :> dir i
    answer writeline "<D:response>"
    webdav_log trace "<D:response>"
    answer writeline "<D:href>"+href+"</D:href>"
    webdav_log trace "<D:href>"+href+"</D:href>"
    for (var Int lap) 0 1
      var CBool some := false
      var Pointer:Str p :> props first ; var Pointer:Str pns :> prop_ns first
      while exists:p
        var Pointer:Str nsid :> namespaces first pns ; var Str tag := ""
        if f=failure
          void
        eif p="resourcetype"
          tag := shunt f:is_directory "<D:resourcetype><D:collection/></D:resourcetype>" "<D:resourcetype/>"
        eif p="getlastmodified"
          tag := "<D:getlastmodified>"+(rfc1123_date f:datetime)+"</D:getlastmodified>"
        eif p="getcontentlength"
          if not f:is_directory
            tag := "<D:getcontentlength>"+(string f:size)+"</D:getcontentlength>"
        eif p="executable"
          if not f:is_directory
            var Int mode := f:options option "mode" Int
            if mode=defined
              if strictly_conforming
                tag := "<"+nsid+":executable>"+(shunt (mode .and. 64)<>0 "T" "F")+"</"+nsid+":executable>"
              else # davfs2 does not check the property value, just it's presence
                if (mode .and. 64)<>0
                  tag := "<"+nsid+":executable>T</"+nsid+":executable>"
        if lap=1
          if tag<>""
            tag := ""
          eif exists:nsid
            tag := "<"+nsid+":"+p+"/>"
        if tag<>""
          if not some
            answer writeline "<D:propstat>"
            webdav_log trace "<D:propstat>"
            answer writeline "<D:prop>"
            webdav_log trace "<D:prop>"
            some := true
          answer writeline tag
          webdav_log trace tag
        p :> props next p ; pns :> prop_ns next pns
      if some
        answer writeline "</D:prop>"
        webdav_log trace "</D:prop>"
        answer writeline "<D:status>HTTP/1.1 "+(shunt lap=0 "200 OK" "404 Not Found")+"</D:status>"
        webdav_log trace "<D:status>HTTP/1.1 "+(shunt lap=0 "200 OK" "404 Not Found")+"</D:status>"
        answer writeline "</D:propstat>"
        webdav_log trace "</D:propstat>"
    answer writeline "</D:response>"
    webdav_log trace "</D:response>"
  answer writeline "</D:multistatus>"
  webdav_log trace "</D:multistatus>"
  webdav_log trace ""
  request send_footer


export '. webdav_depth' '. webdav_propfind'