--
-- $Id: DET_CatFilter.sql,v 1.2 2007/03/28 10:48:50 source Exp $
--
-- This file is part of the OpenLink Software Virtuoso Open-Source (VOS)
-- project.
--
-- Copyright (C) 1998-2006 OpenLink Software
--
-- This project 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; only version 2 of the License, dated June 1991.
--
-- 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, write to the Free Software Foundation, Inc.,
-- 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
--
use DB
;
-- CatFilter ID structure:
-- for categories:
-- vector (UNAME'CatFilter', detcol_id, null, schema_uri, vector (prop1uri, prop1catid, prop1decodedcatvalue, prop1crop, ..., propNuri, propNcatid, propNdecodedcatvalue, propNcrop))
-- for resources:
-- vector (UNAME'CatFilter', detcol_id, original_resource_id, schema_uri, vector (prop1uri, prop1catid, prop1decodedcatvalue, prop1crop, ..., propNuri, propNcatid, propNdecodedcatvalue, propNcrop))
create function "CatFilter_DAV_AUTHENTICATE" (in id any, in what char(1), in req varchar, in auth_uname varchar, in auth_pwd varchar, in auth_uid integer)
{
declare cfc_id integer;
declare rfc_spath, tmp_perms varchar;
declare rfc_list_cond, rfc_del_action any;
declare rc, spath_id, n integer;
-- dbg_obj_princ ('CatFilter_DAV_AUTHENTICATE (', id, what, req, auth_uname, auth_pwd, auth_uid, ')');
rfc_spath := null;
if (DAV_HIDE_ERROR ("CatFilter_GET_CONDITION" (id[1], cfc_id, rfc_spath, rfc_list_cond, rfc_del_action)) is null)
return -1;
if (not ('110' like req))
return -13; -- Internals of ResFilter are not executable.
spath_id := DAV_SEARCH_ID (rfc_spath, 'C');
if (not isinteger (spath_id))
return -13;
if (DAV_HIDE_ERROR (spath_id) is null)
return spath_id;
rc := DAV_AUTHENTICATE (spath_id, 'C', req, auth_uname, auth_pwd, auth_uid);
if (DAV_HIDE_ERROR (rc) is null)
return rc;
if ('C' = what)
{
n := length (id[4]);
if ((n=0) or (mod (n, 4) = 2))
tmp_perms := '100';
else if (length (rfc_del_action) < length (rfc_list_cond))
{
-- dbg_obj_princ ('del_action = ', rfc_del_action, 'rfc_list_cond = ', rfc_list_cond);
tmp_perms := '100';
}
else
tmp_perms := '110';
if (not (tmp_perms like req))
return -13;
return auth_uid;
}
else if ('R' = what)
{
return DAV_AUTHENTICATE (id [2], 'R', req, auth_uname, auth_pwd, auth_uid);
}
return -14;
}
;
create function "CatFilter_GET_CONDITION" (in detcol_id integer, out cfc_id integer, out rfc_spath varchar, out rfc_list_cond any, out rfc_del_action any)
{
-- dbg_obj_princ ('CatFilter_GET_CONDITION (', detcol_id, '...)');
whenever not found goto nf;
if (isarray (detcol_id))
return -20;
select cast ("ResFilter_NORM" (PROP_VALUE) as integer) into cfc_id from WS.WS.SYS_DAV_PROP where PROP_NAME = 'virt:CatFilter-ID' and PROP_PARENT_ID = detcol_id and PROP_TYPE = 'C';
select "ResFilter_NORM" (PROP_VALUE) into rfc_spath from WS.WS.SYS_DAV_PROP where PROP_NAME = 'virt:ResFilter-SearchPath' and PROP_PARENT_ID = detcol_id and PROP_TYPE = 'C';
select "ResFilter_DECODE_FILTER" (PROP_VALUE) into rfc_list_cond from WS.WS.SYS_DAV_PROP where PROP_NAME = 'virt:ResFilter-ListCond' and PROP_PARENT_ID = detcol_id and PROP_TYPE = 'C';
select "ResFilter_DECODE_FILTER" (PROP_VALUE) into rfc_del_action from WS.WS.SYS_DAV_PROP where PROP_NAME = 'virt:ResFilter-DelAction' and PROP_PARENT_ID = detcol_id and PROP_TYPE = 'C';
return 0;
nf:
return -1;
}
;
create function "CatFilter_ENCODE_CATVALUE" (in val varchar) returns varchar
{
declare ses any;
declare ctr, len integer;
declare lastspace integer;
if (val is null)
return '! property is not set !';
if (__tag (val) = 230)
val := cast (val as varchar);
ses := string_output ();
len := length (val);
if (len > 70)
{
val := subseq (val, 0, 65);
lastspace := strrchr (val, ' ');
if (lastspace is not null)
val := subseq (val, 0, lastspace) || ' . . .';
else
val := val || '...';
}
if (len = 0)
return '! empty property value !';
len := length (val);
for (ctr := 0; ctr < len; ctr := ctr + 1)
{
declare ch integer;
ch := val [ctr];
if ((ch < 32) or (ch = 47) or (ch = 92) or (ch = 37) or (ch = 58) or ((ch = 40) and (ctr = 0)))
http (sprintf ('^%02x', ch), ses);
else
http (chr (ch), ses);
}
return string_output_string (ses);
}
;
create function "CatFilter_DECODE_CATVALUE" (in catval varchar, out crop integer)
{
declare val varchar;
declare catvallen integer;
if ('! empty property value !' = catval)
{
crop := 0;
return '';
}
if ('! property is not set !' = catval)
{
crop := 4;
return null;
}
catvallen := length (catval);
if ((catvallen >= 6) and (subseq (catval, catvallen - 6) = ' . . .'))
{
crop := 1;
catvallen := catvallen - 6;
catval := subseq (catval, 0, catvallen);
}
else
if ((catvallen >= 3) and (subseq (catval, catvallen - 3) = '...'))
{
crop := 2;
catvallen := catvallen - 3;
catval := subseq (catval, 0, catvallen);
}
else
crop := 0;
val := split_and_decode (catval, 0, '^');
return val;
}
;
create function "CatFilter_PATH_PARTS_TO_FILTER" (inout path_parts any, out schema_uri varchar, out filter_data any) returns integer
{
declare prop_catnames varchar;
declare pathctr, filtctr, pathlen integer;
declare filt any;
pathlen := length (path_parts) - 1;
if (0 >= pathlen)
{
schema_uri := null;
filter_data := null;
return 0;
}
-- First of all, schema should be located.
retry_after_recomp:
whenever not found goto no_schema;
select RS_URI, deserialize (blob_to_string(RS_PROP_CATNAMES)) into schema_uri, prop_catnames from WS.WS.SYS_RDF_SCHEMAS where RS_CATNAME = path_parts[0] and RS_PROP_CATNAMES is not null;
filt := make_array (2 * (pathlen - 1), 'any');
filtctr := 0;
for (pathctr := 1; pathctr < pathlen; pathctr := pathctr + 2)
{
declare pos integer;
pos := position (path_parts [pathctr], prop_catnames, 2, 6);
if (0 = pos)
{
-- dbg_obj_princ ('CatFilter_PATH_PARTS_TO_FILTER (', path_parts, '...) failed to find catlabel ', path_parts [pathctr], ' in schema ', schema_uri);
return -2;
}
filt [filtctr] := prop_catnames [pos - 2]; -- prop URI
filt [filtctr + 1] := prop_catnames [pos]; -- prop catid
if (pathctr < (pathlen - 1))
{
declare crop_mode integer;
filt [filtctr + 2] := "CatFilter_DECODE_CATVALUE" (path_parts [pathctr + 1], crop_mode);
filt [filtctr + 3] := crop_mode;
}
filtctr := filtctr + 4;
}
filter_data := filt;
return 0;
no_schema:
-- dbg_obj_princ ('CatFilter_PATH_PARTS_TO_FILTER (', path_parts, '...) failed to find schema with catlabel ', path_parts [0]);
if (exists (select top 1 1 from WS.WS.SYS_RDF_SCHEMAS where RS_CATNAME = path_parts[0] and RS_PROP_CATNAMES is null))
{
DAV_GET_RDF_SCHEMA_N3 ((select RS_URI from WS.WS.SYS_RDF_SCHEMAS where RS_CATNAME = path_parts[0]));
goto retry_after_recomp;
}
return -1;
}
;
create procedure "CatFilter_ACC_FILTER_DATA" (inout filter any, inout filter_data any)
{
declare ctr, len integer;
len := length (filter_data);
len := len - mod (len, 4);
for (ctr := 0; ctr < len; ctr := ctr + 4)
{
declare crop_mode integer;
declare pred any;
crop_mode := filter_data [ctr + 3];
if (crop_mode = 0)
pred := vector ('RDF_VALUE', '=', filter_data [ctr + 2], 'http://local.virt/DAV-RDF', filter_data [ctr]);
else
if (crop_mode = 4)
pred := vector ('RDF_VALUE', 'is_null', 'http://local.virt/DAV-RDF', filter_data [ctr]);
else
pred := vector ('RDF_VALUE', 'starts_with', filter_data [ctr + 2], 'http://local.virt/DAV-RDF', filter_data [ctr]);
vectorbld_acc (filter, pred);
}
}
;
create function "CatFilter_DAV_SEARCH_ID_IMPL" (in detcol_id any, in path_parts any, in what char(1), inout cfc_id integer, inout rfc_spath varchar, inout rfc_list_cond any, inout rfc_del_action any, inout filter_data any) returns any
{
declare schema_catname, schema_uri, res_name, colpath, orig_fnameext varchar;
declare prop_catnames, filter, orig_id any;
declare path_len, len, ctr integer;
declare execstate, execmessage varchar;
declare execmeta, execrows any;
declare qry_text varchar;
-- dbg_obj_princ ('CatFilter_DAV_SEARCH_ID_IMPL (', detcol_id, path_parts, what, ')');
path_len := length (path_parts);
if (not (isstring (rfc_spath)))
{
if (0 > "CatFilter_GET_CONDITION" (detcol_id, cfc_id, rfc_spath, rfc_list_cond, rfc_del_action))
{
-- dbg_obj_princ ('broken filter - no items');
return -1;
}
}
if (0 = path_len)
return -1;
res_name := path_parts [path_len - 1];
if ('' = res_name)
{
if ('R' = what)
{
-- dbg_obj_princ ('resource with trailing slash - no items');
return -1;
}
}
else
{
if ('C' = what)
{
-- dbg_obj_princ ('collection without a trailing slash - no items');
return -1;
}
if (1 = path_len)
{
-- dbg_obj_princ ('resource with path length = 1 - no items at depth of schemas');
return -1;
}
if (2 = path_len)
{
-- dbg_obj_princ ('resource with path length = 2 - no items at depth of first property name under schemas');
return -1;
}
if (1 = mod (path_len, 2))
{
-- dbg_obj_princ ('resource with even path length - no items at depth of distinct values');
return -1;
}
}
if (0 > "CatFilter_PATH_PARTS_TO_FILTER" (path_parts, schema_uri, filter_data))
{
-- dbg_obj_princ ('failed to convert path parts to filter - no items');
return -1;
}
if ('C' = what)
return vector (UNAME'CatFilter', detcol_id, null, schema_uri, case (length (filter_data)) when 0 then null else filter_data end);
"ResFilter_FNSPLIT" (res_name, colpath, orig_fnameext, orig_id);
-- dbg_obj_princ ('CatFilter_DAV_SEARCH_ID_IMPL: ', path_parts, colpath, orig_fnameext, orig_id, rfc_spath, rfc_list_cond, filter_data);
if (isarray (orig_id)) -- TODO: remove this and make better processing to return -1 if path contains criteria that filter out orig_id
return orig_id;
len := length (filter_data);
vectorbld_init (filter);
"CatFilter_ACC_FILTER_DATA" (filter, filter_data);
vectorbld_concat_acc (filter, get_keyword ('', rfc_list_cond));
if (orig_id is not null)
{
if (isinteger (orig_id))
vectorbld_acc (filter, vector ('RES_ID', '=', orig_id));
else -- never happens for a while
vectorbld_acc (filter, vector ('RES_ID_SERIALIZED', '=', serialize (orig_id)));
}
vectorbld_final (filter);
qry_text := '
select top 2 RES_ID
from WS.WS.SYS_DAV_RES as _top ' || DAV_FC_PRINT_WHERE (filter, coalesce ((select COL_OWNER from WS.WS.SYS_DAV_COL where COL_ID = detcol_id), -1)) || ' and (_top.RES_NAME = ?) and (_top.RES_FULL_PATH between ? and ?)';
-- dbg_obj_princ ('about to exec:\n', qry_text, '\nrfc_spath = ', rfc_spath);
exec (qry_text,
execstate, execmessage, vector (orig_fnameext, rfc_spath, DAV_COL_PATH_BOUNDARY (rfc_spath)), 100000000, execmeta, execrows );
len := length (execrows);
if (len <> 1)
return -1;
return vector (UNAME'CatFilter', detcol_id, execrows[0][0], schema_uri, case (length (filter_data)) when 0 then null else filter_data end);
}
;
create function "CatFilter_DAV_AUTHENTICATE_HTTP" (in id any, in what char(1), in req varchar, in can_write_http integer, inout a_lines any, inout a_uname varchar, inout a_pwd varchar, inout a_uid integer, inout a_gid integer, inout _perms varchar) returns integer
{
declare cfc_id integer;
declare rfc_spath, tmp_perms varchar;
declare rfc_list_cond, rfc_del_action any;
declare rc, spath_id, n integer;
-- dbg_obj_princ ('"CatFilter_DAV_AUTHENTICATE_HTTP" (', id, what, req, can_write_http, a_lines, a_uname, a_pwd, a_uid, a_gid, _perms, ')');
rfc_spath := null;
rc := DAV_HIDE_ERROR ("CatFilter_GET_CONDITION" (id[1], cfc_id, rfc_spath, rfc_list_cond, rfc_del_action));
if (DAV_HIDE_ERROR (rc) is null)
{
-- dbg_obj_princ ('"CatFilter_DAV_AUTHENTICATE_HTTP" failed at CatFilter_GET_CONDITION, ', rc);
return rc;
}
if (not ('110' like req))
return -13; -- Internals of ResFilter/CatFilter are not executable.
spath_id := DAV_SEARCH_ID (rfc_spath, 'C');
-- dbg_obj_princ ('rfc_spath = ', rfc_spath, ', spath_id = ', spath_id);
if (not isinteger (spath_id))
return -13;
if (DAV_HIDE_ERROR (spath_id) is null)
return spath_id;
rc := DAV_AUTHENTICATE_HTTP (spath_id, 'C', req, can_write_http, a_lines, a_uname, a_pwd, a_uid, a_gid, _perms);
if (DAV_HIDE_ERROR (rc) is null)
{
return rc;
}
if ('C' = what)
{
n := length (id[4]);
if ((n=0) or (mod (n, 4) = 2))
tmp_perms := '100';
else if (length (rfc_del_action) < length (rfc_list_cond))
{
-- dbg_obj_princ ('del_action = ', rfc_del_action, 'rfc_list_cond = ', rfc_list_cond);
tmp_perms := '100';
}
else
tmp_perms := '110';
if (not (tmp_perms like req))
return -13;
return a_uid;
}
else if ('R' = what)
{
return DAV_AUTHENTICATE_HTTP (id[2], 'R', req, can_write_http, a_lines, a_uname, a_pwd, a_uid, a_gid, _perms);
}
return -14;
}
;
create function "CatFilter_DAV_GET_PARENT" (in id any, in st char(1), in path varchar) returns any
{
-- dbg_obj_princ ('CatFilter_DAV_GET_PARENT (', id, st, path, ')');
if (st = 'R')
{
id [2] := null;
return id;
}
else if (st = 'C')
{
declare vlen integer;
vlen := length (id[4]);
if (vlen = 0)
return id [1];
id [4] := subseq (id [4], 0, vlen - 1);
return id;
}
return -20;
}
;
create function "CatFilter_DAV_COL_CREATE" (in detcol_id any, in path_parts any, in permissions varchar, in uid integer, in gid integer, in auth_uid integer) returns any
{
-- dbg_obj_princ ('CatFilter_DAV_COL_CREATE (', detcol_id, path_parts, permissions, uid, gid, auth_uid, ')');
return -20;
}
;
create function "CatFilter_DAV_COL_MOUNT" (in detcol_id any, in path_parts any, in full_mount_path varchar, in mount_det varchar, in permissions varchar, in uid integer, in gid integer, in auth_uid integer) returns any
{
-- dbg_obj_princ ('CatFilter_DAV_COL_MOUNT (', detcol_id, path_parts, full_mount_path, mount_det, permissions, uid, gid, auth_uid, ')');
return -20;
}
;
create function "CatFilter_DAV_COL_MOUNT_HERE" (in parent_id any, in full_mount_path varchar, in permissions varchar, in uid integer, in gid integer, in auth_uid integer) returns any
{
-- dbg_obj_princ ('CatFilter_DAV_COL_MOUNT (', parent_id, full_mount_path, permissions, uid, gid, auth_uid, ')');
return -20;
}
;
create function "CatFilter_DAV_DELETE" (in detcol_id any, in path_parts any, in what char(1), in silent integer, in auth_uid integer) returns integer
{
declare rc integer;
declare cfc_id integer;
declare rfc_spath, propname varchar;
declare rfc_list_cond, rfc_del_action any;
declare orig_id, filter_data, whole_rdf, vals, new_rdf any;
-- dbg_obj_princ ('CatFilter_DAV_DELETE (', detcol_id, path_parts, what, silent, auth_uid, ')');
rfc_spath := null;
orig_id := "CatFilter_DAV_SEARCH_ID_IMPL" (detcol_id, path_parts, what, cfc_id, rfc_spath, rfc_list_cond, rfc_del_action, filter_data);
if (DAV_HIDE_ERROR (orig_id) is null)
return orig_id;
if (length (rfc_del_action) < length (rfc_list_cond))
{
-- dbg_obj_princ ('del_action = ', rfc_del_action, 'rfc_list_cond = ', rfc_list_cond);
return -13;
}
if ('R' <> what)
return -20;
whole_rdf := coalesce ((select PROP_VALUE from WS.WS.SYS_DAV_PROP where PROP_NAME = 'http://local.virt/DAV-RDF' and PROP_TYPE = 'R' and PROP_PARENT_ID = orig_id [2]));
if (whole_rdf is null)
return -1;
if (not isstring (whole_rdf))
whole_rdf := blob_to_string (whole_rdf);
whole_rdf := xml_tree_doc (deserialize (whole_rdf));
propname := filter_data [length (filter_data) - 4];
-- dbg_obj_princ ('rdf is ', whole_rdf);
vals := xpath_eval (
'[xmlns:virt="virt"] /virt:rdf/virt:top-res/virt:prop[*[1][name(.) = \044propname]][virt:value]',
whole_rdf, 0, vector ('propname', filter_data [length (filter_data) - 4]) );
-- dbg_obj_princ ('vals=', vals);
foreach (any val in vals) do
{
declare cval, decenc_val varchar;
declare crop integer;
cval := cast (xpath_eval ('[xmlns:virt="virt"] string (virt:value)', val, 1) as varchar);
decenc_val := "CatFilter_DECODE_CATVALUE" ("CatFilter_ENCODE_CATVALUE" (cval), crop);
-- dbg_obj_princ ('Found value ', val, ' of ', propname, 'decenc=', decenc_val);
if (decenc_val = filter_data [length (filter_data) - 2])
{
-- dbg_obj_princ ('matches');
XMLReplace (whole_rdf, val, null);
}
}
new_rdf := xte_node (xte_head (UNAME' root'), whole_rdf);
update WS.WS.SYS_DAV_PROP set prop_value = serialize (new_rdf) where PROP_NAME = 'http://local.virt/DAV-RDF' and PROP_TYPE = 'R' and PROP_PARENT_ID = orig_id [2];
return 0;
}
;
create function "CatFilter_FILTER_TO_CONDITION" (inout schema_uri varchar, inout filter_data any, inout cond any) returns integer
{
declare ctr, len integer;
if (schema_uri is null)
return -13;
len := length (filter_data);
if ((len = 0) or (0 <> mod (len, 4)))
return -13;
vectorbld_init (cond);
for (ctr := 0; ctr < len; ctr := ctr + 4)
{
declare sample varchar;
declare crop integer;
crop := filter_data [ctr + 3];
--TBD proper support of crop 1,2,4
if (2 = crop)
return -13;
sample := filter_data [ctr + 2];
if (1 = crop)
return -13; --TBD: search for appropriate full text and set sample to the full text.
vectorbld_acc (cond, vector ('RDF_VALUE', '=', sample, 'http://local.virt/DAV-RDF', filter_data [ctr]));
}
vectorbld_final (cond);
return 0;
}
;
create function "CatFilter_DAV_RES_UPLOAD" (in detcol_id any, in path_parts any, inout content any, in type varchar, in permissions varchar, in uid integer, in gid integer, in auth_uid integer) returns any
{
declare rc integer;
declare cfc_id integer;
declare rfc_spath, propname, schema_uri, _colpath, fnameext, orig_fnameext, orig_fullpath varchar;
declare rfc_list_cond, rfc_del_action any;
declare orig_id, filter_data, fit_cond any;
-- dbg_obj_princ ('CatFilter_DAV_RES_UPLOAD (', detcol_id, path_parts, ', [content], ', type, permissions, uid, gid, auth_uid, ')');
rfc_spath := null;
rc := "CatFilter_GET_CONDITION" (detcol_id, cfc_id, rfc_spath, rfc_list_cond, rfc_del_action);
if (DAV_HIDE_ERROR (rc) is null)
return rc;
if (length (rfc_del_action) < length (rfc_list_cond))
{
-- dbg_obj_princ ('del_action = ', rfc_del_action, 'rfc_list_cond = ', rfc_list_cond);
return -13;
}
schema_uri := null;
rc := "CatFilter_PATH_PARTS_TO_FILTER" (path_parts, schema_uri, filter_data);
if (DAV_HIDE_ERROR (rc) is null)
return rc;
rc := "CatFilter_FILTER_TO_CONDITION" (schema_uri, filter_data, fit_cond);
if (DAV_HIDE_ERROR (rc) is null)
return rc;
fit_cond := vector ('', vector_concat (fit_cond, get_keyword ('', rfc_list_cond)));
-- dbg_obj_princ ('fit_cond=', fit_cond);
fnameext := path_parts [length (path_parts) - 1];
"ResFilter_FNSPLIT" (fnameext, _colpath, orig_fnameext, orig_id);
orig_fullpath := null;
if (orig_id is not null)
orig_fullpath := DAV_HIDE_ERROR (DAV_SEARCH_PATH (orig_id, 'R'));
if (orig_fullpath is null)
orig_fullpath := DAV_CONCAT_PATH (rfc_spath, orig_fnameext);
orig_id := DAV_RES_UPLOAD_STRSES_INT (
orig_fullpath,
content, '',
permissions, '', '',
null, null, 0,
null, null, null,
uid, gid, 1 );
-- dbg_obj_princ ('Will call "ResFilter_FIT_INTO_CONDITION" (', orig_id, 'R', fit_cond, auth_uid);
if (DAV_HIDE_ERROR (orig_id) is null)
return orig_id;
if (not (isinteger (orig_id)))
return -13;
"ResFilter_FIT_INTO_CONDITION" (orig_id, 'R', fit_cond, auth_uid);
return vector (UNAME'CatFilter', detcol_id, orig_id, schema_uri, filter_data);
}
;
create function "CatFilter_DAV_PROP_REMOVE" (in id any, in st char(0), in propname varchar, in silent integer, in auth_uid integer) returns integer
{
-- dbg_obj_princ ('CatFilter_DAV_PROP_REMOVE (', id, st, propname, silent, auth_uid, ')');
if (st <> 'R')
return -1;
id := id[2];
if (isarray (id))
return call (cast (id[0] as varchar) || '_DAV_PROP_REMOVE') (id, st, propname, silent, auth_uid);
return DAV_PROP_REMOVE_RAW (id, st, propname, silent, auth_uid);
}
;
create function "CatFilter_DAV_PROP_SET" (in id any, in st char(0), in propname varchar, in propvalue any, in overwrite integer, in auth_uid integer) returns any
{
declare pid integer;
declare resv any;
-- dbg_obj_princ ('CatFilter_DAV_PROP_SET (', id, st, propname, propvalue, overwrite, auth_uid, ')');
if (st <> 'R')
return -1;
id := id[2];
if (isarray (id))
return call (cast (id[0] as varchar) || '_DAV_PROP_SET') (id, st, propname, propvalue, overwrite, auth_uid);
return DAV_PROP_SET_RAW (id, st, propname, propvalue, overwrite, auth_uid);
}
;
create function "CatFilter_DAV_PROP_GET" (in id any, in what char(0), in propname varchar, in auth_uid integer)
{
declare ret varchar;
-- dbg_obj_princ ('CatFilter_DAV_PROP_GET (', id, what, propname, auth_uid, ')');
id := id[2];
if (isarray (id))
return call (cast (id[0] as varchar) || '_DAV_PROP_GET') (id, what, propname, auth_uid);
if (propname[0] = 58)
return DAV_PROP_GET_INT (id, what, propname, 0, null, null, auth_uid);
whenever not found goto no_prop;
select blob_to_string (PROP_VALUE) into ret from WS.WS.SYS_DAV_PROP where PROP_NAME = propname and PROP_PARENT_ID = id and PROP_TYPE = what;
return ret;
no_prop:
return -11;
}
;
create function "CatFilter_DAV_PROP_LIST" (in id any, in what char(0), in propmask varchar, in auth_uid integer)
{
declare ret any;
-- dbg_obj_princ ('CatFilter_DAV_PROP_LIST (', id, what, propmask, auth_uid, ')');
id := id[2];
if (isarray (id))
return call (cast (id[0] as varchar) || '_DAV_PROP_LIST') (id, what, propmask, auth_uid);
vectorbld_init (ret);
for select PROP_NAME, PROP_VALUE from WS.WS.SYS_DAV_PROP where PROP_NAME like propmask and PROP_PARENT_ID = id and PROP_TYPE = what do {
vectorbld_acc (ret, vector (PROP_NAME, blob_to_string (PROP_VALUE)));
}
vectorbld_final (ret);
return ret;
}
;
create function "CatFilter_DAV_DIR_SINGLE" (in id any, in what char(0), in path any, in auth_uid integer) returns any
{
-- dbg_obj_princ ('CatFilter_DAV_DIR_SINGLE (', id, what, path, auth_uid, ')');
if ('C' = what)
{
declare cfc_id integer;
declare rfc_spath varchar;
declare rfc_list_cond, rfc_del_action any;
declare loc_name, subcol_perms varchar;
declare set_readonly integer;
if (0 > "CatFilter_GET_CONDITION" (id[1], cfc_id, rfc_spath, rfc_list_cond, rfc_del_action))
{
-- dbg_obj_princ ('broken filter - no items');
return -1;
}
subcol_perms := coalesce ((select COL_PERMS from WS.WS.SYS_DAV_COL where COL_ID = id[1]), '000000000N');
subcol_perms[2] := 48; subcol_perms[5] := 48; subcol_perms[8] := 48; -- Can't execute in CatFilter so place zero chars.
set_readonly := 0;
if (length (rfc_del_action) < length (rfc_list_cond))
{
-- dbg_obj_princ ('del_action = ', rfc_del_action, 'rfc_list_cond = ', rfc_list_cond);
set_readonly := 1;
}
else
{
declare filt_len integer;
filt_len := length (id[4]);
if ((0 = filt_len) or (mod (filt_len, 4) = 2))
set_readonly := 1;
}
if (set_readonly)
{
subcol_perms[1] := 48; subcol_perms[4] := 48; subcol_perms[7] := 48; -- Can't write in CatFilter so place zero chars.
}
loc_name := path [length (path) - 2];
return vector (path, 'C', 0, now (), id, subcol_perms, 0, auth_uid, now (), 'dav/unix-directory', loc_name );
}
if (isarray (id[2]))
{
declare diritem any;
declare merged varchar;
diritem := call (cast (id[0] as varchar) || '_DAV_DIR_SINGLE') (id[2], what, path, auth_uid);
merged := "ResFilter_FNMERGE" (diritem[10], id[2]);
diritem[0] := DAV_CONCAT_PATH (path, merged);
diritem[10] := merged;
-- dbg_obj_princ ('About to return in DAV_DIR_SINGLE: ', diritem);
return diritem;
}
for select RES_FULL_PATH, RES_ID, length (RES_CONTENT) as clen, RES_MOD_TIME,
RES_PERMS, RES_GROUP, RES_OWNER, RES_CR_TIME, RES_TYPE, RES_NAME as r1_RES_NAME
from WS.WS.SYS_DAV_RES r1
where RES_ID = id[2]
do
{
declare merged varchar;
-- dbg_obj_princ ('About to return in DAV_DIR_SINGLE: ', r1_RES_NAME, RES_ID);
if (regexp_parse ('^([^/][^./]*) -Rf((Id[1-9][0-9]*)|([A-Z][A-Za-z0-9]+)-([A-Za-z0-9~+-]*))([.][^/]*)?\044', r1_RES_NAME, 0)) -- Suspicious names should be qualified
{
merged := "ResFilter_FNMERGE" (r1_RES_NAME, RES_ID);
}
else
{
declare cfc_id integer;
declare rfc_spath varchar;
declare rfc_list_cond, rfc_del_action varchar;
declare tmp_comp, namesakes any;
declare namesakes_no integer;
if (0 > "CatFilter_GET_CONDITION" (id[1], cfc_id, rfc_spath, rfc_list_cond, rfc_del_action))
{
-- dbg_obj_princ ('broken filter - bad id in DIR_SINGLE');
return -1;
}
tmp_comp := vector ('',
vector_concat (
vector (vector ('RES_NAME', '=', r1_RES_NAME)),
get_keyword ('', rfc_list_cond) ) );
namesakes := DAV_DIR_FILTER_INT (rfc_spath, 1, tmp_comp, null, null, auth_uid);
namesakes_no := length (namesakes);
if (0 = namesakes_no)
return -1;
if (1 < namesakes_no)
merged := "ResFilter_FNMERGE" (r1_RES_NAME, RES_ID);
else
merged := r1_RES_NAME;
}
path [length (path) - 1] := merged;
-- 0 1 2 3
return vector (DAV_CONCAT_PATH ('/', path), 'R', clen, RES_MOD_TIME,
-- 4 5 6 7 8 9 10
id, RES_PERMS, RES_GROUP, RES_OWNER, RES_CR_TIME, RES_TYPE, merged);
}
return -1;
}
;
create function "CatFilter_LIST_SCHEMAS" (in rfc_spath varchar, inout rfc_list_cond any, in auth_uid integer) returns any
{
return (select VECTOR_AGG (vector (RS_URI, RS_CATNAME)) from WS.WS.SYS_RDF_SCHEMAS);
}
;
create function "CatFilter_LIST_SCHEMA_PROPS" (in rfc_spath varchar, inout rfc_list_cond any, inout schema_uri varchar, inout filter_data any, in auth_uid integer) returns any
{
declare prop_catnames, res any;
declare len, ctr integer;
-- dbg_obj_princ ('CatFilter_LIST_SCHEMA_PROPS (', rfc_spath, rfc_list_cond, schema_uri, filter_data, auth_uid, ')');
vectorbld_init (res);
retry_after_recomp:
whenever not found goto schema_nf;
select deserialize (cast (RS_PROP_CATNAMES as varchar)) into prop_catnames from WS.WS.SYS_RDF_SCHEMAS where RS_URI = schema_uri and RS_PROP_CATNAMES is not null;
len := length (prop_catnames);
for (ctr := 0; ctr < len; ctr := ctr + 6)
{
if (0 = position (prop_catnames [ctr], filter_data, 1, 4))
vectorbld_acc (res, vector (prop_catnames [ctr], prop_catnames [ctr + 1]));
}
vectorbld_final (res);
return res;
schema_nf:
if (exists (select top 1 1 from WS.WS.SYS_RDF_SCHEMAS where RS_URI = schema_uri and RS_PROP_CATNAMES is null))
{
DAV_GET_RDF_SCHEMA_N3 (schema_uri);
goto retry_after_recomp;
}
return vector();
}
;
create procedure "CatFilter_GET_RDF_INVERSE_HITS_DISTVALS" (in cfc_id integer, inout filter_data any, inout distval_dict any, in auth_uid integer)
{
declare filter_length, p0_id, p1_id, p2_id, p3_id, p4_id, res0_id, res1_id, res2_id, res3_id, res4_id, res_last_id, res_id_max integer;
declare plast_id integer;
declare p0_val, p1_val, p2_val, p3_val, p4_val, v_last, v_max varchar;
declare auth_gid integer;
declare acl_bits, hit_ids any;
declare c_last1 cursor for select DRI_CATVALUE from WS.WS.SYS_DAV_RDF_INVERSE
where DRI_CATF_ID = cfc_id and DRI_PROP_CATID = plast_id and (v_max is null or DRI_CATVALUE > v_max) and
exists (select top 1 1 from WS.WS.SYS_DAV_RES where RES_ID = DRI_RES_ID and case (DAV_CHECK_PERM (RES_PERMS, '1__', auth_uid, auth_gid, RES_GROUP, RES_OWNER)) when 0 then WS.WS.ACL_IS_GRANTED (RES_ACL, auth_uid, acl_bits) else 1 end);
declare c_last2 cursor for select DRI_RES_ID, DRI_CATVALUE from WS.WS.SYS_DAV_RDF_INVERSE
where DRI_CATF_ID = cfc_id and DRI_PROP_CATID = plast_id and (v_max is null or DRI_CATVALUE > v_max) and
exists (select top 1 1 from WS.WS.SYS_DAV_RES where RES_ID = DRI_RES_ID and case (DAV_CHECK_PERM (RES_PERMS, '1__', auth_uid, auth_gid, RES_GROUP, RES_OWNER)) when 0 then WS.WS.ACL_IS_GRANTED (RES_ACL, auth_uid, acl_bits) else 1 end);
declare c0 cursor for select DRI_RES_ID from WS.WS.SYS_DAV_RDF_INVERSE where DRI_CATF_ID = cfc_id and DRI_PROP_CATID = p0_id and DRI_CATVALUE = p0_val and DRI_RES_ID >= res_id_max;
declare c1 cursor for select DRI_RES_ID from WS.WS.SYS_DAV_RDF_INVERSE where DRI_CATF_ID = cfc_id and DRI_PROP_CATID = p1_id and DRI_CATVALUE = p1_val and DRI_RES_ID >= res_id_max;
declare c2 cursor for select DRI_RES_ID from WS.WS.SYS_DAV_RDF_INVERSE where DRI_CATF_ID = cfc_id and DRI_PROP_CATID = p2_id and DRI_CATVALUE = p2_val and DRI_RES_ID >= res_id_max;
declare c3 cursor for select DRI_RES_ID from WS.WS.SYS_DAV_RDF_INVERSE where DRI_CATF_ID = cfc_id and DRI_PROP_CATID = p3_id and DRI_CATVALUE = p3_val and DRI_RES_ID >= res_id_max;
declare c4 cursor for select DRI_RES_ID from WS.WS.SYS_DAV_RDF_INVERSE where DRI_CATF_ID = cfc_id and DRI_PROP_CATID = p4_id and DRI_CATVALUE = p4_val and DRI_RES_ID >= res_id_max;
-- dbg_obj_princ ('CatFilter_GET_RDF_INVERSE_HITS_DISTVALS (', cfc_id, filter_data, auth_uid, ')');
filter_length := length (filter_data);
plast_id := filter_data [filter_length - 1];
res_id_max := 0;
v_max := null;
auth_gid := coalesce ((select U_GROUP from WS.WS.SYS_DAV_USER where U_ID = auth_uid), 0);
acl_bits := DAV_REQ_CHARS_TO_BITMASK ('1__');
if (filter_length = 2) -- distinct propvals with no filtering in front -- a special case
{
whenever not found goto nf_c_last1;
-- dbg_obj_princ ('CatFilter_GET_RDF_INVERSE_HITS_DISTVALS: distinct propvals of ', plast_id, ' in ', cfc_id);
open c_last1 (prefetch 1);
while (1)
{
fetch c_last1 into v_last;
-- dbg_obj_princ ('CatFilter_GET_RDF_INVERSE_HITS_DISTVALS: v_last is ', v_last, ' v_max is ', v_max);
if (v_max is null or (v_last > v_max))
{
v_max := v_last; -- note that vectorbld_acc() will destroy the value of v_last so this assignment should be before vectorbld_acc().
dict_put (distval_dict, v_last, 1);
}
}
nf_c_last1:
close c_last1;
return;
}
res0_id := 0;
res1_id := 0;
res2_id := 0;
res3_id := 0;
res4_id := 0;
hit_ids := dict_new ();
p0_id := filter_data [1];
p0_val := "CatFilter_ENCODE_CATVALUE" (filter_data [2]);
if (filter_length = 6) -- distinct propvals with 1 fixed property
{
whenever not found goto get_distincts_0;
open c0 (prefetch 1);
while (1)
{
while (res0_id <= res_id_max)
fetch c0 into res0_id;
res_id_max := res0_id;
-- dbg_obj_princ ('CatFilter_GET_RDF_INVERSE_HITS_DISTVALS: put hit ', res_id_max);
dict_put (hit_ids, res_id_max, 1);
}
}
p1_id := filter_data [4+1];
p1_val := "CatFilter_ENCODE_CATVALUE" (filter_data [4+2]);
if (filter_length = 10) -- distinct propvals with 2 fixed property
{
whenever not found goto get_distincts_1;
open c0 (prefetch 1);
open c1 (prefetch 1);
while (1)
{
while (res0_id <= res_id_max) fetch c0 into res0_id;
if (res0_id > res_id_max) res_id_max := res0_id;
while (res1_id < res_id_max) fetch c1 into res1_id;
if (res1_id > res_id_max) res_id_max := res1_id;
if ((res0_id = res_id_max) and (res1_id = res_id_max))
{
-- dbg_obj_princ ('CatFilter_GET_RDF_INVERSE_HITS_DISTVALS: put hit ', res_id_max);
dict_put (hit_ids, res_id_max, 1);
}
else
res_id_max := res_id_max + 1;
}
}
p2_id := filter_data [8+1];
p2_val := "CatFilter_ENCODE_CATVALUE" (filter_data [8+2]);
if (filter_length = 14) -- distinct propvals with 3 fixed property
{
whenever not found goto get_distincts_2;
open c0 (prefetch 1);
open c1 (prefetch 1);
open c2 (prefetch 1);
while (1)
{
-- dbg_obj_princ ('CatFilter_GET_RDF_INVERSE_HITS_DISTVALS: res_id_max is ', res_id_max);
-- res_id_max := 0;
while (res0_id <= res_id_max) fetch c0 into res0_id;
-- dbg_obj_princ ('CatFilter_GET_RDF_INVERSE_HITS_DISTVALS: res0_id is ', res0_id);
if (res0_id > res_id_max) res_id_max := res0_id;
while (res1_id < res_id_max) fetch c1 into res1_id;
-- dbg_obj_princ ('CatFilter_GET_RDF_INVERSE_HITS_DISTVALS: res1_id is ', res1_id);
if (res1_id > res_id_max) res_id_max := res1_id;
while (res2_id < res_id_max) fetch c2 into res2_id;
-- dbg_obj_princ ('CatFilter_GET_RDF_INVERSE_HITS_DISTVALS: res2_id is ', res2_id);
if (res2_id > res_id_max) res_id_max := res2_id;
if ((res0_id = res_id_max) and (res1_id = res_id_max) and (res2_id = res_id_max))
{
-- dbg_obj_princ ('CatFilter_GET_RDF_INVERSE_HITS_DISTVALS: put hit ', res_id_max);
dict_put (hit_ids, res_id_max, 1);
}
}
}
p3_id := filter_data [12+1];
p3_val := "CatFilter_ENCODE_CATVALUE" (filter_data [12+2]);
if (filter_length = 18) -- distinct propvals with 4 fixed property
{
whenever not found goto get_distincts_3;
open c0 (prefetch 1);
open c1 (prefetch 1);
open c2 (prefetch 1);
open c3 (prefetch 1);
while (1)
{
while (res0_id <= res_id_max) fetch c0 into res0_id;
if (res0_id > res_id_max) res_id_max := res0_id;
while (res1_id < res_id_max) fetch c1 into res1_id;
if (res1_id > res_id_max) res_id_max := res1_id;
while (res2_id < res_id_max) fetch c2 into res2_id;
if (res2_id > res_id_max) res_id_max := res2_id;
while (res3_id < res_id_max) fetch c3 into res3_id;
if (res3_id > res_id_max) res_id_max := res3_id;
if ((res0_id = res_id_max) and (res1_id = res_id_max) and (res2_id = res_id_max) and (res3_id = res_id_max))
{
-- dbg_obj_princ ('CatFilter_GET_RDF_INVERSE_HITS_DISTVALS: put hit ', res_id_max);
dict_put (hit_ids, res_id_max, 1);
}
}
}
p4_id := filter_data [16+1];
p4_val := "CatFilter_ENCODE_CATVALUE" (filter_data [16+2]);
if (filter_length = 22) -- distinct propvals with 5 fixed property
{
whenever not found goto get_distincts_4;
open c0 (prefetch 1);
open c1 (prefetch 1);
open c2 (prefetch 1);
open c3 (prefetch 1);
open c4 (prefetch 1);
while (1)
{
while (res0_id <= res_id_max) fetch c0 into res0_id;
if (res0_id > res_id_max) res_id_max := res0_id;
while (res1_id < res_id_max) fetch c1 into res1_id;
if (res1_id > res_id_max) res_id_max := res1_id;
while (res2_id < res_id_max) fetch c2 into res2_id;
if (res2_id > res_id_max) res_id_max := res2_id;
while (res3_id < res_id_max) fetch c3 into res3_id;
if (res3_id > res_id_max) res_id_max := res3_id;
while (res4_id < res_id_max) fetch c4 into res4_id;
if (res4_id > res_id_max) res_id_max := res4_id;
if ((res0_id = res_id_max) and (res1_id = res_id_max) and (res2_id = res_id_max) and (res3_id = res_id_max) and (res4_id = res_id_max))
dict_put (hit_ids, res_id_max, 1);
}
}
get_distincts_4:
-- dbg_obj_princ ('CatFilter_GET_RDF_INVERSE_HITS_DISTVALS: close c4');
close c4;
get_distincts_3:
-- dbg_obj_princ ('CatFilter_GET_RDF_INVERSE_HITS_DISTVALS: close c3');
close c3;
get_distincts_2:
-- dbg_obj_princ ('CatFilter_GET_RDF_INVERSE_HITS_DISTVALS: close c2');
close c2;
get_distincts_1:
-- dbg_obj_princ ('CatFilter_GET_RDF_INVERSE_HITS_DISTVALS: close c1');
close c1;
get_distincts_0:
-- dbg_obj_princ ('CatFilter_GET_RDF_INVERSE_HITS_DISTVALS: close c0');
close c0;
-- dbg_obj_princ ('CatFilter_GET_RDF_INVERSE_HITS_DISTVALS: now search in all values of ', plast_id);
whenever not found goto nf_c_last2;
open c_last2 (prefetch 1);
while (1)
{
fetch c_last2 into res_last_id, v_last;
if (v_max is null or (v_last > v_max))
{
-- dbg_obj_princ ('CatFilter_GET_RDF_INVERSE_HITS_DISTVALS: next value ', v_last, ' at ', res_last_id);
if (dict_get (hit_ids, res_last_id, 0))
{
-- dbg_obj_princ ('CatFilter_GET_RDF_INVERSE_HITS_DISTVALS: full hit at ', res_last_id);
v_max := v_last; -- note that vectorbld_acc() will destroy the value of v_last so this assignment should be before vectorbld_acc().
dict_put (distval_dict, v_last, 1);
}
}
}
nf_c_last2:
close c_last2;
}
;
create function "CatFilter_GET_RDF_INVERSE_HITS_RES_IDS" (in cfc_id integer, inout filter_data any, in auth_uid integer) returns any
{
declare filter_length, p0_id, p1_id, p2_id, p3_id, p4_id, res0_id, res1_id, res2_id, res3_id, res4_id, res_id_max integer;
declare acc any;
declare p0_val, p1_val, p2_val, p3_val, p4_val varchar;
declare acl_bits any;
declare auth_gid integer;
declare c0 cursor for select DRI_RES_ID from WS.WS.SYS_DAV_RDF_INVERSE where DRI_CATF_ID = cfc_id and DRI_PROP_CATID = p0_id and DRI_CATVALUE = p0_val and DRI_RES_ID >= res_id_max and
exists (select top 1 1 from WS.WS.SYS_DAV_RES where RES_ID = DRI_RES_ID and case (DAV_CHECK_PERM (RES_PERMS, '1__', auth_uid, auth_gid, RES_GROUP, RES_OWNER)) when 0 then WS.WS.ACL_IS_GRANTED (RES_ACL, auth_uid, acl_bits) else 1 end);
declare c1 cursor for select DRI_RES_ID from WS.WS.SYS_DAV_RDF_INVERSE where DRI_CATF_ID = cfc_id and DRI_PROP_CATID = p1_id and DRI_CATVALUE = p1_val and DRI_RES_ID >= res_id_max;
declare c2 cursor for select DRI_RES_ID from WS.WS.SYS_DAV_RDF_INVERSE where DRI_CATF_ID = cfc_id and DRI_PROP_CATID = p2_id and DRI_CATVALUE = p2_val and DRI_RES_ID >= res_id_max;
declare c3 cursor for select DRI_RES_ID from WS.WS.SYS_DAV_RDF_INVERSE where DRI_CATF_ID = cfc_id and DRI_PROP_CATID = p3_id and DRI_CATVALUE = p3_val and DRI_RES_ID >= res_id_max;
declare c4 cursor for select DRI_RES_ID from WS.WS.SYS_DAV_RDF_INVERSE where DRI_CATF_ID = cfc_id and DRI_PROP_CATID = p4_id and DRI_CATVALUE = p4_val and DRI_RES_ID >= res_id_max;
-- dbg_obj_princ ('CatFilter_GET_RDF_INVERSE_HITS_RES_IDS (', cfc_id, filter_data, auth_uid, ')');
filter_length := length (filter_data);
vectorbld_init (acc);
res0_id := -1;
res1_id := -1;
res2_id := -1;
res3_id := -1;
res4_id := -1;
res_id_max := 0;
auth_gid := coalesce ((select U_GROUP from WS.WS.SYS_DAV_USER where U_ID = auth_uid), 0);
acl_bits := DAV_REQ_CHARS_TO_BITMASK ('1__');
p0_id := filter_data [1];
p0_val := "CatFilter_ENCODE_CATVALUE" (filter_data [2]);
if (filter_length = 4) -- resources with 1 fixed property
{
whenever not found goto get_distincts_0;
open c0 (prefetch 1);
while (1)
{
while (res0_id <= res_id_max)
fetch c0 into res0_id;
res_id_max := res0_id;
-- dbg_obj_princ ('CatFilter_GET_RDF_INVERSE_HITS_RES_IDS: put hit ', res_id_max);
vectorbld_acc (acc, res0_id);
}
}
p1_id := filter_data [4+1];
p1_val := "CatFilter_ENCODE_CATVALUE" (filter_data [4+2]);
if (filter_length = 8) -- resources with 2 fixed properties
{
whenever not found goto get_distincts_1;
open c0 (prefetch 1);
open c1 (prefetch 1);
while (1)
{
while (res1_id < res_id_max) fetch c1 into res1_id;
if (res1_id > res_id_max) res_id_max := res1_id;
while (res0_id < res_id_max) fetch c0 into res0_id;
if (res0_id > res_id_max) res_id_max := res0_id;
if ((res0_id = res_id_max) and (res1_id = res_id_max))
{
-- dbg_obj_princ ('CatFilter_GET_RDF_INVERSE_HITS_RES_IDS: put hit ', res_id_max);
vectorbld_acc (acc, res0_id);
res_id_max := res_id_max + 1;
}
}
}
p2_id := filter_data [8+1];
p2_val := "CatFilter_ENCODE_CATVALUE" (filter_data [8+2]);
if (filter_length = 12) -- resources with 3 fixed properties
{
whenever not found goto get_distincts_2;
open c0 (prefetch 1);
open c1 (prefetch 1);
open c2 (prefetch 1);
while (1)
{
while (res1_id < res_id_max) fetch c1 into res1_id;
if (res1_id > res_id_max) res_id_max := res1_id;
while (res2_id < res_id_max) fetch c2 into res2_id;
if (res2_id > res_id_max) res_id_max := res2_id;
while (res0_id < res_id_max) fetch c0 into res0_id;
if (res0_id > res_id_max) res_id_max := res0_id;
if ((res0_id = res_id_max) and (res1_id = res_id_max) and (res2_id = res_id_max))
{
-- dbg_obj_princ ('CatFilter_GET_RDF_INVERSE_HITS_RES_IDS: put hit ', res_id_max);
vectorbld_acc (acc, res0_id);
res_id_max := res_id_max + 1;
}
}
}
p3_id := filter_data [12+1];
p3_val := "CatFilter_ENCODE_CATVALUE" (filter_data [12+2]);
if (filter_length = 16) -- resources with 4 fixed properties
{
whenever not found goto get_distincts_3;
open c0 (prefetch 1);
open c1 (prefetch 1);
open c2 (prefetch 1);
open c3 (prefetch 1);
while (1)
{
while (res1_id < res_id_max) fetch c1 into res1_id;
if (res1_id > res_id_max) res_id_max := res1_id;
while (res2_id < res_id_max) fetch c2 into res2_id;
if (res2_id > res_id_max) res_id_max := res2_id;
while (res3_id < res_id_max) fetch c3 into res3_id;
if (res3_id > res_id_max) res_id_max := res3_id;
while (res0_id < res_id_max) fetch c0 into res0_id;
if (res0_id > res_id_max) res_id_max := res0_id;
if ((res0_id = res_id_max) and (res1_id = res_id_max) and (res2_id = res_id_max) and (res3_id = res_id_max))
{
-- dbg_obj_princ ('CatFilter_GET_RDF_INVERSE_HITS_RES_IDS: put hit ', res_id_max);
vectorbld_acc (acc, res0_id);
res_id_max := res_id_max + 1;
}
}
}
p4_id := filter_data [16+1];
p4_val := "CatFilter_ENCODE_CATVALUE" (filter_data [16+2]);
if (filter_length = 20) -- resources with 5 fixed properties
{
whenever not found goto get_distincts_4;
open c0 (prefetch 1);
open c1 (prefetch 1);
open c2 (prefetch 1);
open c3 (prefetch 1);
open c4 (prefetch 1);
while (1)
{
while (res1_id < res_id_max) fetch c1 into res1_id;
if (res1_id > res_id_max) res_id_max := res1_id;
while (res2_id < res_id_max) fetch c2 into res2_id;
if (res2_id > res_id_max) res_id_max := res2_id;
while (res3_id < res_id_max) fetch c3 into res3_id;
if (res3_id > res_id_max) res_id_max := res3_id;
while (res4_id < res_id_max) fetch c4 into res4_id;
if (res4_id > res_id_max) res_id_max := res4_id;
while (res0_id < res_id_max) fetch c0 into res0_id;
if (res0_id > res_id_max) res_id_max := res0_id;
if ((res0_id = res_id_max) and (res1_id = res_id_max) and (res2_id = res_id_max) and (res3_id = res_id_max) and (res4_id = res_id_max))
{
-- dbg_obj_princ ('CatFilter_GET_RDF_INVERSE_HITS_RES_IDS: put hit ', res_id_max);
vectorbld_acc (acc, res0_id);
res_id_max := res_id_max + 1;
}
}
}
get_distincts_4:
close c4;
get_distincts_3:
close c3;
get_distincts_2:
close c2;
get_distincts_1:
close c1;
get_distincts_0:
close c0;
finalize:
vectorbld_final (acc);
-- dbg_obj_princ ('CatFilter_GET_RDF_INVERSE_HITS_RES_IDS (', cfc_id, filter_data, auth_uid, ') returns ', acc);
return acc;
}
;
create function "CatFilter_LIST_PROP_DISTVALS_AUX" (inout dict any, inout rfp varchar, inout vals any)
{
-- dbg_obj_princ ('CatFilter_LIST_PROP_DISTVALS_AUX will store ', length (vals), 'values for ', rfp);
foreach (any val in vals) do
{
-- dbg_obj_princ ('CatFilter_LIST_PROP_DISTVALS_AUX will store ', xpath_eval('..', val));
dict_put (dict, "CatFilter_ENCODE_CATVALUE" (cast (val as varchar)), 1);
}
return 1;
}
;
create function "CatFilter_LIST_PROP_DISTVALS" (in detcol_id integer, in cfc_id integer, in rfc_spath varchar, inout rfc_list_cond any, inout schema_uri varchar, inout filter_data any, in auth_uid integer) returns any
{
declare prop_catnames, filter, res any;
-- declare compilation any;
declare len, ctr integer;
declare execstate, execmessage varchar;
declare execmeta, execrows any;
declare qry_ft, qry_where, qry_text varchar;
declare pred_metas, cmp_metas, table_metas any;
declare used_tables any;
declare dict any;
declare auth_gid integer;
-- dbg_obj_princ ('CatFilter_LIST_PROP_DISTVALS (', cfc_id, rfc_spath, rfc_list_cond, schema_uri, filter_data, auth_uid, ')');
dict := dict_new ();
if ((length (get_keyword ('', rfc_list_cond)) = 0) and (length (filter_data) > 0) and (length (filter_data) <= 22))
{ -- Optimized merge intersection on inverse hits
"CatFilter_GET_RDF_INVERSE_HITS_DISTVALS" (cfc_id, filter_data, dict, auth_uid);
goto plain_resources_passed;
}
len := length (filter_data);
vectorbld_init (filter);
"CatFilter_ACC_FILTER_DATA" (filter, filter_data);
vectorbld_concat_acc (filter, get_keyword ('', rfc_list_cond));
vectorbld_final (filter);
-- dbg_obj_princ ('DAV_FC_PRINT_WHERE (', filter, auth_uid, ')');
DAV_FC_PRED_METAS (pred_metas);
DAV_FC_CMP_METAS (cmp_metas);
DAV_FC_TABLE_METAS (table_metas);
qry_ft := sprintf ('virt:rdf/virt:top-res/virt:prop[*[1][self::(!%s!)]]/virt:value', filter_data [len-2]);
used_tables := vector (
'SYS_DAV_RES', vector ('SYS_DAV_RES', '_top', null, vector(), vector(), vector()),
'SYS_DAV_PROP, PROP_NAME=http://local.virt/DAV-RDF', vector ('SYS_DAV_PROP', '_rdf', '(_rdf.PROP_NAME = ''http://local.virt/DAV-RDF'')', vector(), vector(), vector('[' || qry_ft || ']'))
);
qry_where := DAV_FC_PRINT_WHERE_INT (filter, pred_metas, cmp_metas, table_metas, used_tables,
coalesce ((select COL_OWNER from WS.WS.SYS_DAV_COL where COL_ID = detcol_id), -1) );
auth_gid := coalesce ((select U_GROUP from WS.WS.SYS_DAV_USER where U_ID = auth_uid), 0);
-- compilation := vector ('', filter, 'DAV', DAV_FC_PRINT_WHERE (filter, auth_uid));
qry_text := '
select count ( "CatFilter_LIST_PROP_DISTVALS_AUX" (?, _top.RES_FULL_PATH,
xpath_eval (''[xmlns:virt="virt"] /' || qry_ft ||''',
xml_tree_doc (deserialize (cast (_rdf.PROP_VALUE as varchar))),
0 ) ) )
from WS.WS.SYS_DAV_RES as _top
' || qry_where || ' and
(_top.RES_FULL_PATH between ' || WS.WS.STR_SQL_APOS (rfc_spath) || ' and ' || WS.WS.STR_SQL_APOS (DAV_COL_PATH_BOUNDARY (rfc_spath)) || ') and
case (DAV_CHECK_PERM (_top.RES_PERMS, ''1__'', ?, ?, _top.RES_GROUP, _top.RES_OWNER)) when 0 then WS.WS.ACL_IS_GRANTED (_top.RES_ACL, ?, DAV_REQ_CHARS_TO_BITMASK (''1__'')) else 1 end
';
-- dbg_obj_princ ('about to exec:\n', qry_text, '\nrfc_spath = ', rfc_spath);
exec (qry_text,
execstate, execmessage, vector (dict, auth_uid, auth_gid, auth_uid), 1, execmeta, execrows );
-- dbg_obj_princ ('execstate = ', execstate, ' execmessage = ', execmessage);
plain_resources_passed:
for
select CFD_DET_SUBCOL_ID, CFD_DET from WS.WS.SYS_DAV_CATFILTER_DETS where CFD_CF_ID = cfc_id
do
{
if (exists (select top 1 1 from SYS_PROCEDURES where P_NAME = fix_identifier_case('DB.DBA.') || CFD_DET || '_CF_LIST_PROP_DISTVALS'))
call (CFD_DET || '_CF_LIST_PROP_DISTVALS') (CFD_DET_SUBCOL_ID, cfc_id, rfc_spath, rfc_list_cond, schema_uri, filter_data, dict, auth_uid);
}
return dict_list_keys (dict, 1);
}
;
create function "CatFilter_DAV_DIR_LIST" (in detcol_id any, in path_parts any, in detcol_path varchar, in name_mask varchar, in recursive integer, in auth_uid integer) returns any
{
declare cfc_id integer;
declare rfc_spath varchar;
declare rfc_list_cond, rfc_del_action any;
declare davpath, prev_raw_name, schema_uri, subcol_perms varchar;
declare depth integer;
declare res, resources, itm, reps, filter_data any;
declare ctr, itm_ctr, itm_count, prev_is_patched, set_readonly integer;
declare filter any;
-- dbg_obj_princ ('CatFilter_DAV_DIR_LIST (', detcol_id, path_parts, detcol_path, name_mask, recursive, auth_uid, ')');
vectorbld_init (res);
filter_data := null;
if (0 > "CatFilter_GET_CONDITION" (detcol_id, cfc_id, rfc_spath, rfc_list_cond, rfc_del_action))
{
-- dbg_obj_princ ('broken filter - no items');
goto final_res;
}
subcol_perms := coalesce ((select COL_PERMS from WS.WS.SYS_DAV_COL where COL_ID = detcol_id), '000000000N');
subcol_perms[2] := 48; subcol_perms[5] := 48; subcol_perms[8] := 48; -- Can't execute in CatFilter so place zero chars.
if (1 < length(path_parts))
{
if ("CatFilter_PATH_PARTS_TO_FILTER" (path_parts, schema_uri, filter_data) < 0)
{
-- dbg_obj_princ ('"CatFilter_DAV_DIR_LIST" ends due to failed "CatFilter_PATH_PARTS_TO_FILTER"');
goto final_res;
}
}
else
filter_data := null;
set_readonly := 0;
if (length (rfc_del_action) < length (rfc_list_cond))
{
-- dbg_obj_princ ('del_action = ', rfc_del_action, 'rfc_list_cond = ', rfc_list_cond);
set_readonly := 1;
}
else
if (-1 = recursive)
{
if ((2 = length(path_parts)) or (mod (length (filter_data), 4) = 2))
set_readonly := 1;
}
else
{
if ((1 = length(path_parts)) or (mod (length (filter_data), 4) = 0))
set_readonly := 1;
}
if (set_readonly)
{
subcol_perms[1] := 48; subcol_perms[4] := 48; subcol_perms[7] := 48; -- Can't write in CatFilter so place zero chars.
}
depth := length(path_parts);
-- level 0 -- schemas;
if (1 = length(path_parts))
{
declare schemas any;
-- dbg_obj_princ ('level of list of schemas');
if ('' <> path_parts[0])
{
-- dbg_obj_princ ('no resources at level 0');
return vector();
}
schemas := "CatFilter_LIST_SCHEMAS" (rfc_spath, rfc_list_cond, auth_uid);
foreach (any sch in schemas) do
{
declare subcol_fullpath varchar;
subcol_fullpath := DAV_CONCAT_PATH (detcol_path, sch[1] || '/');
vectorbld_acc (res,
vector (subcol_fullpath, 'C', 0, now (),
vector (UNAME'CatFilter', detcol_id, null, sch[0], null),
subcol_perms, 0, auth_uid, now (), 'dav/unix-directory', sch[1]) );
if (recursive > 0)
vectorbld_concat_acc (res,
"CatFilter_DAV_DIR_LIST" (detcol_id,
vector_concat (subseq (path_parts, 0, length (path_parts) - 1), vector (sch[1], '')),
detcol_path, -- not subcol_fullpath,
name_mask, recursive, auth_uid ) );
}
goto final_res;
}
if ("CatFilter_PATH_PARTS_TO_FILTER" (path_parts, schema_uri, filter_data) < 0)
{
-- dbg_obj_princ ('"CatFilter_DAV_DIR_LIST" ends due to failed "CatFilter_PATH_PARTS_TO_FILTER"');
goto final_res;
}
-- dbg_obj_princ ('"CatFilter_DAV_DIR_LIST" founds schema_uri = ', schema_uri, ' filter_data = ', filter_data);
-- We crop at 5 property values, i.e. 20 items in filter data. Sixth property is not displayed to keep URI short.
if (mod (length (filter_data), 4) = 2)
{ -- list distinct values at odd levels
declare distvals any;
-- dbg_obj_princ ('level of distinct values');
distvals := "CatFilter_LIST_PROP_DISTVALS" (detcol_id, cfc_id, rfc_spath, rfc_list_cond, schema_uri, filter_data, auth_uid);
if (-1 = recursive)
{
--if (0 = length (distvals))
-- return vector();
return vector (
vector (DAV_CONCAT_PATH (detcol_path, path_parts), 'C', 0, now (),
vector (UNAME'CatFilter', detcol_id, null, schema_uri, filter_data),
subcol_perms, 0, auth_uid, now (), 'dav/unix-directory', path_parts [depth - 2] ) );
}
foreach (varchar val in distvals) do
{
declare subcol_fullpath varchar;
subcol_fullpath := DAV_CONCAT_PATH ( DAV_CONCAT_PATH (detcol_path, path_parts), val || '/');
vectorbld_acc (res,
vector (subcol_fullpath, 'C', 0, now (),
vector (UNAME'CatFilter', detcol_id, null, schema_uri, vector_concat (filter_data, vector (val))),
subcol_perms, 0, auth_uid, now (), 'dav/unix-directory', val) );
if (recursive > 0)
vectorbld_concat_acc (res,
"CatFilter_DAV_DIR_LIST" (detcol_id,
vector_concat (subseq (path_parts, 0, length (path_parts) - 1), vector (val, '')),
detcol_path, -- not subcol_fullpath,
name_mask, recursive, auth_uid ) );
}
goto final_res;
}
else if (length (filter_data) <= 16)
{
declare sch_props any;
-- dbg_obj_princ ('level of prop list');
sch_props := "CatFilter_LIST_SCHEMA_PROPS" (rfc_spath, rfc_list_cond, schema_uri, filter_data, auth_uid);
if (-1 = recursive)
{
--if (0 = length (sch_props))
-- return vector();
return vector (
vector (DAV_CONCAT_PATH (detcol_path, path_parts), 'C', 0, now (),
vector (UNAME'CatFilter', detcol_id, null, schema_uri, filter_data),
subcol_perms, 0, auth_uid, now (), 'dav/unix-directory', path_parts [depth - 2] ) );
}
-- The 'if' below disables infinite recursion.
-- All resources will be displayed, but not all subcollections.
-- This is the longest possible finite list CatFilter can offer to the application.
if (length (filter_data) >= 4)
recursive := 0;
foreach (any prop in sch_props) do
{
declare subcol_fullpath varchar;
subcol_fullpath := DAV_CONCAT_PATH (DAV_CONCAT_PATH (detcol_path, path_parts), prop[1] || '/');
vectorbld_acc (res,
vector (subcol_fullpath, 'C', 0, now (),
vector (UNAME'CatFilter', detcol_id, null, prop[0], null),
subcol_perms, 0, auth_uid, now (), 'dav/unix-directory', prop[1]) );
if (recursive > 0)
vectorbld_concat_acc (res,
"CatFilter_DAV_DIR_LIST" (detcol_id,
vector_concat (subseq (path_parts, 0, length (path_parts) - 1), vector (prop[1], '')),
detcol_path, -- not subcol_fullpath,
name_mask, recursive, auth_uid ) );
}
}
-- dbg_obj_princ ('res = ', res);
if (0 = length (filter_data))
{
-- dbg_obj_princ ('no resources with 0 filter data len');
goto final_res; -- otherwise all files are listed from all schemas.
}
if ((length (get_keyword ('', rfc_list_cond)) = 0) and (length (filter_data) > 0) and (length (filter_data) <= 20))
{ -- Optimized merge intersection on inverse hits
declare res_ids, res_dir_single any;
res_ids := "CatFilter_GET_RDF_INVERSE_HITS_RES_IDS" (cfc_id, filter_data, auth_uid);
-- dbg_obj_princ ('resources = ', res_ids);
itm_count := length (res_ids);
vectorbld_init (resources);
for (itm_ctr := 0; itm_ctr < itm_count; itm_ctr := itm_ctr + 1)
{
declare r_id integer;
r_id := res_ids [itm_ctr];
res_dir_single := coalesce ((
select
-- 0 1 2 3
vector (DAV_CONCAT_PATH (detcol_path, RES_NAME), 'R', length (RES_CONTENT), RES_MOD_TIME,
-- 4 5 6 7 8 9 10
r_id, RES_PERMS, RES_GROUP, RES_OWNER, RES_CR_TIME, RES_TYPE, RES_NAME )
from WS.WS.SYS_DAV_RES
where RES_ID = r_id ) );
if (res_dir_single is not null)
vectorbld_acc (resources, res_dir_single);
}
for select CFD_DET_SUBCOL_ID, CFD_DET from WS.WS.SYS_DAV_CATFILTER_DETS where CFD_CF_ID = cfc_id do
{
declare det_res_ids any;
if (exists (select top 1 1 from SYS_PROCEDURES where P_NAME = fix_identifier_case('DB.DBA.') || CFD_DET || '_CF_GET_RDF_HITS'))
{
det_res_ids := call (CFD_DET || '_CF_GET_RDF_HITS') (CFD_DET_SUBCOL_ID, cfc_id, rfc_spath, rfc_list_cond, schema_uri, filter_data, detcol_path, 1, auth_uid);
vectorbld_concat_acc (resources, det_res_ids);
}
}
vectorbld_final (resources);
}
else
{
vectorbld_init (filter);
"CatFilter_ACC_FILTER_DATA" (filter, filter_data);
vectorbld_concat_acc (filter, get_keyword ('', rfc_list_cond));
-- dbg_obj_princ ('name_mask = ', name_mask);
if ('%' <> name_mask)
{
-- dbg_obj_princ ('Adding check for name mask');
vectorbld_acc (filter, vector ('RES_NAME', 'like', name_mask));
}
vectorbld_final (filter);
filter := vector ('', filter);
resources := DAV_DIR_FILTER_INT (rfc_spath, 1, filter, null, null, auth_uid);
}
reps := dict_new ();
itm_count := length (resources);
for (itm_ctr := 0; itm_ctr < itm_count; itm_ctr := itm_ctr + 1)
{
declare rname varchar;
declare orig_id any;
itm := resources [itm_ctr];
rname := itm [10];
orig_id := itm[4];
if (isarray (orig_id) or regexp_parse ('^([^/][^./]*) -Rf((Id[1-9][0-9]*)|([A-Z][A-Za-z0-9]+)-([A-Za-z0-9~+-]*))([.][^/]*)?\044', rname, 0)) -- Suspicious names should be qualified
resources [itm_ctr][10] := rname := "ResFilter_FNMERGE" (rname, orig_id);
dict_put (reps, rname, dict_get (reps, rname, 0) + 1);
}
for (itm_ctr := 0; itm_ctr < itm_count; itm_ctr := itm_ctr + 1)
{
declare rname varchar;
declare orig_id integer;
itm := resources [itm_ctr];
rname := itm [10];
orig_id := itm[4];
resources[itm_ctr][4] := vector (UNAME'CatFilter', detcol_id, orig_id);
if (dict_get (reps, rname, 0) > 1) -- Suspicious names should be qualified
resources [itm_ctr][10] := rname := "ResFilter_FNMERGE" (rname, orig_id);
resources[itm_ctr][0] := DAV_CONCAT_PATH (DAV_CONCAT_PATH (detcol_path, path_parts), rname);
}
vectorbld_concat_acc (res, resources);
-- dbg_obj_princ ('res = ', res);
final_res:
vectorbld_final (res);
-- dbg_obj_princ ('\nCatFilter_DAV_DIR_LIST (', detcol_id, path_parts, detcol_path, name_mask, recursive, auth_uid, ') returns ', length (res), ' items:\n');
-- foreach (any i in res) do -- dbg_obj_princ (i);
return res;
}
;
create function "CatFilter_DAV_DIR_FILTER" (in detcol_id any, in path_parts any, in detcol_path varchar, inout compilation any, in recursive integer, in auth_uid integer) returns any
{
declare cfc_id integer;
declare rfc_spath varchar;
declare rfc_list_cond, rfc_del_action any;
declare davpath, prev_raw_name varchar;
declare res, itm, reps any;
declare itm_ctr, itm_count, prev_is_patched integer;
-- dbg_obj_princ ('CatFilter_DAV_DIR_FILTER (', detcol_id, path_parts, detcol_path, compilation, recursive, auth_uid, ')');
if (0 > "CatFilter_GET_CONDITION" (detcol_id, cfc_id, rfc_spath, rfc_list_cond, rfc_del_action))
{
-- dbg_obj_princ ('broken filter - no items');
return vector();
}
if (0 = length (get_keyword ('', compilation)))
res := DAV_DIR_FILTER_INT (rfc_spath, 1, rfc_list_cond, null, null, auth_uid);
else
{
declare tmp_cond any;
tmp_cond := vector ('',
vector_concat (
get_keyword ('', compilation),
get_keyword ('', rfc_list_cond) ) );
res := DAV_DIR_FILTER_INT (rfc_spath, 1, tmp_cond, null, null, auth_uid);
}
reps := dict_new ();
itm_count := length (res);
for (itm_ctr := 0; itm_ctr < itm_count; itm_ctr := itm_ctr + 1)
{
declare rname varchar;
declare orig_id integer;
itm := res [itm_ctr];
rname := itm [10];
orig_id := itm[4];
if (isarray (orig_id) or regexp_parse ('^([^/][^./]*) -Rf((Id[1-9][0-9]*)|([A-Z][A-Za-z0-9]+)-([A-Za-z0-9~+-]*))([.][^/]*)?\044', rname, 0)) -- Suspicious names should be qualified
res [itm_ctr][10] := rname := "ResFilter_FNMERGE" (rname, orig_id);
dict_put (reps, rname, dict_get (reps, rname, 0) + 1);
}
for (itm_ctr := 0; itm_ctr < itm_count; itm_ctr := itm_ctr + 1)
{
declare rname varchar;
declare orig_id integer;
itm := res [itm_ctr];
rname := itm [10];
orig_id := itm[4];
res[itm_ctr][4] := vector (UNAME'CatFilter', detcol_id, orig_id);
if (dict_get (reps, rname, 0) > 1) -- Suspicious names should be qualified
res [itm_ctr][10] := rname := "ResFilter_FNMERGE" (rname, orig_id);
res[itm_ctr][0] := DAV_CONCAT_PATH (DAV_CONCAT_PATH (detcol_path, path_parts), rname);
}
return res;
}
;
create function "CatFilter_DAV_SEARCH_ID" (in detcol_id any, in path_parts any, in what char(1)) returns any
{
declare cfc_id integer;
declare rfc_spath varchar;
declare rfc_list_cond, rfc_del_action any;
declare orig_id, filter_data any;
-- dbg_obj_princ ('CatFilter_DAV_SEARCH_ID (', detcol_id, path_parts, what, ')');
rfc_spath := null;
orig_id := "CatFilter_DAV_SEARCH_ID_IMPL" (detcol_id, path_parts, what, cfc_id, rfc_spath, rfc_list_cond, rfc_del_action, filter_data);
return orig_id;
}
;
create function "CatFilter_DAV_SEARCH_PATH" (in id any, in what char(1)) returns any
{
-- dbg_obj_princ ('CatFilter_DAV_SEARCH_PATH (', id, what, ')');
if ('R' = what)
return coalesce ((select RES_FULL_PATH from WS.WS.SYS_DAV_RES where RES_ID = id[2]), null);
if ('C' = what)
{
declare res varchar;
res := DAV_SEARCH_PATH (id[1], 'C');
if (id[3] is not null)
{
-- TBD
;
}
if (id[4] is not null)
{
-- TBD
;
}
return res;
}
return -14;
}
;
create function "CatFilter_DAV_RES_UPLOAD_COPY" (in detcol_id any, in path_parts any, in source_id any, in what char(1), in overwrite integer, in permissions varchar, in uid integer, in gid integer, in auth_uid integer) returns any
{
declare cfc_id integer;
declare rfc_spath, schema_uri varchar;
declare rfc_list_cond, rfc_del_action, filter_data, fit_cond any;
declare rc integer;
-- dbg_obj_princ ('CatFilter_DAV_RES_UPLOAD_COPY (', detcol_id, path_parts, source_id, what, overwrite, permissions, uid, gid, auth_uid, ')');
if (0 > "CatFilter_GET_CONDITION" (detcol_id, cfc_id, rfc_spath, rfc_list_cond, rfc_del_action))
{
-- dbg_obj_princ ('broken filter - no items');
return -2;
}
if (length (rfc_del_action) < length (rfc_list_cond))
{
-- dbg_obj_princ ('del_action = ', rfc_del_action, 'rfc_list_cond = ', rfc_list_cond);
return -13;
}
rc := "CatFilter_PATH_PARTS_TO_FILTER" (path_parts, schema_uri, filter_data);
if (DAV_HIDE_ERROR (rc) is null)
return rc;
rc := "CatFilter_FILTER_TO_CONDITION" (schema_uri, filter_data, fit_cond);
if (DAV_HIDE_ERROR (rc) is null)
return rc;
fit_cond := vector ('', vector_concat (fit_cond, get_keyword ('', rfc_list_cond)));
if ('R' <> what)
return -2;
if ('' = path_parts [length (path_parts) - 1])
return -2;
if (isinteger (source_id) and
exists (select 1 from WS.WS.SYS_DAV_RES
where RES_ID = source_id and RES_NAME = path_parts [length (path_parts) - 1] and (RES_FULL_PATH between rfc_spath and DAV_COL_PATH_BOUNDARY (rfc_spath)) ) )
{
"ResFilter_FIT_INTO_CONDITION" (source_id, what, fit_cond, auth_uid);
}
else
{
declare new_full_path varchar;
new_full_path := DAV_CONCAT_PATH (rfc_spath, path_parts [length (path_parts) - 1]);
rc := DAV_COPY_INT (DAV_SEARCH_PATH (source_id, what), new_full_path, overwrite, permissions,
coalesce ((select U_NAME from WS.WS.SYS_DAV_USER where U_ID = uid), ''),
coalesce ((select G_NAME from WS.WS.SYS_DAV_GROUP where G_ID = gid), ''),
null, null, 0);
if (DAV_HIDE_ERROR (rc) is null)
return rc;
source_id := DAV_SEARCH_ID (new_full_path, what);
if (DAV_HIDE_ERROR (source_id) is null)
return source_id;
if (not (isinteger (source_id)))
return -13;
"ResFilter_FIT_INTO_CONDITION" (source_id, what, fit_cond, auth_uid);
}
return 1;
}
;
create function "CatFilter_DAV_RES_UPLOAD_MOVE" (in detcol_id any, in path_parts any, in source_id any, in what char(1), in overwrite integer, in auth_uid integer) returns any
{
declare cfc_id integer;
declare rfc_spath, schema_uri varchar;
declare rfc_list_cond, rfc_del_action, filter_data, fit_cond any;
declare rc integer;
-- dbg_obj_princ ('CatFilter_DAV_RES_UPLOAD_MOVE (', detcol_id, path_parts, source_id, what, overwrite, auth_uid, ')');
if (0 > "CatFilter_GET_CONDITION" (detcol_id, cfc_id, rfc_spath, rfc_list_cond, rfc_del_action))
{
-- dbg_obj_princ ('broken filter - no items');
return -2;
}
if (length (rfc_del_action) < length (rfc_list_cond))
{
-- dbg_obj_princ ('del_action = ', rfc_del_action, 'rfc_list_cond = ', rfc_list_cond);
return -13;
}
rc := "CatFilter_PATH_PARTS_TO_FILTER" (path_parts, schema_uri, filter_data);
if (DAV_HIDE_ERROR (rc) is null)
return rc;
rc := "CatFilter_FILTER_TO_CONDITION" (schema_uri, filter_data, fit_cond);
if (DAV_HIDE_ERROR (rc) is null)
return rc;
fit_cond := vector ('', vector_concat (fit_cond, get_keyword ('', rfc_list_cond)));
if ('R' <> what)
return -2;
if ('' = path_parts [length (path_parts) - 1])
return -2;
if (isinteger (source_id) and
exists (select 1 from WS.WS.SYS_DAV_RES
where RES_ID = source_id and RES_NAME = path_parts [length (path_parts) - 1] and (RES_FULL_PATH between rfc_spath and DAV_COL_PATH_BOUNDARY (rfc_spath))))
{
"ResFilter_FIT_INTO_CONDITION" (source_id, what, fit_cond, auth_uid);
}
else
{
declare new_full_path varchar;
new_full_path := DAV_CONCAT_PATH (rfc_spath, path_parts [length (path_parts) - 1]);
rc := DAV_MOVE_INT (DAV_SEARCH_PATH (source_id, what), new_full_path, overwrite, null, null, 0, 1);
if (DAV_HIDE_ERROR (rc) is null)
return rc;
source_id := DAV_SEARCH_ID (new_full_path, what);
if (DAV_HIDE_ERROR (source_id) is null)
return source_id;
if (not (isinteger (source_id)))
return -13;
"ResFilter_FIT_INTO_CONDITION" (source_id, what, fit_cond, auth_uid);
}
return 1;
}
;
create function "CatFilter_DAV_RES_CONTENT" (in id any, inout content any, out type varchar, in content_mode integer) returns integer
{
-- dbg_obj_princ ('CatFilter_DAV_RES_CONTENT (', id, ', [content], [type], ', content_mode, ')');
declare cont any;
if ((content_mode = 0) or (content_mode = 2))
select RES_CONTENT, RES_TYPE into content, type from WS.WS.SYS_DAV_RES where RES_ID = id[2];
else if (content_mode = 1)
select http (RES_CONTENT, content), RES_TYPE into cont, type from WS.WS.SYS_DAV_RES where RES_ID = id[2];
else if (content_mode = 3)
select http (RES_CONTENT), RES_TYPE into cont, type from WS.WS.SYS_DAV_RES where RES_ID = id[2];
return id[2];
}
;
create function "CatFilter_DAV_SYMLINK" (in detcol_id any, in path_parts any, in source_id any, in what char(1), in overwrite integer, in uid integer, in gid integer, in auth_uid integer) returns any
{
-- dbg_obj_princ ('CatFilter_DAV_SYMLINK (', detcol_id, path_parts, source_id, overwrite, uid, gid, auth_uid, ')');
return -20;
}
;
create function "CatFilter_DAV_LOCK" (in path any, inout id any, in type char(1), inout locktype varchar, inout scope varchar, in token varchar, inout owner_name varchar, inout owned_tokens varchar, in depth varchar, in timeout_sec integer, in auth_uid integer) returns any
{
declare rc, u_token, new_token varchar;
-- dbg_obj_princ ('CatFilter_DAV_LOCK (', path, id, type, locktype, scope, token, owner_name, owned_tokens, depth, timeout_sec, auth_uid, ')');
if ('R' <> type)
return -20;
if (DAV_HIDE_ERROR (id) is null)
return -20;
if (isarray (id))
return DAV_LOCK_INT (path, id[2], type, locktype, scope, token, owner_name, owned_tokens, depth, timeout_sec, null, null, auth_uid);
return -20;
}
;
create function "CatFilter_DAV_UNLOCK" (in id any, in type char(1), in token varchar, in auth_uid integer)
{
-- dbg_obj_princ ('CatFilter_DAV_UNLOCK (', id, type, token, auth_uid, ')');
if (isarray (id))
id := id [2];
return DAV_UNLOCK_INT (id, type, token, null, null, auth_uid);
}
;
create function "CatFilter_DAV_IS_LOCKED" (inout id any, inout type char(1), in owned_tokens varchar) returns integer
{
declare rc integer;
declare orig_id any;
declare orig_type char(1);
-- dbg_obj_princ ('CatFilter_DAV_IS_LOCKED (', id, type, owned_tokens, ')');
orig_id := id;
id := orig_id[2];
rc := DAV_IS_LOCKED_INT (id, type, owned_tokens);
if (rc <> 0)
return rc;
id := orig_id[1];
orig_type := type;
type := 'C';
rc := DAV_IS_LOCKED_INT (id, type, owned_tokens);
if (rc <> 0)
return rc;
id := orig_id;
type := orig_type;
return 0;
}
;
create function "CatFilter_DAV_LIST_LOCKS" (in id any, in type char(1), in recursive integer) returns any
{
declare res any;
-- dbg_obj_princ ('CatFilter_DAV_LIST_LOCKS" (', id, type, recursive);
id := id[2];
if (isarray (id))
return call (cast (id[0] as varchar) || '_DAV_LIST_LOCKS') (id, type, recursive);
res := vector();
for select LOCK_TYPE, LOCK_SCOPE, LOCK_TOKEN, LOCK_TIMEOUT, LOCK_OWNER, LOCK_OWNER_INFO
from WS.WS.SYS_DAV_LOCK where LOCK_PARENT_ID = id and LOCK_PARENT_TYPE = type do {
res := vector_concat (res, vector (vector (LOCK_TYPE, LOCK_SCOPE, LOCK_TOKEN, LOCK_TIMEOUT, LOCK_OWNER, LOCK_OWNER_INFO)));
}
return res;
}
;
create function "CatFilter_CONFIGURE" (in col any, in search_path varchar, in filter any, in auth_uname varchar := 'dav', in auth_upwd varchar := 'dav', in auth_uid integer := null) returns integer
{
declare cfid, rc, ctr integer;
declare colname varchar;
declare compilation, del_act any;
compilation := vector ('', filter);
rc := DAV_DIR_FILTER_INT (search_path, 1, compilation, auth_uname, auth_upwd, auth_uid);
if (isinteger (rc))
return rc;
if (not isinteger (col))
return -20;
colname := DAV_SEARCH_PATH (col, 'C');
if (not (isstring (colname)))
return -23;
rc := DAV_SEARCH_ID (search_path, 'C');
if (DAV_HIDE_ERROR (rc) is null)
return rc;
if (search_path <> DAV_SEARCH_PATH (rc, 'C'))
return -2;
if (search_path between colname and (colname || '\255\255\255\255'))
return -28;
rc := DAV_PROP_SET_INT (colname, 'virt:ResFilter-SearchPath', search_path, null, null, 0, 1, 1);
if (DAV_HIDE_ERROR (rc) is null)
return rc;
rc := DAV_PROP_SET_INT (colname, 'virt:ResFilter-ListCond', "ResFilter_ENCODE_FILTER" (compilation), null, null, 0, 1, 1);
if (DAV_HIDE_ERROR (rc) is null)
return rc;
del_act := "ResFilter_MAKE_DEL_ACTION_FROM_CONDITION" (compilation);
-- dbg_obj_princ ('ResFilter_CONFIGURE has made del_action ', del_act, ' from ', compilation);
rc := DAV_PROP_SET_INT (colname, 'virt:ResFilter-DelAction', "ResFilter_ENCODE_FILTER" (del_act), null, null, 0, 1, 1);
if (DAV_HIDE_ERROR (rc) is null)
return rc;
cfid := coalesce ((select CF_ID from WS.WS.SYS_DAV_CATFILTER where CF_SEARCH_PATH = search_path));
if (cfid is null)
{
declare search_path_z varchar;
cfid := WS.WS.GETID ('CF');
insert into WS.WS.SYS_DAV_CATFILTER (CF_ID, CF_SEARCH_PATH) values (cfid, search_path);
search_path_z := search_path || '\255\255\255\255';
for (select p.PROP_VALUE, p.PROP_PARENT_ID
from WS.WS.SYS_DAV_RES r join WS.WS.SYS_DAV_PROP p on (r.RES_ID = p.PROP_PARENT_ID)
where (r.RES_FULL_PATH between search_path and search_path_z) and (p.PROP_NAME = 'http://local.virt/DAV-RDF') and (p.PROP_TYPE = 'R')) do
{
"CatFilter_FEED_DAV_RDF_INVERSE" (PROP_VALUE, PROP_PARENT_ID, 0, cfid);
ctr := ctr + 1;
if (mod (ctr, 1000) = 0)
commit work;
}
commit work;
for (select COL_ID, COL_DET, WS.WS.COL_PATH (COL_ID) as _c_path from WS.WS.SYS_DAV_COL where COL_DET is not null and not (COL_DET like '%Filter')) do
{
if ("LEFT" (_c_path, length (search_path)) = search_path)
{
insert replacing WS.WS.SYS_DAV_CATFILTER_DETS (CFD_CF_ID, CFD_DET_SUBCOL_ID, CFD_DET)
values (cfid, COL_ID, COL_DET);
}
}
}
-- if (search_path between colname and (colname || '\255\255\255\255'))
-- return -28;
-- if (colname between search_path and (search_path || '\255\255\255\255'))
-- return -28;
rc := DAV_PROP_SET_INT (colname, 'virt:CatFilter-ID', cast (cfid as varchar), null, null, 0, 1, 1);
if (DAV_HIDE_ERROR (rc) is null)
return rc;
update WS.WS.SYS_DAV_COL set COL_DET='CatFilter' where COL_ID=col;
return 0;
}
;
create procedure "CatFilter_FEED_DAV_RDF_INVERSE" (inout propval any, inout propparent integer, in is_del integer := 0, in cfid integer := null)
{
declare resfullpath, path_head, pv varchar;
declare doc any;
declare triplets any;
if (126 = __tag (propval))
pv := blob_to_string (propval);
else
{
if ((not isstring (propval)) or (propval = ''))
return;
pv := propval;
}
if (193 <> pv[0])
return;
doc := null;
if (cfid is not null)
{
path_head := '/';
goto cfid_found;
}
else
{
resfullpath := coalesce ((select r.RES_FULL_PATH from WS.WS.SYS_DAV_RES r where r.RES_ID = propparent));
if (resfullpath is null)
return;
path_head := subseq (resfullpath, 0, strrchr (resfullpath, '/'));
}
next_cfid:
while (1)
{
if (length (path_head) <= 1)
return;
cfid := coalesce ((select CF_ID from WS.WS.SYS_DAV_CATFILTER where CF_SEARCH_PATH = (path_head || '/')));
path_head := subseq (path_head, 0, strrchr (path_head, '/'));
if (cfid is not null)
goto cfid_found;
}
cfid_found:
if (doc is null)
{
doc := deserialize (pv);
if (0 = length (doc))
return;
doc := xml_tree_doc (doc);
}
-- dbg_obj_princ ('CatFilter_INS_DAV_RDF_INVERSE: saving res ', propparent, ' in catfilter ', cfid);
triplets := xpath_eval ('[xmlns:virt="virt"] /virt:rdf/virt:top-res/virt:prop[virt:value]', doc, 0);
foreach (any prop in triplets) do
{
declare propname varchar;
declare prop_catid integer;
propname := cast (xpath_eval ('name(*[1])', prop) as varchar);
prop_catid := coalesce ((select RPN_CATID from WS.WS.SYS_RDF_PROP_NAME where RPN_URI = propname));
if (prop_catid is null)
{
prop_catid := WS.WS.GETID ('RPN');
-- dbg_obj_princ ('CatFilter_INS_DAV_RDF_INVERSE: insert into WS.WS.SYS_RDF_PROP_NAME (RPN_URI, RPN_CATID) values (', propname, prop_catid, ')');
insert into WS.WS.SYS_RDF_PROP_NAME (RPN_URI, RPN_CATID) values (propname, prop_catid);
}
if (is_del)
delete from WS.WS.SYS_DAV_RDF_INVERSE
where
(DRI_CATF_ID = cfid) and (DRI_PROP_CATID = prop_catid) and
(DRI_CATVALUE = "CatFilter_ENCODE_CATVALUE" (cast (xpath_eval ('[xmlns:virt="virt"] virt:value', prop) as varchar))) and
(DRI_RES_ID = propparent);
else
insert soft WS.WS.SYS_DAV_RDF_INVERSE (DRI_CATF_ID, DRI_PROP_CATID, DRI_CATVALUE, DRI_RES_ID)
values (
cfid,
prop_catid,
"CatFilter_ENCODE_CATVALUE" (cast (xpath_eval ('[xmlns:virt="virt"] virt:value', prop) as varchar)),
propparent );
}
goto next_cfid;
}
;
create trigger SYS_DAV_PROP_VALUE_RDF_I after insert on WS.WS.SYS_DAV_PROP order 10 referencing new as NP
{
if (NP.PROP_NAME <> 'http://local.virt/DAV-RDF')
return;
if (NP.PROP_TYPE <> 'R')
return;
"CatFilter_FEED_DAV_RDF_INVERSE" (NP.PROP_VALUE, NP.PROP_PARENT_ID);
}
;
create trigger SYS_DAV_PROP_VALUE_RDF_D before delete on WS.WS.SYS_DAV_PROP order 10 referencing old as OP
{
declare pv varchar;
declare doc any;
if (OP.PROP_NAME <> 'http://local.virt/DAV-RDF')
return;
if (OP.PROP_TYPE <> 'R')
return;
"CatFilter_FEED_DAV_RDF_INVERSE" (OP.PROP_VALUE, OP.PROP_PARENT_ID, 1);
}
;
create trigger SYS_DAV_PROP_VALUE_RDF_U after update on WS.WS.SYS_DAV_PROP order 10 referencing old as OP, new as NP
{
declare pv varchar;
declare doc any;
if (OP.PROP_NAME <> 'http://local.virt/DAV-RDF')
goto register_new_propvals;
if (OP.PROP_TYPE <> 'R')
goto register_new_propvals;
"CatFilter_FEED_DAV_RDF_INVERSE" (OP.PROP_VALUE, OP.PROP_PARENT_ID, 1);
register_new_propvals:
if (NP.PROP_NAME <> 'http://local.virt/DAV-RDF')
return;
if (NP.PROP_TYPE <> 'R')
return;
"CatFilter_FEED_DAV_RDF_INVERSE" (NP.PROP_VALUE, NP.PROP_PARENT_ID);
}
;
create procedure "CatFilter_INIT_SYS_DAV_RDF_INVERSE" (in run_if_once integer)
{
declare ctr integer;
set isolation = 'committed';
if (run_if_once)
{
if (0 <> sequence_next('CatFilter_INIT_SYS_DAV_RDF_INVERSE'))
return;
}
else
{
-- For safety, schemas should be recompiled.
update WS.WS.SYS_RDF_SCHEMAS set RS_PRECOMPILED = null, RS_PROP_CATNAMES = null;
commit work;
delete from WS.WS.SYS_DAV_RDF_INVERSE;
}
commit work;
for (select PROP_VALUE, PROP_PARENT_ID from WS.WS.SYS_DAV_PROP where PROP_NAME = 'http://local.virt/DAV-RDF' and PROP_TYPE = 'R') do
{
"CatFilter_FEED_DAV_RDF_INVERSE" (PROP_VALUE, PROP_PARENT_ID);
ctr := ctr + 1;
if (mod (ctr, 1000) = 0)
commit work;
}
}
;