(:
: 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) {
};
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
};
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}
}