<docbook><section><title>VOSBookmarksDETAPI</title><programlisting>--  
--  $Id: DET_Bookmark.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
;

create function &quot;bookmark_FIXNAME&quot; (in mailname any) returns varchar
{
  return
      replace (
        replace (
          replace (
            replace (
              replace (
                replace (
                  replace (mailname, &#39;/&#39;, &#39;_&#39;), &#39;\\&#39;, &#39;_&#39;), &#39;:&#39;, &#39;_&#39;), &#39;+&#39;, &#39;_&#39;), &#39;\&quot;&#39;, &#39;_&#39;), &#39;[&#39;, &#39;_&#39;), &#39;]&#39;, &#39;_&#39;);
}
;

create function &quot;bookmark_COMPOSE_XBEL_NAME&quot; (in title varchar, in id integer) returns varchar
{
  if (title is null or title = &#39;&#39;)
    return &quot;bookmark_FIXNAME&quot;(sprintf(&#39;%d.xbel&#39;, id));
  return &quot;bookmark_FIXNAME&quot;(sprintf(&#39;%s (%d).xbel&#39;, title, id));
}
;

create function &quot;bookmark_ACCESS_PARAMS&quot; (in detcol_id any, out access varchar, out gid integer, out uid integer)
{
  declare access_tmp varchar;
  whenever not found goto ret;
  access := &#39;100000000NN&#39;;
  gid := http_nogroup_gid ();
  uid := http_nobody_uid ();
  if (isinteger (detcol_id))
  {
    select COL_PERMS, COL_GROUP, COL_OWNER into access_tmp, gid, uid from WS.WS.SYS_DAV_COL where COL_ID = detcol_id;
  }
  access[0] := access_tmp[0];
  access[1] := access_tmp[1];
--  access[3] := access_tmp[3];
ret:
  ;
}
;

--| This matches DAV_AUTHENTICATE (in id any, in what char(1), in req varchar, in a_uname varchar, in a_pwd varchar, in a_uid integer := null)
--| The difference is that the DET function should not check whether the pair of name and password is valid; the auth_uid is not a null already.
create function &quot;bookmark_DAV_AUTHENTICATE&quot; (in id any, in what char(1), in req varchar, in auth_uname varchar, in auth_pwd varchar, in auth_uid integer)
{
  --dbg_obj_princ (&#39;bookmark_DAV_AUTHENTICATE (&#39;, id, what, req, auth_uname, auth_pwd, auth_uid, http_dav_uid(), &#39;)&#39;);
  if (auth_uid &lt; 0)
    return -12;
  if (not (&#39;100&#39; like req))
  {
    --dbg_obj_princ (&#39;a_uid2 is &#39;, auth_uid, &#39;, id[3] is &#39;, id[2], &#39; mismatch&#39;);
    return -13;
  }
  if ((auth_uid &lt;&gt; id[2]) and (auth_uid &lt;&gt; http_dav_uid()))
  {
    --dbg_obj_princ (&#39;a_uid is &#39;, auth_uid, &#39;, id[3] is &#39;, id[2], &#39; mismatch&#39;);
    return -13;
  }
  return auth_uid;
}
;

--| This exactly matches 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
--| The function should fully check access because DAV_AUTHENTICATE_HTTP do nothing with auth data either before or after calling this DET function.
--| Unlike DAV_AUTHENTICATE, user name passed to DAV_AUTHENTICATE_HTTP header may not match real DAV user.
--| If DET call is successful, DAV_AUTHENTICATE_HTTP checks whether the user have read permission on mount point collection.
--| Thus even if DET function allows anonymous access, the whole request may fail if mountpoint is not readable by public.
create function &quot;bookmark_DAV_AUTHENTICATE_HTTP&quot; (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 rc integer;
        declare puid, pgid, ruid, rgid integer;
        declare u_password, pperms varchar;
        -- anon are never allowed for mails! declare allow_anon integer;
        if (length (req) &lt;&gt; 3)
                return -15;
        whenever not found goto nf_col_or_res;
        if ((what &lt;&gt; &#39;R&#39;) and (what &lt;&gt; &#39;C&#39;))
                return -14;
        -- allow_anon := WS.WS.PERM_COMP (substring (cast (pperms as varchar), 7, 3), req);
        if (a_uid is null)
        {
                -- if ((not allow_anon) or (&#39;&#39; &lt;&gt; WS.WS.FINDPARAM (a_lines, &#39;Authorization:&#39;)))
                rc := WS.WS.GET_DAV_AUTH (a_lines, 0, can_write_http, a_uname, u_password, a_uid, a_gid, _perms);
                if (rc &lt; 0)
                        return rc;
        }
        if (isinteger (a_uid))
        {
                if (a_uid &lt; 0)
                        return a_uid;
                if (a_uid = 1) -- Anonymous FTP
                {
                        a_uid := http_nobody_uid ();
                        a_gid := http_nogroup_gid ();
                }
        }
        if ((a_uid &lt;&gt; id[2]) and (a_uid &lt;&gt; http_dav_uid()))
        {
                -- dbg_obj_princ (&#39;a_uid is &#39;, a_uid, &#39;, id[3] is &#39;, id[3], &#39; mismatch&#39;);
                return -13;
        }
        if (not (&#39;100&#39; like req))
                return -13;
        return a_uid;
nf_col_or_res:
        return -1;
}
;


--| This matches DAV_GET_PARENT (in id any, in st char(1), in path varchar) returns any
create function &quot;bookmark_DAV_GET_PARENT&quot; (in id any, in st char(1), in path varchar) returns any
{
  -- dbg_obj_princ (&#39;bookmark_DAV_GET_PARENT (&#39;, id, st, path, &#39;)&#39;);
  return -20;
}
;

--| When DAV_COL_CREATE_INT calls DET function, authentication, check for lock and check for overwrite are passed, uid and gid are translated from strings to IDs.
--| Check for overwrite, but the deletion of previously existing collection should be made by DET function.
create function &quot;bookmark_DAV_COL_CREATE&quot; (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 (&#39;bookmark_DAV_COL_CREATE (&#39;, detcol_id, path_parts, permissions, uid, gid, auth_uid, &#39;)&#39;);
  return -20;
}
;

--| It looks like that this is redundant and should be removed at all.
create function &quot;bookmark_DAV_COL_MOUNT&quot; (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 (&#39;bookmark_DAV_COL_MOUNT (&#39;, detcol_id, path_parts, full_mount_path, mount_det, permissions, uid, gid, auth_uid, &#39;)&#39;);
  return -20;
}
;

--| It looks like that this is redundant and should be removed at all.
create function &quot;bookmark_DAV_COL_MOUNT_HERE&quot; (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 (&#39;bookmark_DAV_COL_MOUNT_HERE (&#39;, parent_id, full_mount_path, permissions, uid, gid, auth_uid, &#39;)&#39;);
  return -20;
}
;


--| When DAV_DELETE_INT calls DET function, authentication and check for lock are passed.
create function &quot;bookmark_DAV_DELETE&quot; (in detcol_id any, in path_parts any, in what char(1), in silent integer, in auth_uid integer) returns integer
{
  -- dbg_obj_princ (&#39;bookmark_DAV_DELETE (&#39;, detcol_id, path_parts, what, silent, auth_uid, &#39;)&#39;);
  return -20;
}
;

--| When DAV_RES_UPLOAD_STRSES_INT calls DET function, authentication and check for locks are performed before the call.
--| There&#39;s a special problem, known as &#39;Transaction deadlock after reading from HTTP session&#39;.
--| The DET function should do only one INSERT of the &#39;content&#39; into the table and do it as late as possible.
--| The function should return -29 if deadlocked or otherwise broken after reading blob from HTTP.
create function &quot;bookmark_DAV_RES_UPLOAD&quot; (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
{
  -- dbg_obj_princ (&#39;bookmark_DAV_RES_UPLOAD (&#39;, detcol_id, path_parts, &#39;, [content], &#39;, content, type, permissions, uid, gid, auth_uid, &#39;)&#39;);
  return -20;
}
;


--| When DAV_PROP_REMOVE_INT calls DET function, authentication and check for locks are performed before the call.
--| The check whether it&#39;s a system name or not is _not_ permitted.
create function &quot;bookmark_DAV_PROP_REMOVE&quot; (in id any, in what char(0), in propname varchar, in silent integer, in auth_uid integer) returns integer
{
  -- dbg_obj_princ (&#39;bookmark_DAV_PROP_REMOVE (&#39;, id, what, propname, silent, auth_uid, &#39;)&#39;);
  return -20;
}
;

--| When DAV_PROP_SET_INT calls DET function, authentication and check for locks are performed before the call.
--| The check whether it&#39;s a system property or not is _not_ permitted and the function should return -16 for live system properties.
create function &quot;bookmark_DAV_PROP_SET&quot; (in id any, in what char(0), in propname varchar, in propvalue any, in overwrite integer, in auth_uid integer) returns any
{
  -- dbg_obj_princ (&#39;bookmark_DAV_PROP_SET (&#39;, id, what, propname, propvalue, overwrite, auth_uid, &#39;)&#39;);
  if (propname[0] = 58)
    {
      return -16;
    }
  return -20;
}
;

--| When DAV_PROP_GET_INT calls DET function, authentication and check whether it&#39;s a system property are performed before the call.
create function &quot;bookmark_DAV_PROP_GET&quot; (in id any, in what char(0), in propname varchar, in auth_uid integer)
{
  -- dbg_obj_princ (&#39;bookmark_DAV_PROP_GET (&#39;, id, what, propname, auth_uid, &#39;)&#39;);
  return -11;
}
;

--| When DAV_PROP_LIST_INT calls DET function, authentication is performed before the call.
--| The returned list should contain only user properties.
create function &quot;bookmark_DAV_PROP_LIST&quot; (in id any, in what char(0), in propmask varchar, in auth_uid integer)
{
  -- dbg_obj_princ (&#39;bookmark_DAV_PROP_LIST (&#39;, id, what, propmask, auth_uid, &#39;)&#39;);
  return vector ();
}
;

--| When DAV_PROP_GET_INT or DAV_DIR_LIST_INT calls DET function, authentication is performed before the call.
create function &quot;bookmark_DAV_DIR_SINGLE&quot; (in id any, in what char(0), in path any, in auth_uid integer) returns any
{
        declare sub_id, folder_id, domain_id integer;
        declare colname, fullpath, rightcol, tag_id varchar;
        declare maxrcvdate datetime;
        --dbg_obj_princ (&#39;bookmark_DAV_DIR_SINGLE (&#39;, id, what, path, auth_uid, &#39;)&#39;);
        sub_id := id[3];
        domain_id := id[4];
        folder_id := id[5];
        tag_id := id[7];
        fullpath := &#39;&#39;;
        rightcol := &#39;&#39;;
        if (folder_id &gt; 0)
        {
                if (sub_id = 1)
                {
                        while (folder_id &gt; 0)
                        {
                                colname := (select &quot;bookmark_FIXNAME&quot; (F_NAME)
                                        from BMK.WA.FOLDER
                                        where F_DOMAIN_ID = domain_id and F_ID = folder_id);
                                if (DAV_HIDE_ERROR (colname) is null)
                                        return -1;
                                if (rightcol = &#39;&#39;)
                                        rightcol := colname;
                                fullpath := colname || &#39;/&#39; || fullpath;
                                folder_id := coalesce((select F_PARENT_ID from BMK.WA.FOLDER where F_ID = folder_id), 0);
                        }
                }
                else if (sub_id = 2)
                {
                        if (maxrcvdate is null)
                                maxrcvdate := coalesce ( (select max(BD_LAST_UPDATE) from BMK.WA.BOOKMARK_DOMAIN where year(BD_LAST_UPDATE) = domain_id),
                                        cast (&#39;1980-01-01&#39; as datetime));
                        colname := (select monthname(D.BD_LAST_UPDATE)
                                from SYS_USERS A,
                                        WA_MEMBER B,
                                        WA_INSTANCE C,
                                        BMK.WA.BOOKMARK_DOMAIN D
                                where A.U_ID = id[2]
                                        and B.WAM_USER = A.U_ID
                                        and B.WAM_MEMBER_TYPE = 1
                                        and B.WAM_INST = C.WAI_NAME
                                        and C.WAI_TYPE_NAME = &#39;Bookmark&#39;
                                        and D.BD_DOMAIN_ID = C.WAI_ID
                                        and month(D.BD_LAST_UPDATE) = folder_id
                                        and year(D.BD_LAST_UPDATE) = domain_id);
                        if (DAV_HIDE_ERROR (colname) is null)
                                return -1;
                        if (rightcol = &#39;&#39;)
                                rightcol := colname;
                        fullpath := colname || &#39;/&#39; || fullpath;
                }
        }
        if (domain_id &lt;&gt; 0)
        {
                if (sub_id = 1)
                {
                        if (maxrcvdate is null)
                                maxrcvdate := coalesce ( (select max(BD_LAST_UPDATE) from BMK.WA.BOOKMARK_DOMAIN where BD_DOMAIN_ID = domain_id),
                                        cast (&#39;1980-01-01&#39; as datetime));
                        colname := (select &quot;bookmark_FIXNAME&quot;(C.WAI_NAME) as orig_name
                                from SYS_USERS A,
                                        WA_MEMBER B,
                                        WA_INSTANCE C
                                where A.U_ID = id[2]
                                        and B.WAM_USER = A.U_ID
                                        and B.WAM_MEMBER_TYPE = 1
                                        and B.WAM_INST = C.WAI_NAME
                                        and C.WAI_TYPE_NAME = &#39;Bookmark&#39;
                                        and C.WAI_ID = domain_id);
                }
                else if (sub_id = 2)
                {
                        if (maxrcvdate is null)
                                maxrcvdate := coalesce ( (select max(BD_LAST_UPDATE) from BMK.WA.BOOKMARK_DOMAIN where year(BD_LAST_UPDATE) = domain_id),
                                        cast (&#39;1980-01-01&#39; as datetime));
                        colname := (select cast(year(D.BD_LAST_UPDATE) as varchar)
                                from SYS_USERS A,
                                        WA_MEMBER B,
                                        WA_INSTANCE C,
                                        BMK.WA.BOOKMARK_DOMAIN D
                                where A.U_ID = id[2]
                                        and B.WAM_USER = A.U_ID
                                        and B.WAM_MEMBER_TYPE = 1
                                        and B.WAM_INST = C.WAI_NAME
                                        and C.WAI_TYPE_NAME = &#39;Bookmark&#39;
                                        and D.BD_DOMAIN_ID = C.WAI_ID
                                        and year(D.BD_LAST_UPDATE) = domain_id);
                }
        }
        if (tag_id is not null)
        {
                if (sub_id = 3)
                {
                        if (maxrcvdate is null)
                                maxrcvdate := coalesce ( (select max(T_LAST_UPDATE) from BMK.WA.TAGS where T_TAG = tag_id), cast (&#39;1980-01-01&#39; as datetime));
                        colname := (select T_TAG
                                from SYS_USERS A,
                                        WA_MEMBER B,
                                        WA_INSTANCE C,
                                        BMK.WA.TAGS T
                                where A.U_ID = id[2]
                                        and B.WAM_USER = A.U_ID
                                        and B.WAM_MEMBER_TYPE = 1
                                        and B.WAM_INST = C.WAI_NAME
                                        and C.WAI_TYPE_NAME = &#39;Bookmark&#39;
                                        and T.T_DOMAIN_ID = C.WAI_ID
                                        and T.T_TAG = tag_id);
                }
                if (DAV_HIDE_ERROR (colname) is null)
                        return -1;
                if (rightcol = &#39;&#39;)
                        rightcol := colname;
                fullpath := colname || &#39;/&#39; || fullpath; 
        }
        if (sub_id &lt;&gt; 0)
        {
                if (sub_id = 1)
                        colname := &#39;bookmark&#39;;
                else if (sub_id = 2)
                        colname := &#39;date&#39;;
                else if (sub_id = 3)
                        colname := &#39;tags&#39;;
                else
                        colname := &#39;bookmark&#39;;
                if (DAV_HIDE_ERROR (colname) is null)
                        return -1;
                if (rightcol = &#39;&#39;)
                        rightcol := colname;
                fullpath := colname || &#39;/&#39; || fullpath;
        }
        fullpath := DAV_CONCAT_PATH (DAV_SEARCH_PATH (id[1], &#39;C&#39;), fullpath);
        if (&#39;C&#39; = what)
        {
                if (id[6] &gt;= 0)
                        return -1;
                return vector (fullpath, &#39;C&#39;, 0, maxrcvdate, id, &#39;100000000NN&#39;,
                        0, id[2], maxrcvdate, &#39;dav/unix-directory&#39;, rightcol );
        }
        for select &quot;bookmark_COMPOSE_XBEL_NAME&quot;(BD_NAME, BD_ID) as orig_mname,
                BD_ID as m_id, BD_LAST_UPDATE
                from BMK.WA.BOOKMARK_DOMAIN
                where BD_ID = id[6]
        do
        {
                return vector (fullpath || orig_mname, &#39;R&#39;, 1024, BD_LAST_UPDATE, id, &#39;100000000NN&#39;,
                        0, id[2], BD_LAST_UPDATE, &#39;application/xbel+xml&#39;, orig_mname);
        }
        return -1;
}
;

--| When DAV_PROP_GET_INT or DAV_DIR_LIST_INT calls DET function, authentication is performed before the call.
create function &quot;bookmark_DAV_DIR_LIST&quot; (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
{
        --dbg_obj_princ (&#39;bookmark_DAV_DIR_LIST (&#39;, detcol_id, path_parts, detcol_path, name_mask, recursive, auth_uid,  &#39;)&#39;);
        declare sub_id, folder_id, domain_id, ownergid, owner_uid integer;
        declare top_davpath, access varchar;
        declare res, grand_res any;
        declare top_id, descnames any;
        declare what char (1);
        &quot;bookmark_ACCESS_PARAMS&quot; (detcol_id, access, ownergid, owner_uid);
        if ((0 = length (path_parts)) or (&#39;&#39; = path_parts[length (path_parts) - 1]))
        what := &#39;C&#39;;
        else
        what := &#39;R&#39;;
        sub_id := 0;
        domain_id := 0;
        folder_id := 0;
        grand_res := vector();
        if (&#39;C&#39; = what and 1 = length(path_parts))
                top_id := vector (UNAME&#39;bookmark&#39;, detcol_id, owner_uid, 0, 0, 0, -1, null); -- may be a fake id because top_id[4] may be NULL
        else
                top_id := &quot;bookmark_DAV_SEARCH_ID_IMPL&quot; (detcol_id, path_parts, what, sub_id, owner_uid, domain_id, folder_id);
        if (DAV_HIDE_ERROR (top_id) is null)
                return vector();
        top_davpath := DAV_CONCAT_PATH (detcol_path, path_parts);
        if (&#39;R&#39; = what)
                return vector (&quot;bookmark_DAV_DIR_SINGLE&quot; (top_id, what, top_davpath, auth_uid));
        res := vector();
        if (&#39;C&#39; = what)
        {
                if (top_id[3] = 0) -- top level
                {
                        declare subs any;
                        declare cur varchar;
                        declare i integer;
                        i := 0;
                        subs := vector(&#39;bookmark&#39;, &#39;date&#39;, &#39;tags&#39;);
                        for (i := 0; i &lt; 3; i := i + 1)
                        {
                                cur := cast(subs[i] as varchar);
                                res := vector_concat (res, vector (vector (DAV_CONCAT_PATH (top_davpath, cur) || &#39;/&#39;, &#39;C&#39;, 0, now(),
                                        vector (UNAME&#39;bookmark&#39;, detcol_id, owner_uid, null, null, null, -1, null),
                                        &#39;100000000NN&#39;, ownergid, owner_uid, now(), &#39;dav/unix-directory&#39;, cur) ) );
                        }
                        return res;
                }
                if (top_id[3] = 1 and top_id[4] = 0) -- level of bookmarks, list of Bookmark instances
                {       
                        for select &quot;bookmark_FIXNAME&quot;(C.WAI_NAME) as orig_name
                                         from SYS_USERS A,
                                                  WA_MEMBER B,
                                                  WA_INSTANCE C
                                        where A.U_ID = owner_uid
                                          and B.WAM_USER = A.U_ID
                                          and B.WAM_MEMBER_TYPE = 1
                                          and B.WAM_INST = C.WAI_NAME
                                          and C.WAI_TYPE_NAME = &#39;Bookmark&#39;
                        do
                        {
                          res := vector_concat (res, vector (vector (DAV_CONCAT_PATH (top_davpath, orig_name) || &#39;/&#39;, &#39;C&#39;, 0, now(),
                                vector (UNAME&#39;bookmark&#39;, detcol_id, owner_uid, top_id[3], 0, 0, -1, null),
                                &#39;100000000NN&#39;, ownergid, owner_uid, now(), &#39;dav/unix-directory&#39;, orig_name) ) );
                        }
                        return res;
                }
                if (top_id[3] = 2 and top_id[4] = 0)  -- level of dates
                {
                        for select distinct cast(year(D.BD_LAST_UPDATE) as varchar) as orig_name
                                         from SYS_USERS A,
                                                  WA_MEMBER B,
                                                  WA_INSTANCE C,
                                                  BMK.WA.BOOKMARK_DOMAIN D
                                        where A.U_ID = owner_uid
                                          and B.WAM_USER = A.U_ID
                                          and B.WAM_MEMBER_TYPE = 1
                                          and B.WAM_INST = C.WAI_NAME
                                          and C.WAI_TYPE_NAME = &#39;Bookmark&#39;
                                          and D.BD_DOMAIN_ID = C.WAI_ID
                        do
                        {
                          res := vector_concat (res, vector (vector (DAV_CONCAT_PATH (top_davpath, orig_name) || &#39;/&#39;, &#39;C&#39;, 0, now(),
                                vector (UNAME&#39;bookmark&#39;, detcol_id, owner_uid, top_id[3], 0, 0, -1, null),
                                &#39;100000000NN&#39;, ownergid, owner_uid, now(), &#39;dav/unix-directory&#39;, orig_name) ) );
                        }
                        return res;
                }
                if (top_id[3] = 3 and top_id[4] = 0 and top_id[7] is null)  -- level of tags, lists of keywords
                {
                        for select distinct T_TAG as orig_name
                                         from SYS_USERS A,
                                                  WA_MEMBER B,
                                                  WA_INSTANCE C,
                                                  BMK.WA.TAGS D
                                        where A.U_ID = owner_uid
                                          and B.WAM_USER = A.U_ID
                                          and B.WAM_MEMBER_TYPE = 1
                                          and B.WAM_INST = C.WAI_NAME
                                          and C.WAI_TYPE_NAME = &#39;Bookmark&#39;
                                          and D.T_DOMAIN_ID = C.WAI_ID
                                          and T_TAG &lt;&gt; &#39;&#39;
                        do
                        {
                          res := vector_concat (res, vector (vector (DAV_CONCAT_PATH (top_davpath, orig_name) || &#39;/&#39;, &#39;C&#39;, 0, now(),
                                vector (UNAME&#39;bookmark&#39;, detcol_id, owner_uid, top_id[3], 0, 0, -1, null),
                                &#39;100000000NN&#39;, ownergid, owner_uid, now(), &#39;dav/unix-directory&#39;, orig_name) ) );
                        }
                        return res;
                }
                if (top_id[3] = 2 and top_id[4] &lt;&gt; 0 and top_id[5] = 0)  -- level of dates/years
                {
                        for select distinct monthname(D.BD_LAST_UPDATE) as orig_name
                                         from SYS_USERS A,
                                                  WA_MEMBER B,
                                                  WA_INSTANCE C,
                                                  BMK.WA.BOOKMARK_DOMAIN D
                                        where A.U_ID = owner_uid
                                          and B.WAM_USER = A.U_ID
                                          and B.WAM_MEMBER_TYPE = 1
                                          and B.WAM_INST = C.WAI_NAME
                                          and C.WAI_TYPE_NAME = &#39;Bookmark&#39;
                                          and D.BD_DOMAIN_ID = C.WAI_ID
                                          and year(D.BD_LAST_UPDATE) = top_id[4]
                        do
                        {
                            res := vector_concat (res, vector (vector (DAV_CONCAT_PATH (top_davpath, orig_name) || &#39;/&#39;, &#39;C&#39;, 0, now(),
                                vector (UNAME&#39;bookmark&#39;, detcol_id, owner_uid, top_id[3], 0, 0, -1, null),
                                &#39;100000000NN&#39;, ownergid, owner_uid, now(), &#39;dav/unix-directory&#39;, orig_name) ) );
                        }
                }
                if (top_id[3] = 1 and top_id[4] &lt;&gt; 0) -- and top_id[5] = 0) -- level of bookmark instance, list of bookmark folders
                {
                        declare tmp int;
                        tmp := top_id[5];
                        if (tmp = 0)
                                tmp := -1;
                        for select F_ID, &quot;bookmark_FIXNAME&quot; (F_NAME) as orig_name
                                from BMK.WA.FOLDER
                                where F_DOMAIN_ID = top_id[4] and F_PARENT_ID = coalesce(tmp, -1)
                                order by 1, 2
                        do
                        {
                          res := vector_concat (res, vector (vector (DAV_CONCAT_PATH (top_davpath, orig_name) || &#39;/&#39;, &#39;C&#39;, 0, now(),
                                vector (UNAME&#39;bookmark&#39;, detcol_id, owner_uid, top_id[3], top_id[4], F_ID, -1, null),
                                &#39;100000000NN&#39;, ownergid, owner_uid, now(), &#39;dav/unix-directory&#39;, orig_name) ) );
                        }
                }
                grand_res := res;    
        }
        res := vector();
        if (top_id[3] = 1)
        {
                declare tmp int;
                tmp := top_id[5];
                if (tmp = 0)
                        tmp := -1;

                for select &quot;bookmark_COMPOSE_XBEL_NAME&quot;(BD_NAME, BD_ID) as orig_mname, BD_ID as m_id, BD_LAST_UPDATE
                from BMK.WA.BOOKMARK_DOMAIN
                where BD_DOMAIN_ID = top_id[4] and
                        ((BD_FOLDER_ID  = top_id[5] and top_id[5] &gt; 0) or (BD_FOLDER_ID is null and tmp = -1))
                order by 1, 2
                do
                {
                  res := vector_concat (res, vector (vector (DAV_CONCAT_PATH (top_davpath, orig_mname), &#39;R&#39;, 1024, BD_LAST_UPDATE,
                        vector (UNAME&#39;bookmark&#39;, detcol_id, owner_uid, top_id[3], top_id[4], top_id[5], m_id, null),
                        &#39;100000000NN&#39;, ownergid, owner_uid, BD_LAST_UPDATE, &#39;application/xbel+xml&#39;, orig_mname) ) );
                }
        }
        else if (top_id[3] = 2)
        {
                for select distinct &quot;bookmark_COMPOSE_XBEL_NAME&quot;(BD_NAME, BD_ID) as orig_mname, BD_ID as m_id, BD_LAST_UPDATE
                from SYS_USERS A,
                                                  WA_MEMBER B,
                                                  WA_INSTANCE C,
                                                  BMK.WA.BOOKMARK_DOMAIN D
                                        where A.U_ID = owner_uid
                                          and B.WAM_USER = A.U_ID
                                          and B.WAM_MEMBER_TYPE = 1
                                          and B.WAM_INST = C.WAI_NAME
                                          and C.WAI_TYPE_NAME = &#39;Bookmark&#39;
                                          and D.BD_DOMAIN_ID = C.WAI_ID
                                          and year(D.BD_LAST_UPDATE) = top_id[4] and month(D.BD_LAST_UPDATE) = top_id[5]
                order by 1, 2
                do
                {
                  res := vector_concat (res, vector (vector (DAV_CONCAT_PATH (top_davpath, orig_mname), &#39;R&#39;, 1024, BD_LAST_UPDATE,
                        vector (UNAME&#39;bookmark&#39;, detcol_id, owner_uid, top_id[3], top_id[4], top_id[5], m_id, null),
                        &#39;100000000NN&#39;, ownergid, owner_uid, BD_LAST_UPDATE, &#39;application/xbel+xml&#39;, orig_mname) ) );
                }
        }
        else if (top_id[3] = 3)
        {
                for select distinct &quot;bookmark_COMPOSE_XBEL_NAME&quot;(D.BD_NAME, D.BD_ID) as orig_mname, D.BD_ID as m_id, D.BD_LAST_UPDATE, G.BD_TAGS as tags
                from SYS_USERS A,
                                                  WA_MEMBER B,
                                                  WA_INSTANCE C,
                                                  BMK.WA.BOOKMARK_DOMAIN D,
                                                  BMK.WA.BOOKMARK_DATA G
                                        where A.U_ID = owner_uid
                                          and B.WAM_USER = A.U_ID
                                          and B.WAM_MEMBER_TYPE = 1
                                          and B.WAM_INST = C.WAI_NAME
                                          and C.WAI_TYPE_NAME = &#39;Bookmark&#39;
                                          and D.BD_DOMAIN_ID = C.WAI_ID
                                          and D.BD_BOOKMARK_ID = G.BD_BOOKMARK_ID
                                          and G.BD_TAGS is not null and G.BD_TAGS &lt;&gt; &#39;&#39;
                order by 1, 2
                do
                {
                        declare tags2 any;
                        tags2 := split_and_decode (tags, 0, &#39;\0\0,&#39;);
                        foreach (any tag in tags2) do
                        {
                                tag := trim(tag);
                                if (top_id[7] = tag)
                                {
                                  res := vector_concat (res, vector (vector (DAV_CONCAT_PATH (top_davpath, orig_mname), &#39;R&#39;, 1024, BD_LAST_UPDATE,
                                        vector (UNAME&#39;bookmark&#39;, detcol_id, owner_uid, top_id[3], 0, 0, m_id, tag),
                                        &#39;100000000NN&#39;, ownergid, owner_uid, BD_LAST_UPDATE, &#39;application/xbel+xml&#39;, orig_mname)));
                                }
                        }
                }
        }
        grand_res := vector_concat (grand_res, res);
finalize_res:
        return grand_res;
}
;

create procedure &quot;bookmark_DAV_FC_PRED_METAS&quot; (inout pred_metas any)
{
        pred_metas := vector(
    &#39;BD_ID&#39;,                                    vector (&#39;BOOKMARK_DOMAIN&#39;               , 0, &#39;integer&#39;, &#39;BD_ID&#39;   ),
        &#39;BD_DOMAIN_ID&#39;,                         vector (&#39;BOOKMARK_DOMAIN&#39;               , 0, &#39;integer&#39;, &#39;BD_DOMAIN_ID&#39;   ),
    &#39;BD_BOOKMARK_ID&#39;,                   vector (&#39;BOOKMARK_DOMAIN&#39;               , 0, &#39;integer&#39;, &#39;BD_BOOKMARK_ID&#39;     ),
    &#39;BD_FOLDER_ID&#39;,                     vector (&#39;BOOKMARK_DOMAIN&#39;               , 0, &#39;integer&#39;  , &#39;BD_FOLDER_ID&#39; ),
    &#39;RES_NAME&#39;,                 vector (&#39;BOOKMARK_DOMAIN&#39;             , 0, &#39;varchar&#39;  , &#39;&quot;bookmark_COMPOSE_XBEL_NAME&quot; (BD_NAME, BD_ID)&#39;       ),
    &#39;RES_FULL_PATH&#39;,            vector (&#39;BOOKMARK_DOMAIN&#39;     , 0, &#39;varchar&#39;  , &#39;concat (DAV_CONCAT_PATH (_param.detcolpath, &#39;&#39;bookmark&#39;&#39;, &quot;bookmark_FIXNAME&quot; (WAI_NAME)), &#39;&#39;/&#39;&#39;, &quot;bookmark_COMPOSE_XBEL_NAME&quot; (BD_NAME, BD_ID)&#39;       ),
    &#39;RES_TYPE&#39;,                 vector (&#39;BOOKMARK_DOMAIN&#39;     , 0, &#39;varchar&#39;  , &#39;(&#39;&#39;application/xbel+xml&#39;&#39;)&#39;    ),
    &#39;RES_OWNER_ID&#39;,             vector (&#39;SYS_USERS&#39;       , 0, &#39;integer&#39;  , &#39;U_ID&#39;        ),
    &#39;RES_OWNER_NAME&#39;,           vector (&#39;SYS_USERS&#39;       , 0, &#39;varchar&#39;  , &#39;U_NAME&#39;      ),
    &#39;RES_GROUP_ID&#39;,             vector (&#39;SYS_USERS&#39;     , 0, &#39;integer&#39;  , &#39;http_nogroup_gid()&#39;  ),
    &#39;RES_GROUP_NAME&#39;,           vector (&#39;SYS_USERS&#39;     , 0, &#39;varchar&#39;  , &#39;(&#39;&#39;nogroup&#39;&#39;)&#39;       ),
    &#39;RES_COL_FULL_PATH&#39;,        vector (&#39;BOOKMARK_DOMAIN&#39;     , 0, &#39;varchar&#39;  , &#39;concat (DAV_CONCAT_PATH (_param.detcolpath, &#39;&#39;bookmark&#39;&#39;, &quot;bookmark_FIXNAME&quot; (WAI_NAME)), &#39;&#39;/&#39;&#39;)&#39;      ),
    &#39;RES_COL_NAME&#39;,             vector (&#39;BOOKMARK_DOMAIN&#39;     , 0, &#39;varchar&#39;  , &#39;&quot;bookmark_FIXNAME&quot; (WAI_NAME)&#39;   ),
    &#39;RES_CR_TIME&#39;,              vector (&#39;BOOKMARK_DOMAIN&#39;     , 0, &#39;datetime&#39; , &#39;BD_LAST_UPDATE&#39;        ),
    &#39;RES_MOD_TIME&#39;,             vector (&#39;BOOKMARK_DOMAIN&#39;     , 0, &#39;datetime&#39; , &#39;BD_LAST_UPDATE&#39;  ),
    &#39;RES_PERMS&#39;,                vector (&#39;BOOKMARK_DOMAIN&#39;     , 0, &#39;varchar&#39;  , &#39;(&#39;&#39;110000000RR&#39;&#39;)&#39;   ),
    &#39;RES_CONTENT&#39;,              vector (&#39;BOOKMARK_DOMAIN&#39;     , 0, &#39;text&#39;     , &#39;BD_DESCRIPTION&#39;   )
    );
}
;

create procedure &quot;bookmark_DAV_FC_TABLE_METAS&quot; (inout table_metas any)
{
        table_metas := vector (
                &#39;BOOKMARK_DOMAIN&#39;             , vector (      &#39;&#39;      ,
                                        &#39;&#39;      ,
                                                &#39;BD_NAME&#39;    , &#39;BD_NAME&#39;  , &#39;[__quiet] /&#39; ),
    &#39;WA_INSTANCE&#39;         , vector (      &#39;&#39;      ,
                                        &#39;&#39;      ,
                                                &#39;WAI_NAME&#39;     , &#39;WAI_NAME&#39;   , &#39;[__quiet] /&#39; ),
    &#39;WA_MEMBER&#39;         , vector (      &#39;&#39;      ,
                                        &#39;&#39;      ,
                                                &#39;WAM_INST&#39;     , &#39;WAM_INST&#39;   , &#39;[__quiet] /&#39; ),
                                                
    &#39;SYS_USERS&#39;   , vector (      &#39;&#39;      ,
                                        &#39;&#39;      ,
                                                NULL            , NULL          , NULL          )
        );
}
;

create function &quot;bookmark_DAV_FC_PRINT_WHERE&quot; (inout filter any, in param_uid integer) returns varchar
{
        declare pred_metas, cmp_metas, table_metas any;
        declare used_tables any;
        -- dbg_obj_princ (&#39;Blog_POST_DAV_FC_PRINT_WHERE (&#39;, filter, param_uid, &#39;)&#39;);
        &quot;bookmark_DAV_FC_PRED_METAS&quot; (pred_metas);
        DAV_FC_CMP_METAS (cmp_metas);
        &quot;bookmark_DAV_FC_TABLE_METAS&quot; (table_metas);
        used_tables := vector(
                &#39;BOOKMARK_DOMAIN&#39;, vector (&#39;BOOKMARK_DOMAIN&#39;, &#39;_top&#39;, null, vector (), vector (), vector ()),
                &#39;WA_INSTANCE&#39;, vector (&#39;WA_INSTANCE&#39;, &#39;_instances&#39;, null, vector (), vector (), vector ()),
                &#39;WA_MEMBER&#39;, vector (&#39;WA_MEMBER&#39;, &#39;_members&#39;, null, vector (), vector (), vector ()),
                &#39;SYS_USERS&#39;, vector (&#39;SYS_USERS&#39;, &#39;_users&#39;, null, vector (), vector (), vector ())
        );
        return DAV_FC_PRINT_WHERE_INT (filter, pred_metas, cmp_metas, table_metas, used_tables, param_uid);
}
;

--| When DAV_DIR_FILTER_INT calls DET function, authentication is performed before the call and compilation is initialized.
create function &quot;bookmark_DAV_DIR_FILTER&quot; (in detcol_id any, in path_parts any, in detcol_path any, inout compilation any, in recursive integer, in auth_uid integer) returns any
{
        -- dbg_obj_princ (&#39;bookmark_DAV_DIR_FILTER (&#39;, detcol_id, path_parts, detcol_path, compilation, recursive, auth_uid, &#39;)&#39;);
        declare st, access, qry_text, execstate, execmessage varchar;
        declare res any;
        declare cond_list, execmeta, execrows any;
        declare sub, post_id, condtext, cond_key varchar;
        declare ownergid, owner_uid, domain_id integer;
        &quot;bookmark_ACCESS_PARAMS&quot; (detcol_id, access, ownergid, owner_uid);
        vectorbld_init (res);
        sub := null;
        post_id := null;
        if (((length (path_parts) &lt;= 1) and (recursive &lt;&gt; 1)) or (length (path_parts) &gt; 2))
        {
          -- dbg_obj_princ (&#39;\r\nGoto skip_post_level\r\n&#39;);
          goto finalize;
        }
        if (length (path_parts) &gt;= 2)
        {
                sub := path_parts[0];           
                if (sub = &#39;bookmark&#39;)
                {
                        domain_id := coalesce ((select C.WAI_ID
                                from SYS_USERS A,
                                WA_MEMBER B,
                                WA_INSTANCE C
                        where A.U_ID = owner_uid
                          and B.WAM_USER = A.U_ID
                          and B.WAM_MEMBER_TYPE = 1
                          and B.WAM_INST = C.WAI_NAME
                          and C.WAI_TYPE_NAME = &#39;Bookmark&#39;
                          and &quot;bookmark_FIXNAME&quot;(C.WAI_NAME) = path_parts[1]));
                        if (domain_id is null)
                                goto finalize;
                }
                else
                        goto finalize;
        }
        cond_key := sprintf (&#39;Bookmark&amp;%d&#39;, coalesce (domain_id, 0));
        condtext := get_keyword (cond_key, compilation);
        if (condtext is null)
        {
          cond_list := get_keyword (&#39;&#39;, compilation);
          if (sub is not null)
                cond_list := vector_concat (cond_list, vector ( vector (&#39;BD_DOMAIN_ID&#39;, &#39;=&#39;, domain_id)));
          condtext := &quot;bookmark_DAV_FC_PRINT_WHERE&quot; (cond_list, auth_uid);
          compilation := vector_concat (compilation, vector (cond_key, condtext));
        }
        execstate := &#39;00000&#39;;
        qry_text := &#39;select concat (DAV_CONCAT_PATH (_param.detcolpath, &#39;&#39;bookmark&#39;&#39;, &#39;&#39;/&#39;&#39;, &quot;bookmark_FIXNAME&quot; (WAI_NAME)), &#39;&#39;/&#39;&#39;, &quot;bookmark_COMPOSE_XBEL_NAME&quot; (_top.BD_NAME, _top.BD_ID)),
                &#39;&#39;R&#39;&#39;, &#39;&#39;1024&#39;&#39;, _top.BD_LAST_UPDATE,
                vector (UNAME&#39;&#39;bookmark&#39;&#39;, ?, _users.U_ID, 3, _top.BD_DOMAIN_ID, _top.BD_FOLDER_ID, null, null),
                &#39;&#39;110000000RR&#39;&#39;, http_nogroup_gid(), _users.U_ID, _top.BD_LAST_UPDATE, &#39;&#39;application/xbel+xml&#39;&#39;, &quot;bookmark_COMPOSE_XBEL_NAME&quot; (_top.BD_NAME, _top.BD_ID)
                from
                (select top 1 ? as detcolpath from WS.WS.SYS_DAV_COL) as _param,
                BMK.WA.BOOKMARK_DOMAIN as _top
                join DB.DBA.WA_INSTANCE as _instances on (WAI_ID = BD_DOMAIN_ID and WAI_TYPE_NAME = &#39;&#39;Bookmark&#39;&#39;)
                join DB.DBA.WA_MEMBER as _members on (WAM_MEMBER_TYPE = 1 and WAM_INST = WAI_NAME)
                join DB.DBA.SYS_USERS as _users on (WAM_USER = U_ID and U_ID = ?)
                &#39; || condtext;
          exec (qry_text, execstate, execmessage,
                vector (detcol_id, detcol_path, owner_uid),
                100000000, execmeta, execrows );
          if (&#39;00000&#39; &lt;&gt; execstate)
                signal (execstate, execmessage || &#39; in &#39; || qry_text);
          vectorbld_concat_acc (res, execrows);
finalize:
        vectorbld_final (res);
        return res;
}
;

create function &quot;bookmark_DAV_SEARCH_ID_IMPL&quot; (in detcol_id any, in path_parts any, in what char(1), inout sub_id integer, inout muser_id integer, inout domain_id integer, inout folder_id integer) returns any
{
        --dbg_obj_princ (&#39;bookmark_DAV_SEARCH_ID_IMPL (&#39;, detcol_id, path_parts, what, sub_id, muser_id, domain_id, folder_id, &#39;)&#39;);
        declare ownergid, owner_uid, ctr, len integer;
        declare hitlist any;
        declare access, colpath, tag_id, sub varchar;
        tag_id := null; 
        &quot;bookmark_ACCESS_PARAMS&quot; (detcol_id, access, ownergid, owner_uid);
        if (0 = length(path_parts))
        {
                if (&#39;C&#39; &lt;&gt; what)
                        return -1;
                return vector (UNAME&#39;bookmark&#39;, detcol_id, owner_uid, sub_id, domain_id, folder_id, -1, null);
        }
        if (&#39;&#39; = path_parts[length(path_parts) - 1])
        {
                if (&#39;C&#39; &lt;&gt; what)
                        return -1;
        }
        else
        {
                if (&#39;R&#39; &lt;&gt; what)
                        return -1;
        }
        len := length (path_parts) - 1;
        ctr := 0;
        sub := trim(cast(path_parts[0] as varchar));
        while (ctr &lt; len)
        {
                if (ctr = 0)
                {
                        if (equ(sub, &#39;date&#39;))
                                sub_id := 2;
                        else if (equ(sub, &#39;bookmark&#39;))
                                sub_id := 1;
                        else if (equ(sub, &#39;tags&#39;))
                                sub_id := 3;
                        else
                                sub_id := 1;
                }
                else if (ctr = 1)
                {
                  hitlist := vector ();
                  if (sub_id = 1)
                  {
                          for select C.WAI_ID as D_ID
                                         from SYS_USERS A,
                                                  WA_MEMBER B,
                                                  WA_INSTANCE C
                                        where A.U_ID = owner_uid
                                          and B.WAM_USER = A.U_ID
                                          and B.WAM_MEMBER_TYPE = 1
                                          and B.WAM_INST = C.WAI_NAME
                                          and C.WAI_TYPE_NAME = &#39;Bookmark&#39;
                                          and &quot;bookmark_FIXNAME&quot;(C.WAI_NAME) = path_parts[ctr]
                          do
                          {
                                hitlist := vector_concat (hitlist, vector (D_ID));
                          }
                  }
                  else if (sub_id = 2)
                  {
                        for select distinct year(D.BD_LAST_UPDATE) as D_ID
                                         from SYS_USERS A,
                                                  WA_MEMBER B,
                                                  WA_INSTANCE C,
                                                  BMK.WA.BOOKMARK_DOMAIN D
                                        where A.U_ID = owner_uid
                                          and B.WAM_USER = A.U_ID
                                          and B.WAM_MEMBER_TYPE = 1
                                          and B.WAM_INST = C.WAI_NAME
                                          and C.WAI_TYPE_NAME = &#39;Bookmark&#39;
                                          and D.BD_DOMAIN_ID = C.WAI_ID
                                          and year(D.BD_LAST_UPDATE) = atoi(path_parts[ctr])
                          do
                          {
                                hitlist := vector_concat (hitlist, vector (D_ID));
                          }
                  }
                  else if (sub_id = 3)
                  {
                        for select distinct D.T_TAG as D_ID
                                         from SYS_USERS A,
                                                  WA_MEMBER B,
                                                  WA_INSTANCE C,
                                                  BMK.WA.TAGS D
                                        where A.U_ID = owner_uid
                                          and B.WAM_USER = A.U_ID
                                          and B.WAM_MEMBER_TYPE = 1
                                          and B.WAM_INST = C.WAI_NAME
                                          and C.WAI_TYPE_NAME = &#39;Bookmark&#39;
                                          and D.T_DOMAIN_ID = C.WAI_ID
                                          and D.T_TAG = path_parts[ctr]
                        do
                        {
                                hitlist := vector_concat (hitlist, vector (D_ID));
                        }
                        if (length (hitlist) &lt;&gt; 1)
                                return -1;
                        tag_id := hitlist[0];
                  }
                  if (sub_id &lt;&gt; 3)
                  {
                          if (length (hitlist) &lt;&gt; 1)
                                return -1;
                          domain_id := hitlist[0];
                  }
                }
                else
                {
                        if (sub_id &lt;&gt; 3)
                        {
                                hitlist := vector();
                                if (sub_id = 1)
                                {
                                        for select F_ID
                                                from BMK.WA.FOLDER
                                                where &quot;bookmark_FIXNAME&quot;(F_NAME) = path_parts[ctr] and
                                                F_DOMAIN_ID = domain_id and
                                                ((F_PARENT_ID = folder_id and folder_id &gt; 0) or (F_PARENT_ID = -1 and (folder_id = 0 or folder_id = -1)))
                                        do 
                                        {
                                                hitlist := vector_concat (hitlist, vector (F_ID));
                                        }
                                }
                                else if (sub_id = 2)
                                {
                                        for select distinct month(D.BD_LAST_UPDATE) as D_ID
                                                 from SYS_USERS A,
                                                          WA_MEMBER B,
                                                          WA_INSTANCE C,
                                                          BMK.WA.BOOKMARK_DOMAIN D
                                                where A.U_ID = owner_uid
                                                  and B.WAM_USER = A.U_ID
                                                  and B.WAM_MEMBER_TYPE = 1
                                                  and B.WAM_INST = C.WAI_NAME
                                                  and C.WAI_TYPE_NAME = &#39;Bookmark&#39;
                                                  and D.BD_DOMAIN_ID = C.WAI_ID
                                                  and monthname(D.BD_LAST_UPDATE) = path_parts[ctr]
                                  do
                                  {
                                        hitlist := vector_concat (hitlist, vector (D_ID));
                                  }               
                                }
                                if (length (hitlist) &lt;&gt; 1)
                                        return -1;
                                folder_id := hitlist[0];
                        }
                        else
                                return -1;
                }
                ctr := ctr + 1;
        }
        if (&#39;C&#39; = what)
                return vector (UNAME&#39;bookmark&#39;, detcol_id, owner_uid, sub_id, domain_id, folder_id, -1, tag_id);
        hitlist := vector ();
        if (sub_id = 1)
        {
                for select distinct BD_ID
                        from BMK.WA.BOOKMARK_DOMAIN
                        where ((BD_FOLDER_ID = folder_id and folder_id &gt; 0) or ((folder_id = 0 or folder_id = -1) and BD_FOLDER_ID is null))and
                        &quot;bookmark_COMPOSE_XBEL_NAME&quot; (BD_NAME, BD_ID) = path_parts[ctr] and
                        BD_DOMAIN_ID = domain_id
                do 
                {
                        hitlist := vector_concat (hitlist, vector (BD_ID));
                }
        }
        else if (sub_id = 2)
        {
                for select distinct D.BD_ID as D_ID
                                         from SYS_USERS A,
                                                  WA_MEMBER B,
                                                  WA_INSTANCE C,
                                                  BMK.WA.BOOKMARK_DOMAIN D
                                        where A.U_ID = owner_uid
                                          and B.WAM_USER = A.U_ID
                                          and B.WAM_MEMBER_TYPE = 1
                                          and B.WAM_INST = C.WAI_NAME
                                          and C.WAI_TYPE_NAME = &#39;Bookmark&#39;
                                          and D.BD_DOMAIN_ID = C.WAI_ID
                                          and month(D.BD_LAST_UPDATE) = folder_id
                                          and year(D.BD_LAST_UPDATE) = domain_id
                                          and &quot;bookmark_COMPOSE_XBEL_NAME&quot; (D.BD_NAME, D.BD_ID) = path_parts[ctr]
                do 
                {
                        hitlist := vector_concat (hitlist, vector (D_ID));
                }
        }
        else if (sub_id = 3)
        {
                for select distinct D.BD_ID as D_ID
                                         from SYS_USERS A,
                                                  WA_MEMBER B,
                                                  WA_INSTANCE C,
                                                  BMK.WA.BOOKMARK_DOMAIN D
                                        where A.U_ID = owner_uid
                                          and B.WAM_USER = A.U_ID
                                          and B.WAM_MEMBER_TYPE = 1
                                          and B.WAM_INST = C.WAI_NAME
                                          and C.WAI_TYPE_NAME = &#39;Bookmark&#39;
                                          and D.BD_DOMAIN_ID = C.WAI_ID
                                          and &quot;bookmark_COMPOSE_XBEL_NAME&quot; (D.BD_NAME, D.BD_ID) = path_parts[ctr]
                do 
                {
                        hitlist := vector_concat (hitlist, vector (D_ID));
                }
        }       
        if (length (hitlist) &lt;&gt; 1)
                return -1;
        return vector (UNAME&#39;bookmark&#39;, detcol_id, owner_uid, sub_id, domain_id, folder_id, hitlist[0], tag_id);
}
;

--| When DAV_PROP_GET_INT or DAV_DIR_LIST_INT calls DET function, authentication is performed before the call.
create function &quot;bookmark_DAV_SEARCH_ID&quot; (in detcol_id any, in path_parts any, in what char(1)) returns any
{
  declare sub_id, u_id, folder_id, domain_id integer;
  --dbg_obj_princ (&#39;bookmark_DAV_SEARCH_ID (&#39;, detcol_id, path_parts, what, &#39;)&#39;);
  return &quot;bookmark_DAV_SEARCH_ID_IMPL&quot; (detcol_id, path_parts, what, sub_id, u_id, domain_id, folder_id);
}
;

--| When DAV_SEARCH_PATH_INT calls DET function, authentication is performed before the call.
create function &quot;bookmark_DAV_SEARCH_PATH&quot; (in id any, in what char(1)) returns any
{
  --dbg_obj_princ (&#39;bookmark_DAV_SEARCH_PATH (&#39;, id, what, &#39;)&#39;);
  return NULL;
}
;

--| When DAV_COPY_INT calls DET function, authentication and check for locks are performed before the call, but no check for existing/overwrite.
create function &quot;bookmark_DAV_RES_UPLOAD_COPY&quot; (in detcol_id any, in path_parts any, in source_id any, in what char(1), in overwrite_flags integer, in permissions varchar, in uid integer, in gid integer, in auth_uid integer) returns any
{
  -- dbg_obj_princ (&#39;bookmark_DAV_RES_UPLOAD_COPY (&#39;, detcol_id, path_parts, source_id, what, overwrite_flags, permissions, uid, gid, auth_uid, &#39;)&#39;);
  return -20;
}
;

--| When DAV_COPY_INT calls DET function, authentication and check for locks are performed before the call, but no check for existing/overwrite.
create function &quot;bookmark_DAV_RES_UPLOAD_MOVE&quot; (in detcol_id any, in path_parts any, in source_id any, in what char(1), in overwrite_flags integer, in auth_uid integer) returns any
{
  -- dbg_obj_princ (&#39;bookmark_DAV_RES_UPLOAD_MOVE (&#39;, detcol_id, path_parts, source_id, what, overwrite_flags, auth_uid, &#39;)&#39;);
  return -20;
}
;

--| When DAV_RES_CONTENT or DAV_RES_COPY_INT or DAV_RES_MOVE_INT calls DET function, authentication is made.
--| If content_mode is 1 then content is a valid output stream before the call.
create function &quot;bookmark_DAV_RES_CONTENT&quot; (in id any, inout content any, out type varchar, in content_mode integer) returns integer
{
        --dbg_obj_princ (&#39;bookmark_DAV_RES_CONTENT (&#39;, id, &#39;, [content], [type], &#39;, content_mode, &#39;)&#39;);
        whenever not found goto endline;
        if (id[6] is not null)
        {
                declare link, title, last_date varchar;
                if (id[3] = 1)
                {
                        select D.BD_NAME, cast(D.BD_LAST_UPDATE as varchar), B.B_URI into title, last_date, link
                                from BMK.WA.BOOKMARK_DOMAIN D, BMK.WA.BOOKMARK B
                                where D.BD_DOMAIN_ID = id[4] and
                                        ((D.BD_FOLDER_ID  = id[5] and id[5] &lt;&gt; 0) or (D.BD_FOLDER_ID is null and id[5] = 0)) and
                                        D.BD_ID = id[6] and
                                        B.B_ID = D.BD_BOOKMARK_ID;
                }
                else if (id[3] = 2 or id[3] = 3)
                {
                        select D.BD_NAME, cast(D.BD_LAST_UPDATE as varchar), B.B_URI into title, last_date, link
                                         from BMK.WA.BOOKMARK_DOMAIN D,
                                                  BMK.WA.BOOKMARK B
                                        where D.BD_ID = id[6] and B.B_ID = D.BD_BOOKMARK_ID;
                }
                type := &#39;application/xbel+xml&#39;;
                content := &#39;&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;\n&#39;;
                content := concat(content, &#39;&lt;!DOCTYPE xbel PUBLIC &quot;+//IDN python.org//DTD XML Bookmark Exchange Language 1.0//EN//XML&quot; &quot;http://pyxml.sourceforge.net/topics/dtds/xbel-1.0.dtd&quot;&gt;\n&#39;);
                content := concat(content, &#39;&lt;xbel&gt;\n&#39;);
                content := concat(content, sprintf(&#39;  &lt;bookmark href=&quot;%s&quot;&gt;\n&#39;, link));
                content := concat(content, sprintf(&#39;    &lt;title&gt;%s&lt;/title&gt;\n&#39;, title));
                content := concat(content, &#39;  &lt;/bookmark&gt;\n&#39;);
                content := concat(content, &#39;&lt;/xbel&gt;\n&#39;);
        }
endline:
        return 0;
}
;

--| This adds an extra access path to the existing resource or collection.
create function &quot;bookmark_DAV_SYMLINK&quot; (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 (&#39;bookmark_DAV_SYMLINK (&#39;, detcol_id, path_parts, source_id, overwrite, uid, gid, auth_uid, &#39;)&#39;);
  return -20;
}
;

--| This gets a list of resources and/or collections as it is returned by DAV_DIR_LIST and and writes the list of quads (old_id, &#39;what&#39;, old_full_path, dereferenced_id, dereferenced_full_path).
create function &quot;bookmark_DAV_DEREFERENCE_LIST&quot; (in detcol_id any, inout report_array any) returns any
{
  -- dbg_obj_princ (&#39;bookmark_DAV_DEREFERENCE_LIST (&#39;, detcol_id, report_array, &#39;)&#39;);
  return -20;
}
;

--| This gets one of reference quads returned by ..._DAV_REREFERENCE_LIST() and returns a record (new_full_path, new_dereferenced_full_path, name_may_vary).
create function &quot;bookmark_DAV_RESOLVE_PATH&quot; (in detcol_id any, inout reference_item any, inout old_base varchar, inout new_base varchar) returns any
{
  -- dbg_obj_princ (&#39;bookmark_DAV_RESOLVE_PATH (&#39;, detcol_id, reference_item, old_base, new_base, &#39;)&#39;);
  return -20;
}
;

--| There&#39;s no API function to lock for a while (do we need such?) The &quot;LOCK&quot; DAV method checks that all parameters are valid but does not check for existing locks.
create function &quot;bookmark_DAV_LOCK&quot; (in path any, in 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
{
  -- dbg_obj_princ (&#39;bookmark_DAV_LOCK (&#39;, id, type, locktype, scope, token, owner_name, owned_tokens, depth, timeout_sec, owner_name, auth_uid, &#39;)&#39;);
  return -20;
}
;


--| There&#39;s no API function to unlock for a while (do we need such?) The &quot;UNLOCK&quot; DAV method checks that all parameters are valid but does not check for existing locks.
create function &quot;bookmark_DAV_UNLOCK&quot; (in id any, in type char(1), in token varchar, in auth_uid integer)
{
  -- dbg_obj_princ (&#39;bookmark_DAV_UNLOCK (&#39;, id, type, token, auth_uid, &#39;)&#39;);
  return -27;
}
;

--| The caller does not check if id is valid.
--| This returns -1 if id is not valid, 0 if all existing locks are listed in owned_tokens whitespace-delimited list, 1 for soft 2 for hard lock.
create function &quot;bookmark_DAV_IS_LOCKED&quot; (inout id any, inout type char(1), in owned_tokens varchar) returns integer
{
  -- dbg_obj_princ (&#39;bookmark_DAV_IS_LOCKED (&#39;, id, type, owned_tokens, &#39;)&#39;);
  return 0;
}
;


--| The caller does not check if id is valid.
--| This returns -1 if id is not valid, list of tuples (LOCK_TYPE, LOCK_SCOPE, LOCK_TOKEN, LOCK_TIMEOUT, LOCK_OWNER, LOCK_OWNER_INFO) otherwise.
create function &quot;bookmark_DAV_LIST_LOCKS&quot; (in id any, in type char(1), in recursive integer) returns any
{
  -- dbg_obj_princ (&#39;bookmark_DAV_LIST_LOCKS&quot; (&#39;, id, type, recursive);
  return vector ();
}
;

</programlisting></section></docbook>