Index: openacs-4/packages/oacs-dav/tcl/tDAV-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/oacs-dav/tcl/tDAV-procs.tcl,v diff -u -r1.19.2.4 -r1.19.2.5 --- openacs-4/packages/oacs-dav/tcl/tDAV-procs.tcl 28 Dec 2021 16:58:27 -0000 1.19.2.4 +++ openacs-4/packages/oacs-dav/tcl/tDAV-procs.tcl 25 Sep 2022 20:54:41 -0000 1.19.2.5 @@ -113,18 +113,7 @@ # returns xml text of request proc tdav::read_xml {} { - set fp "" - while {$fp eq ""} { - set tmpfile [ad_tmpnam] - set fp [ns_openexcl $tmpfile] - } - #fconfigure $fp -translation binary -encoding binary - # fconfigure $fp -encoding utf-8 - ns_conncptofp $fp - seek $fp 0 - set xml [read $fp] - close $fp - file delete -- $tmpfile + set xml [ns_getcontent -as_file false -binary false] ns_log debug "\n-----tdav::read_xml XML = -----\n $xml \n ----- end ----- \n " return $xml } @@ -143,16 +132,11 @@ # file written including contents of list proc tdav::dbm_write_list {uri list} { - set file [tdav::get_prop_file $uri] - if {[catch {set f [open $file w]} err]} { - # probably no parent dir, create it: - file mkdir [file dirname $file] - # open again: - set f [open $file w] - } - fconfigure $f -encoding utf-8 - puts $f $list - close $f + regsub {^/} $uri {} uri + ad_set_client_property \ + -persistent t \ + -session_id 0 \ + oacs-dav $uri $list } # tdav::get_prop_file @@ -229,9 +213,11 @@ # File containing user properties for URI is deleted proc tdav::delete_props {uri} { - set entry [tdav::get_prop_file $uri] - catch {[file delete -force -- $entry]} err - return err + regsub {^/} $uri {} uri + ad_set_client_property \ + -persistent t \ + -session_id 0 \ + oacs-dav $uri "" } # tdav::move_props @@ -247,9 +233,20 @@ # to the relative location for newuri proc tdav::move_props {uri newuri} { - set entry [tdav::get_prop_file $uri] - set dest [tdav::get_prop_file $newuri] - catch {[file copy -force -- $entry $dest]} + regsub {^/} $uri {} uri + regsub {^/} $newuri {} newuri + set props [ad_get_client_property \ + -session_id 0 \ + -default "" \ + oacs-dav $uri] + ad_set_client_property \ + -persistent t \ + -session_id 0 \ + oacs-dav $newuri $props + ad_set_client_property \ + -persistent t \ + -session_id 0 \ + oacs-dav $uri "" } # tdav::copy_props @@ -266,9 +263,16 @@ # location corresponding to newuri. proc tdav::copy_props {uri newuri} { - set entry [tdav::get_prop_file $uri] - set dest [tdav::get_prop_file $newuri] - catch {[file copy -force -- $entry $dest]} + regsub {^/} $uri {} uri + regsub {^/} $newuri {} newuri + set props [ad_get_client_property \ + -session_id 0 \ + -default "" \ + oacs-dav $uri] + ad_set_client_property \ + -persistent t \ + -session_id 0 \ + oacs-dav $newuri $props } proc tdav::write_lock {uri list} { @@ -278,11 +282,11 @@ } proc tdav::dbm_read_list {uri} { - set f [open [tdav::get_prop_file $uri] {CREAT RDONLY}] - fconfigure $f -encoding utf-8 - set s [read $f] - close $f - return $s + regsub {^/} $uri {} uri + return [ad_get_client_property \ + -session_id 0 \ + -default "" \ + oacs-dav $uri] } # tdav::read_lock @@ -532,27 +536,13 @@ return filter_return } - set setl [$xd getElementsByTagName "*set"] - set rml [$xd getElementsByTagName "*remove"] + set property_update [$xd documentElement] + set prop_req [list] - foreach node $rml { - set p [[$node childNodes] childNodes] - # we use localname because we always resolve the URI namespace - # for the tag name - set ns [$p namespaceURI] - if {$ns eq ""} { - set name [$p nodeName] - } else { - set name [$p localName] - } - if {[catch {set value [[$p childNodes] nodeValue]}]} { - set value "" - } - lappend prop_req remove [list [list $ns $name] $value] - } - foreach node $setl { - set p [[$node childNodes] childNodes] + foreach node [$property_update childNodes] { + regsub {^.*:} [$node nodeName] {} operation + set p [[$node firstChild] firstChild] # we use localname because we always resolve the URI namespace # for the tag name set ns [$p namespaceURI] @@ -564,7 +554,7 @@ if {[catch {set value [[$p childNodes] nodeValue]}]} { set value "" } - lappend prop_req set [list [list $ns $name] $value] + lappend prop_req $operation [list [list $ns $name] $value] } tdav::conn -set prop_req $prop_req @@ -1340,6 +1330,11 @@ # we don't have to check the tdav fs props or lock properties # they should already be there + set request_properties [list] + foreach pr [tdav::conn prop_req] { + lappend request_properties $pr "" + } + set d [dom createDocumentNS "DAV:" "D:multistatus"] set n [$d documentElement] $n setAttribute "xmlns:b" "urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" @@ -1350,17 +1345,24 @@ $n appendChild $r set h [$d createElement D:href] $h appendChild [$d createTextNode ${href}] - set propstat [$d createElement D:propstat] - set prop [$d createElement D:prop] $r appendChild $h - $r appendChild $propstat - foreach {i j} $props { - # interestingly enough, adding the namespace here to the prop is fine + # + # We will return both the properties we have and the + # properties that were requested (as per RFC). When the + # requested property does not exist, 404 will be returned in + # the status. + # + foreach {i j} [dict merge $request_properties $props] { + set propstat [$d createElement D:propstat] + set prop [$d createElement D:prop] + $r appendChild $propstat + + # interestingly enough, adding the namespace here to the prop is fine lassign $i ns name if {"D" ne $ns && "ns0" ne $ns } { - # for user properties set the namespace explicitly in - # the tag + # for user properties set the namespace explicitly in + # the tag if {$ns ne ""} { set pnode [$d createElementNS $ns $name] } else { @@ -1394,73 +1396,75 @@ $prop appendChild $pnode - } + set supportedlock [$d createElement D:supportedlock] - set supportedlock [$d createElement D:supportedlock] + set lockentry [$d createElement D:lockentry] + set lockscope [$d createElement D:lockscope] + set exclusive [$d createElement D:exclusive] + set locktype [$d createElement D:locktype] + set write_type [$d createElement D:write] - set lockentry [$d createElement D:lockentry] - set lockscope [$d createElement D:lockscope] - set exclusive [$d createElement D:exclusive] - set locktype [$d createElement D:locktype] - set write_type [$d createElement D:write] + $supportedlock appendChild $lockentry - $supportedlock appendChild $lockentry + $locktype appendChild $write_type + $lockscope appendChild $exclusive - $locktype appendChild $write_type - $lockscope appendChild $exclusive + $lockentry appendChild $lockscope + $lockentry appendChild $locktype - $lockentry appendChild $lockscope - $lockentry appendChild $locktype + $prop appendChild $supportedlock - $prop appendChild $supportedlock + set lockdiscovery [$d createElement D:lockdiscovery] + regsub {https?://[^/]+/} $href {/} local_uri + if {[file exists [tdav::get_lock_file $local_uri]]} { + # check for timeout + set lockinfo [tdav::read_lock $local_uri] + set lock_timeout_left [tdav::lock_timeout_left [lindex $lockinfo 4] [lindex $lockinfo 6]] + if {$lock_timeout_left > 0} { - set lockdiscovery [$d createElement D:lockdiscovery] - regsub {https?://[^/]+/} $href {/} local_uri - if {[file exists [tdav::get_lock_file $local_uri]]} { - # check for timeout - set lockinfo [tdav::read_lock $local_uri] - set lock_timeout_left [tdav::lock_timeout_left [lindex $lockinfo 4] [lindex $lockinfo 6]] - if {$lock_timeout_left > 0} { + set activelock [$d createElement D:activelock] + set locktype [$d createElement D:locktype] + set lockscope [$d createElement D:lockscope] + set depth [$d createElement D:depth] + set owner [$d createElement D:owner] + set timeout [$d createElement D:timeout] + set locktoken [$d createElement D:locktoken] + set locktokenhref [$d createElement D:href] - set activelock [$d createElement D:activelock] - set locktype [$d createElement D:locktype] - set lockscope [$d createElement D:lockscope] - set depth [$d createElement D:depth] - set owner [$d createElement D:owner] - set timeout [$d createElement D:timeout] - set locktoken [$d createElement D:locktoken] - set locktokenhref [$d createElement D:href] + $locktype appendChild [$d createElement D:[lindex $lockinfo 0]] + $lockscope appendChild [$d createElement D:[lindex $lockinfo 1]] + $depth appendChild [$d createTextNode [lindex $lockinfo 5]] - $locktype appendChild [$d createElement D:[lindex $lockinfo 0]] - $lockscope appendChild [$d createElement D:[lindex $lockinfo 1]] - $depth appendChild [$d createTextNode [lindex $lockinfo 5]] + $timeout appendChild [$d createTextNode Second-$lock_timeout_left] + $owner appendChild [$d createTextNode [lindex $lockinfo 2]] + $locktokenhref appendChild [$d createTextNode [lindex $lockinfo 3]] + $locktoken appendChild $locktokenhref - $timeout appendChild [$d createTextNode Second-$lock_timeout_left] - $owner appendChild [$d createTextNode [lindex $lockinfo 2]] - $locktokenhref appendChild [$d createTextNode [lindex $lockinfo 3]] - $locktoken appendChild $locktokenhref + $activelock appendChild $locktype + $activelock appendChild $lockscope + $activelock appendChild $depth + $activelock appendChild $timeout + $activelock appendChild $owner + $activelock appendChild $locktoken - $activelock appendChild $locktype - $activelock appendChild $lockscope - $activelock appendChild $depth - $activelock appendChild $timeout - $activelock appendChild $owner - $activelock appendChild $locktoken - - $lockdiscovery appendChild $activelock + $lockdiscovery appendChild $activelock + } } - } - $prop appendChild $lockdiscovery - $propstat appendChild $prop + $prop appendChild $lockdiscovery + $propstat appendChild $prop - set status [$d createElement D:status] - set status_text [$d createTextNode "HTTP/1.1 200 OK"] + set status [$d createElement D:status] + set status_code [expr { + [dict exists $props $i] ? + "HTTP/1.1 200 OK" : "HTTP/1.1 404 Not Found" + }] + set status_text [$d createTextNode $status_code] - $status appendChild $status_text - $propstat appendChild $status + $status appendChild $status_text + $propstat appendChild $status + } - }