--
-- $Id: DET_Blog.sql,v 1.3 2007/09/21 08:59:11 mitko 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
;
EXEC_STMT ('create view BLOG.DBA.SYS_BLOG_OWNERS (U_ID, U_NAME, U_FULL_NAME, U_GROUP,
WAI_ID, WAI_NAME, BI_BLOG_ID )
as select U_ID, U_NAME, U_FULL_NAME, U_GROUP, WAI_ID, WAI_NAME, BI_BLOG_ID
from DB.DBA.SYS_USERS
join WA_MEMBER on (WAM_USER = U_ID)
join WA_INSTANCE on (WAI_NAME = WAM_INST)
join BLOG.DBA.SYS_BLOG_INFO on (BI_WAI_NAME = WAI_NAME)
where U_IS_ROLE = 0 and WAM_MEMBER_TYPE = 1 and WAI_TYPE_NAME = \'WEBLOG2\'', 0)
;
create function "Blog_FIXNAME" (in mailname any) returns varchar
{
return
replace (
replace (
replace (
replace (
replace (
replace (
replace (mailname, '/', '_'), '\\', '_'), ':', '_'), '+', '_'), '\"', '_'), '[', '_'), ']', '_'); --"
}
;
create function "Blog_COMPOSE_HTML_NAME" (in title varchar, in id varchar) returns varchar
{
declare ctr, len integer;
declare res varchar;
if (title is null or title = '')
return sprintf ('[%s].html', id);
return sprintf ('%s [%s].html', "Blog_FIXNAME"(title), id);
}
;
create function "Blog_COMPOSE_COMMENTS_NAME" (in title varchar, in id varchar) returns varchar
{
declare ctr, len integer;
declare res varchar;
if (title is null or title = '')
return sprintf ('[%s] Comments', id);
return sprintf ('%s [%s] Comments', "Blog_FIXNAME"(title), id);
}
;
create procedure "Blog_PARSE_HTML_NAME" (in fullname varchar, out title_pattern varchar, out id varchar)
{
declare split any;
title_pattern := null;
id := null;
split := regexp_parse ('^([^[]*)\\[([A-Za-z0-9_.-]*)\\]\\.html\044', fullname, 0);
if (split is null)
{
split := regexp_parse ('^([^[]*)\\.html\044', fullname, 0);
if (split is null)
return;
id := null;
}
else
id := subseq (fullname, split[4], split[5]);
title_pattern := subseq (fullname, split[2], split[3]);
if (title_pattern <> '')
title_pattern := subseq (title_pattern, 0, length (title_pattern) - 1);
}
;
create procedure "Blog_PARSE_COMMENTS_NAME" (in fullname varchar, out title_pattern varchar, out id varchar)
{
declare split any;
title_pattern := null;
id := null;
split := regexp_parse ('^([^[]*)\\[([A-Za-z0-9_.-]*)\\] Comments\044', fullname, 0);
if (split is null)
return;
id := subseq (fullname, split[4], split[5]);
title_pattern := subseq (fullname, split[2], split[3]);
if (title_pattern <> '')
title_pattern := subseq (title_pattern, 0, length (title_pattern) - 1);
}
;
create function "Blog_CHANNEL_DESC_NAMES" () returns any
{
return vector ('atom.xml', 'index.ocs', 'index.opml', 'index.rdf', 'rss.xml', 'xbel.xml');
}
;
create function "Blog_GET_USER_ID" (in domain_id int) returns int
{
declare user_id int;
user_id := (select A.U_ID
from SYS_USERS A,
WA_MEMBER B,
WA_INSTANCE C
where B.WAM_USER = A.U_ID
and B.WAM_MEMBER_TYPE = 1
and B.WAM_INST = C.WAI_NAME
and C.WAI_ID = domain_id);
return user_id;
}
;
create function "Blog_ACCESS_PARAMS" (in detcol_id any, out access varchar, out gid integer, out uid integer)
{
declare access_tmp varchar;
whenever not found goto ret;
access := '000000000N';
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 "Blog_DAV_AUTHENTICATE" (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 ('Blog_DAV_AUTHENTICATE (', id, what, req, auth_uname, auth_pwd, auth_uid, http_dav_uid(), ')');
if (auth_uid < 0)
return -12;
if (not ('110' like req))
{
return -13;
}
if ((auth_uid <> id[3]) and (auth_uid <> http_dav_uid()))
{
-- dbg_obj_princ ('a_uid is ', auth_uid, ', id[3] is ', id[3], ' mismatch');
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 "Blog_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 rc integer;
declare puid, pgid integer;
declare u_password, pperms varchar;
declare allow_anon integer;
if (length (req) <> 3)
return -15;
whenever not found goto nf_col_or_res;
puid := http_dav_uid();
pgid := coalesce (
( select G_ID from WS.WS.SYS_DAV_GROUP
where G_NAME = 'Blog_' || coalesce ((select COL_NAME from WS.WS.SYS_DAV_COL where COL_ID=id[1] and COL_DET='Blog'), '')
), puid+1);
pperms := '110100100NN';
if ((what <> 'R') and (what <> 'C'))
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 ('' <> WS.WS.FINDPARAM (a_lines, 'Authorization:')))
rc := WS.WS.GET_DAV_AUTH (a_lines, allow_anon, can_write_http, a_uname, u_password, a_uid, a_gid, _perms);
if (rc < 0)
return rc;
}
if (isinteger (a_uid))
{
if (a_uid < 0)
return a_uid;
if (a_uid = 1) -- Anonymous FTP
{
a_uid := 0;
a_gid := 0;
}
}
if (DAV_CHECK_PERM (pperms, req, a_uid, a_gid, pgid, puid))
return a_uid;
return -13;
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 "Blog_DAV_GET_PARENT" (in id any, in st char(1), in path varchar) returns any
{
-- dbg_obj_princ ('Blog_DAV_GET_PARENT (', id, st, path, ')');
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 "Blog_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 ('Blog_DAV_COL_CREATE (', detcol_id, path_parts, permissions, uid, gid, auth_uid, ')');
return -20;
}
;
--| It looks like that this is redundant and should be removed at all.
create function "Blog_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 ('Blog_DAV_COL_MOUNT (', detcol_id, path_parts, full_mount_path, mount_det, permissions, uid, gid, auth_uid, ')');
return -20;
}
;
--| It looks like that this is redundant and should be removed at all.
create function "Blog_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 ('Blog_DAV_COL_MOUNT_HERE (', parent_id, full_mount_path, permissions, uid, gid, auth_uid, ')');
return -20;
}
;
--| When DAV_DELETE_INT calls DET function, authentication and check for lock are passed.
create function "Blog_DAV_DELETE" (in detcol_id any, in path_parts any, in what char(1), in silent integer, in auth_uid integer) returns integer
{
-- dbg_obj_princ ('Blog_DAV_DELETE (', detcol_id, path_parts, what, silent, auth_uid, ')');
return -20;
}
;
--| When DAV_RES_UPLOAD_STRSES_INT calls DET function, authentication and check for locks are performed before the call.
--| There's a special problem, known as 'Transaction deadlock after reading from HTTP session'.
--| The DET function should do only one INSERT of the 'content' 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 "Blog_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
{
-- dbg_obj_princ ('Blog_DAV_RES_UPLOAD (', detcol_id, path_parts, ', [content], ', content, type, permissions, uid, gid, auth_uid, ')');
declare post_title, post_title_pattern, post_id, comment_name, comment_name_pattern, comment_id, blog_id varchar;
declare res_depth, rc int;
whenever not found goto nf;
res_depth := length (path_parts);
if (res_depth < 2)
return -40;
if (res_depth > 3)
return -40;
if (res_depth = 2) -- Posts.
{
"Blog_PARSE_HTML_NAME" (path_parts[1], post_title_pattern, post_id);
if (post_title_pattern is null)
return -40;
if (post_id is null)
return -40; -- TBD: fix this by adding an ability of upload with no specified post id.
select cast (C.B_TITLE as varchar), C.B_BLOG_ID into post_title, blog_id
from BLOG.DBA.SYS_BLOG_INFO B, BLOG.DBA.SYS_BLOGS C
where B.BI_WAI_NAME = path_parts[0] and B.BI_BLOG_ID = C.B_BLOG_ID and
C.B_POST_ID = post_id;
if (not (coalesce (post_title, '') like post_title_pattern))
return -40; -- Id does not match an existing title.
declare exit handler for sqlstate '*'
{
goto nf; -- TBD: fix this by adding an ability of upload with specified post id.
};
update BLOG.DBA.SYS_BLOGS set B_CONTENT = content where B_POST_ID = post_id and B_BLOG_ID = blog_id;
return vector (UNAME_BLOG(), detcol_id, blog_id, uid, post_id, null);
}
if (res_depth = 3)
{
"Blog_PARSE_COMMENT_NAME" (path_parts[1], post_title_pattern, post_id);
if (post_title_pattern is null)
return -40;
if (post_id is null)
return -40;
"Blog_PARSE_HTML_NAME" (path_parts[2], comment_name_pattern, comment_id);
if (comment_name_pattern is null)
return -40;
if (comment_id is null)
return -40; -- TBD: fix this by adding an ability of upload with no specified comment id.
select cast (C.B_TITLE as varchar), C.B_BLOG_ID, D.BM_NAME into post_title, blog_id, comment_name
from BLOG.DBA.SYS_BLOG_INFO B, BLOG.DBA.SYS_BLOGS C, BLOG.DBA.BLOG_COMMENTS D
where B.BI_WAI_NAME = path_parts[0] and B.BI_BLOG_ID = C.B_BLOG_ID and
C.B_BLOG_ID = D.BM_BLOG_ID and D.BM_POST_ID = C.B_POST_ID and C.B_POST_ID = post_id and D.BM_ID = comment_id;
if (not (coalesce (post_title, '') like post_title_pattern))
return -40; -- post id does not match an existing title.
if (not (coalesce (comment_name, '') like comment_name_pattern))
return -40; -- comment id does not match an existing name.
declare exit handler for sqlstate '*'
{
goto nf;
};
update BLOG.DBA.BLOG_COMMENTS set BM_COMMENT = content where BM_POST_ID = post_id and BM_BLOG_ID = blog_id and BM_ID = comment_id;
return vector(UNAME_BLOG(), detcol_id, blog_id, uid, atoi(post_id), comment_id);
}
nf:;
return -1;
}
;
--| When DAV_PROP_REMOVE_INT calls DET function, authentication and check for locks are performed before the call.
--| The check whether it's a system name or not is _not_ permitted.
create function "Blog_DAV_PROP_REMOVE" (in id any, in what char(0), in propname varchar, in silent integer, in auth_uid integer) returns integer
{
-- dbg_obj_princ ('Blog_DAV_PROP_REMOVE (', id, what, propname, silent, auth_uid, ')');
return -20;
}
;
--| When DAV_PROP_SET_INT calls DET function, authentication and check for locks are performed before the call.
--| The check whether it's a system property or not is _not_ permitted and the function should return -16 for live system properties.
create function "Blog_DAV_PROP_SET" (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 ('Blog_DAV_PROP_SET (', id, what, propname, propvalue, overwrite, auth_uid, ')');
if (propname[0] = 58)
{
return -16;
}
return -20;
}
;
--| When DAV_PROP_GET_INT calls DET function, authentication and check whether it's a system property are performed before the call.
create function "Blog_DAV_PROP_GET" (in id any, in what char(0), in propname varchar, in auth_uid integer)
{
-- dbg_obj_princ ('Blog_DAV_PROP_GET (', id, what, propname, auth_uid, ')');
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 "Blog_DAV_PROP_LIST" (in id any, in what char(0), in propmask varchar, in auth_uid integer)
{
-- dbg_obj_princ ('Blog_DAV_PROP_LIST (', id, what, propmask, auth_uid, ')');
return vector ();
}
;
--| When DAV_PROP_GET_INT or DAV_DIR_LIST_INT calls DET function, authentication is performed before the call.
create function "Blog_DAV_DIR_SINGLE" (in id any, in what char(0), in path any, in auth_uid integer) returns any
{
-- dbg_obj_princ ('Blog_DAV_DIR_SINGLE (', id, what, path, auth_uid, ')');
declare fullpath, rightcol, resname varchar;
declare access, title, title2 varchar;
declare ownergid, owner_uid integer;
fullpath := '';
"Blog_ACCESS_PARAMS" (id[1], access, ownergid, owner_uid);
title := coalesce ((select "Blog_FIXNAME" (WAI_NAME)
from BLOG.DBA.SYS_BLOG_OWNERS
where U_ID = owner_uid and BI_BLOG_ID = id[2]));
if (title is null)
return -1;
fullpath := concat(DAV_SEARCH_PATH (id[1], 'C'), title);
if ('C' = what)
{
declare maxrcvdate datetime;
if (id[5] is not null)
return -1;
if (id[4] is not null)
{
whenever not found goto no_comments;
select
cast (SB.B_TITLE as varchar),
(select max (BC.BM_TS)
from BLOG.DBA.BLOG_COMMENTS BC
where BC.BM_BLOG_ID = SB.B_BLOG_ID and BC.BM_POST_ID = SB.B_POST_ID )
into title2, maxrcvdate
from BLOG.DBA.SYS_BLOGS SB
where SB.B_BLOG_ID = id[2] and SB.B_POST_ID = id[4];
if (maxrcvdate is null)
goto no_comments;
title2 := "Blog_COMPOSE_COMMENTS_NAME" (title2, cast (id[4] as varchar));
return vector (fullpath || '/' || title2 || '/', 'C', 0, maxrcvdate,
id,
--access,
'100000000NN',
ownergid, owner_uid, maxrcvdate, 'dav/unix-directory', title2);
no_comments:
return -1;
}
maxrcvdate := coalesce (
(select max(B_TS) from BLOG.DBA.SYS_BLOGS where B_BLOG_ID = id[2]),
cast ('1980-01-01' as datetime));
return vector (fullpath || '/', 'C', 0, maxrcvdate,
id,
--access,
'100000000NN',
ownergid, owner_uid, maxrcvdate, 'dav/unix-directory', title);
}
-- The rest is for resources.
if (id[4] is null) -- special resource for whole channel
{
if (position (id[5], "Blog_CHANNEL_DESC_NAMES" ()) = 0)
return -1;
return vector (fullpath || '/' || id[5], 'R', 1024, now(),
id,
--access,
'100000000N',
ownergid, owner_uid, now(), 'text/xml', id[5]);
}
if (id[5] is null) -- blog post;
{
for select "Blog_COMPOSE_HTML_NAME" (B_TITLE, B_POST_ID) as post_name,
length(B_CONTENT) as DSIZE, B_TS, B_MODIFIED
from BLOG.DBA.SYS_BLOGS SB
where
SB.B_POST_ID = id[4] and SB.B_BLOG_ID = id[2]
do
{
return vector(fullpath || '/' || post_name, 'R', DSIZE, B_TS,
id,
--access,
'110000000N',
ownergid, owner_uid, B_MODIFIED, 'text/html', post_name );
}
return -1;
}
else -- blog comment
{
for select
"Blog_COMPOSE_COMMENTS_NAME" (B_TITLE, B_POST_ID) as orig_mname,
length(B_CONTENT) as DSIZE, B_TS, B_MODIFIED
from BLOG.DBA.SYS_BLOGS SB
where
SB.B_POST_ID = id[4] and SB.B_BLOG_ID = id[2]
do
{
return vector(fullpath || '/' || orig_mname, 'R', DSIZE, B_TS,
id,
--access,
'110000000NN',
ownergid, owner_uid, B_MODIFIED, 'text/html', orig_mname );
}
for select "Blog_COMPOSE_HTML_NAME" (D.BM_NAME, cast(D.BM_ID as varchar)) as comment_name,
D.BM_TS as BM_TS, length(D.BM_COMMENT) as DSIZE
from BLOG.DBA.BLOG_COMMENTS D
where D.BM_BLOG_ID = id[2] and D.BM_POST_ID = id[4] and D.BM_ID = id[5]
do
{
return vector (DAV_CONCAT_PATH (fullpath, comment_name), 'R', DSIZE, BM_TS,
id,
'110000000NN', ownergid, owner_uid, BM_TS, 'text/html', comment_name );
}
return -1;
}
}
;
--| When DAV_PROP_GET_INT or DAV_DIR_LIST_INT calls DET function, authentication is performed before the call.
create function "Blog_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
{
-- dbg_obj_princ ('Blog_DAV_DIR_LIST (', detcol_id, path_parts, detcol_path, name_mask, recursive, auth_uid, ')');
declare mdomain_id, muser_id, mfolder_id integer;
declare mnamefmt varchar;
declare top_davpath varchar;
declare res any;
declare top_id, descnames any;
declare what char (1);
declare access varchar;
declare ownergid, owner_uid, dn_ctr, dn_count integer;
mnamefmt := null;
vectorbld_init (res);
"Blog_ACCESS_PARAMS" (detcol_id, access, ownergid, owner_uid);
if ((0 = length (path_parts)) or ('' = path_parts[length (path_parts) - 1]))
what := 'C';
else
what := 'R';
if ('C' = what and 1 = length(path_parts))
top_id := vector (UNAME_BLOG(), detcol_id, null, owner_uid, null, null); -- may be a fake id because top_id[4] may be NULL
else
top_id := "Blog_DAV_SEARCH_ID" (detcol_id, path_parts, what);
if (DAV_HIDE_ERROR (top_id) is null)
{
return vector();
}
top_davpath := DAV_CONCAT_PATH (detcol_path, path_parts);
if ('R' = what)
{
return vector ("Blog_DAV_DIR_SINGLE" (top_id, what, top_davpath, auth_uid));
}
if (top_id[2] is null)
{
for select WAI_NAME as wai_orig_name, "Blog_FIXNAME" (WAI_NAME) as wai_fixed_name, WAI_ID as id, BI_BLOG_ID as blog_id
from BLOG.DBA.SYS_BLOG_OWNERS
where U_ID = owner_uid
do
{
declare maxrcvdate datetime;
maxrcvdate := coalesce (
(select max(B_TS) from BLOG.DBA.SYS_BLOGS SB where SB.B_BLOG_ID = blog_id),
cast ('1980-01-01' as datetime));;
vectorbld_acc (res, vector (DAV_CONCAT_PATH (top_davpath, wai_fixed_name) || '/', 'C', 0, maxrcvdate,
vector (UNAME_BLOG(), detcol_id, blog_id, owner_uid, null, null),
access, ownergid, owner_uid, maxrcvdate, 'dav/unix-directory', wai_fixed_name) );
}
goto finalize_res;
}
if (top_id[4] is null)
{
for select
"Blog_COMPOSE_HTML_NAME" (B_TITLE, B_POST_ID) as post_name,
"Blog_COMPOSE_COMMENTS_NAME" (B_TITLE, B_POST_ID) as comments_name,
B_BLOG_ID, B_POST_ID as m_id, B_TS, length(B_CONTENT) as DSIZE, B_MODIFIED as B_MODIFIED
from BLOG.DBA.SYS_BLOGS
where B_BLOG_ID = top_id[2]
do
{
if (post_name like name_mask)
vectorbld_acc (res, vector (DAV_CONCAT_PATH (top_davpath, post_name), 'R', DSIZE, B_TS,
vector (UNAME_BLOG(), detcol_id, top_id[2], owner_uid, m_id, null),
access, ownergid, owner_uid, B_MODIFIED, 'text/html', post_name ) );
if (exists (select top 1 1 from BLOG.DBA.BLOG_COMMENTS where BM_POST_ID = m_id and BM_BLOG_ID = top_id[2]))
{
vectorbld_acc (res, vector (DAV_CONCAT_PATH (top_davpath, comments_name) || '/', 'C', 0, B_TS,
vector (UNAME_BLOG(), detcol_id, top_id[2], owner_uid, m_id, null),
access, ownergid, owner_uid, B_MODIFIED, 'dav/unix-directory', comments_name) );
}
}
descnames := "Blog_CHANNEL_DESC_NAMES"();
dn_count := length (descnames);
for (dn_ctr := 0; dn_ctr < dn_count; dn_ctr := dn_ctr + 1)
{
declare dname varchar;
dname := descnames[dn_ctr];
vectorbld_acc (res, vector(DAV_CONCAT_PATH(top_davpath, dname), 'R', 1024, now(),
vector(UNAME_BLOG(), detcol_id, top_id[2], owner_uid, null, dname),
access, ownergid, owner_uid, now(), 'text/xml', dname ) );
}
}
else
{
for select orig_mname, DSIZE, BM_TS, BM_ID
from (select "Blog_COMPOSE_HTML_NAME" (BM_NAME, cast(BM_ID as varchar)) as orig_mname, BM_ID,
BM_TS, length (BM_COMMENT) as DSIZE
from BLOG.DBA.BLOG_COMMENTS
where BM_BLOG_ID = top_id[2] and BM_POST_ID = top_id[4]) m1
where orig_mname like name_mask
do
{
vectorbld_acc (res, vector (DAV_CONCAT_PATH(top_davpath, orig_mname), 'R', DSIZE, BM_TS,
vector (UNAME_BLOG(), detcol_id, top_id[2], owner_uid, top_id[4], BM_ID),
access, ownergid, owner_uid, BM_TS, 'text/html', orig_mname ) );
}
}
finalize_res:
vectorbld_final (res);
return res;
}
;
create procedure "Blog_POST_DAV_FC_PRED_METAS" (inout pred_metas any)
{
pred_metas := vector (
'B_BLOG_ID', vector ('SYS_BLOGS' , 0, 'varchar' , 'B_BLOG_ID' ),
'B_POST_ID', vector ('SYS_BLOGS' , 0, 'varchar' , 'B_POST_ID' ),
'RES_ID', vector ('SYS_BLOGS' , 0, 'any' , 'vector (UNAME_BLOG(), B_BLOG_ID, U_ID, B_POST_ID, null)' ),
'RES_ID_SERIALIZED', vector ('SYS_BLOGS' , 0, 'varchar' , 'serialize (vector (UNAME_BLOG(), B_BLOG_ID, U_ID, B_POST_ID, null))' ),
'RES_NAME', vector ('SYS_BLOGS' , 0, 'varchar' , '"Blog_COMPOSE_HTML_NAME" (B_TITLE, B_POST_ID)' ),
'RES_FULL_PATH', vector ('SYS_BLOGS' , 0, 'varchar' , 'concat (DAV_CONCAT_PATH (_param.detcolpath, "Blog_FIXNAME" (WAI_NAME)), ''/'', "Blog_COMPOSE_HTML_NAME" (B_TITLE, B_POST_ID))' ),
'RES_TYPE', vector ('SYS_BLOGS' , 0, 'varchar' , '(''text/plain'')' ),
'RES_OWNER_ID', vector ('SYS_BLOG_OWNERS' , 0, 'integer' , 'U_ID' ),
'RES_OWNER_NAME', vector ('SYS_BLOG_OWNERS' , 0, 'varchar' , 'U_NAME' ),
'RES_GROUP_ID', vector ('SYS_BLOGS' , 0, 'integer' , 'http_nogroup_gid()' ),
'RES_GROUP_NAME', vector ('SYS_BLOGS' , 0, 'varchar' , '(''nogroup'')' ),
'RES_COL_FULL_PATH', vector ('SYS_BLOGS' , 0, 'varchar' , 'concat (DAV_CONCAT_PATH (_param.detcolpath, "Blog_FIXNAME" (WAI_NAME)), ''/'')' ),
'RES_COL_NAME', vector ('SYS_BLOGS' , 0, 'varchar' , '"Blog_FIXNAME" (WAI_NAME)' ),
-- 'RES_COL_ID', vector ('SYS_DAV_RES' , 0, 'varchar' , 'RES_COL' ),
'RES_CR_TIME', vector ('SYS_BLOGS' , 0, 'datetime' , 'B_TS' ),
'RES_MOD_TIME', vector ('SYS_BLOGS' , 0, 'datetime' , 'B_MODIFIED' ),
'RES_PERMS', vector ('SYS_BLOGS' , 0, 'varchar' , '(''110000000RR'')' ),
'RES_CONTENT', vector ('SYS_BLOGS' , 0, 'text' , 'B_CONTENT' ),
'PROP_NAME', vector ('SYS_BLOGS' , 0, 'varchar' , '(''Content'')' ),
'PROP_VALUE', vector ('SYS_BLOGS' , 1, 'text' , 'B_CONTENT' ),
'RES_TAGS', vector ('SYS_BLOGS' , 0, 'varchar' , '('''')' ), -- 'varchar', not 'text-tag' because there's no free-text on union
'RES_PUBLIC_TAGS', vector ('SYS_BLOGS' , 0, 'varchar' , '('''')' ),
'RES_PRIVATE_TAGS', vector ('SYS_BLOGS' , 0, 'varchar' , '('''')' ),
'RDF_PROP', vector ('SYS_BLOGS' , 1, 'varchar' , NULL ),
'RDF_VALUE', vector ('SYS_BLOGS' , 2, 'XML' , NULL ),
'RDF_OBJ_VALUE', vector ('SYS_BLOGS' , 3, 'XML' , NULL )
);
}
;
create procedure "Blog_POST_DAV_FC_TABLE_METAS" (inout table_metas any)
{
table_metas := vector (
'SYS_BLOGS' , vector ( '\n inner join BLOG.DBA.SYS_BLOGS as ^{alias}^ on ((^{alias}^.B_BLOG_ID = _top.B_BLOG_ID) and (^{alias}^.B_POST_ID = _top.B_POST_ID)^{andpredicates}^)' ,
'\n exists (select 1 from BLOG.DBA.SYS_BLOGS as ^{alias}^ where (^{alias}^.B_BLOG_ID = _top.B_BLOG_ID) and (^{alias}^.B_POST_ID = _top.B_POST_ID)^{andpredicates}^)' ,
'B_CONTENT' , 'B_CONTENT' , '[__quiet] /' ),
'SYS_BLOG_OWNERS' , vector ( '' ,
'' ,
NULL , NULL , NULL )
-- 'SYS_BLOG_OWNERS' , vector ( '\n left outer join BLOG.DBA.SYS_BLOG_OWNERS as ^{alias}^ on ((^{alias}^.BI_BLOG_ID = _top.B_BLOG_ID)^{andpredicates}^)' ,
-- '\n exists (select 1 from BLOG.DBA.SYS_BLOG_OWNERS as ^{alias}^ where (^{alias}^.BI_BLOG_ID = _top.B_BLOG_ID)^{andpredicates}^)' ,
-- NULL , NULL , NULL )
-- 'SYS_DAV_COL' , vector ( '\n inner join WS.WS.SYS_DAV_COL as ^{alias}^ on ((^{alias}^.COL_ID = _param.detcol)^{andpredicates}^)' ,
-- '\n exists (select 1 from WS.WS.SYS_DAV_COL as ^{alias}^ where (^{alias}^.COL_ID = _param.detcol)^{andpredicates}^)' ,
-- NULL , NULL , NULL ),
-- 'SYS_DAV_GROUP' , vector ( '\n left outer join WS.WS.SYS_DAV_GROUP as ^{alias}^ on ((^{alias}^.G_ID = _top.RES_GROUP)^{andpredicates}^)' ,
-- '\n exists (select 1 from WS.WS.SYS_DAV_GROUP as ^{alias}^ where (^{alias}^.G_ID = _top.RES_GROUP)^{andpredicates}^)' ,
-- NULL , NULL , NULL )--,
-- 'SYS_DAV_PROP' , vector ( '\n inner join WS.WS.SYS_DAV_PROP as ^{alias}^ on ((^{alias}^.PROP_PARENT_ID = _top.RES_ID) and (^{alias}^.PROP_TYPE = ''R'')^{andpredicates}^)' ,
-- '\n exists (select 1 from WS.WS.SYS_DAV_PROP as ^{alias}^ where (^{alias}^.PROP_PARENT_ID = _top.RES_ID) and (^{alias}^.PROP_TYPE = ''R'')^{andpredicates}^)' ,
-- 'PROP_VALUE' , 'PROP_VALUE' , '[__quiet __davprop xmlns:virt="virt"] .' ),
-- 'public-tags' , vector ( '\n inner join WS.WS.SYS_DAV_TAG as ^{alias}^ on ((^{alias}^.DT_RES_ID = _top.RES_ID) and (^{alias}^.DT_U_ID = http_nobody_uid())^{andpredicates}^)' ,
-- '\n exists (select 1 from WS.WS.SYS_DAV_TAG as ^{alias}^ where (^{alias}^.DT_RES_ID = _top.RES_ID) and (^{alias}^.DT_U_ID = http_nobody_uid())^{andpredicates}^)' ,
-- 'DT_TAGS' , 'DT_TAGS' , NULL ),
-- 'private-tags' , vector ( '\n inner join WS.WS.SYS_DAV_TAG as ^{alias}^ on ((^{alias}^.DT_RES_ID = _top.RES_ID) and (^{alias}^.DT_U_ID = ^{uid}^)^{andpredicates}^)' ,
-- '\n exists (select 1 from WS.WS.SYS_DAV_TAG as ^{alias}^ where (^{alias}^.DT_RES_ID = _top.RES_ID) and (^{alias}^.DT_U_ID = ^{uid}^)^{andpredicates}^)' ,
-- 'DT_TAGS' , 'DT_TAGS' , NULL ),
-- 'all-tags' , vector ( '\n inner join (select * from WS.WS.SYS_DAV_TAG ^{alias}^_pub where ^{alias}^_pub.DT_U_ID = http_nobody_uid() union select * from WS.WS.SYS_DAV_TAG ^{alias}^_prv where ^{alias}^_prv.DT_U_ID = ^{uid}^) as ^{alias}^ on ((^{alias}^.DT_RES_ID = _top.RES_ID)^{andpredicates}^)' ,
-- '\n exists (select 1 from (select * from WS.WS.SYS_DAV_TAG ^{alias}^_pub where ^{alias}^_pub.DT_U_ID = http_nobody_uid() union select * from WS.WS.SYS_DAV_TAG ^{alias}^_prv where ^{alias}^_prv.DT_U_ID = ^{uid}^) as ^{alias}^ where (^{alias}^.DT_RES_ID = _top.RES_ID)^{andpredicates}^)' ,
-- 'DT_TAGS' , 'DT_TAGS' , NULL )
);
}
;
-- This prints the fragment that starts after 'FROM WS.WS.SYS_BLOGS' and contains the rest of FROM and whole 'WHERE'
create function "Blog_POST_DAV_FC_PRINT_WHERE" (inout filter any, in param_uid integer) returns varchar
{
declare pred_metas, cmp_metas, table_metas any;
declare used_tables any;
-- dbg_obj_princ ('Blog_POST_DAV_FC_PRINT_WHERE (', filter, param_uid, ')');
"Blog_POST_DAV_FC_PRED_METAS" (pred_metas);
DAV_FC_CMP_METAS (cmp_metas);
"Blog_POST_DAV_FC_TABLE_METAS" (table_metas);
used_tables := vector (
'SYS_BLOGS', vector ('SYS_BLOGS', '_top', null, vector (), vector (), vector ()),
'SYS_BLOG_OWNERS', vector ('SYS_BLOG_OWNERS', '_owners', null, vector (), vector (), vector ())
);
return DAV_FC_PRINT_WHERE_INT (filter, pred_metas, cmp_metas, table_metas, used_tables, param_uid);
}
;
create procedure "Blog_COMMENT_DAV_FC_PRED_METAS" (inout pred_metas any)
{
pred_metas := vector (
'BM_BLOG_ID', vector ('BLOG_COMMENTS' , 0, 'varchar' , 'BM_BLOG_ID' ),
'BM_POST_ID', vector ('BLOG_COMMENTS' , 0, 'varchar' , 'BM_POST_ID' ),
'RES_ID', vector ('BLOG_COMMENTS' , 0, 'any' , 'vector (UNAME_BLOG(), B_BLOG_ID, U_ID, B_POST_ID, BM_ID)' ),
'RES_ID_SERIALIZED', vector ('BLOG_COMMENTS' , 0, 'varchar' , 'serialize (vector (UNAME_BLOG(), B_BLOG_ID, U_ID, B_POST_ID, BM_ID))' ),
'RES_NAME', vector ('BLOG_COMMENTS' , 0, 'varchar' , '"Blog_COMPOSE_HTML_NAME" (BM_NAME, cast (BM_ID as varchar))' ),
'RES_FULL_PATH', vector ('BLOG_COMMENTS' , 0, 'varchar' , 'concat (DAV_CONCAT_PATH (_param.detcolpath, "Blog_FIXNAME" (WAI_NAME)), ''/'', "Blog_COMPOSE_COMMENTS_NAME" (B_TITLE, B_POST_ID), ''/'', "Blog_COMPOSE_HTML_NAME" (BM_NAME, cast (BM_ID as varchar)))' ),
'RES_TYPE', vector ('BLOG_COMMENTS' , 0, 'varchar' , '(''text/plain'')' ),
'RES_OWNER_ID', vector ('SYS_BLOG_OWNERS' , 0, 'integer' , 'U_ID' ),
'RES_OWNER_NAME', vector ('SYS_BLOG_OWNERS' , 0, 'varchar' , 'U_NAME' ),
'RES_GROUP_ID', vector ('BLOG_COMMENTS' , 0, 'integer' , 'http_nogroup_gid()' ),
'RES_GROUP_NAME', vector ('BLOG_COMMENTS' , 0, 'varchar' , '(''nogroup'')' ),
'RES_COL_FULL_PATH', vector ('SYS_BLOGS' , 0, 'varchar' , 'concat (DAV_CONCAT_PATH (_param.detcolpath, "Blog_FIXNAME" (WAI_NAME)), ''/'', "Blog_COMPOSE_COMMENTS_NAME" (B_TITLE, B_POST_ID))' ),
'RES_COL_NAME', vector ('SYS_BLOGS' , 0, 'varchar' , '"Blog_COMPOSE_COMMENTS_NAME" (B_TITLE, B_POST_ID)' ),
-- 'RES_COL_ID', vector ('SYS_DAV_RES' , 0, 'varchar' , 'RES_COL' ),
'RES_CR_TIME', vector ('BLOG_COMMENTS' , 0, 'datetime' , 'BM_TS' ),
'RES_MOD_TIME', vector ('BLOG_COMMENTS' , 0, 'datetime' , 'BM_TS' ),
'RES_PERMS', vector ('BLOG_COMMENTS' , 0, 'varchar' , '(''110000000RR'')' ),
'RES_CONTENT', vector ('BLOG_COMMENTS' , 0, 'text' , 'BM_COMMENT' ),
'PROP_NAME', vector ('BLOG_COMMENTS' , 0, 'varchar' , '(''Content'')' ),
'PROP_VALUE', vector ('BLOG_COMMENTS' , 1, 'text' , 'BM_COMMENT' ),
'RES_TAGS', vector ('BLOG_COMMENTS' , 0, 'varchar' , '('''')' ), -- 'varchar', not 'text-tag' because there's no free-text on union
'RES_PUBLIC_TAGS', vector ('BLOG_COMMENTS' , 0, 'varchar' , '('''')' ),
'RES_PRIVATE_TAGS', vector ('BLOG_COMMENTS' , 0, 'varchar' , '('''')' ),
'RDF_PROP', vector ('BLOG_COMMENTS' , 1, 'varchar' , NULL ),
'RDF_VALUE', vector ('BLOG_COMMENTS' , 2, 'XML' , NULL ),
'RDF_OBJ_VALUE', vector ('BLOG_COMMENTS' , 3, 'XML' , NULL )
);
}
;
create procedure "Blog_COMMENT_DAV_FC_TABLE_METAS" (inout table_metas any)
{
table_metas := vector (
'BLOG_COMMENTS' , vector ( '' ,
'' ,
'BM_COMMENT' , 'BM_COMMENT' , '[__quiet] /' ),
'SYS_BLOGS' , vector ( '' ,
'' ,
'B_CONTENT' , 'B_CONTENT' , '[__quiet] /' ),
'SYS_BLOG_OWNERS' , vector ( '' ,
'' ,
NULL , NULL , NULL )
-- 'SYS_BLOG_OWNERS' , vector ( '\n left outer join BLOG.DBA.SYS_BLOG_OWNERS as ^{alias}^ on ((^{alias}^.BI_BLOG_ID = _top.B_BLOG_ID)^{andpredicates}^)' ,
-- '\n exists (select 1 from BLOG.DBA.SYS_BLOG_OWNERS as ^{alias}^ where (^{alias}^.BI_BLOG_ID = _top.B_BLOG_ID)^{andpredicates}^)' ,
-- NULL , NULL , NULL )
-- 'SYS_DAV_COL' , vector ( '\n inner join WS.WS.SYS_DAV_COL as ^{alias}^ on ((^{alias}^.COL_ID = _param.detcol)^{andpredicates}^)' ,
-- '\n exists (select 1 from WS.WS.SYS_DAV_COL as ^{alias}^ where (^{alias}^.COL_ID = _param.detcol)^{andpredicates}^)' ,
-- NULL , NULL , NULL ),
-- 'SYS_DAV_GROUP' , vector ( '\n left outer join WS.WS.SYS_DAV_GROUP as ^{alias}^ on ((^{alias}^.G_ID = _top.RES_GROUP)^{andpredicates}^)' ,
-- '\n exists (select 1 from WS.WS.SYS_DAV_GROUP as ^{alias}^ where (^{alias}^.G_ID = _top.RES_GROUP)^{andpredicates}^)' ,
-- NULL , NULL , NULL )--,
-- 'SYS_DAV_PROP' , vector ( '\n inner join WS.WS.SYS_DAV_PROP as ^{alias}^ on ((^{alias}^.PROP_PARENT_ID = _top.RES_ID) and (^{alias}^.PROP_TYPE = ''R'')^{andpredicates}^)' ,
-- '\n exists (select 1 from WS.WS.SYS_DAV_PROP as ^{alias}^ where (^{alias}^.PROP_PARENT_ID = _top.RES_ID) and (^{alias}^.PROP_TYPE = ''R'')^{andpredicates}^)' ,
-- 'PROP_VALUE' , 'PROP_VALUE' , '[__quiet __davprop xmlns:virt="virt"] .' ),
-- 'public-tags' , vector ( '\n inner join WS.WS.SYS_DAV_TAG as ^{alias}^ on ((^{alias}^.DT_RES_ID = _top.RES_ID) and (^{alias}^.DT_U_ID = http_nobody_uid())^{andpredicates}^)' ,
-- '\n exists (select 1 from WS.WS.SYS_DAV_TAG as ^{alias}^ where (^{alias}^.DT_RES_ID = _top.RES_ID) and (^{alias}^.DT_U_ID = http_nobody_uid())^{andpredicates}^)' ,
-- 'DT_TAGS' , 'DT_TAGS' , NULL ),
-- 'private-tags' , vector ( '\n inner join WS.WS.SYS_DAV_TAG as ^{alias}^ on ((^{alias}^.DT_RES_ID = _top.RES_ID) and (^{alias}^.DT_U_ID = ^{uid}^)^{andpredicates}^)' ,
-- '\n exists (select 1 from WS.WS.SYS_DAV_TAG as ^{alias}^ where (^{alias}^.DT_RES_ID = _top.RES_ID) and (^{alias}^.DT_U_ID = ^{uid}^)^{andpredicates}^)' ,
-- 'DT_TAGS' , 'DT_TAGS' , NULL ),
-- 'all-tags' , vector ( '\n inner join (select * from WS.WS.SYS_DAV_TAG ^{alias}^_pub where ^{alias}^_pub.DT_U_ID = http_nobody_uid() union select * from WS.WS.SYS_DAV_TAG ^{alias}^_prv where ^{alias}^_prv.DT_U_ID = ^{uid}^) as ^{alias}^ on ((^{alias}^.DT_RES_ID = _top.RES_ID)^{andpredicates}^)' ,
-- '\n exists (select 1 from (select * from WS.WS.SYS_DAV_TAG ^{alias}^_pub where ^{alias}^_pub.DT_U_ID = http_nobody_uid() union select * from WS.WS.SYS_DAV_TAG ^{alias}^_prv where ^{alias}^_prv.DT_U_ID = ^{uid}^) as ^{alias}^ where (^{alias}^.DT_RES_ID = _top.RES_ID)^{andpredicates}^)' ,
-- 'DT_TAGS' , 'DT_TAGS' , NULL )
);
}
;
-- This prints the fragment that starts after 'FROM WS.WS.SYS_BLOGS' and contains the rest of FROM and whole 'WHERE'
create function "Blog_COMMENT_DAV_FC_PRINT_WHERE" (inout filter any, in param_uid integer) returns varchar
{
declare pred_metas, cmp_metas, table_metas any;
declare used_tables any;
-- dbg_obj_princ ('Blog_POST_DAV_FC_PRINT_WHERE (', filter, param_uid, ')');
"Blog_COMMENT_DAV_FC_PRED_METAS" (pred_metas);
DAV_FC_CMP_METAS (cmp_metas);
"Blog_COMMENT_DAV_FC_TABLE_METAS" (table_metas);
used_tables := vector (
'BLOG_COMMENTS', vector ('BLOG_COMMENTS', '_top', null, vector (), vector (), vector ()),
'SYS_BLOGS', vector ('SYS_BLOGS', '_blogs', null, vector (), vector (), vector ()),
'SYS_BLOG_OWNERS', vector ('SYS_BLOG_OWNERS', '_owners', 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 "Blog_DAV_DIR_FILTER" (in detcol_id any, in path_parts any, in detcol_path any, inout compilation any, in recursive integer, in auth_uid integer) returns any
{
declare st, access, qry_text, execstate, execmessage varchar;
declare res any;
declare cond_list, execmeta, execrows any;
declare blog_id, blog_colname, post_id, condtext, cond_key varchar;
declare ownergid, owner_uid integer;
-- dbg_obj_princ ('Blog_DAV_DIR_FILTER (', detcol_id, path_parts, detcol_path, compilation, recursive, auth_uid, ')');
"Blog_ACCESS_PARAMS" (detcol_id, access, ownergid, owner_uid);
vectorbld_init (res);
blog_id := null;
post_id := null;
if (((length (path_parts) <= 1) and (recursive <> 1)) or (length (path_parts) > 2))
{
-- dbg_obj_princ ('\r\nGoto skip_post_level\r\n');
goto skip_post_level;
}
if (length (path_parts) >= 2)
{
blog_id := coalesce ((select BI_BLOG_ID from BLOG.DBA.SYS_BLOG_OWNERS where U_ID = owner_uid and "Blog_FIXNAME" (WAI_NAME) = path_parts[0]));
if (blog_id is null)
{
-- dbg_obj_princ ('\r\nGoto finalize\r\n');
goto finalize;
}
}
cond_key := sprintf ('Blog_POST&%V', coalesce (blog_id, ''));
condtext := get_keyword (cond_key, compilation);
-- dbg_obj_princ ('Cached condtext is ', condtext);
if (condtext is null)
{
cond_list := get_keyword ('', compilation);
-- dbg_obj_princ ('cond_list is ', cond_list);
if (blog_id is not null)
cond_list := vector_concat (cond_list, vector ( vector ('B_BLOG_ID', '=', blog_id)));
condtext := "Blog_POST_DAV_FC_PRINT_WHERE" (cond_list, auth_uid);
-- dbg_obj_princ ('\r\ncondtext2 ', condtext, '\r\n');
compilation := vector_concat (compilation, vector (cond_key, condtext));
-- dbg_obj_princ ('\r\ncompilation ', compilation, '\r\n');
}
execstate := '00000';
qry_text := 'select concat (DAV_CONCAT_PATH (_param.detcolpath, "Blog_FIXNAME" (WAI_NAME)), ''/'', "Blog_COMPOSE_HTML_NAME" (B_TITLE, B_POST_ID)),
''R'', length (_top.B_CONTENT), _top.B_MODIFIED,
vector (UNAME_BLOG(), ?, B_BLOG_ID, U_ID, B_POST_ID, null),
''110000000RR'', http_nogroup_gid(), U_ID, _top.B_TS, ''text/plain'', "Blog_COMPOSE_HTML_NAME" (B_TITLE, B_POST_ID)
from
(select top 1 ? as detcolpath from WS.WS.SYS_DAV_COL) as _param,
BLOG.DBA.SYS_BLOGS as _top
join BLOG.DBA.SYS_BLOG_OWNERS as _owners on (BI_BLOG_ID = B_BLOG_ID and U_ID = ?)
' || condtext;
-- dbg_obj_princ ('Collection of blog posts, blog_id=', blog_id, ', qry_text = ', qry_text);
exec (qry_text, execstate, execmessage,
vector (detcol_id, detcol_path, owner_uid),
100000000, execmeta, execrows );
-- dbg_obj_princ ('Collection of blog posts: execstate = ', execstate, ', execmessage = ', execmessage);
if ('00000' <> execstate)
signal (execstate, execmessage || ' in ' || qry_text);
vectorbld_concat_acc (res, execrows);
skip_post_level:
if (((length (path_parts) <= 2) and (recursive <> 1)) or (length (path_parts) > 3))
goto skip_post_level;
if (length (path_parts) >= 3)
{
declare post_title_pattern varchar;
"Blog_PARSE_COMMENTS_NAME" (path_parts[1], post_title_pattern, post_id);
if (post_id is null)
goto finalize;
if (not exists (select top 1 1 from BLOG.DBA.SYS_BLOGS where B_BLOG_ID = blog_id and B_POST_ID = post_id and B_TITLE like post_title_pattern))
goto finalize;
}
cond_key := sprintf ('Blog_COMMENT&%V&%V', coalesce (blog_id, ''), coalesce (post_id, ''));
condtext := get_keyword (cond_key, compilation);
if (condtext is null)
{
cond_list := get_keyword ('', compilation);
if (blog_id is not null)
cond_list := vector_concat (cond_list, vector ( vector ('BM_BLOG_ID', '=', blog_id)));
if (post_id is not null)
cond_list := vector_concat (cond_list, vector ( vector ('BM_POST_ID', '=', post_id)));
condtext := "Blog_COMMENT_DAV_FC_PRINT_WHERE" (cond_list, auth_uid);
compilation := vector_concat (compilation, vector (cond_key, condtext));
}
execstate := '00000';
qry_text := '
select
concat (DAV_CONCAT_PATH (_param.detcolpath, "Blog_FIXNAME" (_owners.WAI_NAME)), ''/'', "Blog_COMPOSE_COMMENTS_NAME" (_blogs.B_TITLE, _blogs.B_POST_ID), ''/'', "Blog_COMPOSE_HTML_NAME" (_top.BM_NAME, cast (_top.BM_ID as varchar))),
''R'', length (_top.BM_COMMENT), _top.BM_TS,
vector (UNAME_BLOG(), ?, _top.BM_BLOG_ID, _owners.U_ID, _top.BM_POST_ID, _top.BM_ID),
''110000000RR'', http_nogroup_gid(), _owners.U_ID, _top.BM_TS, ''text/plain'', "Blog_COMPOSE_HTML_NAME" (_top.BM_NAME, cast (_top.BM_ID as varchar))
from
(select top 1 ? as detcolpath from WS.WS.SYS_DAV_COL) as _param,
BLOG.DBA.BLOG_COMMENTS as _top
join BLOG.DBA.SYS_BLOGS as _blogs on (B_BLOG_ID = BM_BLOG_ID and B_POST_ID = BM_POST_ID)
join BLOG.DBA.SYS_BLOG_OWNERS as _owners on (BI_BLOG_ID = B_BLOG_ID and U_ID = ?)
' || condtext;
-- dbg_obj_princ ('Collection of blog comments, blog_id=', blog_id, ', post_id=', post_id, ', qry_text = ', qry_text);
exec (qry_text, execstate, execmessage,
vector (detcol_id, detcol_path, owner_uid),
100000000, execmeta, execrows );
-- dbg_obj_princ ('Collection of blog comments: execstate = ', execstate, ', execmessage = ', execmessage);
if ('00000' <> execstate)
signal (execstate, execmessage || ' in ' || qry_text);
vectorbld_concat_acc (res, execrows);
finalize:
vectorbld_final (res);
return res;
}
;
--| When DAV_PROP_GET_INT or DAV_DIR_LIST_INT calls DET function, authentication is performed before the call.
create function "Blog_DAV_SEARCH_ID" (in detcol_id any, in path_parts any, in what char(1)) returns any
{
-- dbg_obj_princ ('Blog_DAV_SEARCH_ID (', detcol_id, path_parts, what, ')');
if (path_parts[0] = '' or path_parts[0] is null)
return -1;
declare blog_id, colpath, merged_fnameext, orig_fnameext varchar;
declare orig_id, ctr, len integer;
declare hitlist any;
declare access varchar;
declare ownergid, owner_uid integer;
"Blog_ACCESS_PARAMS" (detcol_id, access, ownergid, owner_uid);
len := length (path_parts);
if (0 = len)
{
if ('C' <> what)
{
-- dbg_obj_princ ('resource with empty path - no items');
return -1;
}
return vector (UNAME_BLOG(), detcol_id, null, owner_uid, null, null);
}
if ('' = path_parts[length(path_parts) - 1])
{
if ('C' <> what)
{
-- dbg_obj_princ ('resource without a name - no items');
return -1;
}
}
else
{
if ('R' <> what)
{
-- dbg_obj_princ ('non-resource with a name - no items');
return -1;
}
}
blog_id := coalesce ((select BI_BLOG_ID
from BLOG.DBA.SYS_BLOG_OWNERS
where U_ID = owner_uid and "Blog_FIXNAME" (WAI_NAME) = path_parts[0]));
if (blog_id is null)
return -1;
if ('C' = what)
{
if (2 = len)
return vector (UNAME_BLOG(), detcol_id, blog_id, owner_uid, null, null);
if (3 = len)
{
declare post_title_pattern, post_id varchar;
"Blog_PARSE_COMMENTS_NAME" (path_parts[1], post_title_pattern, post_id);
if (post_title_pattern is null or post_id is null)
return -1;
if (exists (select top 1 1
from BLOG.DBA.SYS_BLOGS join BLOG.DBA.SYS_BLOG_OWNERS on (B_BLOG_ID = BI_BLOG_ID)
where U_ID = owner_uid and
cast (B_TITLE as varchar) like post_title_pattern and B_POST_ID = post_id))
return vector (UNAME_BLOG(), detcol_id, blog_id, owner_uid, post_id, null);
}
return -1;
}
if (len = 2)
{
declare post_title_pattern, post_id varchar;
if (position (path_parts[1], "Blog_CHANNEL_DESC_NAMES" ()))
return vector (UNAME_BLOG(), detcol_id, blog_id, owner_uid, null, path_parts[1]);
"Blog_PARSE_HTML_NAME" (path_parts[1], post_title_pattern, post_id);
if (post_title_pattern is null or post_id is null)
return -1;
if (exists (select top 1 1
from BLOG.DBA.SYS_BLOGS join BLOG.DBA.SYS_BLOG_OWNERS on (B_BLOG_ID = BI_BLOG_ID)
where U_ID = owner_uid and
cast (B_TITLE as varchar) like post_title_pattern and B_POST_ID = post_id))
return vector (UNAME_BLOG(), detcol_id, blog_id, owner_uid, post_id, null);
}
if (len = 3)
{
declare post_title_pattern, post_id, comment_title_pattern, comment_id varchar;
"Blog_PARSE_COMMENTS_NAME" (path_parts[1], post_title_pattern, post_id);
if (post_title_pattern is null or post_id is null)
return -1;
"Blog_PARSE_HTML_NAME" (path_parts[2], comment_title_pattern, comment_id);
if (comment_title_pattern is null or comment_id is null)
return -1;
if (exists (select top 1 1
from BLOG.DBA.SYS_BLOG_OWNERS
join BLOG.DBA.SYS_BLOGS on (B_BLOG_ID = BI_BLOG_ID)
join BLOG.DBA.BLOG_COMMENTS on ((BM_BLOG_ID = B_BLOG_ID) and (BM_POST_ID = B_POST_ID))
where U_ID = owner_uid and
cast (B_TITLE as varchar) like post_title_pattern and B_POST_ID = post_id and
BM_NAME like comment_title_pattern and BM_ID = comment_id ) )
return vector (UNAME_BLOG(), detcol_id, blog_id, owner_uid, post_id, cast (comment_id as integer));
}
return -1;
}
;
--| When DAV_SEARCH_PATH_INT calls DET function, authentication is performed before the call.
create function "Blog_DAV_SEARCH_PATH" (in id any, in what char(1)) returns any
{
-- dbg_obj_princ ('Blog_DAV_SEARCH_PATH (', id, what, ')');
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 "Blog_DAV_RES_UPLOAD_COPY" (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 ('Blog_DAV_RES_UPLOAD_COPY (', detcol_id, path_parts, source_id, what, overwrite_flags, permissions, uid, gid, auth_uid, ')');
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 "Blog_DAV_RES_UPLOAD_MOVE" (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 ('Blog_DAV_RES_UPLOAD_MOVE (', detcol_id, path_parts, source_id, what, overwrite_flags, auth_uid, ')');
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 "Blog_DAV_RES_CONTENT" (in id any, inout content any, out type varchar, in content_mode integer) returns integer
{
-- dbg_obj_princ ('Blog_DAV_RES_CONTENT (', id, ', [content], [type], ', content_mode, ')');
declare cont any;
declare len int;
if (id[4] is null and id[5] is not null)
{
declare hdr any;
type := 'text/xml';
for (select BI_HOME
from BLOG.DBA.SYS_BLOG_INFO
where BI_BLOG_ID = id[2])
do
{
declare doc_base varchar;
declare uri, host, olduri varchar;
host := http_request_header (http_request_header (), 'Host', null);
if (isstring (host) and strchr (host, ':') is null)
{
declare hp varchar;
declare hpa any;
hp := sys_connected_server_address ();
hpa := split_and_decode (hp, 0, '\0\0:');
host := host || ':' || hpa[1];
}
if (host is null)
host := sys_connected_server_address ();
uri := 'http://' || host || BI_HOME || 'gems/';
if (position (id[5], "Blog_CHANNEL_DESC_NAMES" ()))
uri := uri || id[5];
olduri := uri;
again:
-- dbg_obj_princ(uri);
commit work;
content := http_get(uri, hdr);
if (hdr[0] not like 'HTTP/1._ 200 %')
{
if (hdr[0] like 'HTTP/1._ 30_ %')
{
uri := http_request_header (hdr, 'Location');
if (isstring (uri))
goto again;
}
signal ('22023', trim(hdr[0], '\r\n'), 'BLOG0');
return 0;
}
}
return 0;
}
type := 'text/html';
if (id[5] is null)
{
for (select B_CONTENT from BLOG.DBA.SYS_BLOGS SB where SB.B_BLOG_ID = id[2] and SB.B_POST_ID = id[4])
do
{
if ((content_mode = 0) or (content_mode = 2))
content := B_CONTENT;
else if (content_mode = 1)
http (B_CONTENT, content);
else if (content_mode = 3)
http (B_CONTENT);
}
}
else
{
for (select BM_COMMENT
from BLOG.DBA.BLOG_COMMENTS BC
where BC.BM_BLOG_ID = id[2] and BC.BM_POST_ID = id[4] and BC.BM_ID = id[5]
)
do
{
if ((content_mode = 0) or (content_mode = 2))
content := BM_COMMENT;
else if (content_mode = 1)
http (BM_COMMENT, content);
else if (content_mode = 3)
http (BM_COMMENT);
}
}
return 0;
}
;
--| This adds an extra access path to the existing resource or collection.
create function "Blog_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 ('Blog_DAV_SYMLINK (', detcol_id, path_parts, source_id, overwrite, uid, gid, auth_uid, ')');
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, 'what', old_full_path, dereferenced_id, dereferenced_full_path).
create function "Blog_DAV_DEREFERENCE_LIST" (in detcol_id any, inout report_array any) returns any
{
-- dbg_obj_princ ('Blog_DAV_DEREFERENCE_LIST (', detcol_id, report_array, ')');
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 "Blog_DAV_RESOLVE_PATH" (in detcol_id any, inout reference_item any, inout old_base varchar, inout new_base varchar) returns any
{
-- dbg_obj_princ ('Blog_DAV_RESOLVE_PATH (', detcol_id, reference_item, old_base, new_base, ')');
return -20;
}
;
--| There's no API function to lock for a while (do we need such?) The "LOCK" DAV method checks that all parameters are valid but does not check for existing locks.
create function "Blog_DAV_LOCK" (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 ('Blog_DAV_LOCK (', id, type, locktype, scope, token, owner_name, owned_tokens, depth, timeout_sec, owner_name, auth_uid, ')');
return -20;
}
;
--| There's no API function to unlock for a while (do we need such?) The "UNLOCK" DAV method checks that all parameters are valid but does not check for existing locks.
create function "Blog_DAV_UNLOCK" (in id any, in type char(1), in token varchar, in auth_uid integer)
{
-- dbg_obj_princ ('Blog_DAV_UNLOCK (', id, type, token, auth_uid, ')');
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 "Blog_DAV_IS_LOCKED" (inout id any, inout type char(1), in owned_tokens varchar) returns integer
{
-- dbg_obj_princ ('Blog_DAV_IS_LOCKED (', id, type, owned_tokens, ')');
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 "Blog_DAV_LIST_LOCKS" (in id any, in type char(1), in recursive integer) returns any
{
-- dbg_obj_princ ('Blog_DAV_LIST_LOCKS" (', id, type, recursive);
return vector ();
}
;
create procedure "Blog_CF_PROPNAME_TO_COLNAME" (in prop varchar)
{
return get_keyword (prop, vector (
'http://purl.org/rss/1.0/title', 'BLOG_INFO.BI_TITLE',
'http://purl.org/rss/1.0/copyright', 'BLOG_INFO.BI_COPYRIGHT',
'http://purl.org/rss/1.0/description', 'BLOG_INFO.BI_ABOUT',
'http://purl.org/rss/1.0/link', '"Blog_CF_COMPOSE_BLOG_LINK" (BLOG_INFO.BI_BLOG_ID)',
'http://purl.org/rss/1.0/lastBuildDate', 'cast (BLOG_INFO.BI_LAST_UPDATE as varchar)' ) );
}
;
create procedure "Blog_CF_FEED_FROM_AND_WHERE" (in detcol_id integer, in cfc_id integer, inout rfc_list_cond any, inout filter_data any, in distexpn varchar, in auth_uid integer)
{
declare where_clause, from_clause varchar;
declare access varchar;
declare ownergid, owner_uid, proppos, filter_len, filter_idx integer;
-- dbg_obj_princ ('Blog_CF_FEED_FROM_AND_WHERE (', detcol_id, cfc_id, rfc_list_cond, filter_data, distexpn, auth_uid, ')');
"Blog_ACCESS_PARAMS" (detcol_id, access, ownergid, owner_uid);
-- dbg_obj_princ ('"Blog_ACCESS_PARAMS" (', detcol_id, ',...) reports ', access, ownergid, owner_uid );
from_clause := '
from
BLOG.DBA.SYS_BLOG_INFO as BLOG_INFO
';
where_clause := 'BLOG_INFO.BI_OWNER = ' || cast (owner_uid as varchar);
filter_len := length (filter_data);
for (filter_idx := 0; filter_idx < (filter_len - 3); filter_idx := filter_idx + 4)
{
declare mode integer;
declare cmp_col, cmp_val varchar;
cmp_col := "Blog_CF_PROPNAME_TO_COLNAME" (filter_data [filter_idx]);
cmp_val := filter_data [filter_idx + 2];
-- dbg_obj_princ ('cmp_col=', cmp_col, ', cmp_val=', cmp_val);
if (cmp_col is null)
{
if ('' <> cmp_val)
{
where_clause := '1 = 2';
goto where_clause_complete;
}
goto where_oper_complete;
}
if (where_clause <> '')
where_clause := where_clause || ' and ';
mode := filter_data [filter_idx + 3];
if (mode = 0)
where_clause := where_clause || sprintf ('(%s = %s)', cmp_col, WS.WS.STR_SQL_APOS (cmp_val));
else if (mode = 4)
where_clause := where_clause || sprintf ('(%s is null)', cmp_col);
else -- truncation
where_clause := where_clause || sprintf ('(%s between %s and %s)', cmp_col, WS.WS.STR_SQL_APOS (cmp_val), WS.WS.STR_SQL_APOS (cmp_val || '\377\377\377\377'));
where_oper_complete:
;
}
where_clause_complete:
if (where_clause <> '')
return from_clause || ' where ' || where_clause;
return from_clause;
}
;
create procedure "Blog_CF_LIST_PROP_DISTVALS" (in detcol_id integer, in cfc_id integer, in rfc_spath varchar, inout rfc_list_cond any, in schema_uri varchar, inout filter_data any, inout distval_dict any, in auth_uid integer)
{
declare distprop, distexpn varchar;
declare from_and_where_text, qry_text varchar;
declare execstate, execmessage varchar;
declare execmeta, execrows any;
-- dbg_obj_princ ('Blog_CF_LIST_PROP_DISTVALS (', detcol_id, cfc_id, rfc_spath, rfc_list_cond, schema_uri, filter_data, distval_dict, auth_uid, ')');
if (schema_uri = 'http://purl.org/rss/1.0/')
{ -- channel description
distprop := filter_data[length (filter_data) - 2];
distexpn := "Blog_CF_PROPNAME_TO_COLNAME" (distprop);
if (distexpn is null)
{
dict_put (distval_dict, '! empty property value !', 1);
return;
}
from_and_where_text := Blog_CF_FEED_FROM_AND_WHERE (detcol_id, cfc_id, rfc_list_cond, filter_data, distexpn, auth_uid);
qry_text := 'select distinct ' || distexpn || from_and_where_text;
execstate := '00000';
execmessage := 'OK';
-- dbg_obj_princ ('Will exec: ', qry_text);
exec (qry_text,
execstate, execmessage,
vector (), 100000000, execmeta, execrows );
-- dbg_obj_princ ('exec returns: ', execstate, execmessage, execrows);
if (isarray (execrows))
foreach (any execrow in execrows) do
{
dict_put (distval_dict, "CatFilter_ENCODE_CATVALUE" (execrow[0]), 1);
}
return;
}
}
;
create function "Blog_CF_GET_RDF_HITS" (in detcol_id integer, in cfc_id integer, in rfc_spath varchar, inout rfc_list_cond any, in schema_uri varchar, inout filter_data any, in detcol_path varchar, in make_diritems integer, in auth_uid integer) returns any
{
declare from_and_where_text, qry_text varchar;
declare execstate, execmessage varchar;
declare acc_len, acc_ctr integer;
declare execmeta, acc any;
declare access varchar;
declare ownergid, owner_uid integer;
-- dbg_obj_princ ('\n\n\nBlog_CF_GET_RDF_HITS (', detcol_id, cfc_id, rfc_spath, rfc_list_cond, schema_uri, filter_data, make_diritems, auth_uid, ')');
acc := vector ();
acc_len := 0;
if (schema_uri = 'http://purl.org/rss/1.0/')
{ -- channel description
"Blog_ACCESS_PARAMS" (detcol_id, access, ownergid, owner_uid);
from_and_where_text := Blog_CF_FEED_FROM_AND_WHERE (detcol_id, cfc_id, rfc_list_cond, filter_data, 'CHANNEL_DETAILS.ECD_CHANNEL_URI', auth_uid);
qry_text := 'select CHANNEL_DETAILS.ECD_CHANNEL_URI' || from_and_where_text;
execstate := '00000';
execmessage := 'OK';
-- dbg_obj_princ ('Will exec: ', qry_text);
exec (qry_text,
execstate, execmessage,
vector (), 100000000, execmeta, acc );
-- dbg_obj_princ ('exec returns: ', execstate, execmessage, acc);
acc_len := length (acc);
acc_ctr := 0;
while (acc_ctr < acc_len)
{
declare r_id integer;
declare fullname varchar;
declare full_id, diritm any;
r_id := acc[acc_ctr][0];
full_id := vector (UNAME_BLOG(), detcol_id, r_id, owner_uid, null, null);
if (make_diritems = 1)
{
diritm := "Blog_DAV_DIR_SINGLE" (full_id, 'R', '(fake path)', auth_uid);
if (DAV_HIDE_ERROR (diritm) is not null)
{
diritm [0] := DAV_CONCAT_PATH (detcol_path, diritm[10]); -- now we can remove the fake path.
acc [acc_ctr] := diritm;
acc_ctr := acc_ctr + 1;
}
else --collision in the air: someone just removed the resource from the disk :(
{
if (acc_len > 1)
{
acc [acc_ctr] := acc [acc_len - 1];
acc_len := acc_len - 1;
-- no need in acc_ctr := acc_ctr + 1;
}
}
}
else
{
acc [acc_ctr] := full_id;
acc_ctr := acc_ctr + 1;
}
}
}
if (acc_len < length (acc)) -- There were collisions in the air
{
acc := subseq (acc, 0, acc_len);
}
-- dbg_obj_princ ('Blog_CF_GET_RDF_HITS_RES_IDS (', detcol_id, cfc_id, rfc_spath, rfc_list_cond, schema_uri, filter_data, make_diritems, auth_uid, ') returns ', acc);
return acc;
}
;
create function "Blog_RF_ID2SUFFIX" (in id any, in what char(1)) returns varchar
{
-- dbg_obj_princ ('Blog_RF_ID2SUFFIX (', id, what, ')');
if ((id[4] is null) and (what='R'))
{
return sprintf ('BlogFeed-%d-%d', id[1], coalesce ((select WAI_ID from BLOG.DBA.SYS_BLOG_OWNERS where BI_BLOG_ID = id[2])));
}
signal ('OBLOM', 'Blog_RF_ID2SUFFIX supports only feeds for a while');
}
;
create procedure "BlogFeed_RF_SUFFIX2ID" (in suffix varchar, in what char(1))
{
declare pairs any;
declare detcol_id, wainst_id, owner_uid integer;
declare blog_id varchar;
-- dbg_obj_princ ('BlogFeed_RF_SUFFIX2ID (', suffix, what, ')');
pairs := regexp_parse ('^([1-9][0-9]*)-([1-9][0-9]*)\044', suffix, 0);
if (pairs is null)
{
;
-- dbg_obj_princ ('BlogFeed_RF_SUFFIX2ID (', suffix, what, ') failed to parse the argument');
}
detcol_id := cast (subseq (suffix, pairs[2], pairs[3]) as integer);
wainst_id := cast (subseq (suffix, pairs[4], pairs[5]) as integer);
whenever not found goto oblom;
select U_ID, BI_BLOG_ID into owner_uid, blog_id
from BLOG.DBA.SYS_BLOG_OWNERS
where WAI_ID = wainst_id;
return vector (UNAME_BLOG(), detcol_id, blog_id, owner_uid, null, null);
oblom:
return NULL;
}
;
create function UNAME_BLOG() returns any { return UNAME'Blog'; };