\)|$href2$href3\1|"
+-- select val from $ts where key="title" and id="$id";
+select
+ coalesce((select ",e," from blog where rowid=$rowid and author='$user'),'')
+||val||" "
+||case (select val from $ts where key="mode" and id="$id")
+ when 'report-closed' then "レポート提出用(自身のファイルのみ参照可),s,"
+ when 'report-open' then "レポート提出用,s,"
+ else ""
+ end
+ from $ts where key="ctime" and id="$id";
+select val from $ts where key="heading" and id="$id";
+EOF
+ cat<
+
+EOF
+
+ #(2)Display following articles
+textform='
+
+
添付ファイル:
+
+
+
+'
+ ## 6/11の次: articleを出して行く
+: <&3
+ #case $ct in
+ # [Ii]mage*) anch="$fn" ;;
+ # *) anch=$fn ;;
+ # esac
+ # Should not contain newlines for sed argument
+ # echo -n "$anch"
+ iconhref $td/$fn "$hrfb+$ri" "$fn" "$fn"
+ done)
+ fi
+ fi
+
+ ### number=$((number+1))
+# reply=""
+ getgecos="(select rowid from user where name='$author')||':'||\
+ coalesce((select val from user_s \
+ where name='$author' and key='gecos'), '$author')||',[/a],'"
+ href="$myname?editart+$arid+$rowid"
+ link="編集"
+ cat<|" \
+ -e 's|,\[/a\],||' \
+ -e 's/,n,/ /g' -e "s|,i,|$imgs|" \
+ -e "s|
\(
\)|
\1|" \
+ -e "s|\(
\)\(
\),e,|\1\2$link|"
+select
+ coalesce((select ",e," from article where id='$aid' and author='$user'),"")
+ ||
+ max(case key when 'ctime' then ",n,"||val||
+ ",n,"||$getgecos end) as TIME,
+-- max(case key when 'parent' then val||"への返信" end) as REPLYTO,
+ max(case key when 'text' then val||",i," end) as TEXT
+ from article_s where id = '$aid'
+ group by id order by TIME;
+EOF
+ done
+ echo "
"
+
+
+ blog_writable $rowid $user && cat<
+
コメント記入
+
+
+
+$textform
+
+EOF
+ echo ""
+
+ # Record access log
+ acclog blog $rowid
+}
+
+lshandout() {
+ # $1=rowid of blog
+ time=`getvalbyid blog ctime $1|colrm 11`
+ owner=`getvalbyid blog owner $1`
+ title=`getvalbyid blog title $1`
+ ge=`gecos $owner`
+ lshandoutsub $owner "$@" \
+ |m4 -D_TITLE_="提出状況" \
+ -D_SUBTITLE_="$time [$title]@${ge:-$owner}" -D_DIARY_="" \
+ -D_FORM_="syscmd(cat)" -D_BLOGS_= -D_DUMPTABLE_= \
+ $layout/html.m4.html $layout/diary.m4.html
+}
+lshandoutsub() {
+ # $1=owner $2=rowid of blog
+ if isgroup $1; then
+ sample="(select user from grp_mem where gname='$1')"
+ else
+ sample="(select distinct author as user from arts)"
+ echo "
(集計は板への投稿者のみ)
"
+ fi
+ sql="with arts as (select id,author from article \
+ where blogid=(select id from blog where rowid=$2))\
+ select (select rowid from user where name=c0.user)||' '|| \
+ coalesce((select val from user_s where name=c0.user \
+ and key='gecos'),\
+ c0.user) as 'メンバー',\
+ sum(case when c1.key is not null then 1 else 0 end)\
+ as 'コメント記入',\
+ sum(case when c2.key is not null then 1 else 0 end)\
+ as 'ファイルの提出'\
+ from $sample c0 \
+ left join (select id,author from arts) a\
+ on c0.user=a.author\
+ left join (select id,key from article_s where key='text') c1\
+ on a.id=c1.id left join (select id,key from article_m ) c2\
+ on c1.id=c2.id group by c0.user order by c0.user;"
+ err ishandoutsub: sql="$sql"
+ echo '
'
+ hrb="
\)\([^ ]*\) \(.*\)
,\1$hrb\2\">\3," -e 's,
0
,
0
,'
+ echo '
'
+}
+gethandout() {
+ # $1=rowid of blog
+ i=0
+ bd=$tmpd/archive.$$
+ mkdir $bd
+ query "select m.rowid,author,m.val from article a join article_m m\
+ on a.id=m.id where blogid=(select id from blog where rowid=$1)\
+ and m.key in ('image', 'document', 'binary');" \
+ | while IFS='|' read rowid author filename; do
+ # err isfilereadable $user article_m $1
+ isfilereadable $user article_m $1 || continue
+ err ok
+ i=$((i+1))
+ dir=`printf $bd/%03d $i`
+ mkdir $dir
+ query "select quote(bin) from article_m where rowid=$rowid;" \
+ | unhexize > $dir/$filename
+ done
+ if [ ! -d $bd/001 ]; then
+ contenttype; echo
+ echo "
取得できるファイルがありませんでした。
"
+ return
+ fi
+ (cd $bd
+ err cdto$bd; (pwd; ls -lFa) 1>&3
+ tar zcf .archive.tar.gz * && mv .archive.tar.gz archive.tar.gz
+ )
+ arc=$bd/archive.tar.gz
+ echo "Content-type: application/x-gzip"
+ echo "Content-Length: `cat $arc|wc -c`"
+ echo "Content-Disposition: filename=\"archive.tar.gz\""
+ echo
+ cat $arc
+}
+
+listblog() (
+ # $1=user
+ cond="where a.id in (select id from blog_s where key='owner' and val='$1') order by ctime desc"
+ DT_CHLD=article:blogid
+ cgi_form searchart<`cgi_text kwd`という語を含む記事を検索
+`cgi_hidden owner $user`
+EOF
+ dumptable html blog 'ctime title heading' "$cond"
+)
+
+blog_addentry() {
+ # $1=GRPname(if it is a group)
+ grprowid=$1
+ rowid=`getpar rowid`
+err ba: rowid=$rowid
+ #if [ -z "$rowid" ]; then
+ # When rowid is SET, it is updation of existing entry
+ if [ -z "$1" ]; then
+ listing=$user guide="[個人]"
+#listing代入は rowid 時でもするべき
+ else
+ grp=`getgroupbyid $grprowid`
+ if [ -n "$grp" ]; then
+ listing=$1 guide="[${grp}]" GF_OWNER=$grp
+ else
+ echo "
無効なグループ指定です。
"
+ return
+ fi
+ fi
+ #fi
+ if [ -n "`getpar title`" ]; then
+ owner=`getpar owner`
+ if isuser $owner; then
+ if [ x"$user" != x"$owner" ]; then
+ echo "
他人の日記は書けません
"
+ return
+ fi
+ elif isgroup $owner; then # if write to group log
+ grp=$owner #\`getpar grp\`
+ err ismember: $user $grp
+ if ! ismember "$user" "$grp"; then
+ echo "
(話題作成はこのグループに加入してから)
"
+ return
+ fi
+ fi
+ par2table $formdir/blog.def
+ serial=`getpar serial`
+ err SERIAL: $serial ROWID=$rowid listing=$listing
+ id=""
+ if [ -n "$rowid" ]; then
+ # Here, id becomes NULL when removal of entries at par2table
+ id=`query "select rowid from blog where rowid=$rowid;"`
+ elif [ -n "$serial" ]; then
+ # If new blog leader created, traverse to its head.
+ id=`query "select rowid from blog where id='$serial';"`
+ fi
+ if [ -n "$id" ]; then
+ ## If new aritcle is entered, JUMP to blog_reply
+ blog_reply $id
+ return
+ fi
+ fi
+ m4 -D_TITLE_="${guide}新規話題作成" -D_DIARY_="新規話題の記入" \
+ -D_SUBTITLE_="序文は簡単に詳しくはコメントに" \
+ -D_BLOGS_="これまでの蓄積" \
+ -D_FORM_="`genform $formdir/blog.def`" \
+ -D_DUMPTABLE_="`listblog $listing`" \
+ $layout/html.m4.html \
+ $layout/diary.m4.html
+}
+
+blog_reply() {
+ rowid=$1
+err rowid=$1
+
+ if [ -z "$rowid" ]; then
+ echo "
表示する日記番号が未指定です。
"
+ return
+ fi
+ title=`getvalbyid blog title $rowid`
+ owner=`getvalbyid blog owner $rowid`
+ if isuser "$owner"; then
+ subtitle="`gecos $owner` さんの話題"
+ else
+ grprowid=`query "select rowid from grp where gname=\"$owner\";"`
+ subtitle="`gecos $owner` での話題"
+ fi
+ if [ -z "$title" ]; then
+ echo "
日記番号指定が無効です。
"
+ return
+ fi
+
+ text=`getpar text`
+ if [ -n "$text" ]; then
+ if blog_writable $rowid $user; then
+ if par2table $formdir/article.def; then
+ blog_notify_reply $rowid $user "$text"
+ fi
+ else
+ title="$title(加入してないので書き込み不可)"
+ fi
+ fi
+ def=$formdir/article.def
+ cat $layout/html.m4.html $layout/diary.m4.html \
+ | sed '/_DIARY_/q' \
+ | m4 -D_TITLE_="$title" -D_DIARY_="" -D_BODYCLASS_=general \
+ -D_SUBTITLE_="$subtitle"
+ blog_showentry blog $rowid
+ sed '1,/_DIARY_/d' $layout/diary.m4.html | m4 -D_FORM_= -D_DUMPTABLE_=
+}
diff -r 636df1c1bdf2 -r 01f579d2c889 s4-cgi.sh
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/s4-cgi.sh Tue Jul 21 14:43:24 2015 +0900
@@ -0,0 +1,108 @@
+#
+# cgi functions
+#
+cgi_form() {
+ # $1=stage
+ : ${myname:?'Sure to set $myname to this script name'}
+ cont=`cat`
+ cat<
+$cont
+
+
+
+
+EOF
+}
+cgi_submit() {
+ cat<
+EOF
+}
+cgi_radio() {
+ echo ""
+}
+cgi_hidden() {
+ echo ""
+}
+cgi_passwd() {
+ cat<
+
現パスワード
+
新パスワード
+
新パスワード(確認)
+
+EOF
+}
+cgi_text() {
+ echo ""
+}
+cgi_textarea() {
+ cat<$2
+EOF
+}
+cgi_file() ( # In a subshell
+ # $1=name $2=val(as filename) $3=args(if any)
+ # Using global variable $dir
+ if [ -s $dir/$2 -a -s $dir/$2.content-type ]; then
+ file=$dir/$2
+ bn=${file##*/}
+ ct=`cat $dir/$2.content-type`
+ data=`percenthex $file`
+ icon=""
+ fi
+ cat<
+EOF
+)
+cgi_multi() (
+ # $1=name $2=dir $3=func $4=args...
+ # `dir' should contain $name.count and $name.N where N is 1 upto N
+ i=1 name=$1 dir=$2 func=$3
+ n=`cat $dir/$name.count`
+ echo '
'
+ while [ $i -le $n ]; do
+ file=$name.$i ctf=$dir/$name.content-type
+ vname=$file.`cat $dir/$file.rowid`
+ if [ -s $ctf ]; then
+ case `cat $ctf` in
+ *:[Ii]mage:*)
+
+ ;;
+
+ esac
+ fi
+ val="`cat $dir/$file`"
+ cat<
($i)
+
+
+
+
+`$func $vname "$val" "$4"`$val
+
+EOF
+ i=$((i+1))
+ done
+ cat<
(新規)
`$func $name "" "$4"`
+
+EOF
+)
+# In these functions, $2 should be quoted because it can be null
+cgi_multi_text() {
+ cgi_multi $1 "$2" cgi_text "$3"
+}
+cgi_multi_textarea() {
+ cgi_multi $1 "$2" cgi_textarea "$3"
+}
+cgi_multi_file() {
+ # $1=name $2=val(filename)
+ cgi_multi $1 "$2" cgi_file "$3"
+}
diff -r 636df1c1bdf2 -r 01f579d2c889 s4-funcs.sh
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/s4-funcs.sh Tue Jul 21 14:43:24 2015 +0900
@@ -0,0 +1,1898 @@
+#!/bin/sh
+# Here's global variable table. Do not use this names.
+# $HGid$
+myname=`basename ${SCRIPT_NAME:-$0}`
+mydir=`dirname ${SCRIPT_FILENAME:-$0}`
+myargs="$@"
+#bindir=`(cd $mydir/bin; pwd)`
+# :$bindir
+PATH=/usr/local/sqlite3/bin:/usr/local/vim7/bin:/usr/iekei/ImageMagick/bin:/usr/local/ImageMagick/bin:$PATH
+tmpdir=${TMPDIR:-tmp}
+dbdir=${DBDIR:-db}
+tmpfiles=""
+db=${DB:-$dbdir/cgi.sq3}
+admin=wwwadmin@gentei.org
+templ=${TEMPL:-templ}
+layout=$templ/default
+formdir=$templ/form
+imgdir=img
+url=${URL:-"${REQUEST_SCHEME:-http${HTTPS:+s}}://$HTTP_HOST$REQUEST_URI"}
+urlbase=${url%%\?*}
+msg=$templ/msg
+timeout="+2 days"
+dumpcollen=20
+thumbxy=120x120
+thumbxy=96x96
+maximagexy=1600x1600
+### maximagexy=400x400
+tconfs=""
+imgcached=imgcache.`date +%Y/%m`
+conftbl=_tblconf
+nl="
+"
+. ./s4-cgi.sh
+
+: < "hoge", "owner" => "yuuji", "date" => "2015-04-27",
+ "text" => "hogehoge ..",
+ "reply" => [ {"serial" => 1,
+ "author" => "taro",
+ "date" => "2015-04-28",
+ "parent" => "/",
+ "path" => "/1",
+ "text" => "blah, blah, ....",
+ "image" => ["a.jpg", "b.jpg"] },
+ {"serial" => 2,
+ "author" => "hanako",
+ "date" => "2015-04-29",
+ "parent" => "/",
+ "path" => "/2",
+ "text" => "blah, blah, ....",
+ "image" => [] }]},
+ {"title" => "buha", ...} ]
+
+
+user:=
+ ユーザ名(英数字):name:p:text:length="20" maxlength="40"
+ パスワード:pswd:s:password:length="20" maxlength="40"
+ 説明(日本語OK):gecos:s:text:length="20" maxlength="40"
+ セッションキー:skey:s:session
+ メイルアドレス:email:m:text:length="20" maxlength="40"
+ 住所:address:m:textarea:maxlength="400"
+ プロフィール画像:profimg:m:image:maxlength="400K"
+ 履歴書:profpdf:m:document:maxlength="4M"
+
+変換表
+/user/email=m
+
+blog:=
+ シリアル:id:p:serial
+ タイトル:title:s:text:
+ 所有者:owner:s:owner:
+ 時刻:ctime:s:stamp:
+ リード文:heading:s:textarea:
+ リプライ:reply:m:*article:
+
+article:=
+ シリアル:id:p:serial
+ 筆者:author:s:owner
+ 時刻:ctime:s:stamp:
+ 参照元:parent:s:parent:
+ パス:path:s:path:
+ 本文:text:s:textarea:
+ 画像:image:m:image:
+
+履歴書:profpdf:m:document:maxlength="4M"
+
+
+EOF
+
+sq() {
+ # ./args.rb -cmd ".timeout 3000" "$@"
+ sqlite3 -cmd 'PRAGMA foreign_keys=ON' -cmd ".timeout 3000" "$@"
+}
+####XXXXXXXXXXXXXXXXXXXXXX 場所移動
+sqi=/tmp/sqi.$$
+sqo=/tmp/sqo.$$
+mkfifo $sqi $sqo
+tail -f $sqi | sq $db &
+sq3pid="`jobs -p` $!"
+
+query() {
+ cat< $sqi
+.once $sqo
+$@
+EOF
+ cat $sqo
+}
+exec 3>> $tmpdir/debug.out
+exec 2>> $tmpdir/error.out
+err() {
+ echo "$@" 1>&3
+}
+
+_m4() {
+
+}
+ismember() {
+ # $1=user, $2=group
+err ismem: "select user from grp_mem where gname=$(sqlquote $2) and user='$1';"
+ test -n "`query \"select user from grp_mem where gname=$(sqlquote $2) and user='$1';\"`"
+}
+isuser() { # Check if $1 is a valid user
+ test -n "`query \"select name from user where name='$1';\"`"
+}
+isgroup() { # Check if $1 is a valid group
+ err isgroup: "select gname from grp where gname=$(sqlquote $1);"
+ test -n "`query \"select gname from grp where gname=$(sqlquote $1);\"`"
+}
+isgrpowner() (
+ # $1=user, $2=group
+ gn=`sqlquote "$2"`
+ sql="select user from grp_adm where gname=$gn and user='$1';"
+ err isgrpowner: $sql
+ test -n "`query $sql`"
+)
+getgroupbyid() (
+ # $1=id|gname
+ sql="select coalesce((select gname from grp where gname=$(sqlquote $1)),
+ (select gname from grp where rowid=$(sqlquote $1)));"
+err ggbyid: `echo $sql`
+ query $sql
+)
+isfilereadable() { # $1=user $2=tbl $3=rowid
+ # Return true if user($1) can read attachment files in tbl($2):rowid($3)
+ [ -z "$1" -o -z "$2" -o -z "$3" ] && return 1 # invalid argument
+
+ # case `getvalbyid blog mode $2` in
+ # normal|*open*|"") return 0 ;;
+ # *closed*)
+ # owner=`getvalbyid blog owner $2`
+ # if isgrp $owner; then
+ # isgrpowner $1 $owner && return 0 || return 1
+ # elif isuser $owner; then
+ # [ x"$1" = x"$owner" ] && return 0 || return 1
+ # fi
+ # esac
+ # ↑ 要はこういう処理を↓で一気にやっている
+ sql="with getblog as (\
+ select key,val from blog_s where id=(\
+ select blogid from article where id in\
+ (select id from $2 where rowid=$3))),\
+ getowner as (select val from getblog where key='owner'),\
+ getmode as (select val from getblog where key='mode')\
+ select case\
+ when (select author from article where\
+ id=(select id from $2 where rowid=$3))='$1' \
+ then 'author'\
+ when (select val from getmode) in ('report-open', 'normal')\
+ then 'open'\
+ when (select val from getmode) is null \
+ then 'open'
+ when (select val from getowner) in (select gname from grp)\
+ then (select user from grp_adm where \
+ gname=(select val from getowner) and \
+ user='$1')\
+ else 'user' end;"
+ err isfilereadable: sql="$sql"
+ # caseのネストで内側のcaseがスカラーtrueを返しても外側はtrue扱いにならない
+ result=`query "$sql"`
+ [ -n "$result" ] && return 0
+ return 2
+}
+linkhome() {
+ # $1=UserOrGroup
+ echo -n '`gecos $1`"
+}
+acclog() {
+ # $1=table, $2=rowid
+ if [ -n "$2" ]; then
+ now=`date +"%F %T"`
+ query "replace into acclog values('$user', '$1', '$2', '$now');"
+ fi
+}
+gecos() (
+ u=`sqlquote ${1:-$user}`
+ #gecos=`query "select val from user_s where name='$u' and key='gecos';"`
+ sql="select case when (select name from user where name=$u) is not null
+ then (select val from user_s where name=$u and key='gecos')
+ when (select gname from grp where gname=$u) is not null
+ then (select val from grp_s where gname=$u and key='gecos')
+ else $u
+ end;"
+ query "$sql"
+)
+setpar() {
+ query "replace into par values('$session', '$1', '$2', \"$3\");"
+}
+replpar() {
+ query "update par set val=\"$3\" where sessid='$session' and var='$1' and type='$2';"
+}
+getpar() {
+err getpar: "select val from par where var='$1' and sessid='$session' $2;"
+ val=`query "select val from par where var='$1' and sessid='$session' $2;"`
+err getpar/val1: "val=[$val]"
+ if [ -z "$val" ]; then
+ val=`query "select val from cookie where var='$1' and sessid='$session' $2;"`
+ fi
+err getpar/val2: "val=[$val]"
+ case "$var" in
+ owner)
+ if [ x"$user" = x"$val" ]; then
+ echo $user; return
+ elif ismember $user $val; then
+ echo $val; return
+ fi ;;
+ esac
+err getpar/ret: "val=[$val]"
+ echo "$val"
+}
+
+getpartype() {
+ query "select type from par where var='$1' and sessid='$session' $2;"
+}
+getparcount() {
+ query "select count(*) from par where var='$1' and sessid='$session' $2;"
+}
+getparfilename() {
+ # null if type of $1 is not file
+ (f=`query "select val from par where var='$1' and sessid='$session' and type='file' $2;"`
+ [ -n "$f" ] && echo $f)
+}
+sqlquote() {
+ (v="$1"
+ case "$v" in
+ "") return ;; # null
+ "X'"*) # quoted hex string
+ echo $1 ;;
+ *\"*) # string including dbl-quote"
+ v=`echo "$v"|sed -e 's/\"/\"\"/g'`
+ echo "\"$v\""
+ return ;;
+ *.*.*|*-*-*|*[Ee]*[Ee]*|[Ee]*|*[\ -,:-df-~]*) # string
+ echo "\"$v\""
+ return ;;
+ *)
+ if expr "$v" : '[-0-9.Ee][-0-9.Ee]*$' >/dev/null 2>&1; then
+ echo $v # MAYBE numeric, maybe...
+ else
+ echo "\"$v\""
+ fi ;;
+ esac)
+}
+mktempd() {
+ TMPDIR=$tmpd mktemp -d -t $session
+}
+getval() {
+ # $1=table $2=col $3(optional)=condition
+ case `gettbl_coltype "/$1/$2"` in
+ user|author) # author added 2015-06-18 for article(author)
+ echo "$user" ;;
+ stamp|datetime)
+ date "+%F %T" ;;
+ serial)
+ (s=`getpar serial`
+ if [ -n "$s" ]; then echo $s; else echo "`date +%s`x$$"; fi) ;;
+ *)
+ getpar "$2" "$3";;
+ esac
+}
+
+getvalquote() {
+ # $1=table $2=col $3(optional)=condition
+ (v=`getval "$@"`
+ case "$v" in
+ "") echo NULL ;;
+ *) sqlquote "$v" ;;
+ esac)
+}
+getparquote() {
+ sqlquote `getpar $1`
+}
+getvalbyid() {
+ # $1=tbl $2=col $3=rowid $4=tmpdirForBinary
+ # If two or more values found, save them to $tmpd/${column}.$N and
+ # store the number of files into $tmpd/${column}.count and
+ # their each rowid stored into $tmpd/${column}.$N.rowid.
+ ### err gtb-$1=`gettblcols $1`, tbl=$1, col=$2, '$3'=$3
+ (for c in `gettblcols $1`; do
+ if [ x"$2" = x"$c" ]; then
+ err "select $2 from $1 where rowid=$3"
+ ###sq $db "select $2 from $1 where rowid=$3"
+ query "select $2 from $1 where rowid=$3;"
+ return
+ fi
+ done
+ pk=`gettblpkey $1`
+# key=`sq $db "select $pk from $1 where rowid=$3"`
+ key=`query "select $pk from $1 where rowid=$3;"`
+ ### err "select $pk from $1 where rowid=$3" - key=$key '$4(tmp)'=$4
+ for kt in s m; do
+ td=${4:-$tmpd}
+ [ -d $td ] || mkdir -p $td
+ t=${1}_$kt
+ for c in `gettbl_${kt}_cols $1`; do
+ vcount=1 # count(val)
+ if [ x"$2" = x"$c" ]; then
+ cond="$t where $pk=\"$key\" and key=\"$c\""
+ ###val=`query "select val from $cond;"`
+ val=`query "select val from $cond limit 1;"`
+ ###type=`query "select type from $cond;"`
+ type=`query "select type from $cond limit 1;"`
+ if [ $kt = m ]; then
+ ###vcount=`sq $db "select count(val) from $cond"`
+ # Reset val to store filenames if type is string
+ val=`query "select val from $cond and type like 'file:%' order by rowid;"`
+ vcount=`query "select count(val) from $cond;"`
+ echo $vcount > $td/$c.count
+ i=0
+ while [ $i -lt $vcount ]; do
+ slice="order by rowid limit 1 offset $i"
+ i=$((i+1))
+ fn=$c.$i
+##err td=$td, fn=$fn, type=$type, val="[$val]"
+ case $type in
+ file:*)
+ #file=$td/$val
+ file=$td/`query "select val from $cond $slice;"`
+####tmp [ -s $file -a -s $td/$fn.rowid ] && continue
+ sq $db< $file
+.output $td/$fn.rowid
+select rowid from $cond $slice;
+.output $td/$fn
+select val from $cond $slice;
+.output $file.content-type
+select substr(type, 6) from $cond $slice;
+.output stdout
+select quote(bin) from $cond $slice;
+EOF
+ ## err i=$i - file=$file rowid=`cat $td/$fn.rowid`
+ ln $td/$fn.rowid $file.rowid 2>&3 # for convenience
+ case $type in
+ *:[Ii]mage*) mogrify -geometry $thumbxy $file ;;
+ ### ここのアイコンを増やしたい
+ *|*:[Aa]pplication*)
+ convert -geometry $thumbxy $imgdir/file-icon.png \
+ png:- > $file
+ ;;
+ esac
+ ;;
+ *)
+ sq $db< $file
+ echo ${type#file:} > $file.content-type
+# err TTTTTTTTTTTTTTTT: $type
+ case $type in
+ *:[Ii]mage*) mogrify -geometry $thumbxy $file ;;
+ *:[Aa]pplication*)
+ convert -geometry $thumbxy $imgdir/file-icon.png \
+ png:- > $file ;;
+ esac
+ fi
+ done
+ ;;
+ esac
+ fi
+ echo "$val" # Keep newlines by ""
+ return
+ fi
+ done
+ done)
+}
+getvalbypkey() (
+ # $1=tbl $2=col $3=pkey $4=tmpdirForBinary
+ pk=`gettblpkey $1`
+ rowid=`query "select rowid from $1 where $pk='$3';"`
+ getvalbyid "$1" "$2" $rowid $4
+)
+getvalbycond() {
+ # $1=tbl $2=col $3=SQL-Condition
+ ###rowid=`sq $db "select rowid from $1 where $3"`
+ rowid=`query "select rowid from $1 where $3;"`
+ if [ -n "$rowid" ]; then
+ getvalbyid "$1" "$2" $rowid "$4"
+ fi
+}
+getpwfield() {
+ # getpwfield user column
+# val=`sqlite3 $db "select $2 from passwd where name='$1' $3"`
+ val=`getvalbycond user $2 "name='$1'"`
+ if [ -n "$val" ]; then
+ echo "$val"
+ return 0
+ else
+ return 1
+ fi
+}
+encode() {
+ if [ -z "$sha1" ]; then
+ if type sha1 >/dev/null 2>&1; then
+ sha1=sha1
+ elif type sha1sum >/dev/null 2>&1; then
+ sha1=sha1sum
+ elif type gsha1sum >/dev/null 2>&1; then
+ sha1=gsha1sum
+ fi
+ fi
+ $sha1 "$@" | cut -d' ' -f1
+}
+mycrypt() (
+ key=$1 salt=$2
+err \$2=$2
+ case $2 in
+ '$'*'$'*) salt=${salt#\$4\$}
+ salt=${salt%\$*} ;;
+ esac
+ echo -n '$4$'"$salt"'$'
+ echo "$salt$key" | encode
+)
+hexize() {
+ if [ -z "$hexize" ]; then
+ if type xxd >/dev/null 2>&1; then
+ hexize="xxd -p"
+ else
+ hexize_hd() {
+ hexdump -ve '1/1 "%.2x"'
+ }
+ hexize="hexize_hd"
+ fi
+ fi
+ cat $1 | $hexize | tr -d '\n'
+}
+unhexize() {
+ if [ -z "$unhex" ]; then
+ if type xxd >/dev/null 2>&1; then
+ unhex="xxd -p -r"
+ elif type perl >/dev/null 2>&1; then
+ cat >$tmpd/unhex.pl</dev/null 2>&1; then
+ enascii="kakasi -Ha -Ka -Ja -Ea -ka"
+ else
+ enascii_now=`date +%FT%T`
+ enascii_sed() {
+ nkf -Z0Z1Z2 \
+ | sed -e "s/^/$enascii_now/" -e "s|[^-0-9.A-z/,()_=]|x|g"
+ }
+ enascii="enascii_sed"
+ fi
+ fi
+ cat "$@" | $enascii
+}
+gettblconf() {
+ if [ -z "$tconfs" ]; then
+## tconfs=`sq $db \
+ tconfs=`query \
+ "select tbl||'/'||col||'='||keytype||'/'||objtype from $conftbl;"`
+ fi
+ # /tb1/col1=p/text /tb1/col2=s/text /tb1/col3=m/image /tb2/col1=p/text ...
+}
+gettblkeys() {
+ # $1=tbl
+ gettblconf
+ echo "$tconfs" | fgrep "/$1/" | \
+ (type="" keys="" fks="" cols="" scols="" mcols="" hcols=""
+ while IFS='=' read tc conf; do # tc=/tb1/col1 conf=s/text
+ col=${tc##*/} type=${conf%%/*}
+ case $type in
+ *p*)
+ cols=$cols"${cols:+:}$col"
+ keys=$keys"${keys:+:}$col" ;;
+ *f*) cols=$cols"${cols:+:}$col"
+ fks=$fks"${fks:+:}$col" ;;
+ *m*) mcols=$mcols"${mcols:+:}$col" ;;
+ *s*) scols=$scols"${scols:+:}$col" ;;
+ esac
+ case $type in
+ *h*) hcols=$hcols"${hcols:+:}$col" ;;
+ esac
+ done
+ echo "_keys=$keys _fks=$fks _cols=$cols _scols=$scols _mcols=$mcols _hcols=$hcols")
+}
+gettblpkey() {
+ # $1=tbl
+ gettblkeys $1 | cut -d ' ' -f 1 | sed -e 's/.*=//' -e 's/:/ /g'
+}
+gettblfkey() {
+ (x=`gettblkeys $1`
+ x=${x#*_fks=} # cut before "_fks=" including
+ echo ${x%% *} | tr ':' ' ')
+}
+gettblcols() {
+ (x=`gettblkeys $1`
+ x=${x#*_cols=} # cut before "_cols=" including
+ echo ${x%% *} | tr ':' ' ')
+}
+gettbl_s_cols() {
+ (x=`gettblkeys $1`
+ x=${x#*_scols=} # cut before "_scols=" including
+ echo ${x%% *} | tr ':' ' ')
+}
+gettbl_m_cols() {
+ (x=`gettblkeys $1`
+ x=${x#*_mcols=} # cut before "_mcols=" including
+ echo ${x%% *} | tr ':' ' ')
+}
+gettbl_h_cols() {
+ (x=`gettblkeys $1`
+ x=${x#*_hcols=} # cut before "_hcols=" including
+ echo ${x%% *} | tr ':' ' ')
+}
+gettbl_coltype() (
+ gettblconf
+ x=`echo "$tconfs"|fgrep $1=`
+ x=${x#*=} # cut before =
+ echo ${x#*/} # cut before p/ including
+)
+is_hidden() {
+ # $1=Tbl $2=col
+ gettblconf
+ x=`echo "$tconfs"|fgrep /$1/$2=`
+ x=${x#*=} # cut before =
+ x=${x%%/*} # cut after /
+ case $x in
+ *h*) return 0 ;;
+ *) return 1 ;;
+ esac
+}
+
+dbsetbyid() {
+ # $1=tbl $2=id $3=col $4=val/filename - &optional - $5=content-type
+ (t0=$1 t=$1 p=$2 c=$3
+ tsc=$t/$c val=$4
+ unset primary update
+ gettblconf
+#err tsc=$tsc, tconfs="$tconfs"
+ conf=`echo "$tconfs"|fgrep "$tsc"=`
+#err conf=$conf
+ case ${conf#*=} in
+ p*) primary=1 ;;
+ f*) update=1 ;;
+ u*) ;;
+ m*) t=${t}_m;;
+ s*) t=${t}_s;;
+ esac
+#err t=$t
+ type=text fn=""
+ case $conf in
+ */password)
+ type=encoded ### val=`echo $val|encode`
+ ;;
+ */image*|*/document*)
+ type=`file --mime-type $val`
+ bin="X'`hexize $val`'"
+ ;;
+ esac
+ pkey=`echo "$tconfs"|grep "${t0}/.*=p"|sed 1q`
+ pkey=${pkey#/*/} # cut $tbl/
+ pkey=${pkey%=p/*} # cut =p/... -> primary key
+ if [ "$primary" ]; then
+ nulls=`echo "$tconfs"|grep "$t/.*=[fu]/"|sed 's/^.*/, NULL/'|tr -d '\n'`
+ ###sq $db "replace into $t values(\"$val\"$nulls)"
+ query "replace into $t values(\"$val\"$nulls);"
+ elif [ "$update" ]; then
+ ###sq $db "update $1 set $c=\"$val\" where $pkey=\"$p\""
+ query "update $1 set $c=\"$val\" where $pkey=\"$p\";"
+ else
+#err "replace into $t values(\"$p\", \"$c\", \"$type\", \"$val\", \"$bin\")"
+ ###sq $db "replace into $t values(\"$p\", \"$c\", \"$type\", \"$val\", \"$bin\")"
+ query "replace into $t values(\"$p\", \"$c\", \"$type\", \"$val\", \"$bin\");"
+ fi
+ )
+}
+expire() (
+ at="${1:-$timeout}"
+ FMT="${2:-%F %T}"
+ TZ=GMT gdate -d "$at" +"$FMT"
+)
+addsession() {
+ # expireをセット
+ # loginの先にどの画面に行くかの状態遷移表書式を決める
+ expire=`expire ${2:-"+1min"}`
+err addsession "$1" exp=$expire
+ sq $db "replace into session values('$1', '$expire')"
+ # Remove old session parameters
+ now=`expire now`
+ sq $db "delete from session where expire < '$now'"
+}
+gencookie() (
+ for kv; do
+ expire="`expire '' '%a, %d-%b-%Y %H:%M:%S GMT'`"
+ echo "Set-Cookie: $kv; expires=$expire"
+ done
+)
+contenttype() {
+ echo "Content-type: ${1:-text/html; charset=utf-8}"
+ contenttype() {} # Only need to work once
+}
+putheader() {
+
+}
+putfooter() {
+ m4 -D_TITLE_="${TITLE:-$myname}" $layout/footer.m4.html
+}
+getcookie() (
+ for kv in `echo $HTTP_COOKIE|sed 's/[;, ]/ /g'`; do
+ k="${kv%%=*}"
+ v="`echo ${kv#*=}|nkf -Ww -mQ|sed -e 's/\"/\"\"/g'`"
+ query "replace into cookie values('$session', '$k', 'string', \"$v\");"
+ done
+)
+genrandom() {
+ # $1=columns (default: 10)
+ dd if=/dev/urandom count=1 2>/dev/null|nkf -MB|fold -w${1:-10}|sed -n 10p
+}
+smail() {
+ # smail rcpt subj (file)
+ rcpt=`echo $1` # strip newlines
+ subj="`echo $2|nkf -jM`"
+ # echo rcpt=$rcpt
+ (m4 -D_RCPT_="$rcpt" -D_SUBJ_="$subj" -D_FROM_=$admin $msg/mail-header.m4
+ cat $3 | nkf -jd ) | sendmail -f $admin $rcpt
+}
+setviastring() {
+ table=$1
+ oifs="$IFS"
+ IFS="&"
+ for us in $2; do
+ k=${us%%=*}
+ v="`echo ${us#*=}|tr '%+' '= '|nkf -Ww -mQ|sed -e 's/\"/\"\"/g'`"
+ sq $db "replace into $table values('$session', '$k', 'string', \"$v\")";
+ #echo $k=$v
+ done
+ IFS="$oifs"
+}
+checkdomain() (
+ # Check the validity of domain by referring DNS
+ item=$1
+ host ${item#@*} >/dev/null 2>&1
+)
+pwcheck() {
+ # $1=passwd
+ dbpswd=`getpwfield $user pswd`
+ encpswd=`mycrypt "$1" "$dbpswd"`
+ err user=$user, pswd=$1, db=$dbpswd, enc=$encpswd
+ [ x"$dbpswd" = x"$encpswd" ]
+}
+mypwhash() {
+ mycrypt `cat` `genrandom 5`
+}
+wasureta() {
+ user=$1
+ if checkdomain $user; then
+ echo "ユーザ名には正しいメイルアドレスが必要です。"
+ exit 0
+ fi
+ newpswd=`genrandom` # newsalt=`genrandom 5`
+ #encpswd=`mycrypt "$newpswd" "$newsalt"`
+ encpswd=`echo $newpswd|mypwhash`
+ dbsetbyid user $user pswd "$encpswd"
+ m4 -D_USER_="$user" -D_PSWD_="$newpswd" -D_URL_="$url" \
+ $msg/mail-newaccount.m4 \
+ | smail $user "New Account"
+}
+checkauth() {
+ user=`getpar user`
+ skc=`getpar skey` # from cookie
+ [ -z "$user" ] && return 3
+ skey="`getpwfield $user skey`"
+err user=$user skey=$skey
+ if [ -n "$skey" ]; then
+ if [ x"$skey" = x"$skc" ]; then
+ return 0
+ fi
+ fi
+ pswd=`getpar pswd`
+ if [ x"$pswd" = x"wasureta" ]; then
+ wasureta $user
+ return 1 # wasureta error
+ fi
+ # dbpswd="`sq $db \"select pswd from passwd where name='$user'\"`"
+ # putheader; echo; echo user=$user, db=$dbpswd, enc=$encpswd
+ if pwcheck "$pswd"; then
+ newsession=`genrandom 50`
+ dbsetbyid user $user skey "$newsession"
+ gencookie "user=$user" "skey=$newsession"
+ return 0
+ fi
+ return 2 # Password mismatch
+}
+showlogin() {
+ args=`echo $myargs|tr ' ' '+'`
+ m4 -D_SYSNAME_="Welcome" -D_MYNAME_="$myname${args+?}$args" \
+ $layout/login.m4.html
+ exit 0
+}
+dologin() {
+ checkauth
+ st=$?
+ if [ $st != 0 ]; then
+ contenttype; echo
+ m4 -D_USER_="$user" -D_URL_="$url" -D_ADMIN_="$admin" \
+ $msg/login-fail-$st.m4.html
+ showlogin # and EXIT
+ fi
+}
+cleanup() {
+ echo .quit > $sqi
+ kill $sq3pid
+ rm -f $sqo $sqi
+ rm -rf $tmpfiles
+}
+trap cleanup INT HUP EXIT
+# trap cleanup INT HUP
+cgiinit() {
+ session=`date +%F-$$`
+ tmpf=tmp/stream
+ tmpd=`tmpd=$tmpdir mktempd`
+ tmpfiles=$tmpfiles" $tmpd"
+ addsession $session
+ getcookie
+ case "$REQUEST_METHOD" in
+ get|GET) s="$QUERY_STRING" ;;
+ post|POST) ## dd count=$CONTENT_LENGTH bs=1 of=$tmpf 2>/dev/null #slow
+ # cat > $tmpf # too much?
+ head -c $CONTENT_LENGTH > $tmpf # safe?
+ (echo CL=$CONTENT_LENGTH; ls -lF $tmpf) 1>&3
+ s="`cat tmp/stream`"
+ tmpfiles=$tmpfiles"${tmpfiles+ }$tmpf"
+ ;;
+ esac
+ case "$CONTENT_TYPE" in
+ *boundary*)
+ bndry=${CONTENT_TYPE#*boundary=}
+ #for us in `LC_CTYPE=C ./mpsplit.rb "$bndry" $tmpd < $tmpf`
+ for us in `LC_CTYPE=C ./mpsplit.pl "$bndry" $tmpd < $tmpf`
+ do
+ k=${us%%\=*}
+ #echo u=$us
+ #v="`echo ${us#*=}|nkf -Ww -mQ|sed -e 's/\"/\"\"/g'`"
+ v="`echo ${us#*=}|unhexize|sed -e 's/\"/\"\"/g'`"
+ # err k=$k v=$v
+ case "$k" in
+ *:filename)
+ type='file'; k=${k%:filename}
+(echo k=$k; ls -lF $tmpd/$v; file --mime-type $tmpd/$v) 1>&3
+ case `file --mime-type $tmpd/$v|cut -d' ' -f2` in
+ [Ii]mage/*)
+ mogrify -resize $maximagexy'>' $tmpd/$v
+ ;;
+ esac
+ ;;
+ *)
+ type='string'
+ ;;
+ esac
+ #sq $db "replace into par values('$session', '$k', '$type', \"$v\")"
+ setpar "$k" "$type" "$v"
+ done
+ ;;
+ *)
+ setviastring par "$s"
+ ;;
+ esac
+}
+collectemail() {
+ # Collect email addresses for group $1
+ if isuser "$1"; then
+ em=`query "select val from user_m where name='$1' and key='email';"`
+ [ -n "$em" ] && echo "$em" || echo "$1"
+ else
+ query "with recursive allmem as
+ (select gname,val from grp_m where gname='$1'
+ union all select grp_m.gname,grp_m.val from grp_m,allmem
+ where allmem.val=grp_m.gname)
+ select coalesce(b.val,a.val)
+ from allmem a left join grp_mem_s b
+ on a.gname=b.gname and a.val=b.user and b.key='email'
+ where a.val in (select name from user) limit 10000;"
+ fi
+}
+sendinvitation() (
+ # $1=email
+ iss="invite-`date +%s`-$(genrandom 10)"
+ addsession $iss +7days # 1 week due date
+ query "replace into par values('$iss', 'invite', 'string', \"$1\");"
+ gecos=`gecos`
+ name=$user"${gecos:+($gecos)}"
+ regist="$urlbase?reg+$iss"
+ m4 -D_URL_="$urlbase" \
+ -D_USER_="$name" \
+ -D_EMAIL_="$1" \
+ -D_REGIST_="$regist" \
+ -D_ADMIN_="$admin" \
+ $msg/mail-invite.m4 \
+ | smail $1 "BBSへの御招待"
+ return 0
+)
+emaildomaincheck() {
+ case "$1" in
+ *@*@*) echo "無効なアドレスです"; return 1 ;;
+ *@*)
+ local=${1%@*} domain=${1#*@}
+ if ! host $domain >/dev/null 2>&1; then
+ echo "ドメイン($domain)が見付かりません。"
+ return 2
+ fi
+ return 0
+ ;;
+ *) echo "正しいメイルアドレスをいれてください"; return 3 ;;
+ esac
+}
+invite() {
+ email=`getpar email`
+ case $email in
+ *@*@*) repo="無効なアドレスです" ;;
+ *@*)
+ local=${email%@*} domain=${email#*@}
+ if ! repo=`emaildomaincheck $email`; then
+ repo="招待アドレスのエラー: $repo"
+ elif [ -n "`query \"select * from user where name='$email';\"`" ]; then
+ repo="$email さんは既に加入しています。"
+ elif sendinvitation $email; then
+ repo="アドレス($email)宛に案内を送信しました。"
+ fi ;;
+ "") repo="招待したい人のメイルアドレスを入力してください。" ;;
+ *) repo="無効なアドレスです" ;;
+ esac
+ m4 -D_REPORT_="$repo" -D_ACTION_="$myname?invite" \
+ $layout/html.m4.html $layout/invite.m4.html
+}
+regist() {
+ # $1=session-id-for-invitation
+ m4 -D_TITLE_="Invitation" $layout/html.m4.html
+ if [ -z "$1" ]; then
+ echo "
bye bye
"
+ reutrn
+ fi
+ email=`session=$1 getpar invite`
+ if [ -z "$email" ];then
+ cat<無効な招待状チケットです。
'
+ cgi_form searchart<`cgi_text kwd`という語を含むコメントを検索
+`cgi_hidden owner $grp`
+EOF
+ cond="where a.id in (select id from blog_s where key='owner' and val='$grp') order by ctime desc"
+ DT_CHLD=article:blogid \
+ DT_VIEW=replyblog dumptable html blog 'ctime title heading' "$cond"
+
+ c="group by b.name having b.name in (select user from grp_mem where gname='$grp')"
+ cm="?commission+$mmgrp"
+ thumbxy=50x50 listmember "" "$c" \
+ |sed -e "s|\( \),not=\(.*\)|\1管理者委託|"
+}
+joingrp() {
+ # $1=group $2=user $3=yes/no $4=email(if any $5=AsAdmin)
+err joingrp: \$1=$1 \$2=$2 \$3=$3 \$4=$4
+ isgrpowner "$user" "$1" && isowner="yes" || isowner=""
+err jg:isgrpowner: isowner="$isowner"
+ if [ x"$2" != x"$user" ]; then # if user is not login user
+ if [ -z "$isowner" ; then
+ echo "
本人か、グループ管理者しか加入操作はできません。
"
+ return
+ fi
+ fi
+ cond="where gname='$1' and user='$2'"
+ if [ x"$3" = x"yes" ]; then
+ query "replace into grp_mem values('$1', '$2');"
+ if [ -n "$4" ]; then
+ if msg=`emaildomaincheck "$4"`; then
+err "replace into grp_mem_s values('$1', '$user', 'email', \
+ 'string', '$4', NULL);"
+ query "replace into grp_mem_s values('$1', '$user', 'email', \
+ 'string', '$4', NULL);"
+ if [ -n "$5" ]; then # as ADMIN
+ # Coming here means newly created group
+ sql="select case\
+ when (select count(*) from grp_mem where gname='$1')=1\
+ then (select user from grp_mem\
+ where gname='$1' and user='$user')\
+ else '' end;"
+ err NewGrpChk: $sql
+ if [ -n "`query \"$sql\"`" ]; then
+ err ADMIN: "replace into grp_adm values('$1', '$user');"
+ query "replace into grp_adm values('$1', '$user');"
+ fi
+ fi
+ else
+ echo $msg
+ fi
+ else
+ query "delete from grp_mem_s $cond and key='email';"
+ fi
+ else
+ query "delete from grp_mem $cond;
+delete from grp_mem_s $cond;
+delete from grp_mem_m $cond;"
+ fi
+}
+grp_reg_adm() {
+ # $1=grp $2=user-rowid
+ if ! isgrpowner $user $1; then
+ echo "
$1 グループの管理者しかこの操作はできません。"; return
+ fi
+ newadm=`query "select name from user where rowid=$2;"`
+ if [ -z "$newadm" ]; then
+ echo "
指定ユーザIDがおかしいようです。
"; return
+ fi
+err GRP_reg_adm: "replace into grp_adm values('$1', '$newadm');"
+err ismember $newadm $1
+ if ismember $newadm $1; then
+ # OK, go ahead
+ query "replace into grp_adm values('$1', '$newadm');"
+ # confirm insertion
+ sql="select * from grp_adm where gname='$1' and user='$newadm'"
+ if [ -n "`query \"$sql;\"`" ]; then
+ echo "
追加完了
"
+ else
+ echo "
追加失敗($1 $2)
"
+ fi
+ fi
+ showgroup $1
+}
+dumptable() {
+ # $1=mode $2=Table $3=column-list-of-*_s(defaults to *) $4=conditions(if any)
+ # textのフィールドだけ全てダンプにしたほうがいいか
+ # $DT_VIEW sets link
+ # 6/17の次: editリンクじゃなくてスレッドVIEWリンクでいいんちゃう?
+ ### elink="EDIT"
+ VIEW=${DT_VIEW-replyblog}
+ if [ -n "$VIEW" ]; then
+ dvlink=" VIEW"
+ fi
+ # $DT_CHLD=ChildTable:BindColumn
+ if [ -n "$DT_CHLD" ]; then
+ _t=${DT_CHLD%:*} _i=${DT_CHLD#*:}
+ cntall="(select count($_i) from $_t where $_i=a.id)"
+ cntnew="(select count(val) from ${_t}_s where key='ctime' \
+ and id in (select id from $_t where $_i=a.id) \
+ and val > coalesce((select time from acclog where \
+ user='$user' and tbl='$2' and rowid=a.rowid),\
+ '1970-01-01'))"
+ cnt="$cntnew||'/'||$cntall as '新着/総数',"
+ dt_class=" td2r"
+ fi
+ # Construct join expression
+ eav="" scols=""
+ pk=`gettblpkey $2`
+ substr=${dumpcollen:+"substr(val, 0, $dumpcollen)"}
+ substr=${substr:-val}
+ for col in ${3:-`gettbl_s_cols $2`}; do
+ case $col in
+ *:*) col=${col%:*} as=${col#*:} ;;
+ *) as=${col} ;;
+ esac
+ eav=$eav${eav:+,}" max(case key when '$col' then $substr end) as $as"
+ scols="$scols${scols:+, }b.$as"
+ done
+#case author when '$user' then a.rowid else '---' end as ID,
+ sql="select \
+a.rowid as ID,\
+$cnt\
+$scols from $2 a left join (select $pk,$eav from ${2}_s group by $pk) b on a.$pk=b.$pk $4;"
+err SQL="$sql"
+ cat<
\)\([1-9][0-9]*\)
,\1$elink$dvlink,"
+
+
+`sq -header -cmd ".mode $1" $db "$sql"`
+
+
+EOF
+}
+
+par2table() (
+ # copy current parameters of par into destination table
+ # $1=definition-file
+ # Using $user and $session
+ rowid=`getpar rowid`
+err ...........rowid=$rowid
+ if [ ! -e $1 ]; then
+ echo "
テーブル定義ファイルが見付かりません
"
+ exit 1
+ fi
+ tbl=${1%.def}
+ tbl=${tbl##*/}
+ if [ -n "$rowid" ]; then # Modify existing entry
+ if [ x"$tbl" = x"user" ]; then
+ rowowner=`query "select name from $tbl where rowid=$rowid;"`
+ elif [ x"$tbl" = x"grp" ]; then
+ sql="select gname from $tbl where rowid=$rowid;"
+ ##err p2t:grp:q $sql
+ isgrpowner $user "`query $sql`" && rowowner=$user
+ else
+ rowowner=`query "select owner from $tbl where rowid=$rowid;"`
+ rowowner=${rowowner:-`query "select author from $tbl
+ where rowid=$rowid;"`}
+ fi
+ ### err rowowner=$rowowner
+ if [ x"$user" != x"$rowowner" ]; then
+ echo "
"
+ return
+ fi
+ rm=`getpar rm` cfm=`getpar confirm`
+ # Editing existent entry
+ if [ x"$rm" = x"yes" ]; then
+ if [ x"$rm$cfm" = x"yesyes" ]; then
+ query "delete from $tbl where rowid=$rowid;"
+ return
+ else
+ echo "
消去確認のチェックがないので消さなかったの...
"
+ return
+ fi
+ fi
+ fi
+ # XX: Subshelling here is unnecessary 2015-07-05
+ (ts=${tbl}_s tm=${tbl}_m val="" pval="" formaster="" getrow=""
+ if [ -n "$rowid" ]; then
+ # Update of existing record
+ for col in `gettblcols $tbl`; do
+ val=`getparquote $col`
+ [ -z "$val" ] && continue
+ err sq $db "update $tbl set $col=$val where rowid=$rowid"
+ query "update $tbl set $col=$val where rowid=$rowid;"
+ done
+ # Then, set up $pval for further insertion of tbl_s and tbl_m
+ for col in `gettblpkey $tbl`; do
+ val=`query "select $col from $tbl where rowid=$rowid;"|sed -e 's/\"/\"\"/g'`
+ pval="$pval${pval:+, }\"$val\""
+ done
+ else
+ # New entry
+ # Generate values() for primary keys
+ for col in `gettblpkey $tbl`; do
+ # Genuine primary keys for _m and _s
+ val=`getvalquote $tbl $col`
+ [ -z "$val" ] && continue
+ pval="$pval${pval:+, }$val"
+ done
+err pval=$pval
+ for col in `gettblfkey $tbl`; do
+ # args for values() to insertion into master table
+ val=`getvalquote $tbl $col`
+ [ -z "$val" ] && continue
+ formaster=$formaster"${formaster:+, }$val"
+ done
+ formaster="$pval${formaster:+, }$formaster"
+err formaster=$formaster
+ if [ -z "$formaster" ]; then
+ echo "
項目を全て埋めてください
"
+ return 1
+ fi
+ err "replace into $tbl values($formaster);"
+ echo "replace into $tbl values($formaster); $getrow" | sq $db
+ ## Insertion to master table, done
+ fi
+
+ for kt in s m; do
+ tb2=${tbl}_$kt
+ for col in `gettbl_${kt}_cols $tbl`; do
+ ptype=`getpartype $col "limit 1"`
+
+ # First, check update of existing entries in _m
+ if [ $kt = m ]; then
+ # sessID|address.1.22|string|Somewhere-x.y.z
+ sql=""
+err dots from query "select var from par where var like '$col.%';"
+ for v in `query "select var from par where var like '$col.%';"`; do
+ # v=address.1.22
+ rowid=${v##*.}
+ origcol=${v%%.*} # original column derived from
+err Updating for $v rowid=$rowid, partype=`getpartype $v`
+ ##case `getpartype $v` in
+ err CASE `gettbl_coltype $tbl/$origcol` in
+ err edit flag = `getpar action.$v`
+ case `getpar action.$v` in
+ rm)
+ if [ x`getpar confirm.$v` = x"yes" ]; then
+ newsql="delete from $tb2"
+ else
+ echo "
削除確認未チェック
"
+ fi ;;
+ edit)
+ case `gettbl_coltype $tbl/$origcol` in
+ image|document|binary)
+ file=$tmpd/`getparfilename $v`
+ err type=file=$file
+ [ -z "$file" ] && continue
+ bn=${file##*/}
+ bin="X'"$(hexize $file)"'"
+ ct=`file --mime-type $file|cut -d' ' -f2`
+ type=\"file:$ct\"
+ newsql="update $tb2 set val='$bn', type=$type, bin=$bin"
+ ;;
+ *)
+ newsql="update $tb2 set val=(select val from par where var \
+like '$col.%.$rowid')"
+ ;;
+ esac
+ ;;
+ *) # maybe `keep', do not modify value
+ continue
+ ;;
+ esac
+# err newsql=$newsql
+ sql=$sql$nl"$newsql where rowid=$rowid;"
+ done
+ echo "$sql
+delete from $tb2 where type='string' and val='';" | sq $db
+ # Rest of kt==m: set multiple mode
+ nr=`getparcount $col`
+ else
+ nr=1 # for kt==s, number of records is 1
+ fi
+
+ i=0
+ while [ $i -lt $nr ]; do
+ limit="limit 1 offset $i"
+ i=$((i+1)) # increase beforehand against continue
+ val=`getvalquote $tbl $col "$limit"`
+ [ -z "$val" -o x"$val" = x'""' -o x"$val" = x"NULL" ] && continue
+err $col=$val
+ bin=NULL
+err partype$col=`getpartype $col "$limit"`
+ case $ptype in
+ file) file=$tmpd/`getparfilename $col "$limit"`
+err parfile-$col=$file
+ [ -z "$file" ] && continue
+ bin="X'"$(hexize $file)"'"
+ ct=`file --mime-type $file|cut -d' ' -f2`
+ type=\"file:$ct\" ;;
+ "*"*) continue ;; # foreign table
+ *) type=\"string\" ;;
+ esac
+ case `gettbl_coltype $tbl/$col` in
+ password) # special care for password
+ # name={password,pswd1,pswd2}
+ p1=`getpar pswd1 "$limit"`
+ if [ -z "$p1" ]; then
+ continue # SKIP password setting, if p1 is empty
+ else
+ pswd=`getpar pswd "$limit"` p2=`getpar pswd2 "$limit"`
+## err pswd=$pswd
+ if pwcheck "$pswd"; then
+ if [ x"$p1" = x"$p2" ]; then
+ case "$p1" in
+ ????????*) ;;
+ *) echo "
"
+ return
+ fi
+ fi
+ ;;
+ esac
+## err p2t: "replace into $tb2 values($pval, \"$col\", $type, $val, $bin);"
+ echo "replace into $tb2 values($pval, \"$col\", $type, $val, $bin);" \
+ | sq $db
+ done
+ done
+ done
+ return 0
+ err donee)
+)
+par2table_old() {
+ # copy current parameters of par into destination table
+ # $1=dst-table $2=definition-file
+ # Using $user and $session
+ rowid=`getpar rowid`
+ if [ -n "$rowid" ]; then
+ rm=`getpar rm` cfm=`getpar confirm`
+ if [ x"$rm$cfm" = x"yesyes" ]; then
+ sq $db "delete from $1 where rowid=$rowid and owner=\"$user\""
+ return
+ fi
+ fi
+ cat $2 \
+ | (cols=""
+ while IFS=: read prompt name type args; do
+ [ x"$name" = x"stage" ] && continue
+ if [ -n "$rowid" ]; then
+ val=`getpar $name|sed -e 's/\"/\"\"/g'`
+ sq $db "update $1 set $name=\"$val\" where rowid=$rowid and owner=\"$user\""
+ else
+ eav=$eav${eav+,}" max(case var when '$name' then val end)"
+ fi
+ done
+ [ -n "$rowid" ] && return
+ cond="where sessid='$session' group by sessid"
+ sq $db "replace into $1 select $eav,\"$user\" from par $cond"
+ # Think over again about putting $user
+ )
+}
+genform() {
+ # $1 = form definition file
+ # $2, $3 (optional)= table name and ROWID
+ # If $GF_VIEWONLY set and nonNull, output values without form
+ # If $GF_HIDDEN set, use it hidden values
+ # If $GF_OWNER set, use it as value of name="owner"
+ # If $GF_STAGE set, use it as value of name="stage"
+ forms="" hiddens="" rowid=$3
+ if [ ! -e "$1" ]; then
+ echo "
そのようなデータベースはないようです($2)。
"
+ return
+ elif [ -n "$2" ]; then
+err genform1: "select * from $2 where rowid='$rowid'"
+ rec=`query "select * from $2 where rowid='$rowid';"`
+ if [ -z "$rec" ]; then
+ pk=`gettblpkey $2`
+ ###rec=`sq $db "select rowid from $2 where $pk='$rowid'"`
+err "select rowid from $2 where $pk='$rowid';"
+ rec=`query "select rowid from $2 where $pk='$rowid';"`
+err rec-rowid=$rec
+ rowid=$rec
+ rec=$3
+ fi
+ if [ -z "$rec" ]; then
+ echo "
そんなレコードはないみたいね...
"
+ return
+ fi
+ fi
+ if [ -z "$GF_VIEWONLY" ]; then
+ rm='
+ほんとうに消しますよ(確認)!
+はい'
+ fi
+ while IFS=: read prompt name keytype type args; do
+ [ -z "${prompt%%\#*}" ] && continue # skip comment line(#)
+ sp="${args:+ }"
+ form="" val=""
+ if [ -n "$rowid" ]; then
+ val=`getvalbyid $2 $name $rowid $tmpd`
+ fi
+ if [ -n "$GF_VIEWONLY" ]; then
+ is_hidden "$2" "$name" && continue
+ fi
+ case "$type" in
+ text*)
+ cgiform=cgi_multi_$type
+ if [ -s $tmpd/$name.count ]; then
+ form=`$cgiform $name $tmpd`
+ val=$(echo "$val"|
+ while read fn; do
+ echo "
"
+ if [ -n "$owner" ]; then
+ cond="where key='owner' and val='$owner'"
+ if isuser $owner; then
+ echo "
(`linkhome $owner` さんの記録からの検索)
"
+ else
+ linkhome $owner 1>&3
+ echo "
(`linkhome $owner` グループからの検索)
"
+ fi
+ fi
+ # article_s: id=article-id, key='text', val='TEXT'
+ # article: id=article-id, blogid=blogkd
+ # blog: id=blog-id, author=LeaderAuthor
+ # blog_s: id=blog-id, key='title', val='BLOG-TITLE'
+ # WANT: blog-ROWid,article-id,val(TEXT)
+ sql="select b.rowid||'#'||x.id as '',
+ b.title as TITLE,
+ substr(x.val, 0, 80) as TEXT
+ from (select blog.rowid,blog.*,bs.val as title from blog join blog_s bs
+ on blog.id=bs.id and bs.key='title') b
+ join
+ (select a.id,a.blogid,s.val from article a join article_s s
+ on a.id=s.id where s.val like '%$kwd%')
+ x on b.id=x.blogid
+ where b.id in (select id from blog_s
+ $cond);"
+ sedopt="s,
\)|$href2$href3\1|"
--- select val from $ts where key="title" and id="$id";
-select
- coalesce((select ",e," from blog where rowid=$rowid and author='$user'),'')
-||val||" "
-||case (select val from $ts where key="mode" and id="$id")
- when 'report-closed' then "レポート提出用(自身のファイルのみ参照可),s,"
- when 'report-open' then "レポート提出用,s,"
- else ""
- end
- from $ts where key="ctime" and id="$id";
-select val from $ts where key="heading" and id="$id";
-EOF
- cat<
-
-EOF
-
- #(2)Display following articles
-textform='
-
-
添付ファイル:
-
-
-
-'
- ## 6/11の次: articleを出して行く
-: <&3
- #case $ct in
- # [Ii]mage*) anch="$fn" ;;
- # *) anch=$fn ;;
- # esac
- # Should not contain newlines for sed argument
- # echo -n "$anch"
- iconhref $td/$fn "$hrfb+$ri" "$fn" "$fn"
- done)
- fi
- fi
-
- ### number=$((number+1))
-# reply=""
- getgecos="(select rowid from user where name='$author')||':'||\
- coalesce((select val from user_s \
- where name='$author' and key='gecos'), '$author')||',[/a],'"
- href="$myname?editart+$arid+$rowid"
- link="編集"
- cat<|" \
- -e 's|,\[/a\],||' \
- -e 's/,n,/ /g' -e "s|,i,|$imgs|" \
- -e "s|
\(
\)|
\1|" \
- -e "s|\(
\)\(
\),e,|\1\2$link|"
-select
- coalesce((select ",e," from article where id='$aid' and author='$user'),"")
- ||
- max(case key when 'ctime' then ",n,"||val||
- ",n,"||$getgecos end) as TIME,
--- max(case key when 'parent' then val||"への返信" end) as REPLYTO,
- max(case key when 'text' then val||",i," end) as TEXT
- from article_s where id = '$aid'
- group by id order by TIME;
-EOF
- done
- echo "
"
-
-
- blog_writable $rowid $user && cat<
-
コメント記入
-
-
-
-$textform
-
-EOF
- echo ""
-
- # Record access log
- acclog blog $rowid
-}
-
-lshandout() {
- # $1=rowid of blog
- time=`getvalbyid blog ctime $1|colrm 11`
- owner=`getvalbyid blog owner $1`
- title=`getvalbyid blog title $1`
- ge=`gecos $owner`
- lshandoutsub $owner "$@" \
- |m4 -D_TITLE_="提出状況" \
- -D_SUBTITLE_="$time [$title]@${ge:-$owner}" -D_DIARY_="" \
- -D_FORM_="syscmd(cat)" -D_BLOGS_= -D_DUMPTABLE_= \
- $layout/html.m4.html $layout/diary.m4.html
-}
-lshandoutsub() {
- # $1=owner $2=rowid of blog
- if isgroup $1; then
- sample="(select user from grp_mem where gname='$1')"
- else
- sample="(select distinct author as user from arts)"
- echo "
(集計は板への投稿者のみ)
"
- fi
- sql="with arts as (select id,author from article \
- where blogid=(select id from blog where rowid=$2))\
- select (select rowid from user where name=c0.user)||' '|| \
- coalesce((select val from user_s where name=c0.user \
- and key='gecos'),\
- c0.user) as 'メンバー',\
- sum(case when c1.key is not null then 1 else 0 end)\
- as 'コメント記入',\
- sum(case when c2.key is not null then 1 else 0 end)\
- as 'ファイルの提出'\
- from $sample c0 \
- left join (select id,author from arts) a\
- on c0.user=a.author\
- left join (select id,key from article_s where key='text') c1\
- on a.id=c1.id left join (select id,key from article_m ) c2\
- on c1.id=c2.id group by c0.user order by c0.user;"
- err ishandoutsub: sql="$sql"
- echo '
'
- hrb="
\)\([^ ]*\) \(.*\)
,\1$hrb\2\">\3," -e 's,
0
,
0
,'
- echo '
'
-}
-gethandout() {
- # $1=rowid of blog
- i=0
- bd=$tmpd/archive.$$
- mkdir $bd
- query "select m.rowid,author,m.val from article a join article_m m\
- on a.id=m.id where blogid=(select id from blog where rowid=$1)\
- and m.key in ('image', 'document', 'binary');" \
- | while IFS='|' read rowid author filename; do
- # err isfilereadable $user article_m $1
- isfilereadable $user article_m $1 || continue
- err ok
- i=$((i+1))
- dir=`printf $bd/%03d $i`
- mkdir $dir
- query "select quote(bin) from article_m where rowid=$rowid;" \
- | unhexize > $dir/$filename
- done
- if [ ! -d $bd/001 ]; then
- contenttype; echo
- echo "
取得できるファイルがありませんでした。
"
- return
- fi
- (cd $bd
- err cdto$bd; (pwd; ls -lFa) 1>&3
- tar zcf .archive.tar.gz * && mv .archive.tar.gz archive.tar.gz
- )
- arc=$bd/archive.tar.gz
- echo "Content-type: application/x-gzip"
- echo "Content-Length: `cat $arc|wc -c`"
- echo "Content-Disposition: filename=\"archive.tar.gz\""
- echo
- cat $arc
-}
-
-listblog() (
- # $1=user
- cond="where a.id in (select id from blog_s where key='owner' and val='$1') order by ctime desc"
- DT_CHLD=article:blogid
- cgi_form searchart<`cgi_text kwd`という語を含む記事を検索
-`cgi_hidden owner $user`
-EOF
- dumptable html blog 'ctime title heading' "$cond"
-)
-
-blog_addentry() {
- # $1=GRPname(if it is a group)
- grprowid=$1
- rowid=`getpar rowid`
-err ba: rowid=$rowid
- #if [ -z "$rowid" ]; then
- # When rowid is SET, it is updation of existing entry
- if [ -z "$1" ]; then
- listing=$user guide="[個人]"
-#listing代入は rowid 時でもするべき
- else
- grp=`getgroupbyid $grprowid`
- if [ -n "$grp" ]; then
- listing=$1 guide="[${grp}]" GF_OWNER=$grp
- else
- echo "
無効なグループ指定です。
"
- return
- fi
- fi
- #fi
- if [ -n "`getpar title`" ]; then
- owner=`getpar owner`
- if isuser $owner; then
- if [ x"$user" != x"$owner" ]; then
- echo "
他人の日記は書けません
"
- return
- fi
- elif isgroup $owner; then # if write to group log
- grp=$owner #\`getpar grp\`
- err ismember: $user $grp
- if ! ismember "$user" "$grp"; then
- echo "
(話題作成はこのグループに加入してから)
"
- return
- fi
- fi
- par2table $formdir/blog.def
- serial=`getpar serial`
- err SERIAL: $serial ROWID=$rowid listing=$listing
- id=""
- if [ -n "$rowid" ]; then
- # Here, id becomes NULL when removal of entries at par2table
- id=`query "select rowid from blog where rowid=$rowid;"`
- elif [ -n "$serial" ]; then
- # If new blog leader created, traverse to its head.
- id=`query "select rowid from blog where id='$serial';"`
- fi
- if [ -n "$id" ]; then
- ## If new aritcle is entered, JUMP to blog_reply
- blog_reply $id
- return
- fi
- fi
- m4 -D_TITLE_="${guide}新規話題作成" -D_DIARY_="新規話題の記入" \
- -D_SUBTITLE_="序文は簡単に詳しくはコメントに" \
- -D_BLOGS_="これまでの蓄積" \
- -D_FORM_="`genform $formdir/blog.def`" \
- -D_DUMPTABLE_="`listblog $listing`" \
- $layout/html.m4.html \
- $layout/diary.m4.html
-}
-
-blog_reply() {
- rowid=$1
-err rowid=$1
-
- if [ -z "$rowid" ]; then
- echo "
表示する日記番号が未指定です。
"
- return
- fi
- title=`getvalbyid blog title $rowid`
- owner=`getvalbyid blog owner $rowid`
- if isuser "$owner"; then
- subtitle="`gecos $owner` さんの話題"
- else
- grprowid=`query "select rowid from grp where gname=\"$owner\";"`
- subtitle="`gecos $owner` での話題"
- fi
- if [ -z "$title" ]; then
- echo "
日記番号指定が無効です。
"
- return
- fi
-
- text=`getpar text`
- if [ -n "$text" ]; then
- if blog_writable $rowid $user; then
- if par2table $formdir/article.def; then
- blog_notify_reply $rowid $user "$text"
- fi
- else
- title="$title(加入してないので書き込み不可)"
- fi
- fi
- def=$formdir/article.def
- cat $layout/html.m4.html $layout/diary.m4.html \
- | sed '/_DIARY_/q' \
- | m4 -D_TITLE_="$title" -D_DIARY_="" -D_BODYCLASS_=general \
- -D_SUBTITLE_="$subtitle"
- blog_showentry blog $rowid
- sed '1,/_DIARY_/d' $layout/diary.m4.html | m4 -D_FORM_= -D_DUMPTABLE_=
-}
diff -r 636df1c1bdf2 -r 01f579d2c889 y4-cgi.sh
--- a/y4-cgi.sh Tue Jul 21 14:38:21 2015 +0900
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,108 +0,0 @@
-#
-# cgi functions
-#
-cgi_form() {
- # $1=stage
- : ${myname:?'Sure to set $myname to this script name'}
- cont=`cat`
- cat<
-$cont
-
-
-
-
-EOF
-}
-cgi_submit() {
- cat<
-EOF
-}
-cgi_radio() {
- echo ""
-}
-cgi_hidden() {
- echo ""
-}
-cgi_passwd() {
- cat<
-
現パスワード
-
新パスワード
-
新パスワード(確認)
-
-EOF
-}
-cgi_text() {
- echo ""
-}
-cgi_textarea() {
- cat<$2
-EOF
-}
-cgi_file() ( # In a subshell
- # $1=name $2=val(as filename) $3=args(if any)
- # Using global variable $dir
- if [ -s $dir/$2 -a -s $dir/$2.content-type ]; then
- file=$dir/$2
- bn=${file##*/}
- ct=`cat $dir/$2.content-type`
- data=`percenthex $file`
- icon=""
- fi
- cat<
-EOF
-)
-cgi_multi() (
- # $1=name $2=dir $3=func $4=args...
- # `dir' should contain $name.count and $name.N where N is 1 upto N
- i=1 name=$1 dir=$2 func=$3
- n=`cat $dir/$name.count`
- echo '
'
- while [ $i -le $n ]; do
- file=$name.$i ctf=$dir/$name.content-type
- vname=$file.`cat $dir/$file.rowid`
- if [ -s $ctf ]; then
- case `cat $ctf` in
- *:[Ii]mage:*)
-
- ;;
-
- esac
- fi
- val="`cat $dir/$file`"
- cat<
($i)
-
-
-
-
-`$func $vname "$val" "$4"`$val
-
-EOF
- i=$((i+1))
- done
- cat<
(新規)
`$func $name "" "$4"`
-
-EOF
-)
-# In these functions, $2 should be quoted because it can be null
-cgi_multi_text() {
- cgi_multi $1 "$2" cgi_text "$3"
-}
-cgi_multi_textarea() {
- cgi_multi $1 "$2" cgi_textarea "$3"
-}
-cgi_multi_file() {
- # $1=name $2=val(filename)
- cgi_multi $1 "$2" cgi_file "$3"
-}
diff -r 636df1c1bdf2 -r 01f579d2c889 y4-funcs.sh
--- a/y4-funcs.sh Tue Jul 21 14:38:21 2015 +0900
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1898 +0,0 @@
-#!/bin/sh
-# Here's global variable table. Do not use this names.
-# $HGid$
-myname=`basename ${SCRIPT_NAME:-$0}`
-mydir=`dirname ${SCRIPT_FILENAME:-$0}`
-myargs="$@"
-#bindir=`(cd $mydir/bin; pwd)`
-# :$bindir
-PATH=/usr/local/sqlite3/bin:/usr/local/vim7/bin:/usr/iekei/ImageMagick/bin:/usr/local/ImageMagick/bin:$PATH
-tmpdir=${TMPDIR:-tmp}
-dbdir=${DBDIR:-db}
-tmpfiles=""
-db=${DB:-$dbdir/cgi.sq3}
-admin=wwwadmin@gentei.org
-templ=${TEMPL:-templ}
-layout=$templ/default
-formdir=$templ/form
-imgdir=img
-url=${URL:-"${REQUEST_SCHEME:-http${HTTPS:+s}}://$HTTP_HOST$REQUEST_URI"}
-urlbase=${url%%\?*}
-msg=$templ/msg
-timeout="+2 days"
-dumpcollen=20
-thumbxy=120x120
-thumbxy=96x96
-maximagexy=1600x1600
-### maximagexy=400x400
-tconfs=""
-imgcached=imgcache.`date +%Y/%m`
-conftbl=_tblconf
-nl="
-"
-. ./y4-cgi.sh
-
-: < "hoge", "owner" => "yuuji", "date" => "2015-04-27",
- "text" => "hogehoge ..",
- "reply" => [ {"serial" => 1,
- "author" => "taro",
- "date" => "2015-04-28",
- "parent" => "/",
- "path" => "/1",
- "text" => "blah, blah, ....",
- "image" => ["a.jpg", "b.jpg"] },
- {"serial" => 2,
- "author" => "hanako",
- "date" => "2015-04-29",
- "parent" => "/",
- "path" => "/2",
- "text" => "blah, blah, ....",
- "image" => [] }]},
- {"title" => "buha", ...} ]
-
-
-user:=
- ユーザ名(英数字):name:p:text:length="20" maxlength="40"
- パスワード:pswd:s:password:length="20" maxlength="40"
- 説明(日本語OK):gecos:s:text:length="20" maxlength="40"
- セッションキー:skey:s:session
- メイルアドレス:email:m:text:length="20" maxlength="40"
- 住所:address:m:textarea:maxlength="400"
- プロフィール画像:profimg:m:image:maxlength="400K"
- 履歴書:profpdf:m:document:maxlength="4M"
-
-変換表
-/user/email=m
-
-blog:=
- シリアル:id:p:serial
- タイトル:title:s:text:
- 所有者:owner:s:owner:
- 時刻:ctime:s:stamp:
- リード文:heading:s:textarea:
- リプライ:reply:m:*article:
-
-article:=
- シリアル:id:p:serial
- 筆者:author:s:owner
- 時刻:ctime:s:stamp:
- 参照元:parent:s:parent:
- パス:path:s:path:
- 本文:text:s:textarea:
- 画像:image:m:image:
-
-履歴書:profpdf:m:document:maxlength="4M"
-
-
-EOF
-
-sq() {
- # ./args.rb -cmd ".timeout 3000" "$@"
- sqlite3 -cmd 'PRAGMA foreign_keys=ON' -cmd ".timeout 3000" "$@"
-}
-####XXXXXXXXXXXXXXXXXXXXXX 場所移動
-sqi=/tmp/sqi.$$
-sqo=/tmp/sqo.$$
-mkfifo $sqi $sqo
-tail -f $sqi | sq $db &
-sq3pid="`jobs -p` $!"
-
-query() {
- cat< $sqi
-.once $sqo
-$@
-EOF
- cat $sqo
-}
-exec 3>> $tmpdir/debug.out
-exec 2>> $tmpdir/error.out
-err() {
- echo "$@" 1>&3
-}
-
-_m4() {
-
-}
-ismember() {
- # $1=user, $2=group
-err ismem: "select user from grp_mem where gname=$(sqlquote $2) and user='$1';"
- test -n "`query \"select user from grp_mem where gname=$(sqlquote $2) and user='$1';\"`"
-}
-isuser() { # Check if $1 is a valid user
- test -n "`query \"select name from user where name='$1';\"`"
-}
-isgroup() { # Check if $1 is a valid group
- err isgroup: "select gname from grp where gname=$(sqlquote $1);"
- test -n "`query \"select gname from grp where gname=$(sqlquote $1);\"`"
-}
-isgrpowner() (
- # $1=user, $2=group
- gn=`sqlquote "$2"`
- sql="select user from grp_adm where gname=$gn and user='$1';"
- err isgrpowner: $sql
- test -n "`query $sql`"
-)
-getgroupbyid() (
- # $1=id|gname
- sql="select coalesce((select gname from grp where gname=$(sqlquote $1)),
- (select gname from grp where rowid=$(sqlquote $1)));"
-err ggbyid: `echo $sql`
- query $sql
-)
-isfilereadable() { # $1=user $2=tbl $3=rowid
- # Return true if user($1) can read attachment files in tbl($2):rowid($3)
- [ -z "$1" -o -z "$2" -o -z "$3" ] && return 1 # invalid argument
-
- # case `getvalbyid blog mode $2` in
- # normal|*open*|"") return 0 ;;
- # *closed*)
- # owner=`getvalbyid blog owner $2`
- # if isgrp $owner; then
- # isgrpowner $1 $owner && return 0 || return 1
- # elif isuser $owner; then
- # [ x"$1" = x"$owner" ] && return 0 || return 1
- # fi
- # esac
- # ↑ 要はこういう処理を↓で一気にやっている
- sql="with getblog as (\
- select key,val from blog_s where id=(\
- select blogid from article where id in\
- (select id from $2 where rowid=$3))),\
- getowner as (select val from getblog where key='owner'),\
- getmode as (select val from getblog where key='mode')\
- select case\
- when (select author from article where\
- id=(select id from $2 where rowid=$3))='$1' \
- then 'author'\
- when (select val from getmode) in ('report-open', 'normal')\
- then 'open'\
- when (select val from getmode) is null \
- then 'open'
- when (select val from getowner) in (select gname from grp)\
- then (select user from grp_adm where \
- gname=(select val from getowner) and \
- user='$1')\
- else 'user' end;"
- err isfilereadable: sql="$sql"
- # caseのネストで内側のcaseがスカラーtrueを返しても外側はtrue扱いにならない
- result=`query "$sql"`
- [ -n "$result" ] && return 0
- return 2
-}
-linkhome() {
- # $1=UserOrGroup
- echo -n '`gecos $1`"
-}
-acclog() {
- # $1=table, $2=rowid
- if [ -n "$2" ]; then
- now=`date +"%F %T"`
- query "replace into acclog values('$user', '$1', '$2', '$now');"
- fi
-}
-gecos() (
- u=`sqlquote ${1:-$user}`
- #gecos=`query "select val from user_s where name='$u' and key='gecos';"`
- sql="select case when (select name from user where name=$u) is not null
- then (select val from user_s where name=$u and key='gecos')
- when (select gname from grp where gname=$u) is not null
- then (select val from grp_s where gname=$u and key='gecos')
- else $u
- end;"
- query "$sql"
-)
-setpar() {
- query "replace into par values('$session', '$1', '$2', \"$3\");"
-}
-replpar() {
- query "update par set val=\"$3\" where sessid='$session' and var='$1' and type='$2';"
-}
-getpar() {
-err getpar: "select val from par where var='$1' and sessid='$session' $2;"
- val=`query "select val from par where var='$1' and sessid='$session' $2;"`
-err getpar/val1: "val=[$val]"
- if [ -z "$val" ]; then
- val=`query "select val from cookie where var='$1' and sessid='$session' $2;"`
- fi
-err getpar/val2: "val=[$val]"
- case "$var" in
- owner)
- if [ x"$user" = x"$val" ]; then
- echo $user; return
- elif ismember $user $val; then
- echo $val; return
- fi ;;
- esac
-err getpar/ret: "val=[$val]"
- echo "$val"
-}
-
-getpartype() {
- query "select type from par where var='$1' and sessid='$session' $2;"
-}
-getparcount() {
- query "select count(*) from par where var='$1' and sessid='$session' $2;"
-}
-getparfilename() {
- # null if type of $1 is not file
- (f=`query "select val from par where var='$1' and sessid='$session' and type='file' $2;"`
- [ -n "$f" ] && echo $f)
-}
-sqlquote() {
- (v="$1"
- case "$v" in
- "") return ;; # null
- "X'"*) # quoted hex string
- echo $1 ;;
- *\"*) # string including dbl-quote"
- v=`echo "$v"|sed -e 's/\"/\"\"/g'`
- echo "\"$v\""
- return ;;
- *.*.*|*-*-*|*[Ee]*[Ee]*|[Ee]*|*[\ -,:-df-~]*) # string
- echo "\"$v\""
- return ;;
- *)
- if expr "$v" : '[-0-9.Ee][-0-9.Ee]*$' >/dev/null 2>&1; then
- echo $v # MAYBE numeric, maybe...
- else
- echo "\"$v\""
- fi ;;
- esac)
-}
-mktempd() {
- TMPDIR=$tmpd mktemp -d -t $session
-}
-getval() {
- # $1=table $2=col $3(optional)=condition
- case `gettbl_coltype "/$1/$2"` in
- user|author) # author added 2015-06-18 for article(author)
- echo "$user" ;;
- stamp|datetime)
- date "+%F %T" ;;
- serial)
- (s=`getpar serial`
- if [ -n "$s" ]; then echo $s; else echo "`date +%s`x$$"; fi) ;;
- *)
- getpar "$2" "$3";;
- esac
-}
-
-getvalquote() {
- # $1=table $2=col $3(optional)=condition
- (v=`getval "$@"`
- case "$v" in
- "") echo NULL ;;
- *) sqlquote "$v" ;;
- esac)
-}
-getparquote() {
- sqlquote `getpar $1`
-}
-getvalbyid() {
- # $1=tbl $2=col $3=rowid $4=tmpdirForBinary
- # If two or more values found, save them to $tmpd/${column}.$N and
- # store the number of files into $tmpd/${column}.count and
- # their each rowid stored into $tmpd/${column}.$N.rowid.
- ### err gtb-$1=`gettblcols $1`, tbl=$1, col=$2, '$3'=$3
- (for c in `gettblcols $1`; do
- if [ x"$2" = x"$c" ]; then
- err "select $2 from $1 where rowid=$3"
- ###sq $db "select $2 from $1 where rowid=$3"
- query "select $2 from $1 where rowid=$3;"
- return
- fi
- done
- pk=`gettblpkey $1`
-# key=`sq $db "select $pk from $1 where rowid=$3"`
- key=`query "select $pk from $1 where rowid=$3;"`
- ### err "select $pk from $1 where rowid=$3" - key=$key '$4(tmp)'=$4
- for kt in s m; do
- td=${4:-$tmpd}
- [ -d $td ] || mkdir -p $td
- t=${1}_$kt
- for c in `gettbl_${kt}_cols $1`; do
- vcount=1 # count(val)
- if [ x"$2" = x"$c" ]; then
- cond="$t where $pk=\"$key\" and key=\"$c\""
- ###val=`query "select val from $cond;"`
- val=`query "select val from $cond limit 1;"`
- ###type=`query "select type from $cond;"`
- type=`query "select type from $cond limit 1;"`
- if [ $kt = m ]; then
- ###vcount=`sq $db "select count(val) from $cond"`
- # Reset val to store filenames if type is string
- val=`query "select val from $cond and type like 'file:%' order by rowid;"`
- vcount=`query "select count(val) from $cond;"`
- echo $vcount > $td/$c.count
- i=0
- while [ $i -lt $vcount ]; do
- slice="order by rowid limit 1 offset $i"
- i=$((i+1))
- fn=$c.$i
-##err td=$td, fn=$fn, type=$type, val="[$val]"
- case $type in
- file:*)
- #file=$td/$val
- file=$td/`query "select val from $cond $slice;"`
-####tmp [ -s $file -a -s $td/$fn.rowid ] && continue
- sq $db< $file
-.output $td/$fn.rowid
-select rowid from $cond $slice;
-.output $td/$fn
-select val from $cond $slice;
-.output $file.content-type
-select substr(type, 6) from $cond $slice;
-.output stdout
-select quote(bin) from $cond $slice;
-EOF
- ## err i=$i - file=$file rowid=`cat $td/$fn.rowid`
- ln $td/$fn.rowid $file.rowid 2>&3 # for convenience
- case $type in
- *:[Ii]mage*) mogrify -geometry $thumbxy $file ;;
- ### ここのアイコンを増やしたい
- *|*:[Aa]pplication*)
- convert -geometry $thumbxy $imgdir/file-icon.png \
- png:- > $file
- ;;
- esac
- ;;
- *)
- sq $db< $file
- echo ${type#file:} > $file.content-type
-# err TTTTTTTTTTTTTTTT: $type
- case $type in
- *:[Ii]mage*) mogrify -geometry $thumbxy $file ;;
- *:[Aa]pplication*)
- convert -geometry $thumbxy $imgdir/file-icon.png \
- png:- > $file ;;
- esac
- fi
- done
- ;;
- esac
- fi
- echo "$val" # Keep newlines by ""
- return
- fi
- done
- done)
-}
-getvalbypkey() (
- # $1=tbl $2=col $3=pkey $4=tmpdirForBinary
- pk=`gettblpkey $1`
- rowid=`query "select rowid from $1 where $pk='$3';"`
- getvalbyid "$1" "$2" $rowid $4
-)
-getvalbycond() {
- # $1=tbl $2=col $3=SQL-Condition
- ###rowid=`sq $db "select rowid from $1 where $3"`
- rowid=`query "select rowid from $1 where $3;"`
- if [ -n "$rowid" ]; then
- getvalbyid "$1" "$2" $rowid "$4"
- fi
-}
-getpwfield() {
- # getpwfield user column
-# val=`sqlite3 $db "select $2 from passwd where name='$1' $3"`
- val=`getvalbycond user $2 "name='$1'"`
- if [ -n "$val" ]; then
- echo "$val"
- return 0
- else
- return 1
- fi
-}
-encode() {
- if [ -z "$sha1" ]; then
- if type sha1 >/dev/null 2>&1; then
- sha1=sha1
- elif type sha1sum >/dev/null 2>&1; then
- sha1=sha1sum
- elif type gsha1sum >/dev/null 2>&1; then
- sha1=gsha1sum
- fi
- fi
- $sha1 "$@" | cut -d' ' -f1
-}
-mycrypt() (
- key=$1 salt=$2
-err \$2=$2
- case $2 in
- '$'*'$'*) salt=${salt#\$4\$}
- salt=${salt%\$*} ;;
- esac
- echo -n '$4$'"$salt"'$'
- echo "$salt$key" | encode
-)
-hexize() {
- if [ -z "$hexize" ]; then
- if type xxd >/dev/null 2>&1; then
- hexize="xxd -p"
- else
- hexize_hd() {
- hexdump -ve '1/1 "%.2x"'
- }
- hexize="hexize_hd"
- fi
- fi
- cat $1 | $hexize | tr -d '\n'
-}
-unhexize() {
- if [ -z "$unhex" ]; then
- if type xxd >/dev/null 2>&1; then
- unhex="xxd -p -r"
- elif type perl >/dev/null 2>&1; then
- cat >$tmpd/unhex.pl</dev/null 2>&1; then
- enascii="kakasi -Ha -Ka -Ja -Ea -ka"
- else
- enascii_now=`date +%FT%T`
- enascii_sed() {
- nkf -Z0Z1Z2 \
- | sed -e "s/^/$enascii_now/" -e "s|[^-0-9.A-z/,()_=]|x|g"
- }
- enascii="enascii_sed"
- fi
- fi
- cat "$@" | $enascii
-}
-gettblconf() {
- if [ -z "$tconfs" ]; then
-## tconfs=`sq $db \
- tconfs=`query \
- "select tbl||'/'||col||'='||keytype||'/'||objtype from $conftbl;"`
- fi
- # /tb1/col1=p/text /tb1/col2=s/text /tb1/col3=m/image /tb2/col1=p/text ...
-}
-gettblkeys() {
- # $1=tbl
- gettblconf
- echo "$tconfs" | fgrep "/$1/" | \
- (type="" keys="" fks="" cols="" scols="" mcols="" hcols=""
- while IFS='=' read tc conf; do # tc=/tb1/col1 conf=s/text
- col=${tc##*/} type=${conf%%/*}
- case $type in
- *p*)
- cols=$cols"${cols:+:}$col"
- keys=$keys"${keys:+:}$col" ;;
- *f*) cols=$cols"${cols:+:}$col"
- fks=$fks"${fks:+:}$col" ;;
- *m*) mcols=$mcols"${mcols:+:}$col" ;;
- *s*) scols=$scols"${scols:+:}$col" ;;
- esac
- case $type in
- *h*) hcols=$hcols"${hcols:+:}$col" ;;
- esac
- done
- echo "_keys=$keys _fks=$fks _cols=$cols _scols=$scols _mcols=$mcols _hcols=$hcols")
-}
-gettblpkey() {
- # $1=tbl
- gettblkeys $1 | cut -d ' ' -f 1 | sed -e 's/.*=//' -e 's/:/ /g'
-}
-gettblfkey() {
- (x=`gettblkeys $1`
- x=${x#*_fks=} # cut before "_fks=" including
- echo ${x%% *} | tr ':' ' ')
-}
-gettblcols() {
- (x=`gettblkeys $1`
- x=${x#*_cols=} # cut before "_cols=" including
- echo ${x%% *} | tr ':' ' ')
-}
-gettbl_s_cols() {
- (x=`gettblkeys $1`
- x=${x#*_scols=} # cut before "_scols=" including
- echo ${x%% *} | tr ':' ' ')
-}
-gettbl_m_cols() {
- (x=`gettblkeys $1`
- x=${x#*_mcols=} # cut before "_mcols=" including
- echo ${x%% *} | tr ':' ' ')
-}
-gettbl_h_cols() {
- (x=`gettblkeys $1`
- x=${x#*_hcols=} # cut before "_hcols=" including
- echo ${x%% *} | tr ':' ' ')
-}
-gettbl_coltype() (
- gettblconf
- x=`echo "$tconfs"|fgrep $1=`
- x=${x#*=} # cut before =
- echo ${x#*/} # cut before p/ including
-)
-is_hidden() {
- # $1=Tbl $2=col
- gettblconf
- x=`echo "$tconfs"|fgrep /$1/$2=`
- x=${x#*=} # cut before =
- x=${x%%/*} # cut after /
- case $x in
- *h*) return 0 ;;
- *) return 1 ;;
- esac
-}
-
-dbsetbyid() {
- # $1=tbl $2=id $3=col $4=val/filename - &optional - $5=content-type
- (t0=$1 t=$1 p=$2 c=$3
- tsc=$t/$c val=$4
- unset primary update
- gettblconf
-#err tsc=$tsc, tconfs="$tconfs"
- conf=`echo "$tconfs"|fgrep "$tsc"=`
-#err conf=$conf
- case ${conf#*=} in
- p*) primary=1 ;;
- f*) update=1 ;;
- u*) ;;
- m*) t=${t}_m;;
- s*) t=${t}_s;;
- esac
-#err t=$t
- type=text fn=""
- case $conf in
- */password)
- type=encoded ### val=`echo $val|encode`
- ;;
- */image*|*/document*)
- type=`file --mime-type $val`
- bin="X'`hexize $val`'"
- ;;
- esac
- pkey=`echo "$tconfs"|grep "${t0}/.*=p"|sed 1q`
- pkey=${pkey#/*/} # cut $tbl/
- pkey=${pkey%=p/*} # cut =p/... -> primary key
- if [ "$primary" ]; then
- nulls=`echo "$tconfs"|grep "$t/.*=[fu]/"|sed 's/^.*/, NULL/'|tr -d '\n'`
- ###sq $db "replace into $t values(\"$val\"$nulls)"
- query "replace into $t values(\"$val\"$nulls);"
- elif [ "$update" ]; then
- ###sq $db "update $1 set $c=\"$val\" where $pkey=\"$p\""
- query "update $1 set $c=\"$val\" where $pkey=\"$p\";"
- else
-#err "replace into $t values(\"$p\", \"$c\", \"$type\", \"$val\", \"$bin\")"
- ###sq $db "replace into $t values(\"$p\", \"$c\", \"$type\", \"$val\", \"$bin\")"
- query "replace into $t values(\"$p\", \"$c\", \"$type\", \"$val\", \"$bin\");"
- fi
- )
-}
-expire() (
- at="${1:-$timeout}"
- FMT="${2:-%F %T}"
- TZ=GMT gdate -d "$at" +"$FMT"
-)
-addsession() {
- # expireをセット
- # loginの先にどの画面に行くかの状態遷移表書式を決める
- expire=`expire ${2:-"+1min"}`
-err addsession "$1" exp=$expire
- sq $db "replace into session values('$1', '$expire')"
- # Remove old session parameters
- now=`expire now`
- sq $db "delete from session where expire < '$now'"
-}
-gencookie() (
- for kv; do
- expire="`expire '' '%a, %d-%b-%Y %H:%M:%S GMT'`"
- echo "Set-Cookie: $kv; expires=$expire"
- done
-)
-contenttype() {
- echo "Content-type: ${1:-text/html; charset=utf-8}"
- contenttype() {} # Only need to work once
-}
-putheader() {
-
-}
-putfooter() {
- m4 -D_TITLE_="${TITLE:-$myname}" $layout/footer.m4.html
-}
-getcookie() (
- for kv in `echo $HTTP_COOKIE|sed 's/[;, ]/ /g'`; do
- k="${kv%%=*}"
- v="`echo ${kv#*=}|nkf -Ww -mQ|sed -e 's/\"/\"\"/g'`"
- query "replace into cookie values('$session', '$k', 'string', \"$v\");"
- done
-)
-genrandom() {
- # $1=columns (default: 10)
- dd if=/dev/urandom count=1 2>/dev/null|nkf -MB|fold -w${1:-10}|sed -n 10p
-}
-smail() {
- # smail rcpt subj (file)
- rcpt=`echo $1` # strip newlines
- subj="`echo $2|nkf -jM`"
- # echo rcpt=$rcpt
- (m4 -D_RCPT_="$rcpt" -D_SUBJ_="$subj" -D_FROM_=$admin $msg/mail-header.m4
- cat $3 | nkf -jd ) | sendmail -f $admin $rcpt
-}
-setviastring() {
- table=$1
- oifs="$IFS"
- IFS="&"
- for us in $2; do
- k=${us%%=*}
- v="`echo ${us#*=}|tr '%+' '= '|nkf -Ww -mQ|sed -e 's/\"/\"\"/g'`"
- sq $db "replace into $table values('$session', '$k', 'string', \"$v\")";
- #echo $k=$v
- done
- IFS="$oifs"
-}
-checkdomain() (
- # Check the validity of domain by referring DNS
- item=$1
- host ${item#@*} >/dev/null 2>&1
-)
-pwcheck() {
- # $1=passwd
- dbpswd=`getpwfield $user pswd`
- encpswd=`mycrypt "$1" "$dbpswd"`
- err user=$user, pswd=$1, db=$dbpswd, enc=$encpswd
- [ x"$dbpswd" = x"$encpswd" ]
-}
-mypwhash() {
- mycrypt `cat` `genrandom 5`
-}
-wasureta() {
- user=$1
- if checkdomain $user; then
- echo "ユーザ名には正しいメイルアドレスが必要です。"
- exit 0
- fi
- newpswd=`genrandom` # newsalt=`genrandom 5`
- #encpswd=`mycrypt "$newpswd" "$newsalt"`
- encpswd=`echo $newpswd|mypwhash`
- dbsetbyid user $user pswd "$encpswd"
- m4 -D_USER_="$user" -D_PSWD_="$newpswd" -D_URL_="$url" \
- $msg/mail-newaccount.m4 \
- | smail $user "New Account"
-}
-checkauth() {
- user=`getpar user`
- skc=`getpar skey` # from cookie
- [ -z "$user" ] && return 3
- skey="`getpwfield $user skey`"
-err user=$user skey=$skey
- if [ -n "$skey" ]; then
- if [ x"$skey" = x"$skc" ]; then
- return 0
- fi
- fi
- pswd=`getpar pswd`
- if [ x"$pswd" = x"wasureta" ]; then
- wasureta $user
- return 1 # wasureta error
- fi
- # dbpswd="`sq $db \"select pswd from passwd where name='$user'\"`"
- # putheader; echo; echo user=$user, db=$dbpswd, enc=$encpswd
- if pwcheck "$pswd"; then
- newsession=`genrandom 50`
- dbsetbyid user $user skey "$newsession"
- gencookie "user=$user" "skey=$newsession"
- return 0
- fi
- return 2 # Password mismatch
-}
-showlogin() {
- args=`echo $myargs|tr ' ' '+'`
- m4 -D_SYSNAME_="Welcome" -D_MYNAME_="$myname${args+?}$args" \
- $layout/login.m4.html
- exit 0
-}
-dologin() {
- checkauth
- st=$?
- if [ $st != 0 ]; then
- contenttype; echo
- m4 -D_USER_="$user" -D_URL_="$url" -D_ADMIN_="$admin" \
- $msg/login-fail-$st.m4.html
- showlogin # and EXIT
- fi
-}
-cleanup() {
- echo .quit > $sqi
- kill $sq3pid
- rm -f $sqo $sqi
- rm -rf $tmpfiles
-}
-trap cleanup INT HUP EXIT
-# trap cleanup INT HUP
-cgiinit() {
- session=`date +%F-$$`
- tmpf=tmp/stream
- tmpd=`tmpd=$tmpdir mktempd`
- tmpfiles=$tmpfiles" $tmpd"
- addsession $session
- getcookie
- case "$REQUEST_METHOD" in
- get|GET) s="$QUERY_STRING" ;;
- post|POST) ## dd count=$CONTENT_LENGTH bs=1 of=$tmpf 2>/dev/null #slow
- # cat > $tmpf # too much?
- head -c $CONTENT_LENGTH > $tmpf # safe?
- (echo CL=$CONTENT_LENGTH; ls -lF $tmpf) 1>&3
- s="`cat tmp/stream`"
- tmpfiles=$tmpfiles"${tmpfiles+ }$tmpf"
- ;;
- esac
- case "$CONTENT_TYPE" in
- *boundary*)
- bndry=${CONTENT_TYPE#*boundary=}
- #for us in `LC_CTYPE=C ./mpsplit.rb "$bndry" $tmpd < $tmpf`
- for us in `LC_CTYPE=C ./mpsplit.pl "$bndry" $tmpd < $tmpf`
- do
- k=${us%%\=*}
- #echo u=$us
- #v="`echo ${us#*=}|nkf -Ww -mQ|sed -e 's/\"/\"\"/g'`"
- v="`echo ${us#*=}|unhexize|sed -e 's/\"/\"\"/g'`"
- # err k=$k v=$v
- case "$k" in
- *:filename)
- type='file'; k=${k%:filename}
-(echo k=$k; ls -lF $tmpd/$v; file --mime-type $tmpd/$v) 1>&3
- case `file --mime-type $tmpd/$v|cut -d' ' -f2` in
- [Ii]mage/*)
- mogrify -resize $maximagexy'>' $tmpd/$v
- ;;
- esac
- ;;
- *)
- type='string'
- ;;
- esac
- #sq $db "replace into par values('$session', '$k', '$type', \"$v\")"
- setpar "$k" "$type" "$v"
- done
- ;;
- *)
- setviastring par "$s"
- ;;
- esac
-}
-collectemail() {
- # Collect email addresses for group $1
- if isuser "$1"; then
- em=`query "select val from user_m where name='$1' and key='email';"`
- [ -n "$em" ] && echo "$em" || echo "$1"
- else
- query "with recursive allmem as
- (select gname,val from grp_m where gname='$1'
- union all select grp_m.gname,grp_m.val from grp_m,allmem
- where allmem.val=grp_m.gname)
- select coalesce(b.val,a.val)
- from allmem a left join grp_mem_s b
- on a.gname=b.gname and a.val=b.user and b.key='email'
- where a.val in (select name from user) limit 10000;"
- fi
-}
-sendinvitation() (
- # $1=email
- iss="invite-`date +%s`-$(genrandom 10)"
- addsession $iss +7days # 1 week due date
- query "replace into par values('$iss', 'invite', 'string', \"$1\");"
- gecos=`gecos`
- name=$user"${gecos:+($gecos)}"
- regist="$urlbase?reg+$iss"
- m4 -D_URL_="$urlbase" \
- -D_USER_="$name" \
- -D_EMAIL_="$1" \
- -D_REGIST_="$regist" \
- -D_ADMIN_="$admin" \
- $msg/mail-invite.m4 \
- | smail $1 "BBSへの御招待"
- return 0
-)
-emaildomaincheck() {
- case "$1" in
- *@*@*) echo "無効なアドレスです"; return 1 ;;
- *@*)
- local=${1%@*} domain=${1#*@}
- if ! host $domain >/dev/null 2>&1; then
- echo "ドメイン($domain)が見付かりません。"
- return 2
- fi
- return 0
- ;;
- *) echo "正しいメイルアドレスをいれてください"; return 3 ;;
- esac
-}
-invite() {
- email=`getpar email`
- case $email in
- *@*@*) repo="無効なアドレスです" ;;
- *@*)
- local=${email%@*} domain=${email#*@}
- if ! repo=`emaildomaincheck $email`; then
- repo="招待アドレスのエラー: $repo"
- elif [ -n "`query \"select * from user where name='$email';\"`" ]; then
- repo="$email さんは既に加入しています。"
- elif sendinvitation $email; then
- repo="アドレス($email)宛に案内を送信しました。"
- fi ;;
- "") repo="招待したい人のメイルアドレスを入力してください。" ;;
- *) repo="無効なアドレスです" ;;
- esac
- m4 -D_REPORT_="$repo" -D_ACTION_="$myname?invite" \
- $layout/html.m4.html $layout/invite.m4.html
-}
-regist() {
- # $1=session-id-for-invitation
- m4 -D_TITLE_="Invitation" $layout/html.m4.html
- if [ -z "$1" ]; then
- echo "
bye bye
"
- reutrn
- fi
- email=`session=$1 getpar invite`
- if [ -z "$email" ];then
- cat<無効な招待状チケットです。
-
'
- cgi_form searchart<`cgi_text kwd`という語を含むコメントを検索
-`cgi_hidden owner $grp`
-EOF
- cond="where a.id in (select id from blog_s where key='owner' and val='$grp') order by ctime desc"
- DT_CHLD=article:blogid \
- DT_VIEW=replyblog dumptable html blog 'ctime title heading' "$cond"
-
- c="group by b.name having b.name in (select user from grp_mem where gname='$grp')"
- cm="?commission+$mmgrp"
- thumbxy=50x50 listmember "" "$c" \
- |sed -e "s|\( \),not=\(.*\)|\1管理者委託|"
-}
-joingrp() {
- # $1=group $2=user $3=yes/no $4=email(if any $5=AsAdmin)
-err joingrp: \$1=$1 \$2=$2 \$3=$3 \$4=$4
- isgrpowner "$user" "$1" && isowner="yes" || isowner=""
-err jg:isgrpowner: isowner="$isowner"
- if [ x"$2" != x"$user" ]; then # if user is not login user
- if [ -z "$isowner" ; then
- echo "
本人か、グループ管理者しか加入操作はできません。
"
- return
- fi
- fi
- cond="where gname='$1' and user='$2'"
- if [ x"$3" = x"yes" ]; then
- query "replace into grp_mem values('$1', '$2');"
- if [ -n "$4" ]; then
- if msg=`emaildomaincheck "$4"`; then
-err "replace into grp_mem_s values('$1', '$user', 'email', \
- 'string', '$4', NULL);"
- query "replace into grp_mem_s values('$1', '$user', 'email', \
- 'string', '$4', NULL);"
- if [ -n "$5" ]; then # as ADMIN
- # Coming here means newly created group
- sql="select case\
- when (select count(*) from grp_mem where gname='$1')=1\
- then (select user from grp_mem\
- where gname='$1' and user='$user')\
- else '' end;"
- err NewGrpChk: $sql
- if [ -n "`query \"$sql\"`" ]; then
- err ADMIN: "replace into grp_adm values('$1', '$user');"
- query "replace into grp_adm values('$1', '$user');"
- fi
- fi
- else
- echo $msg
- fi
- else
- query "delete from grp_mem_s $cond and key='email';"
- fi
- else
- query "delete from grp_mem $cond;
-delete from grp_mem_s $cond;
-delete from grp_mem_m $cond;"
- fi
-}
-grp_reg_adm() {
- # $1=grp $2=user-rowid
- if ! isgrpowner $user $1; then
- echo "
$1 グループの管理者しかこの操作はできません。"; return
- fi
- newadm=`query "select name from user where rowid=$2;"`
- if [ -z "$newadm" ]; then
- echo "
指定ユーザIDがおかしいようです。
"; return
- fi
-err GRP_reg_adm: "replace into grp_adm values('$1', '$newadm');"
-err ismember $newadm $1
- if ismember $newadm $1; then
- # OK, go ahead
- query "replace into grp_adm values('$1', '$newadm');"
- # confirm insertion
- sql="select * from grp_adm where gname='$1' and user='$newadm'"
- if [ -n "`query \"$sql;\"`" ]; then
- echo "
追加完了
"
- else
- echo "
追加失敗($1 $2)
"
- fi
- fi
- showgroup $1
-}
-dumptable() {
- # $1=mode $2=Table $3=column-list-of-*_s(defaults to *) $4=conditions(if any)
- # textのフィールドだけ全てダンプにしたほうがいいか
- # $DT_VIEW sets link
- # 6/17の次: editリンクじゃなくてスレッドVIEWリンクでいいんちゃう?
- ### elink="EDIT"
- VIEW=${DT_VIEW-replyblog}
- if [ -n "$VIEW" ]; then
- dvlink=" VIEW"
- fi
- # $DT_CHLD=ChildTable:BindColumn
- if [ -n "$DT_CHLD" ]; then
- _t=${DT_CHLD%:*} _i=${DT_CHLD#*:}
- cntall="(select count($_i) from $_t where $_i=a.id)"
- cntnew="(select count(val) from ${_t}_s where key='ctime' \
- and id in (select id from $_t where $_i=a.id) \
- and val > coalesce((select time from acclog where \
- user='$user' and tbl='$2' and rowid=a.rowid),\
- '1970-01-01'))"
- cnt="$cntnew||'/'||$cntall as '新着/総数',"
- dt_class=" td2r"
- fi
- # Construct join expression
- eav="" scols=""
- pk=`gettblpkey $2`
- substr=${dumpcollen:+"substr(val, 0, $dumpcollen)"}
- substr=${substr:-val}
- for col in ${3:-`gettbl_s_cols $2`}; do
- case $col in
- *:*) col=${col%:*} as=${col#*:} ;;
- *) as=${col} ;;
- esac
- eav=$eav${eav:+,}" max(case key when '$col' then $substr end) as $as"
- scols="$scols${scols:+, }b.$as"
- done
-#case author when '$user' then a.rowid else '---' end as ID,
- sql="select \
-a.rowid as ID,\
-$cnt\
-$scols from $2 a left join (select $pk,$eav from ${2}_s group by $pk) b on a.$pk=b.$pk $4;"
-err SQL="$sql"
- cat<
\)\([1-9][0-9]*\)
,\1$elink$dvlink,"
-
-
-`sq -header -cmd ".mode $1" $db "$sql"`
-
-
-EOF
-}
-
-par2table() (
- # copy current parameters of par into destination table
- # $1=definition-file
- # Using $user and $session
- rowid=`getpar rowid`
-err ...........rowid=$rowid
- if [ ! -e $1 ]; then
- echo "
テーブル定義ファイルが見付かりません
"
- exit 1
- fi
- tbl=${1%.def}
- tbl=${tbl##*/}
- if [ -n "$rowid" ]; then # Modify existing entry
- if [ x"$tbl" = x"user" ]; then
- rowowner=`query "select name from $tbl where rowid=$rowid;"`
- elif [ x"$tbl" = x"grp" ]; then
- sql="select gname from $tbl where rowid=$rowid;"
- ##err p2t:grp:q $sql
- isgrpowner $user "`query $sql`" && rowowner=$user
- else
- rowowner=`query "select owner from $tbl where rowid=$rowid;"`
- rowowner=${rowowner:-`query "select author from $tbl
- where rowid=$rowid;"`}
- fi
- ### err rowowner=$rowowner
- if [ x"$user" != x"$rowowner" ]; then
- echo "
"
- return
- fi
- rm=`getpar rm` cfm=`getpar confirm`
- # Editing existent entry
- if [ x"$rm" = x"yes" ]; then
- if [ x"$rm$cfm" = x"yesyes" ]; then
- query "delete from $tbl where rowid=$rowid;"
- return
- else
- echo "
消去確認のチェックがないので消さなかったの...
"
- return
- fi
- fi
- fi
- # XX: Subshelling here is unnecessary 2015-07-05
- (ts=${tbl}_s tm=${tbl}_m val="" pval="" formaster="" getrow=""
- if [ -n "$rowid" ]; then
- # Update of existing record
- for col in `gettblcols $tbl`; do
- val=`getparquote $col`
- [ -z "$val" ] && continue
- err sq $db "update $tbl set $col=$val where rowid=$rowid"
- query "update $tbl set $col=$val where rowid=$rowid;"
- done
- # Then, set up $pval for further insertion of tbl_s and tbl_m
- for col in `gettblpkey $tbl`; do
- val=`query "select $col from $tbl where rowid=$rowid;"|sed -e 's/\"/\"\"/g'`
- pval="$pval${pval:+, }\"$val\""
- done
- else
- # New entry
- # Generate values() for primary keys
- for col in `gettblpkey $tbl`; do
- # Genuine primary keys for _m and _s
- val=`getvalquote $tbl $col`
- [ -z "$val" ] && continue
- pval="$pval${pval:+, }$val"
- done
-err pval=$pval
- for col in `gettblfkey $tbl`; do
- # args for values() to insertion into master table
- val=`getvalquote $tbl $col`
- [ -z "$val" ] && continue
- formaster=$formaster"${formaster:+, }$val"
- done
- formaster="$pval${formaster:+, }$formaster"
-err formaster=$formaster
- if [ -z "$formaster" ]; then
- echo "
項目を全て埋めてください
"
- return 1
- fi
- err "replace into $tbl values($formaster);"
- echo "replace into $tbl values($formaster); $getrow" | sq $db
- ## Insertion to master table, done
- fi
-
- for kt in s m; do
- tb2=${tbl}_$kt
- for col in `gettbl_${kt}_cols $tbl`; do
- ptype=`getpartype $col "limit 1"`
-
- # First, check update of existing entries in _m
- if [ $kt = m ]; then
- # sessID|address.1.22|string|Somewhere-x.y.z
- sql=""
-err dots from query "select var from par where var like '$col.%';"
- for v in `query "select var from par where var like '$col.%';"`; do
- # v=address.1.22
- rowid=${v##*.}
- origcol=${v%%.*} # original column derived from
-err Updating for $v rowid=$rowid, partype=`getpartype $v`
- ##case `getpartype $v` in
- err CASE `gettbl_coltype $tbl/$origcol` in
- err edit flag = `getpar action.$v`
- case `getpar action.$v` in
- rm)
- if [ x`getpar confirm.$v` = x"yes" ]; then
- newsql="delete from $tb2"
- else
- echo "
削除確認未チェック
"
- fi ;;
- edit)
- case `gettbl_coltype $tbl/$origcol` in
- image|document|binary)
- file=$tmpd/`getparfilename $v`
- err type=file=$file
- [ -z "$file" ] && continue
- bn=${file##*/}
- bin="X'"$(hexize $file)"'"
- ct=`file --mime-type $file|cut -d' ' -f2`
- type=\"file:$ct\"
- newsql="update $tb2 set val='$bn', type=$type, bin=$bin"
- ;;
- *)
- newsql="update $tb2 set val=(select val from par where var \
-like '$col.%.$rowid')"
- ;;
- esac
- ;;
- *) # maybe `keep', do not modify value
- continue
- ;;
- esac
-# err newsql=$newsql
- sql=$sql$nl"$newsql where rowid=$rowid;"
- done
- echo "$sql
-delete from $tb2 where type='string' and val='';" | sq $db
- # Rest of kt==m: set multiple mode
- nr=`getparcount $col`
- else
- nr=1 # for kt==s, number of records is 1
- fi
-
- i=0
- while [ $i -lt $nr ]; do
- limit="limit 1 offset $i"
- i=$((i+1)) # increase beforehand against continue
- val=`getvalquote $tbl $col "$limit"`
- [ -z "$val" -o x"$val" = x'""' -o x"$val" = x"NULL" ] && continue
-err $col=$val
- bin=NULL
-err partype$col=`getpartype $col "$limit"`
- case $ptype in
- file) file=$tmpd/`getparfilename $col "$limit"`
-err parfile-$col=$file
- [ -z "$file" ] && continue
- bin="X'"$(hexize $file)"'"
- ct=`file --mime-type $file|cut -d' ' -f2`
- type=\"file:$ct\" ;;
- "*"*) continue ;; # foreign table
- *) type=\"string\" ;;
- esac
- case `gettbl_coltype $tbl/$col` in
- password) # special care for password
- # name={password,pswd1,pswd2}
- p1=`getpar pswd1 "$limit"`
- if [ -z "$p1" ]; then
- continue # SKIP password setting, if p1 is empty
- else
- pswd=`getpar pswd "$limit"` p2=`getpar pswd2 "$limit"`
-## err pswd=$pswd
- if pwcheck "$pswd"; then
- if [ x"$p1" = x"$p2" ]; then
- case "$p1" in
- ????????*) ;;
- *) echo "
"
- return
- fi
- fi
- ;;
- esac
-## err p2t: "replace into $tb2 values($pval, \"$col\", $type, $val, $bin);"
- echo "replace into $tb2 values($pval, \"$col\", $type, $val, $bin);" \
- | sq $db
- done
- done
- done
- return 0
- err donee)
-)
-par2table_old() {
- # copy current parameters of par into destination table
- # $1=dst-table $2=definition-file
- # Using $user and $session
- rowid=`getpar rowid`
- if [ -n "$rowid" ]; then
- rm=`getpar rm` cfm=`getpar confirm`
- if [ x"$rm$cfm" = x"yesyes" ]; then
- sq $db "delete from $1 where rowid=$rowid and owner=\"$user\""
- return
- fi
- fi
- cat $2 \
- | (cols=""
- while IFS=: read prompt name type args; do
- [ x"$name" = x"stage" ] && continue
- if [ -n "$rowid" ]; then
- val=`getpar $name|sed -e 's/\"/\"\"/g'`
- sq $db "update $1 set $name=\"$val\" where rowid=$rowid and owner=\"$user\""
- else
- eav=$eav${eav+,}" max(case var when '$name' then val end)"
- fi
- done
- [ -n "$rowid" ] && return
- cond="where sessid='$session' group by sessid"
- sq $db "replace into $1 select $eav,\"$user\" from par $cond"
- # Think over again about putting $user
- )
-}
-genform() {
- # $1 = form definition file
- # $2, $3 (optional)= table name and ROWID
- # If $GF_VIEWONLY set and nonNull, output values without form
- # If $GF_HIDDEN set, use it hidden values
- # If $GF_OWNER set, use it as value of name="owner"
- # If $GF_STAGE set, use it as value of name="stage"
- forms="" hiddens="" rowid=$3
- if [ ! -e "$1" ]; then
- echo "
そのようなデータベースはないようです($2)。
"
- return
- elif [ -n "$2" ]; then
-err genform1: "select * from $2 where rowid='$rowid'"
- rec=`query "select * from $2 where rowid='$rowid';"`
- if [ -z "$rec" ]; then
- pk=`gettblpkey $2`
- ###rec=`sq $db "select rowid from $2 where $pk='$rowid'"`
-err "select rowid from $2 where $pk='$rowid';"
- rec=`query "select rowid from $2 where $pk='$rowid';"`
-err rec-rowid=$rec
- rowid=$rec
- rec=$3
- fi
- if [ -z "$rec" ]; then
- echo "
そんなレコードはないみたいね...
"
- return
- fi
- fi
- if [ -z "$GF_VIEWONLY" ]; then
- rm='
-ほんとうに消しますよ(確認)!
-はい'
- fi
- while IFS=: read prompt name keytype type args; do
- [ -z "${prompt%%\#*}" ] && continue # skip comment line(#)
- sp="${args:+ }"
- form="" val=""
- if [ -n "$rowid" ]; then
- val=`getvalbyid $2 $name $rowid $tmpd`
- fi
- if [ -n "$GF_VIEWONLY" ]; then
- is_hidden "$2" "$name" && continue
- fi
- case "$type" in
- text*)
- cgiform=cgi_multi_$type
- if [ -s $tmpd/$name.count ]; then
- form=`$cgiform $name $tmpd`
- val=$(echo "$val"|
- while read fn; do
- echo "
"
- if [ -n "$owner" ]; then
- cond="where key='owner' and val='$owner'"
- if isuser $owner; then
- echo "
(`linkhome $owner` さんの記録からの検索)
"
- else
- linkhome $owner 1>&3
- echo "
(`linkhome $owner` グループからの検索)
"
- fi
- fi
- # article_s: id=article-id, key='text', val='TEXT'
- # article: id=article-id, blogid=blogkd
- # blog: id=blog-id, author=LeaderAuthor
- # blog_s: id=blog-id, key='title', val='BLOG-TITLE'
- # WANT: blog-ROWid,article-id,val(TEXT)
- sql="select b.rowid||'#'||x.id as '',
- b.title as TITLE,
- substr(x.val, 0, 80) as TEXT
- from (select blog.rowid,blog.*,bs.val as title from blog join blog_s bs
- on blog.id=bs.id and bs.key='title') b
- join
- (select a.id,a.blogid,s.val from article a join article_s s
- on a.id=s.id where s.val like '%$kwd%')
- x on b.id=x.blogid
- where b.id in (select id from blog_s
- $cond);"
- sedopt="s,