(: : eXide - web-based XQuery IDE : : Copyright (C) 2011 Wolfgang Meier : : This program is free software: you can redistribute it and/or modify : it under the terms of the GNU General Public License as published by : the Free Software Foundation, either version 3 of the License, or : (at your option) any later version. : : This program is distributed in the hope that it will be useful, : but WITHOUT ANY WARRANTY; without even the implied warranty of : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the : GNU General Public License for more details. : : You should have received a copy of the GNU General Public License : along with this program. If not, see . :) xquery version "3.0"; declare namespace json="http://www.json.org"; declare option exist:serialize "method=json media-type=text/javascript"; declare function local:sub-collections($root as xs:string, $children as xs:string*, $user as xs:string) { for $child in $children let $processChild := local:collections(concat($root, '/', $child), $child, $user) where exists($processChild) order by $child ascending return { $processChild } }; declare function local:collections($root as xs:string, $child as xs:string, $user as xs:string) { if (sm:has-access(xs:anyURI($root), "x")) then let $children := xmldb:get-child-collections($root) let $canWrite := (: local:canWrite($root, $user) :) sm:has-access(xs:anyURI($root), "w") return if (sm:has-access(xs:anyURI($root), "r")) then ( {xmldb:decode-uri(xs:anyURI($child))}, true, {xmldb:decode-uri(xs:anyURI($root))}, {if ($canWrite) then 'true' else 'false'}, {if ($canWrite) then 'writable' else 'readable'}, if (exists($children)) then local:sub-collections($root, $children, $user) else () ) else () else () }; declare function local:list-collection-contents($collection as xs:string, $user as xs:string) { let $subcollections := for $child in xmldb:get-child-collections($collection) where sm:has-access(xs:anyURI(concat($collection, "/", $child)), "r") return concat("/", $child) let $resources := for $r in xmldb:get-child-resources($collection) where sm:has-access(xs:anyURI(concat($collection, "/", $r)), "r") return $r for $resource in ($subcollections, $resources) order by $resource ascending return $resource }; declare function local:resources($collection as xs:string, $user as xs:string) { let $start := number(request:get-parameter("start", 0)) + 1 let $endParam := number(request:get-parameter("end", 1000000)) + 1 let $resources := local:list-collection-contents($collection, $user) let $count := count($resources) + 1 let $end := if ($endParam gt $count) then $count else $endParam let $subset := subsequence($resources, $start, $end - $start + 1) let $parent := $start = 1 and $collection != "/db" return {count($resources) + (if ($parent) then 1 else 0)} { if ($parent) then .. { sm:has-access(xs:anyURI($collection), "w") } true else () } { for $resource in $subset let $isCollection := starts-with($resource, "/") let $path := if ($isCollection) then concat($collection, $resource) else concat($collection, "/", $resource) where sm:has-access(xs:anyURI($path), "r") order by $resource ascending return let $permissions := if ($isCollection) then xmldb:permissions-to-string(xmldb:get-permissions($path)) else xmldb:permissions-to-string(xmldb:get-permissions($collection, $resource)) let $owner := if ($isCollection) then xmldb:get-owner($path) else xmldb:get-owner($collection, $resource) let $group := if ($isCollection) then xmldb:get-group($path) else xmldb:get-group($collection, $resource) let $lastMod := let $date := if ($isCollection) then xmldb:created($path) else xmldb:created($collection, $resource) return if (xs:date($date) = current-date()) then format-dateTime($date, "Today [H00]:[m00]:[s00]") else format-dateTime($date, "[M00]/[D00]/[Y0000] [H00]:[m00]:[s00]") let $canWrite := sm:has-access(xs:anyURI($collection || "/" || $resource), "w") return {xmldb:decode-uri(if ($isCollection) then substring-after($resource, "/") else $resource)} {$permissions} {$owner} {$group} {$lastMod} {$canWrite} {$isCollection} } }; declare function local:create-collection($collName as xs:string, $user as xs:string) { let $parent := xmldb:encode-uri(request:get-parameter("collection", "/db")) return if (sm:has-access(xs:anyURI($parent), "w")) then let $null := xmldb:create-collection($parent, $collName) return else You are not allowed to write to collection {xmldb:decode-uri(xs:anyURI($parent))} }; declare function local:delete-collection($collName as xs:string, $user as xs:string) { if (sm:has-access(xs:anyURI($collName), "w")) then let $null := xmldb:remove($collName) return else You are not allowed to write to collection {xmldb:decode-uri(xs:anyURI($collName))} }; declare function local:delete-resource($collection as xs:string, $resource as xs:string+, $user as xs:string) { let $canWrite := sm:has-access(xs:anyURI($collection || "/" || $resource), "w") and sm:has-access(xs:anyURI($collection), "w") return if ($canWrite) then let $removed := xmldb:remove($collection, $resource) return else }; declare function local:delete($collection as xs:string, $selection as xs:string+, $user as xs:string) { let $result := for $docOrColl in $selection let $docOrColl := xmldb:encode($docOrColl) let $path := if (starts-with($docOrColl, "/")) then $docOrColl else $collection || "/" || $docOrColl let $isCollection := xmldb:collection-available($path) let $response := if ($isCollection) then local:delete-collection($path, $user) else local:delete-resource($collection, $docOrColl, $user) return $response return if ($result/@status = "fail") then Deletion of the following items failed: {string-join($result/@item, ", ")}. else }; declare function local:copyOrMove($operation as xs:string, $target as xs:string, $sources as xs:string+, $user as xs:string) { if (sm:has-access(xs:anyURI($target), "w")) then for $source in $sources let $isCollection := xmldb:collection-available($source) return try { if ($isCollection) then let $null := switch ($operation) case "move" return xmldb:move($source, $target) default return xmldb:copy($source, $target) return else let $split := text:groups($source, "^(.*)/([^/]+)$") let $null := switch ($operation) case "move" return xmldb:move($split[2], $target, $split[3]) default return xmldb:copy($split[2], $target, $split[3]) return } catch * { { $err:description } } else You are not allowed to write to collection {xmldb:decode-uri(xs:anyURI($target))} }; declare function local:rename($collection as xs:string, $source as xs:string) { let $target := request:get-parameter("target", ()) let $isCollection := xmldb:collection-available($collection || "/" || $source) return try { if ($isCollection) then let $null := xmldb:rename($collection || "/" || $source, $target) return else let $null := xmldb:rename($collection, $source, $target) return } catch * { { $err:description } } }; declare %private function local:merge-properties($maps as map(*)+) { map:new( for $key in map:keys($maps[1]) let $values := distinct-values(for $map in $maps return $map($key)) return map:entry($key, if (count($values) = 1) then $values[1] else "") ) }; declare %private function local:get-property-map($resource as xs:string) as map(*) { let $isCollection := xmldb:collection-available($resource) return if ($isCollection) then map { "owner" := xmldb:get-owner($resource), "group" := xmldb:get-group($resource), "last-modified" := format-dateTime(xmldb:created($resource), "[MNn] [D00] [Y0000] [H00]:[m00]:[s00]"), "permissions" := xmldb:permissions-to-string(xmldb:get-permissions($resource)), "mime" := xmldb:get-mime-type(xs:anyURI($resource)) } else let $components := text:groups($resource, "^(.*)/([^/]+)$") return map { "owner" := xmldb:get-owner($components[2], $components[3]), "group" := xmldb:get-group($components[2], $components[3]), "last-modified" := format-dateTime(xmldb:created($components[2], $components[3]), "[MNn] [D00] [Y0000] [H00]:[m00]:[s00]"), "permissions" := xmldb:permissions-to-string(xmldb:get-permissions($components[2], $components[3])), "mime" := xmldb:get-mime-type(xs:anyURI($resource)) } }; declare %private function local:get-properties($resources as xs:string*) as map(*) { local:merge-properties(for $resource in $resources return local:get-property-map($resource)) }; declare %private function local:checkbox($name as xs:string, $test as xs:boolean) { { if ($test) then attribute checked { 'checked' } else () } }; declare %private function local:get-permissions($perms as xs:string) {
User Group World
{ local:checkbox("ur", substring($perms, 1, 1) = "r") } read { local:checkbox("gr", substring($perms, 4, 1) = "r") } read { local:checkbox("wr", substring($perms, 7, 1) = "r") } read
{ local:checkbox("uw", substring($perms, 2, 1) = "w") } write { local:checkbox("gw", substring($perms, 5, 1) = "w") } write { local:checkbox("ww", substring($perms, 8, 1) = "w") } write
{ local:checkbox("ux", substring($perms, 3, 1) = "x") } execute { local:checkbox("gx", substring($perms, 6, 1) = "x") } execute { local:checkbox("wx", substring($perms, 9, 1) = "x") } execute
}; declare %private function local:get-users() { distinct-values( for $group in sm:get-groups() return sm:get-group-members($group) ) }; declare function local:edit-properties($resources as xs:string*) { util:declare-option("exist:serialize", "media-type=text/html method=html5"), let $props := local:get-properties($resources) let $users := local:get-users() return
{ if ($props("mime") != "") then
else () }
Permissions { local:get-permissions($props("permissions")) }
}; declare %private function local:permissions-from-form() { string-join( for $type in ("u", "g", "w") for $perm in ("r", "w", "x") let $param := request:get-parameter($type || $perm, ()) return if ($param) then $perm else "-", "" ) }; declare function local:change-properties($resources as xs:string*) { let $owner := request:get-parameter("owner", ()) let $group := request:get-parameter("group", ()) for $resource in $resources let $uri := xs:anyURI($resource) return ( sm:chown($uri, $owner), sm:chgrp($uri, $group), sm:chmod($uri, local:permissions-from-form()) ), }; let $deleteCollection := request:get-parameter("remove", ()) let $deleteResource := request:get-parameter("remove[]", ()) let $properties := request:get-parameter("properties[]", ()) let $modify := request:get-parameter("modify[]", ()) let $copy := request:get-parameter("copy[]", ()) let $move := request:get-parameter("move[]", ()) let $rename := request:get-parameter("rename", ()) let $createCollection := request:get-parameter("create", ()) let $view := request:get-parameter("view", "c") let $collection := request:get-parameter("root", "/db") let $collName := replace($collection, "^.*/([^/]+$)", "$1") let $user := if (request:get-attribute('org.exist.login.user')) then request:get-attribute('org.exist.login.user') else "guest" return try { if (exists($copy)) then let $result := local:copyOrMove("copy", xmldb:encode-uri($collection), $copy, $user) return ($result[@status = "fail"], $result[1])[1] else if (exists($move)) then let $result := local:copyOrMove("move", xmldb:encode-uri($collection), $move, $user) return ($result[@status = "fail"], $result[1])[1] else if (exists($rename)) then local:rename($collection, $rename) else if (exists($deleteResource)) then local:delete(xmldb:encode-uri($collection), $deleteResource, $user) else if (exists($properties)) then local:edit-properties($properties) else if (exists($modify)) then local:change-properties($modify) else if ($createCollection) then local:create-collection(xmldb:encode-uri($createCollection), $user) else if ($view eq "c") then {local:collections(xmldb:encode-uri($collection), xmldb:encode-uri($collName), $user)} else local:resources(xmldb:encode-uri($collection), $user) } catch * { {$err:description} }