yuuji@0: #!/bin/sh yuuji@0: # Here's global variable table. Do not use this names. yuuji@1: # $HGid$ yuuji@26: yuuji@26: [ -f s4-config.sh ] && . ./s4-config.sh yuuji@26: yuuji@0: myname=`basename ${SCRIPT_NAME:-$0}` yuuji@0: mydir=`dirname ${SCRIPT_FILENAME:-$0}` yuuji@0: myargs="$@" yuuji@8: PATH=/usr/local/sqlite3/bin:/usr/local/vim7/bin:/usr/iekei/ImageMagick/bin:/usr/local/ImageMagick/bin:$PATH yuuji@0: tmpdir=${TMPDIR:-tmp} yuuji@2: dbdir=${DBDIR:-db} yuuji@0: tmpfiles="" yuuji@2: db=${DB:-$dbdir/cgi.sq3} yuuji@83: admin=${ADMIN:-hostmaster@example.org} yuuji@3: templ=${TEMPL:-templ} yuuji@67: layout=${LAYOUT:-$templ/default} yuuji@67: formdir=${FORMDIR:-$templ/form} yuuji@67: imgdir=${IMGDIR:-img} yuuji@16: url=${URL:-"${REQUEST_SCHEME:-http${HTTPS:+s}}://$HTTP_HOST$REQUEST_URI"} yuuji@0: urlbase=${url%%\?*} yuuji@117: msgdir=$templ/msg yuuji@0: timeout="+2 days" yuuji@117: memoplimitdays="7" yuuji@252: dumpcollen=22 yuuji@67: #thumbxy=120x120 yuuji@0: thumbxy=96x96 yuuji@322: iconxy_S=80x80 yuuji@322: iconxy_M=400x400 yuuji@0: maximagexy=1600x1600 yuuji@0: ### maximagexy=400x400 yuuji@209: file_accept='accept="image/*,text/*,audio/*,application/vnd.oasis.*,application/pdf,application/x-*"' yuuji@236: blogreadflagrowid=0 yuuji@471: blogcutoffflagrowid=-1 yuuji@358: querylog=$tmpdir/query.log yuuji@207: yuuji@0: tconfs="" yuuji@231: imgcached=cache/img.`date +%Y/%m` yuuji@4: conftbl=_tblconf yuuji@0: nl=" yuuji@0: " yuuji@322: iconcachekey="profimgcache_S" yuuji@352: case "$HTTP_USER_AGENT" in yuuji@352: *i[Pp]hone*|*[Aa]ndroid*) touchpanel=1 ;; yuuji@352: *) touchpanel="" ;; yuuji@352: esac yuuji@17: . ./s4-cgi.sh yuuji@0: yuuji@0: : < "hoge", "owner" => "yuuji", "date" => "2015-04-27", yuuji@0: "text" => "hogehoge ..", yuuji@0: "reply" => [ {"serial" => 1, yuuji@0: "author" => "taro", yuuji@0: "date" => "2015-04-28", yuuji@0: "parent" => "/", yuuji@0: "path" => "/1", yuuji@0: "text" => "blah, blah, ....", yuuji@0: "image" => ["a.jpg", "b.jpg"] }, yuuji@0: {"serial" => 2, yuuji@0: "author" => "hanako", yuuji@0: "date" => "2015-04-29", yuuji@0: "parent" => "/", yuuji@0: "path" => "/2", yuuji@0: "text" => "blah, blah, ....", yuuji@0: "image" => [] }]}, yuuji@0: {"title" => "buha", ...} ] yuuji@0: yuuji@0: yuuji@0: user:= yuuji@0: ユーザ名(英数字):name:p:text:length="20" maxlength="40" yuuji@0: パスワード:pswd:s:password:length="20" maxlength="40" yuuji@0: 説明(日本語OK):gecos:s:text:length="20" maxlength="40" yuuji@0: セッションキー:skey:s:session yuuji@0: メイルアドレス:email:m:text:length="20" maxlength="40" yuuji@0: 住所:address:m:textarea:maxlength="400" yuuji@0: プロフィール画像:profimg:m:image:maxlength="400K" yuuji@0: 履歴書:profpdf:m:document:maxlength="4M" yuuji@0: yuuji@0: 変換表 yuuji@0: /user/email=m yuuji@0: yuuji@0: blog:= yuuji@0: シリアル:id:p:serial yuuji@0: タイトル:title:s:text: yuuji@0: 所有者:owner:s:owner: yuuji@0: 時刻:ctime:s:stamp: yuuji@0: リード文:heading:s:textarea: yuuji@0: リプライ:reply:m:*article: yuuji@0: yuuji@0: article:= yuuji@0: シリアル:id:p:serial yuuji@0: 筆者:author:s:owner yuuji@0: 時刻:ctime:s:stamp: yuuji@0: 参照元:parent:s:parent: yuuji@0: パス:path:s:path: yuuji@0: 本文:text:s:textarea: yuuji@0: 画像:image:m:image: yuuji@0: yuuji@0: 履歴書:profpdf:m:document:maxlength="4M" yuuji@0: yuuji@0: yuuji@0: EOF yuuji@0: yuuji@0: sq() { yuuji@0: # ./args.rb -cmd ".timeout 3000" "$@" yuuji@0: sqlite3 -cmd 'PRAGMA foreign_keys=ON' -cmd ".timeout 3000" "$@" yuuji@0: } yuuji@163: dbsetup() { yuuji@163: [ -d $tmpdir ] || mkdir -m 1777 $tmpdir yuuji@163: [ -d $dbdir ] || mkdir -m 1775 $dbdir yuuji@163: sqi=$tmpdir/sqi.$$ yuuji@163: sqo=$tmpdir/sqo.$$ yuuji@163: mkfifo $sqi $sqo yuuji@163: #tail -f $sqi | sq $db & # "tail -f" is too heavy. DO NOT USE!! yuuji@163: sq $db < $sqi & yuuji@163: sq3pid="`jobs -p` $!" yuuji@163: exec 2>> $tmpdir/error.out yuuji@163: exec 3>> $tmpdir/debug.out yuuji@163: exec 5> $sqi # Turning $sqi access through fd5 for continuous open state yuuji@163: rm $sqi yuuji@163: } yuuji@396: cleanup2() { # Dirty workaround for produced zombie processes yuuji@396: pkill -9 -u `id -u` -P 1 yuuji@396: } yuuji@163: cleanup() { yuuji@337: trap '' INT HUP EXIT TERM PIPE yuuji@163: echo .quit >&5 yuuji@163: kill $sq3pid yuuji@163: kill $sq3pid yuuji@163: rm -f $sqo $sqi yuuji@163: rm -rf $tmpfiles yuuji@396: cleanup2 yuuji@118: } yuuji@358: # We want to use piped function to put querylog, but we use yuuji@358: # simple redirection for the sake of speed. yuuji@0: query() { yuuji@180: echo ".once $sqo" >&5 yuuji@359: echo "`date '+%F %T'`:[${user:-NULL}] <<<" >> $querylog yuuji@180: if [ -z "$1" ]; then yuuji@358: tee -a $querylog yuuji@180: else yuuji@358: echo "$@" >> $querylog yuuji@180: echo "$@" yuuji@358: fi >&5 yuuji@0: cat $sqo yuuji@358: echo '>>>' >> $querylog yuuji@0: } yuuji@187: _m4() { yuuji@187: #_S4NAME_=f,f,f yuuji@187: m4 ${_S4NAME_:+"-D_S4NAME_=${_S4NAME_}"} "$@" yuuji@187: } yuuji@0: ismember() { yuuji@0: # $1=user, $2=group yuuji@16: err ismem: "select user from grp_mem where gname=$(sqlquote $2) and user='$1';" yuuji@431: test -n "`query \"select user from grp_mem where gname=$(sqlquote \"$2\") and user='$1';\"`" yuuji@0: } yuuji@0: isuser() { # Check if $1 is a valid user yuuji@0: test -n "`query \"select name from user where name='$1';\"`" yuuji@0: } yuuji@0: isgroup() { # Check if $1 is a valid group yuuji@16: err isgroup: "select gname from grp where gname=$(sqlquote $1);" yuuji@431: test -n "`query \"select gname from grp where gname=$(sqlquote \"$1\");\"`" yuuji@0: } yuuji@16: isgrpowner() ( yuuji@0: # $1=user, $2=group yuuji@16: gn=`sqlquote "$2"` yuuji@16: sql="select user from grp_adm where gname=$gn and user='$1';" yuuji@16: err isgrpowner: $sql yuuji@16: test -n "`query $sql`" yuuji@16: ) yuuji@117: getgroupadminmails() { yuuji@117: # $1=group yuuji@117: for i in $(getgroupadmins $1); do yuuji@117: email4group "$1" "$i" ; yuuji@117: done yuuji@117: } yuuji@56: getgroupadmins() { # $1=group yuuji@56: # This function is called in a backquote, so needn't to be subshellized yuuji@56: qgrp=`sqlquote "$1"` yuuji@56: query "select user from grp_adm where gname=$qgrp;" yuuji@56: } yuuji@117: getgroupattr() { # $1=group $2=attr yuuji@117: # This function is called in a backquote, so needn't to be subshellized yuuji@117: getvalbyid grp $2 \ yuuji@431: $(query "select rowid from grp where gname=`sqlquote \"$1\"`;") yuuji@117: } yuuji@56: getgroupbyid() { yuuji@16: # $1=id|gname yuuji@431: sql="select coalesce((select gname from grp where gname=$(sqlquote \"$1\")), yuuji@16: (select gname from grp where rowid=$(sqlquote $1)));" yuuji@71: # err ggbyid: `echo $sql` yuuji@16: query $sql yuuji@56: } yuuji@0: isfilereadable() { # $1=user $2=tbl $3=rowid yuuji@0: # Return true if user($1) can read attachment files in tbl($2):rowid($3) yuuji@0: [ -z "$1" -o -z "$2" -o -z "$3" ] && return 1 # invalid argument yuuji@78: yuuji@78: # Return true when anonymous mode yuuji@78: [ "$anonymousmode" ] && return 0 yuuji@0: # case `getvalbyid blog mode $2` in yuuji@0: # normal|*open*|"") return 0 ;; yuuji@0: # *closed*) yuuji@0: # owner=`getvalbyid blog owner $2` yuuji@0: # if isgrp $owner; then yuuji@0: # isgrpowner $1 $owner && return 0 || return 1 yuuji@0: # elif isuser $owner; then yuuji@0: # [ x"$1" = x"$owner" ] && return 0 || return 1 yuuji@0: # fi yuuji@0: # esac yuuji@0: # ↑ 要はこういう処理を↓で一気にやっている yuuji@0: sql="with getblog as (\ yuuji@0: select key,val from blog_s where id=(\ yuuji@0: select blogid from article where id in\ yuuji@0: (select id from $2 where rowid=$3))),\ yuuji@0: getowner as (select val from getblog where key='owner'),\ yuuji@0: getmode as (select val from getblog where key='mode')\ yuuji@0: select case\ yuuji@0: when (select author from article where\ yuuji@0: id=(select id from $2 where rowid=$3))='$1' \ yuuji@0: then 'author'\ yuuji@0: when (select val from getmode) in ('report-open', 'normal')\ yuuji@0: then 'open'\ yuuji@0: when (select val from getmode) is null \ yuuji@0: then 'open' yuuji@0: when (select val from getowner) in (select gname from grp)\ yuuji@0: then (select user from grp_adm where \ yuuji@0: gname=(select val from getowner) and \ yuuji@0: user='$1')\ yuuji@39: when (select author from article where\ yuuji@39: id=(select id from $2 where rowid=$3))='$1' yuuji@39: then 'user+author' yuuji@39: else '' end;" yuuji@356: ## err isfilereadable: sql="`echo $sql`" yuuji@0: # caseのネストで内側のcaseがスカラーtrueを返しても外側はtrue扱いにならない yuuji@0: result=`query "$sql"` yuuji@0: [ -n "$result" ] && return 0 yuuji@0: return 2 yuuji@0: } yuuji@0: linkhome() { yuuji@0: # $1=UserOrGroup yuuji@0: echo -n '`gecos $1`" yuuji@0: } yuuji@208: hreflink() { yuuji@284: # s4 specific notation: yuuji@284: # ^href=URL yuuji@284: # ^iframe=URL yuuji@478: # [[#NUM]] - Jump to article ID NUM yuuji@478: # [[#Keyword] - Jump to keywrod search for "Keyword" yuuji@284: # OSM umap Wikistyle Notation: yuuji@284: # [[URL]] - Simle Link yuuji@284: # [[URL|Word]] - Link with anchor word yuuji@284: # {{URL}} - yuuji@284: # {{URL|width}} - yuuji@284: # {{{URL}} } - yuuji@284: # {{{URL|height}} - yuuji@485: # Other Style yuuji@485: # ---- -
(In the beginning of line) yuuji@485: # *Word* - Word yuuji@485: # _Word_ - Word yuuji@485: # **Word** - Word yuuji@485: # __Word__ - Word yuuji@267: _hrefptn="[-A-Za-z0-9,.:;/~_%#&+?=@!]*" yuuji@482: _hrefptn="[A-Za-z0-9/~%+?=@!.][^][()<> ]*" # URL should start with ASCII yuuji@451: sed -e "s|\[\[\#\([0-9][0-9]*\)\]\]|#\1|g" \ yuuji@479: -e "s|\[\[#\([^]&]*\)\]\]|\#\1|g" \ yuuji@451: -e "s|\[\[\($_hrefptn\)\|\([^]]*\)\]\]|\2|g" \ yuuji@284: -e "s|\[\[\($_hrefptn\)\]\]|\1|" \ yuuji@284: -e "s|{{{\($_hrefptn\)\|\(.*\)}}}||g" \ yuuji@284: -e "s|{{{\($_hrefptn\)}}}||g" \ yuuji@284: -e "s|{{\($_hrefptn\)\|\(.*\)}}||g" \ yuuji@284: -e "s|{{\($_hrefptn\)}}||g"\ yuuji@284: -e "s|^href=\($_hrefptn\)|\1|" \ yuuji@425: -e "s|^iframe=\($_hrefptn\)||" \ yuuji@426: -e "s,^#### *\(.*\),

\1

," \ yuuji@426: -e "s,^### *\(.*\),

\1

," \ yuuji@483: -e "s,^## *\(.*\),

\1

," \ yuuji@485: -e 's,^----*$,
,' \ yuuji@486: -e 's, \*\*\([^* |][^*|]*[^ |]\)\*\* ,\1,g' \ yuuji@486: -e 's, __\([^_ |][^_]*[^ ]\)__ ,\1,g' \ yuuji@486: -e 's, \*\([^* |][^*|]*[^ |]\)\* ,\1,g' \ yuuji@486: -e 's, _\([^_ ][^_]*[^ ]\)_ ,\1,g' yuuji@208: } yuuji@291: minitbl() { yuuji@291: sed -n ' yuuji@295: /^|.*|/ {; # If the line begin with "|" and has 2 or more "|" yuuji@291: s,|$,,; # Remove trailing "|" first yuuji@291: s,|\* *\([^|]*\) *,\1,g; # "|*..." to "..." yuuji@291: s,| *\([^|]*\) *,\1,g; # "|..." to "..." yuuji@291: s,^,,; s,$,,; # Enclose with "" and "" yuuji@291: H; # Concat this line to HoldSpace yuuji@291: s/.*//; # Delete PatternSpace for finalization yuuji@291: $ b cont yuuji@291: d; # If in final line, output the rest, else jump to next turn yuuji@291: } yuuji@291: :cont yuuji@291: x; # For non-"|" lines, check HoldSpace yuuji@291: /^./ {; # If HoldSpace has "|" table elements yuuji@398: s|^.||; # Enclose whole elements like this: yuuji@398: # . of ^. is workaround for FreeBSD sed yuuji@291: # s|$|
|; # ..\n..
yuuji@291: p; # Print whole "table" element yuuji@291: s/.*//; # Erase all when done. yuuji@291: x; s|^||; x; # Preppend /table to the next line yuuji@291: } yuuji@291: x; # Back to the newest line yuuji@489: p; # Print rest' | miniul yuuji@489: } yuuji@489: miniul() { yuuji@489: sed -e ' yuuji@489: /^\* / {; # 行頭 "* " yuuji@489: x; s,^,,; # 箇条書を書き切って終わり yuuji@489: H; x yuuji@489: } yuuji@489: x' yuuji@291: } yuuji@179: acclog() ( yuuji@0: # $1=table, $2=rowid yuuji@471: n=${2%%[!-0-9]*} # Remove non-digit chars from $2(should be rowid) yuuji@179: if [ -n "$n" ]; then yuuji@0: now=`date +"%F %T"` yuuji@179: #query "replace into acclog values('$user', '$1', '$n', '$now');" yuuji@278: #query "replace into acclog values('$user', '$1', $n, '$now');" yuuji@278: query "replace into tblaccesses values('$user', '$1', $n, '$now');" yuuji@0: fi yuuji@179: ) yuuji@0: gecos() ( yuuji@431: u=`sqlquote "${1:-$user}"` yuuji@173: query "select gecos from gecoses where name=$u;" yuuji@0: ) yuuji@16: setpar() { yuuji@16: query "replace into par values('$session', '$1', '$2', \"$3\");" yuuji@16: } yuuji@16: replpar() { yuuji@16: query "update par set val=\"$3\" where sessid='$session' and var='$1' and type='$2';" yuuji@16: } yuuji@0: getpar() { yuuji@0: val=`query "select val from par where var='$1' and sessid='$session' $2;"` yuuji@356: ## err getpar/val1: "val=[$val]" yuuji@0: if [ -z "$val" ]; then yuuji@0: val=`query "select val from cookie where var='$1' and sessid='$session' $2;"` yuuji@0: fi yuuji@356: ## err getpar/val2: "val=[$val]" yuuji@0: case "$var" in yuuji@0: owner) yuuji@0: if [ x"$user" = x"$val" ]; then yuuji@0: echo $user; return yuuji@0: elif ismember $user $val; then yuuji@0: echo $val; return yuuji@0: fi ;; yuuji@0: esac yuuji@356: ## err getpar/ret: "val=[$val]" yuuji@0: echo "$val" yuuji@0: } yuuji@0: yuuji@0: getpartype() { yuuji@0: query "select type from par where var='$1' and sessid='$session' $2;" yuuji@0: } yuuji@0: getparcount() { yuuji@0: query "select count(*) from par where var='$1' and sessid='$session' $2;" yuuji@0: } yuuji@0: getparfilename() { yuuji@0: # null if type of $1 is not file yuuji@0: (f=`query "select val from par where var='$1' and sessid='$session' and type='file' $2;"` yuuji@13: [ -n "$f" ] && echo $f) yuuji@0: } yuuji@0: sqlquote() { yuuji@0: (v="$1" yuuji@0: case "$v" in yuuji@0: "") return ;; # null yuuji@0: "X'"*) # quoted hex string yuuji@0: echo $1 ;; yuuji@0: *\"*) # string including dbl-quote" yuuji@0: v=`echo "$v"|sed -e 's/\"/\"\"/g'` yuuji@0: echo "\"$v\"" yuuji@0: return ;; yuuji@0: *.*.*|*-*-*|*[Ee]*[Ee]*|[Ee]*|*[\ -,:-df-~]*) # string yuuji@0: echo "\"$v\"" yuuji@0: return ;; yuuji@0: *) yuuji@0: if expr "$v" : '[-0-9.Ee][-0-9.Ee]*$' >/dev/null 2>&1; then yuuji@0: echo $v # MAYBE numeric, maybe... yuuji@0: else yuuji@0: echo "\"$v\"" yuuji@0: fi ;; yuuji@0: esac) yuuji@0: } yuuji@298: sqlquotestr() ( yuuji@298: case "$1" in yuuji@298: *\'*) v=`echo "$1"| sed "s/'/''/g"` yuuji@298: echo "'$v'" ;; yuuji@298: *) echo "'$1'" ;; yuuji@298: esac yuuji@298: ) yuuji@0: mktempd() { yuuji@11: TMPDIR=$tmpd mktemp -d -t $session yuuji@0: } yuuji@69: getcachedir() { # $1=maintable yuuji@69: if [ -n "$imgcached" ]; then yuuji@231: echo $imgcached/$(echo ${1:-hoge}|md5)/$thumbxy yuuji@69: else yuuji@69: echo $tmpd/$thumbxy yuuji@69: fi yuuji@69: } yuuji@0: getval() { yuuji@0: # $1=table $2=col $3(optional)=condition yuuji@0: case `gettbl_coltype "/$1/$2"` in yuuji@0: user|author) # author added 2015-06-18 for article(author) yuuji@0: echo "$user" ;; yuuji@0: stamp|datetime) yuuji@0: date "+%F %T" ;; yuuji@0: serial) yuuji@218: (s=`getpar $2` yuuji@0: if [ -n "$s" ]; then echo $s; else echo "`date +%s`x$$"; fi) ;; yuuji@0: *) yuuji@0: getpar "$2" "$3";; yuuji@0: esac yuuji@0: } yuuji@0: yuuji@0: getvalquote() { yuuji@0: # $1=table $2=col $3(optional)=condition yuuji@0: (v=`getval "$@"` yuuji@0: case "$v" in yuuji@0: "") echo NULL ;; yuuji@0: *) sqlquote "$v" ;; yuuji@0: esac) yuuji@0: } yuuji@0: getparquote() { yuuji@431: sqlquote "`getpar $1`" yuuji@0: } yuuji@78: getbinbyid() { yuuji@78: # $1=tbl $2=col $3=rowid $4=tmpdirForBinary yuuji@78: yuuji@78: } yuuji@0: getvalbyid() { yuuji@0: # $1=tbl $2=col $3=rowid $4=tmpdirForBinary yuuji@0: # If two or more values found, save them to $tmpd/${column}.$N and yuuji@0: # store the number of files into $tmpd/${column}.count and yuuji@0: # their each rowid stored into $tmpd/${column}.$N.rowid. yuuji@81: ## err gtb-$1=`gettblcols $1`, tbl=$1, col=$2, '$3'=$3 yuuji@81: yuuji@0: (for c in `gettblcols $1`; do yuuji@0: if [ x"$2" = x"$c" ]; then yuuji@0: ###sq $db "select $2 from $1 where rowid=$3" yuuji@0: query "select $2 from $1 where rowid=$3;" yuuji@0: return yuuji@0: fi yuuji@0: done yuuji@231: rowid=$3 yuuji@0: pk=`gettblpkey $1` yuuji@0: key=`query "select $pk from $1 where rowid=$3;"` yuuji@33: getkey="(select $pk from $1 where rowid=$3)" yuuji@388: td=${4:-$tmpd} yuuji@388: [ -d $td ] || mkdir -p $td yuuji@0: ### err "select $pk from $1 where rowid=$3" - key=$key '$4(tmp)'=$4 yuuji@0: for kt in s m; do yuuji@0: t=${1}_$kt yuuji@0: for c in `gettbl_${kt}_cols $1`; do yuuji@0: vcount=1 # count(val) yuuji@0: if [ x"$2" = x"$c" ]; then yuuji@33: #### cond="$t where $pk=\"$key\" and key=\"$c\"" #2015-07-22 yuuji@33: cond="$t where $pk=$getkey and key=\"$c\"" yuuji@3: val=`query "select val from $cond limit 1;"` yuuji@3: type=`query "select type from $cond limit 1;"` yuuji@0: if [ $kt = m ]; then yuuji@0: ###vcount=`sq $db "select count(val) from $cond"` yuuji@0: # Reset val to store filenames if type is string yuuji@0: val=`query "select val from $cond and type like 'file:%' order by rowid;"` yuuji@59: err gvb1-sql: "select count(val) from $cond;" yuuji@0: vcount=`query "select count(val) from $cond;"` yuuji@0: echo $vcount > $td/$c.count yuuji@0: i=0 yuuji@326: ## err gvbid: i=$i vcount=$vcount yuuji@0: while [ $i -lt $vcount ]; do yuuji@0: slice="order by rowid limit 1 offset $i" yuuji@0: i=$((i+1)) yuuji@0: fn=$c.$i yuuji@113: err td=$td, fn=$fn, type=$type, val="[$val]" yuuji@0: case $type in yuuji@0: file:*) yuuji@0: #file=$td/$val yuuji@326: r_f=`query "select rowid||'//'||val from $cond $slice;"` yuuji@326: f_rid=${r_f%%//*} yuuji@326: file=$td/${r_f##*//} yuuji@47: # FOR SPEED: Skip file generation if imgcache exists yuuji@326: [ -s "$file" -a -s "$td/$fn.rowid" -a -s "$file.rowid" ] \ yuuji@326: && [ x"$f_rid" = x"`cat $td/$fn.rowid`" ] \ yuuji@326: && continue yuuji@78: # err gvbid-get="select quote(bin) from $cond $slice;" yuuji@326: ## err output: "fn=[$fn] file=[$file]" yuuji@326: sq $db< "$file" yuuji@326: .output '$td/$fn.rowid' yuuji@0: select rowid from $cond $slice; yuuji@326: .output '$td/$fn' yuuji@0: select val from $cond $slice; yuuji@326: .output '$td/${fn}.content-type' yuuji@0: select substr(type, 6) from $cond $slice; yuuji@0: .output stdout yuuji@0: select quote(bin) from $cond $slice; yuuji@0: EOF yuuji@131: ## err gvbid-get2: "`ls -lF $file`" yuuji@3: ## err i=$i - file=$file rowid=`cat $td/$fn.rowid` yuuji@326: cp "$td/$fn.rowid" "$file.rowid" 2>&3 # for convenience yuuji@326: cp "$file" "$file.orig" 2>&3 yuuji@326: ls -lh "$file" | yuuji@326: awk '{print $5"B"}'|sed 's/BB/B/' > "$file.size" yuuji@326: case "$type" in yuuji@326: *:[Ii]mage*) mogrify -geometry $thumbxy "$file" ;; yuuji@0: ### ここのアイコンを増やしたい yuuji@0: *|*:[Aa]pplication*) yuuji@0: convert -geometry $thumbxy $imgdir/file-icon.png \ yuuji@326: png:- > "$file" yuuji@0: ;; yuuji@0: esac yuuji@0: ;; yuuji@0: *) yuuji@0: sq $db< "$file" yuuji@326: ##@@## -- echo ${type#file:} > "$file.content-type" yuuji@0: case $type in yuuji@326: *:[Ii]mage*) mogrify -geometry $thumbxy "$file" ;; yuuji@0: *:[Aa]pplication*) yuuji@0: convert -geometry $thumbxy $imgdir/file-icon.png \ yuuji@0: png:- > $file ;; yuuji@0: esac yuuji@0: fi yuuji@0: done yuuji@0: ;; yuuji@0: esac yuuji@0: fi yuuji@0: echo "$val" # Keep newlines by "" yuuji@0: return yuuji@0: fi yuuji@0: done yuuji@0: done) yuuji@0: } yuuji@0: getvalbypkey() ( yuuji@0: # $1=tbl $2=col $3=pkey $4=tmpdirForBinary yuuji@0: pk=`gettblpkey $1` yuuji@0: rowid=`query "select rowid from $1 where $pk='$3';"` yuuji@0: getvalbyid "$1" "$2" $rowid $4 yuuji@0: ) yuuji@0: getvalbycond() { yuuji@0: # $1=tbl $2=col $3=SQL-Condition yuuji@0: ###rowid=`sq $db "select rowid from $1 where $3"` yuuji@0: rowid=`query "select rowid from $1 where $3;"` yuuji@0: if [ -n "$rowid" ]; then yuuji@0: getvalbyid "$1" "$2" $rowid "$4" yuuji@0: fi yuuji@0: } yuuji@0: getpwfield() { yuuji@0: # getpwfield user column yuuji@0: # val=`sqlite3 $db "select $2 from passwd where name='$1' $3"` yuuji@0: val=`getvalbycond user $2 "name='$1'"` yuuji@0: if [ -n "$val" ]; then yuuji@0: echo "$val" yuuji@0: return 0 yuuji@0: else yuuji@0: return 1 yuuji@0: fi yuuji@0: } yuuji@0: encode() { yuuji@0: if [ -z "$sha1" ]; then yuuji@0: if type sha1 >/dev/null 2>&1; then yuuji@0: sha1=sha1 yuuji@0: elif type sha1sum >/dev/null 2>&1; then yuuji@0: sha1=sha1sum yuuji@0: elif type gsha1sum >/dev/null 2>&1; then yuuji@0: sha1=gsha1sum yuuji@0: fi yuuji@0: fi yuuji@0: $sha1 "$@" | cut -d' ' -f1 yuuji@0: } yuuji@322: enjpeg() { yuuji@322: if [ -z "$cjpeg" ]; then yuuji@322: if type cjpeg >/dev/null 2>&1; then yuuji@322: cjpeg="cjpeg" yuuji@322: else yuuji@322: cjpeg="convert - jpeg:-" yuuji@322: fi yuuji@322: fi yuuji@322: $cjpeg "$@" yuuji@322: } yuuji@0: mycrypt() ( yuuji@0: key=$1 salt=$2 yuuji@0: err \$2=$2 yuuji@0: case $2 in yuuji@0: '$'*'$'*) salt=${salt#\$4\$} yuuji@0: salt=${salt%\$*} ;; yuuji@0: esac yuuji@0: echo -n '$4$'"$salt"'$' yuuji@144: echo "$salt$key" | encode || exit 1 # Abort if fail to call encode yuuji@0: ) yuuji@0: hexize() { yuuji@0: if [ -z "$hexize" ]; then yuuji@0: if type xxd >/dev/null 2>&1; then yuuji@0: hexize="xxd -p" yuuji@0: else yuuji@8: hexize_hd() { yuuji@8: hexdump -ve '1/1 "%.2x"' yuuji@8: } yuuji@8: hexize="hexize_hd" yuuji@0: fi yuuji@0: fi yuuji@326: cat "$@" | $hexize | tr -d '\n' yuuji@0: } yuuji@8: unhexize() { yuuji@8: if [ -z "$unhex" ]; then yuuji@8: if type xxd >/dev/null 2>&1; then yuuji@8: unhex="xxd -p -r" yuuji@8: elif type perl >/dev/null 2>&1; then yuuji@8: cat >$tmpd/unhex.pl</\>/g" yuuji@155: } yuuji@0: enascii() { yuuji@0: if [ -z "$enascii" ]; then yuuji@0: if type kakasi >/dev/null 2>&1; then yuuji@0: enascii="kakasi -Ha -Ka -Ja -Ea -ka" yuuji@0: else yuuji@0: enascii_now=`date +%FT%T` yuuji@0: enascii_sed() { yuuji@0: nkf -Z0Z1Z2 \ yuuji@0: | sed -e "s/^/$enascii_now/" -e "s|[^-0-9.A-z/,()_=]|x|g" yuuji@0: } yuuji@0: enascii="enascii_sed" yuuji@0: fi yuuji@0: fi yuuji@0: cat "$@" | $enascii yuuji@0: } yuuji@154: size_h() { yuuji@164: i="$1" oi=$1 yuuji@164: set -- B B KB MB GB TB yuuji@164: while [ $((i)) -gt 9 -a -n "$1" ]; do # -gt 9 means $oi > 1024 yuuji@154: oi=$i yuuji@154: i=$((i/1024)) yuuji@164: shift yuuji@154: done yuuji@154: echo ${oi}$1 yuuji@154: } yuuji@0: gettblconf() { yuuji@0: if [ -z "$tconfs" ]; then yuuji@0: ## tconfs=`sq $db \ yuuji@0: tconfs=`query \ yuuji@0: "select tbl||'/'||col||'='||keytype||'/'||objtype from $conftbl;"` yuuji@0: fi yuuji@0: # /tb1/col1=p/text /tb1/col2=s/text /tb1/col3=m/image /tb2/col1=p/text ... yuuji@0: } yuuji@0: gettblkeys() { yuuji@0: # $1=tbl yuuji@0: gettblconf yuuji@0: echo "$tconfs" | fgrep "/$1/" | \ yuuji@0: (type="" keys="" fks="" cols="" scols="" mcols="" hcols="" yuuji@0: while IFS='=' read tc conf; do # tc=/tb1/col1 conf=s/text yuuji@0: col=${tc##*/} type=${conf%%/*} yuuji@0: case $type in yuuji@0: *p*) yuuji@0: cols=$cols"${cols:+:}$col" yuuji@0: keys=$keys"${keys:+:}$col" ;; yuuji@0: *f*) cols=$cols"${cols:+:}$col" yuuji@0: fks=$fks"${fks:+:}$col" ;; yuuji@0: *m*) mcols=$mcols"${mcols:+:}$col" ;; yuuji@0: *s*) scols=$scols"${scols:+:}$col" ;; yuuji@0: esac yuuji@0: case $type in yuuji@0: *h*) hcols=$hcols"${hcols:+:}$col" ;; yuuji@0: esac yuuji@0: done yuuji@0: echo "_keys=$keys _fks=$fks _cols=$cols _scols=$scols _mcols=$mcols _hcols=$hcols") yuuji@0: } yuuji@0: gettblpkey() { yuuji@0: # $1=tbl yuuji@0: gettblkeys $1 | cut -d ' ' -f 1 | sed -e 's/.*=//' -e 's/:/ /g' yuuji@0: } yuuji@0: gettblfkey() { yuuji@0: (x=`gettblkeys $1` yuuji@0: x=${x#*_fks=} # cut before "_fks=" including yuuji@0: echo ${x%% *} | tr ':' ' ') yuuji@0: } yuuji@0: gettblcols() { yuuji@0: (x=`gettblkeys $1` yuuji@0: x=${x#*_cols=} # cut before "_cols=" including yuuji@0: echo ${x%% *} | tr ':' ' ') yuuji@0: } yuuji@0: gettbl_s_cols() { yuuji@0: (x=`gettblkeys $1` yuuji@0: x=${x#*_scols=} # cut before "_scols=" including yuuji@0: echo ${x%% *} | tr ':' ' ') yuuji@0: } yuuji@0: gettbl_m_cols() { yuuji@0: (x=`gettblkeys $1` yuuji@0: x=${x#*_mcols=} # cut before "_mcols=" including yuuji@0: echo ${x%% *} | tr ':' ' ') yuuji@0: } yuuji@0: gettbl_h_cols() { yuuji@0: (x=`gettblkeys $1` yuuji@0: x=${x#*_hcols=} # cut before "_hcols=" including yuuji@0: echo ${x%% *} | tr ':' ' ') yuuji@0: } yuuji@0: gettbl_coltype() ( yuuji@0: gettblconf yuuji@0: x=`echo "$tconfs"|fgrep $1=` yuuji@0: x=${x#*=} # cut before = yuuji@0: echo ${x#*/} # cut before p/ including yuuji@0: ) yuuji@0: is_hidden() { yuuji@0: # $1=Tbl $2=col yuuji@0: gettblconf yuuji@0: x=`echo "$tconfs"|fgrep /$1/$2=` yuuji@0: x=${x#*=} # cut before = yuuji@0: x=${x%%/*} # cut after / yuuji@0: case $x in yuuji@0: *h*) return 0 ;; yuuji@0: *) return 1 ;; yuuji@0: esac yuuji@0: } yuuji@0: yuuji@0: dbsetbyid() { yuuji@0: # $1=tbl $2=id $3=col $4=val/filename - &optional - $5=content-type yuuji@0: (t0=$1 t=$1 p=$2 c=$3 yuuji@0: tsc=$t/$c val=$4 yuuji@386: quotedp=$(sqlquotestr "$p") yuuji@0: unset primary update yuuji@0: gettblconf yuuji@0: #err tsc=$tsc, tconfs="$tconfs" yuuji@0: conf=`echo "$tconfs"|fgrep "$tsc"=` yuuji@0: #err conf=$conf yuuji@0: case ${conf#*=} in yuuji@0: p*) primary=1 ;; yuuji@0: f*) update=1 ;; yuuji@0: u*) ;; yuuji@0: m*) t=${t}_m;; yuuji@0: s*) t=${t}_s;; yuuji@0: esac yuuji@0: #err t=$t yuuji@386: type=string fn="" yuuji@0: case $conf in yuuji@0: */password) yuuji@0: type=encoded ### val=`echo $val|encode` yuuji@0: ;; yuuji@0: */image*|*/document*) yuuji@326: type=`file --mime-type - < "$val" | cut -d' ' -f2` yuuji@326: bin="X'`hexize "$val"`'" yuuji@0: ;; yuuji@0: esac yuuji@0: pkey=`echo "$tconfs"|grep "${t0}/.*=p"|sed 1q` yuuji@0: pkey=${pkey#/*/} # cut $tbl/ yuuji@0: pkey=${pkey%=p/*} # cut =p/... -> primary key yuuji@0: if [ "$primary" ]; then yuuji@0: nulls=`echo "$tconfs"|grep "$t/.*=[fu]/"|sed 's/^.*/, NULL/'|tr -d '\n'` yuuji@0: ###sq $db "replace into $t values(\"$val\"$nulls)" yuuji@0: query "replace into $t values(\"$val\"$nulls);" yuuji@0: elif [ "$update" ]; then yuuji@386: query "update $1 set $c=\"$val\" where $pkey=$quotedp;" yuuji@0: else yuuji@386: query "replace into $t values($quotedp, \"$c\", \"$type\", \"$val\", \"$bin\");" yuuji@0: fi yuuji@0: ) yuuji@0: } yuuji@3: expire() ( yuuji@3: at="${1:-$timeout}" yuuji@3: FMT="${2:-%F %T}" yuuji@6: TZ=GMT gdate -d "$at" +"$FMT" yuuji@3: ) yuuji@0: addsession() { yuuji@0: # expireをセット yuuji@0: # loginの先にどの画面に行くかの状態遷移表書式を決める yuuji@0: expire=`expire ${2:-"+1min"}` yuuji@309: query "replace into session values('$1', '$expire');" yuuji@0: # Remove old session parameters yuuji@0: now=`expire now` yuuji@309: query "delete from session where expire < '$now';" yuuji@0: } yuuji@3: gencookie() ( yuuji@3: for kv; do yuuji@3: expire="`expire '' '%a, %d-%b-%Y %H:%M:%S GMT'`" yuuji@3: echo "Set-Cookie: $kv; expires=$expire" yuuji@3: done yuuji@3: ) yuuji@0: contenttype() { yuuji@0: echo "Content-type: ${1:-text/html; charset=utf-8}" yuuji@0: contenttype() {} # Only need to work once yuuji@0: } yuuji@0: putheader() { yuuji@0: yuuji@0: } yuuji@0: putfooter() { yuuji@187: _m4 -D_TITLE_="${TITLE:-$myname}" $layout/footer.m4.html yuuji@0: } yuuji@3: getcookie() ( yuuji@0: for kv in `echo $HTTP_COOKIE|sed 's/[;, ]/ /g'`; do yuuji@0: k="${kv%%=*}" yuuji@0: v="`echo ${kv#*=}|nkf -Ww -mQ|sed -e 's/\"/\"\"/g'`" yuuji@3: query "replace into cookie values('$session', '$k', 'string', \"$v\");" yuuji@0: done yuuji@3: ) yuuji@0: genrandom() { yuuji@0: # $1=columns (default: 10) yuuji@468: dd if=/dev/urandom count=1 2>/dev/null|nkf -MB \ yuuji@468: | tr -d '+='|fold -w${1:-10}|sed -n 10p yuuji@0: } yuuji@268: genserial() { yuuji@268: echo $((($(date +%s)-1433084400)/10))c$$ yuuji@268: } yuuji@0: smail() { yuuji@166: # smail rcpts subj (file) yuuji@300: # $SMAIL_TO <- Recipient value of To: header yuuji@300: # $MAIL_FROM <- From: header value yuuji@300: from=`echo "${MAIL_FROM:-$admin}"|nkf -jM|tr -d '\n'` yuuji@411: rcpt=`echo $1|tr ' ' '\n'|sort -u|tr '\n' ' '` # uniq and strip newlines yuuji@117: subj=`echo $2|nkf -jM|tr -d '\n'` yuuji@300: (_m4 -D_RCPT_="${SMAIL_TO:-$rcpt}" -D_SUBJ_="\`$subj'" -D_FROM_="$from" $msgdir/mail-header.m4 yuuji@0: cat $3 | nkf -jd ) | sendmail -f $admin $rcpt yuuji@0: } yuuji@0: setviastring() { yuuji@0: table=$1 yuuji@0: oifs="$IFS" yuuji@0: IFS="&" yuuji@0: for us in $2; do yuuji@0: k=${us%%=*} yuuji@0: v="`echo ${us#*=}|tr '%+' '= '|nkf -Ww -mQ|sed -e 's/\"/\"\"/g'`" yuuji@309: query "replace into $table values('$session', '$k', 'string', \"$v\");" yuuji@0: #echo $k=$v yuuji@0: done yuuji@0: IFS="$oifs" yuuji@0: } yuuji@3: checkdomain() ( yuuji@3: # Check the validity of domain by referring DNS yuuji@3: item=$1 yuuji@83: err checkdomain $1 yuuji@83: host ${item#*@} 1>&3 2>&3 yuuji@83: host ${item#*@} >/dev/null 2>&1 yuuji@3: ) yuuji@0: pwcheck() { yuuji@0: # $1=passwd yuuji@0: dbpswd=`getpwfield $user pswd` yuuji@0: encpswd=`mycrypt "$1" "$dbpswd"` yuuji@356: ## err user=$user, pswd=$1, db=$dbpswd, enc=$encpswd yuuji@0: [ x"$dbpswd" = x"$encpswd" ] yuuji@0: } yuuji@0: mypwhash() { yuuji@0: mycrypt `cat` `genrandom 5` yuuji@0: } yuuji@0: wasureta() { yuuji@0: user=$1 yuuji@83: if ! checkdomain $user; then yuuji@83: contenttype; echo yuuji@187: _m4 -D_TITLE_='Invalid email' $layout/title-only.html yuuji@83: echo "ユーザ名($user)には正しいメイルアドレスが必要です。" | html p yuuji@83: putfooter yuuji@0: exit 0 yuuji@0: fi yuuji@0: newpswd=`genrandom` # newsalt=`genrandom 5` yuuji@0: #encpswd=`mycrypt "$newpswd" "$newsalt"` yuuji@0: encpswd=`echo $newpswd|mypwhash` yuuji@0: dbsetbyid user $user pswd "$encpswd" yuuji@100: # Avoid $user substitution with m4, because $url comes from user input. yuuji@187: _m4 -D_PSWD_="$newpswd" -D_URL_="$url" -D_ADMIN_="$admin" \ yuuji@117: $msgdir/mail-newaccount.m4 \ yuuji@100: | sed "s/_USER_/$user/g" \ yuuji@0: | smail $user "New Account" yuuji@0: } yuuji@0: checkauth() { yuuji@0: user=`getpar user` yuuji@0: skc=`getpar skey` # from cookie yuuji@0: [ -z "$user" ] && return 3 yuuji@0: skey="`getpwfield $user skey`" yuuji@0: if [ -n "$skey" ]; then yuuji@0: if [ x"$skey" = x"$skc" ]; then yuuji@0: return 0 yuuji@0: fi yuuji@0: fi yuuji@0: pswd=`getpar pswd` yuuji@298: quser=`sqlquotestr "$user"` yuuji@298: dbuser=`query "SELECT name FROM user WHERE name=$quser;"` yuuji@298: if [ -z "$dbuser" ]; then yuuji@299: return 1 yuuji@298: elif [ x"$pswd" = x"wasureta" ]; then yuuji@0: wasureta $user yuuji@0: return 1 # wasureta error yuuji@0: fi yuuji@0: # dbpswd="`sq $db \"select pswd from passwd where name='$user'\"`" yuuji@0: # putheader; echo; echo user=$user, db=$dbpswd, enc=$encpswd yuuji@0: if pwcheck "$pswd"; then yuuji@0: newsession=`genrandom 50` yuuji@0: dbsetbyid user $user skey "$newsession" yuuji@474: dbsetbyid user $user login "`date '+%F %T'`" yuuji@0: gencookie "user=$user" "skey=$newsession" yuuji@0: return 0 yuuji@0: fi yuuji@0: return 2 # Password mismatch yuuji@0: } yuuji@0: showlogin() { yuuji@0: args=`echo $myargs|tr ' ' '+'` yuuji@187: _m4 -D_SYSNAME_="Welcome" -D_MYNAME_="$myname${args+?}$args" \ yuuji@0: $layout/login.m4.html yuuji@0: exit 0 yuuji@0: } yuuji@0: dologin() { yuuji@0: checkauth yuuji@0: st=$? yuuji@0: if [ $st != 0 ]; then yuuji@0: contenttype; echo yuuji@187: _m4 -D_USER_="$user" -D_URL_="$url" -D_ADMIN_="$admin" \ yuuji@117: $msgdir/login-fail-$st.m4.html yuuji@0: showlogin # and EXIT yuuji@0: fi yuuji@0: } yuuji@67: yuuji@67: # Do instant jobs here yuuji@163: dbsetup yuuji@187: trap cleanup INT HUP EXIT TERM PIPE yuuji@163: # trap cleanup INT HUP yuuji@67: yuuji@67: err() { yuuji@67: echo "$@" 1>&3 yuuji@67: } yuuji@67: yuuji@0: cgiinit() { yuuji@0: session=`date +%F-$$` yuuji@0: tmpf=tmp/stream yuuji@11: tmpd=`tmpd=$tmpdir mktempd` yuuji@0: tmpfiles=$tmpfiles" $tmpd" yuuji@0: addsession $session yuuji@0: getcookie yuuji@0: case "$REQUEST_METHOD" in yuuji@0: get|GET) s="$QUERY_STRING" ;; yuuji@13: post|POST) ## dd count=$CONTENT_LENGTH bs=1 of=$tmpf 2>/dev/null #slow yuuji@137: ## dd bs=$CONTENT_LENGTH count=1 of=$tmpf # NOT working yuuji@13: # cat > $tmpf # too much? yuuji@13: head -c $CONTENT_LENGTH > $tmpf # safe? yuuji@13: (echo CL=$CONTENT_LENGTH; ls -lF $tmpf) 1>&3 yuuji@0: s="`cat tmp/stream`" yuuji@0: tmpfiles=$tmpfiles"${tmpfiles+ }$tmpf" yuuji@0: ;; yuuji@0: esac yuuji@0: case "$CONTENT_TYPE" in yuuji@0: *boundary*) yuuji@0: bndry=${CONTENT_TYPE#*boundary=} yuuji@13: #for us in `LC_CTYPE=C ./mpsplit.rb "$bndry" $tmpd < $tmpf` yuuji@13: for us in `LC_CTYPE=C ./mpsplit.pl "$bndry" $tmpd < $tmpf` yuuji@0: do yuuji@0: k=${us%%\=*} yuuji@0: #echo u=$us yuuji@11: #v="`echo ${us#*=}|nkf -Ww -mQ|sed -e 's/\"/\"\"/g'`" yuuji@16: v="`echo ${us#*=}|unhexize|sed -e 's/\"/\"\"/g'`" yuuji@0: # err k=$k v=$v yuuji@0: case "$k" in yuuji@0: *:filename) yuuji@0: type='file'; k=${k%:filename} yuuji@326: # DO NOT ALLOW Space and '|' in file names yuuji@326: newv=`echo "$v"|sed 's/[ \|]/X/g'` yuuji@326: if [ x"$v" != x"$newv" ]; then yuuji@329: : yuuji@326: fi yuuji@326: # (echo k=$k v="[$v]"; ls -lF "$tmpd/$v"; file --mime-type "$tmpd/$v") 1>&3 yuuji@326: case `file --mime-type - < "$tmpd/$v"|cut -d' ' -f2` in yuuji@132: [Ii]mage/x-xcf) yuuji@326: bzip2 "$tmpd/$v" yuuji@132: v=${v}.bz2 yuuji@132: ;; yuuji@132: [Ii]mage/x-*|*/vnd.*) ;; yuuji@0: [Ii]mage/*) yuuji@326: mogrify -resize $maximagexy'>' "$tmpd/$v" yuuji@0: ;; yuuji@0: esac yuuji@0: ;; yuuji@0: *) yuuji@0: type='string' yuuji@0: ;; yuuji@0: esac yuuji@16: #sq $db "replace into par values('$session', '$k', '$type', \"$v\")" yuuji@16: setpar "$k" "$type" "$v" yuuji@0: done yuuji@0: ;; yuuji@0: *) yuuji@0: setviastring par "$s" yuuji@0: ;; yuuji@0: esac yuuji@0: } yuuji@58: email4group() { yuuji@59: # Get for-$1=group email address(es) for $2...=users yuuji@58: qgrp=`sqlquote "$1"`; shift yuuji@58: users=`for i; do sqlquote "$i"; done` yuuji@58: users=`echo $users|tr ' ' ','` yuuji@56: sql="select coalesce(s.val, g.user) from grp_mem g yuuji@58: left join grp_mem_s s on g.gname=s.gname and g.user=s.user yuuji@58: and s.key='email' yuuji@58: where g.gname=$qgrp and g.user in ($users);" yuuji@56: query "$sql" yuuji@58: } yuuji@59: email4groupbyuid() { yuuji@59: # Get for-$1=group email address(es) for $2...=user-ids yuuji@59: qgrp=`sqlquote "$1"`; shift yuuji@59: uids=`echo "$@"` yuuji@59: uids=`echo $uids|tr ' ' ','` yuuji@240: sql="WITH yuuji@240: grpemails AS ( yuuji@240: SELECT gname, user, val email yuuji@240: FROM grp_mem NATURAL JOIN grp_mem_s yuuji@240: WHERE key='email' AND gname=$qgrp), yuuji@240: useremails AS ( yuuji@240: SELECT user.rowid rid, user.name, val email yuuji@240: FROM user yuuji@240: LEFT JOIN user_s yuuji@240: ON user.name=user_s.name AND user_s.key='email') yuuji@240: SELECT DISTINCT coalesce(g.email, u.name) yuuji@240: FROM useremails u LEFT JOIN grpemails g yuuji@240: ON u.name=g.user yuuji@240: WHERE u.rid in ($uids);" yuuji@356: ## err email4gByid `echo $sql` yuuji@59: query "$sql" yuuji@59: } yuuji@443: collectmembersbyid() { yuuji@443: # Collect user names of group specified by grid yuuji@443: rid=${1%%[!0-9]*} # Cleaning yuuji@443: query "SELECT user FROM grp_mem \ yuuji@443: WHERE gname=(SELECT gname FROM grp WHERE rowid=$rid);" yuuji@443: } yuuji@443: collectmembersbyid() { yuuji@443: # Collect user names of group name yuuji@443: qgrp=`sqlquote "$1"` yuuji@443: query "SELECT user FROM grp_mem WHERE gname=$qgrp;" yuuji@443: } yuuji@443: collectgecosesbyid() { yuuji@443: # Collect user gecoses of group yuuji@443: rid=${1%%[!0-9]*} # Cleaning yuuji@443: query<<-EOF yuuji@443: SELECT gecos yuuji@443: FROM gecoses yuuji@443: WHERE name IN (SELECT user FROM grp_mem yuuji@443: WHERE gname=(SELECT gname FROM grp WHERE rowid=$rid)); yuuji@443: EOF yuuji@443: } yuuji@47: collectemail() ( yuuji@0: # Collect email addresses for group $1 yuuji@222: # If $TEAM is set, filter by team name yuuji@222: # If $EXCEPT is set as username(s) delimited by comma, yuuji@222: # remove $EXCEPT from list: ....NOT IN ($EXCEPT) yuuji@47: for e; do yuuji@47: if isuser "$e"; then yuuji@222: em=`query "select val from user_m where name='$e' and key='email';"` yuuji@222: [ -n "$em" ] && echo "$em" || echo "$e" yuuji@47: else yuuji@56: qgrp=`sqlquote "$e"` yuuji@222: if [ -z "$TEAM" ]; then yuuji@222: gmem="grp_mem" yuuji@222: else yuuji@222: tm=`sqlquote "$TEAM"` yuuji@222: gmem="(SELECT gname, user FROM grp_mem_m WHERE gname='$e' AND key='team' AND val=$tm)" yuuji@222: fi yuuji@222: ex=${EXCEPT:+"AND g.user NOT IN ($EXCEPT)"} yuuji@62: sql="select coalesce(s.val,um.val,g.user) from yuuji@222: $gmem g left join grp_mem_s s yuuji@26: on g.gname=s.gname and g.user=s.user and s.key='email' yuuji@62: left join user_m um on g.user=um.name and um.key='email' yuuji@222: where g.gname=$qgrp $ex;" yuuji@356: ## err CollectEmail: `echo "$sql"` yuuji@47: query "$sql" yuuji@47: fi yuuji@47: done yuuji@47: ) yuuji@0: sendinvitation() ( yuuji@0: # $1=email yuuji@26: iss="invite-`date +%s`-$user" yuuji@117: addsession $iss +${memoplimitdays}days # 1 week due date yuuji@0: query "replace into par values('$iss', 'invite', 'string', \"$1\");" yuuji@0: gecos=`gecos` yuuji@0: name=$user"${gecos:+($gecos)}" yuuji@0: regist="$urlbase?reg+$iss" yuuji@187: _m4 -D_URL_="$urlbase" \ yuuji@187: -D_USER_="$name" \ yuuji@187: -D_EMAIL_="$1" \ yuuji@187: -D_REGIST_="$regist" \ yuuji@187: -D_ADMIN_="$admin" \ yuuji@187: $msgdir/mail-invite.m4 \ yuuji@0: | smail $1 "BBSへの御招待" yuuji@0: return 0 yuuji@0: ) yuuji@0: emaildomaincheck() { yuuji@0: case "$1" in yuuji@0: *@*@*) echo "無効なアドレスです"; return 1 ;; yuuji@0: *@*) yuuji@0: local=${1%@*} domain=${1#*@} yuuji@0: if ! host $domain >/dev/null 2>&1; then yuuji@0: echo "ドメイン($domain)が見付かりません。" yuuji@0: return 2 yuuji@0: fi yuuji@0: return 0 yuuji@0: ;; yuuji@0: *) echo "正しいメイルアドレスをいれてください"; return 3 ;; yuuji@0: esac yuuji@0: } yuuji@0: invite() { yuuji@0: email=`getpar email` yuuji@0: case $email in yuuji@0: *@*@*) repo="無効なアドレスです" ;; yuuji@0: *@*) yuuji@0: local=${email%@*} domain=${email#*@} yuuji@0: if ! repo=`emaildomaincheck $email`; then yuuji@0: repo="招待アドレスのエラー: $repo" yuuji@0: elif [ -n "`query \"select * from user where name='$email';\"`" ]; then yuuji@0: repo="$email さんは既に加入しています。" yuuji@0: elif sendinvitation $email; then yuuji@0: repo="アドレス($email)宛に案内を送信しました。" yuuji@0: fi ;; yuuji@0: "") repo="招待したい人のメイルアドレスを入力してください。" ;; yuuji@0: *) repo="無効なアドレスです" ;; yuuji@0: esac yuuji@26: addr=`query "select val from par where sessid like 'invite-%-$user';"` yuuji@26: if [ -n "$addr" ]; then yuuji@26: susp="

招待済みで加入待ちのアドレス

$addr
" yuuji@26: fi yuuji@187: _m4 -D_TITLE_="招待" -D_REPORT_="\`$repo'" -D_ACTION_="?invite" \ yuuji@187: -D_BODYCLASS_="default" -D_SUSPENDED_="$susp" \ yuuji@187: $layout/html.m4.html $layout/invite.m4.html yuuji@0: } yuuji@0: regist() { yuuji@0: # $1=session-id-for-invitation yuuji@187: _m4 -D_TITLE_="Invitation" $layout/html.m4.html yuuji@0: if [ -z "$1" ]; then yuuji@61: echo "bye bye" | html p yuuji@0: reutrn yuuji@0: fi yuuji@0: email=`session=$1 getpar invite` yuuji@0: if [ -z "$email" ];then yuuji@0: cat<無効な招待状チケットです。

yuuji@0:

招待状の有効期限(1週間)が切れているか、チケット番号が異なっています。 yuuji@0: 加入している人に、再度招待してもらいましょう。

yuuji@0: EOF yuuji@65: return yuuji@0: fi yuuji@61: echo "$email さんようこそ" | html h2 yuuji@0: query "replace into user values('$email');" yuuji@0: # Fake login password to wasureta yuuji@0: query "replace into par values('$session', 'pswd', 'string', 'wasureta'), yuuji@0: ('$session', 'user', 'string', '$email');" yuuji@0: wasureta $email yuuji@61: echo "このアドレスに初期パスワードを送信しました。" |html p yuuji@61: echo "新着メイルを確認してログインしてください。" |html p yuuji@26: addsession $1 # for removal after 1 minute yuuji@187: _m4 -D_SYSNAME_="Initial Login" -D_MYNAME_="$myname?userconf" \ yuuji@187: $layout/login.m4.html yuuji@0: return yuuji@0: } yuuji@222: group_safename() { yuuji@222: # Convert $1 to safe group name yuuji@222: echo "$1" | tr -d '"'"'", yuuji@113: } yuuji@113: groupupdate() { yuuji@78: gname=`getpar gname` yuuji@431: qgname=`sqlquote "$gname"` yuuji@78: if [ -n "$gname" ]; then yuuji@81: # See ALSO same job in showgroup() yuuji@222: newgname=`group_safename "$gname"` yuuji@113: err newgname=$newgname yuuji@78: if [ x"$newgname" != x"$gname" ]; then yuuji@78: err NewGNAME: gname=$newgname yuuji@81: gname=$newgname yuuji@78: echo "使用禁止文字を除去し $gname としました。" | html p yuuji@78: replpar gname string "$gname" yuuji@78: fi yuuji@113: # Name confliction check yuuji@113: parow=`getpar rowid` yuuji@356: ## err parow=$parow yuuji@431: qgname=`sqlquote "$gname"` # Set again in case gname modified yuuji@113: query "BEGIN EXCLUSIVE;" yuuji@356: ## err "select count(gname) from grp where rowid != ${parow:-0} and gname = $qgname;" yuuji@113: count=$(query "select count(gname) from grp where rowid != ${parow:-0} and gname = $qgname;") yuuji@113: if [ $count -gt 0 ]; then yuuji@113: echo "そのグループ名は既にあります。" | html p yuuji@113: query "END;" yuuji@113: return yuuji@113: fi yuuji@123: par2table $formdir/grp.def yuuji@122: query "END TRANSACTION;" yuuji@163: # Remove orphan yuuji@122: : <作成" \ yuuji@384: | html p yuuji@384: fi yuuji@0: } yuuji@79: mems() { yuuji@187: _m4 -D_TITLE_="参加者一覧" -D_BODYCLASS_=listmember $layout/html.m4.html yuuji@79: kwd=`getpar kwd` yuuji@79: listmember $kwd yuuji@79: } yuuji@79: grps() { yuuji@187: _m4 -D_TITLE_="グループ一覧" -D_BODYCLASS_=listgroup $layout/html.m4.html yuuji@79: kwd=`getpar kwd` yuuji@79: listgroup $kwd \ yuuji@187: | _m4 -D_DUMPTABLE_="syscmd(cat)" \ yuuji@187: -D_TITLE_="グループ関連操作" \ yuuji@187: -D_FORM_="新規グループ作成" \ yuuji@187: $layout/form+dump.m4.html yuuji@79: } yuuji@79: grp() { # $1=group-rowid yuuji@79: gpg=`getpar grp` yuuji@79: grid=${1:-$gpg} yuuji@79: grp=`getgroupbyid "$grid"` yuuji@79: ## . ./s4-blog.sh yuuji@79: jg=`getpar joingrp` yuuji@79: if [ -n "$jg" ]; then yuuji@79: [ -n "$jg" -a -n "$grp" ] && yuuji@79: joingrp "$grp" "$user" "$jg" "`getpar email`" yuuji@79: fi yuuji@259: htmlheader=$layout/html.m4.html yuuji@79: showgroup "$grid" yuuji@79: } yuuji@343: sql4interestblogs() { yuuji@343: cat< '$deftime' yuuji@471: GROUP BY id yuuji@175: ), blog_title_owner as ( yuuji@343: SELECT blg.rid brid, id, yuuji@175: max(case key when 'title' then val end) title, yuuji@175: max(case key when 'owner' then val end) owner yuuji@343: FROM interestblogs blg, blog_s using(id) group by id yuuji@175: ), blogall as ( yuuji@471: SELECT * FROM blog_title_owner b JOIN article_ctime ac ON b.id=ac.blogid yuuji@343: ), news as ( yuuji@471: SELECT brid, bl.id blid, bl.title, ctime, yuuji@471: coalesce(al.time, '$deftime') atime, yuuji@471: count(bl.id) "新着", bl.author yuuji@471: FROM blogall bl yuuji@471: LEFT JOIN yuuji@471: (SELECT * FROM acclog WHERE user='$user' AND tbl='blog') al yuuji@471: ON bl.brid=al.tblrowid yuuji@471: WHERE atime < bl.ctime yuuji@471: GROUP by bl.id ORDER BY ctime desc,"新着" desc, bl.id yuuji@343: LIMIT 10 yuuji@343: ) SELECT brid LINK, "新着", yuuji@343: (SELECT count(*) FROM article WHERE blogid=blid) "総数", yuuji@343: ctime, title, yuuji@343: (SELECT gecos FROM gecoses WHERE name=author) gecos yuuji@343: FROM news; yuuji@175: EOF yuuji@175: } yuuji@175: yuuji@243: search_form() { yuuji@301: help="(1)空白区切りの単語で本文検索 yuuji@302: (2)@YYYY-MM-DD 日付け(シェルパターン可)で日付け検索 yuuji@352: @2016-0[1-6] → 2016年1月から6月 yuuji@352: @>2016-01 @<2016-02-15 → 2016年1月から2月14日までの期間 yuuji@352: @week → 最近一週間 yuuji@302: (3)#番号 で記事ID検索 yuuji@302: (1)と(2)は組み合わせOK yuuji@302: 例: @2016-10-0[1-9] 芋煮 yuuji@445: → 2016年10月上旬でキーワード「芋煮」を含む記事検索 yuuji@445: ※クイズ板は検索対象から外されます。" yuuji@331: auth="" yuuji@331: placeholder="全記事からの検索" yuuji@331: case "$1" in yuuji@331: author=*) yuuji@331: a=`echo "${1#author=}"|htmlescape` yuuji@331: g=`gecos ${1#author=}` yuuji@331: auth="" yuuji@331: placeholder="このユーザの書込検索" yuuji@331: help="★★ $g さんの書き込みから検索します$nl$help" yuuji@331: ;; yuuji@418: grp=*) yuuji@418: a=`echo "${1#grp=}"|htmlescape` yuuji@418: g=`gecos ${1#grp=}` yuuji@418: auth="" yuuji@418: placeholder="このグループからの検索" yuuji@418: ;; yuuji@331: esac yuuji@243: cat<<-EOF yuuji@418:
yuuji@331:
$auth yuuji@301: yuuji@352: ${touchpanel:+

$help

} yuuji@243: yuuji@243:
yuuji@243:
yuuji@243: EOF yuuji@243: } yuuji@243: yuuji@311: imgsrc_cache() ( yuuji@311: # $1 = directory for cache'ing yuuji@322: # $2 = table (user_m or grp_m) yuuji@322: # $3 = keycond (was: condition for choosingowner) yuuji@322: # $4 = size : S = Small, M = Medium, O = Original yuuji@322: dir="$1" tbl="$2" yuuji@322: keycond="$3" yuuji@322: whos="$keycond AND key='profimg' AND type LIKE 'file:image%' yuuji@327: ORDER BY rowid DESC LIMIT 1" yuuji@332: [ -d "$dir" ] || mkdir -p "$dir" yuuji@391: tmpf=$tmpd/imgsrc_cache.$$ yuuji@322: case "$4" in yuuji@322: [Ss]) size=S ;; yuuji@322: [Oo]) size=O ;; yuuji@322: *) size=M ;; yuuji@322: esac yuuji@322: # ImageCache filename storing schema: yuuji@322: # .{key, val}={"profimgcache_S", "$cacheimg_S"} yuuji@312: sql0="SELECT val || '//' || type FROM $tbl WHERE $whos;" yuuji@312: sql1="SELECT hex(bin) FROM $tbl WHERE $whos;" yuuji@311: valtype=`query "$sql0"` yuuji@311: filename=${valtype%%//*} yuuji@311: filetype=${valtype##*//file:} yuuji@339: if [ x"$filename" = x"${filename%.*}" ]; then yuuji@339: # If nor filename extension found, set it to image type yuuji@339: case "$filetype" in yuuji@339: image/*) filename=$filename.${filetype#image/} ;; yuuji@339: esac yuuji@339: fi yuuji@322: cacheimg_S=$dir/S_$filename yuuji@322: cacheimg_M=$dir/M_$filename yuuji@322: cacheimg_O=$dir/$filename yuuji@322: cacheimg=$dir/${size}_$filename yuuji@322: sumfile="$dir/$filename.sum" yuuji@311: sum=`query "$sql1" | tee $tmpf | encode` # encode() is maybe sha1 yuuji@391: if test -s "$sumfile" && [ x"`cat \"$sumfile\"`" = x"$sum" ] \ yuuji@391: && test -s "$cacheimg_S" && test -s "$cacheimg_M" ; then yuuji@391: # if cache is fresh and has the same checksum, yuuji@311: echo "" yuuji@311: else yuuji@391: fifo=`mktemp "$tmpf.fifo.XXXXXXX"` yuuji@391: rm -f $fifo # Safe, because $tmpf is in mktemp dir. yuuji@391: fifo2=$fifo.2 yuuji@391: mkfifo $fifo $fifo2 yuuji@311: fmt=${filename##*.} yuuji@322: ## [[ NOTE ]] yuuji@322: ## a. convert oldimage newimage yuuji@322: ## b. convert oldimage fmt:- | convert - newimage yuuji@322: ## b is much smaller than a yuuji@311: cat $tmpf | unhexize \ yuuji@322: | tee $fifo \ yuuji@392: | convert -define ${fmt}:size=${iconxy_M} \ yuuji@392: -resize ${iconxy_M}'>' - ${fmt}:- \ yuuji@391: | tee $fifo2 \ yuuji@326: | convert - "$cacheimg_M" & yuuji@392: cat $fifo | convert -define ${fmt}:size=${iconxy_S} \ yuuji@392: -resize ${iconxy_S}'>' - ${fmt}:- \ yuuji@326: | convert - "$cacheimg_S" & yuuji@311: printf '%s' "' yuuji@311: echo "$sum" > $sumfile yuuji@311: fi yuuji@322: ## Now preparing cache image, done. yuuji@322: ## Store this information to DB yuuji@322: stbl=${tbl%_m}_s # user_s or grp_s yuuji@322: pkey=${keycond%%=*} # Primary Key name yuuji@322: pval=${keycond#*=} # Primary Key value yuuji@322: query <<-EOF yuuji@322: REPLACE INTO $stbl($pkey, key, type, val) yuuji@322: VALUES($pval, '$iconcachekey', 'string', `sqlquote "$cacheimg_S"`); yuuji@322: EOF yuuji@311: ) yuuji@311: yuuji@0: showhome() { yuuji@0: # $1=userRowIdToShow yuuji@81: err showhome \$1=$1 yuuji@0: case "$1" in yuuji@0: *@*) uname=`getvalbypkey user name "$1"` ;; yuuji@0: *) uname=`getvalbyid user name $1` ;; yuuji@0: esac yuuji@356: ## err ShowHome: uname=$uname yuuji@311: td=`getcachedir home/"$1"` yuuji@0: gecos=`gecos "$uname"` yuuji@356: ## err SH:gecos=$gecos yuuji@0: GF_VIEWONLY=1 yuuji@0: cond="gname in (select gname from grp_mem where user='$uname')" yuuji@331: search_form_args="" yuuji@0: if [ x"$user" = x"$uname" ]; then yuuji@469: usermenu="プロフィールの編集 / yuuji@341: 新規話題の作成" yuuji@80: # Display folders yuuji@80: sql="select count(id) from article_m where id yuuji@80: in (select id from article where author='$user') yuuji@80: and type like 'file:%';" yuuji@356: ## err nfile-sql=`echo "$sql"` yuuji@80: nfile=`query "$sql"` yuuji@312: # err nfile=$nfile yuuji@80: if [ $nfile -gt 0 ]; then yuuji@469: usermenu="$usermenu / 過去の提出ファイル" yuuji@80: fi yuuji@331: else yuuji@469: latestlog=`query "SELECT max(time) FROM acclog WHERE user='$uname' \ yuuji@469: GROUP BY user;"` yuuji@469: usermenu="

Last seen on $latestlog

" yuuji@331: search_form_args="author=$uname" yuuji@0: fi yuuji@17: . ./s4-blog.sh yuuji@3: yuuji@243: tf=$tmpd/title.$$ pf=$tmpd/profile.$$ bf=$tmpd/blogs.$$ sf=$tmpd/search.$$ yuuji@331: search_form $search_form_args > $sf yuuji@331: echo "$gecos さん" > $tf yuuji@319: { echo "
" yuuji@319: viewtable $formdir/user.def user $1 yuuji@319: echo "
" yuuji@319: } > $pf yuuji@146: yuuji@147: sqcond="WHERE name='$uname' AND key='profimg' AND type LIKE 'file:image%'" yuuji@146: img=`query "SELECT type FROM user_m $sqcond LIMIT 1;"` yuuji@148: imf=$tmpd/profimg.$$; touch $imf yuuji@146: if [ -n "$img" ]; then yuuji@311: if true; then yuuji@311: tbl=user_m yuuji@322: enticond="name='$uname'" yuuji@322: imgsrc_cache "$td/main" user_m "$enticond" M yuuji@311: else yuuji@311: { printf '%s' "' yuuji@311: } yuuji@311: fi > $imf yuuji@146: fi yuuji@150: nblog=`query "SELECT count(id) FROM blog_s WHERE key='owner' AND \ yuuji@150: val='$uname';"` yuuji@81: listblog $uname > $bf yuuji@260: yuuji@260: hometail=$tmpd/tail.$$ yuuji@260: mkfifo $hometail yuuji@260: yuuji@260: #Calling listgroupbytable, originally here yuuji@81: yuuji@260: ( yuuji@328: # Display Most Recent Entry yuuji@328: shortval=${dumpcollen:+"substr(val, 0, $dumpcollen)"} yuuji@328: shortval=${shortval:-val} yuuji@252: yuuji@340: # The m.aid in the next line is suspicious. But works fine in SQLite3... yuuji@328: DT_SQL="SELECT b.rowid || '#' || m.aid LINK, yuuji@253: ctime, yuuji@253: (SELECT $shortval FROM blog_s WHERE key='title' AND id=b.id) title, yuuji@253: (SELECT gecos FROM gecoses yuuji@253: WHERE name=(SELECT val FROM blog_s yuuji@257: WHERE key='owner' AND id=b.id)) owner, yuuji@257: (SELECT $shortval val FROM article_s WHERE id=m.aid AND key='text') text yuuji@253: FROM blog b yuuji@253: JOIN yuuji@254: (SELECT distinct blogid, a.id aid, max(val) ctime yuuji@253: FROM article a, article_s s yuuji@328: ON a.id=s.id AND a.author='$uname' AND s.key='ctime' yuuji@253: GROUP BY blogid ORDER BY val DESC LIMIT 50 yuuji@253: ) m yuuji@253: ON b.id=m.blogid;" yuuji@328: # This should be as follows yuuji@328: : <最近の書き込み先 yuuji@260:
yuuji@194: `DT_VIEW=replyblog dumptable html blog` yuuji@194:
yuuji@194: EOF yuuji@328: unset DT_SQL yuuji@328: if [ x"$user" = x"$uname" ]; then yuuji@81: # Display NEWS yuuji@351: # 2016-06-26 yuuji@351: if [ x"`getpar readchk``getpar read`" = x"yesyes" ]; then yuuji@351: acclog blog $blogreadflagrowid yuuji@351: # echo "全部既読にしました" | html p yuuji@175: fi yuuji@351: # 2016-02-19 Counting NEWS without using dumptable. yuuji@351: sql=`listnewblogsql "$user"` yuuji@471: # echo "$sql" > tmp/listnew yuuji@351: new10=`DT_SQL="$sql" DT_VIEW=replyblog dumptable html blog` yuuji@81: cont=`echo "$new10"|grep "^"|wc -l` yuuji@81: cont=$((cont-1)) yuuji@81: err newcount=$cont yuuji@81: if [ $cont -gt 0 ]; then yuuji@260: #echo "全体の新着記事${cont}傑" | html h2 yuuji@340: cgi_radio foldtabs yes 'id="new10" accesskey="f"' yuuji@428: echo "
" yuuji@236: cat<<-EOF | html form 'action="?home"' yuuji@262: `cgi_checkbox readchk yes 'id="read"'` yuuji@260: `cgi_submit '確定'` yuuji@236: `cgi_hidden read yes` yuuji@236: EOF yuuji@260: echo "$new10 " yuuji@260: echo "
" yuuji@471: else # If news is 0, set log cut off flag yuuji@471: acclog blog $blogcutoffflagrowid # for speed yuuji@81: fi yuuji@328: else # Not My Home ($user != $uname) yuuji@329: : # DT_SQL= yuuji@81: fi yuuji@260: ) > $hometail & # Is background call safe to m4?? yuuji@128: # yuuji@260: listgroupbytable $formdir/grp.def $cond | yuuji@260: _m4 -D_BODYCLASS_=home -D_TITLE_="spaste(\`$tf')" \ yuuji@469: -D_PROFILE_="spaste(\`$pf')$usermenu" \ yuuji@260: -D_PROFIMG_="spaste(\`$imf')" \ yuuji@260: -D_BLOGS_="spaste(\`$bf')" \ yuuji@260: -D_SEARCH_="spaste(\`$sf')" \ yuuji@260: -D_NBLOG_="$nblog" \ yuuji@260: -D_GROUPS_="syscmd(\`cat')" \ yuuji@260: -D_HOMETAIL_="syscmd(\`cat $hometail')" \ yuuji@260: $layout/html.m4.html $layout/home.m4.html yuuji@260: yuuji@0: # Record access log yuuji@0: [ -n "$1" ] && [ x"$1" != x"$user" ] && acclog user $1 yuuji@0: } yuuji@79: commission() { # $1=grp-rowid $2=user-rowid yuuji@79: contenttype; echo yuuji@356: ## err commission: "$@" yuuji@79: gname=`getgroupbyid $1` yuuji@81: echo "グループ $gname 管理者委任" \ yuuji@187: | _m4 -D_TITLE_="syscmd(\`cat')" $layout/html.m4.html yuuji@79: if [ -n "$2" ]; then yuuji@79: grp_reg_adm "$@" yuuji@79: else yuuji@79: echo "無効な指定です。普通のアクセスならここに来ないはず。"|html p yuuji@79: fi yuuji@79: } yuuji@0: listgroupbytable() { yuuji@52: # $1=deffile $2...=condition yuuji@0: tagline=`grep :tag: $1`; shift yuuji@52: and="${1:+and }" where=${1:+where } yuuji@0: href="' yuuji@26: NGsql="select distinct tag from\ yuuji@26: (select gname, max(case key when 'tag' then val end) as tag, \ yuuji@26: max(case key when 'ctime' then val end) as ctime\ yuuji@26: from grp_s group by gname order by ctime);" yuuji@26: sql="select val from grp_s where key='tag' $and$* group by val;" yuuji@356: ## err ListGRP: query sql="$sql" yuuji@13: for tag in `query "$sql"` yuuji@0: do yuuji@356: ## err ListGrp: tag=$tag yuuji@0: tn=${tagline%%=${tag}*} yuuji@0: tn=${tn##*[ :]} yuuji@113: sql="select rowid||':'||gname as 'グループ名',説明 from yuuji@113: (select (select rowid from grp g where g.gname=grp_s.gname) yuuji@113: as rowid, yuuji@113: gname, yuuji@113: max(case key when 'gecos' then val end) as '説明', yuuji@113: max(case key when 'tag' then val end) as 'tag', yuuji@113: max(case key when 'mtime' then val end) as mtime from grp_s yuuji@113: $where$* group by gname having tag='$tag' order by mtime desc);" yuuji@356: ## err PersonalGroupList= `echo $sql` yuuji@0: echo "

$tn

" yuuji@0: echo '' yuuji@0: sq -header -html $db "$sql" \ yuuji@494: | sed "s,\(,\1$href\2\">\3," yuuji@0: echo '
\)\([0-9]*\):\([^<]*\)
' yuuji@0: done yuuji@0: echo '' yuuji@0: } yuuji@0: iconhref() ( yuuji@0: # $1=icon-file, $2=Href $3=title $4...=anchor yuuji@326: data=`percenthex "$1"` yuuji@326: ct=`file --mime-type - < "$1"|cut -d' ' -f2` yuuji@356: ## err iconhref: \$1=$1 \$2=$2 \$3="$@" yuuji@0: href=$2; title=$3; shift 3 yuuji@0: echo "
$@" yuuji@0: ) yuuji@0: iconhref2() ( yuuji@0: # $1=icon-file, $2=Href $3=title $4...=anchor yuuji@0: src=$1 yuuji@0: href=$2; title=$3; shift 3 yuuji@0: echo "$@" yuuji@0: ) yuuji@0: listentry() ( yuuji@246: # $1=user/group $2=SearchKeyword $3=condition(if any) $4=grprowid(if in grp) yuuji@0: # Referring variable $iamowner=$grp to attach owner-request links yuuji@356: ## err listentry: \$1=$1 \$2=$2 \$3=$3 yuuji@246: cond='' hiddens='' yuuji@447: offset=`getpar offset`; offset=${offset%%[!0-9]*} yuuji@447: if [ -z "$offset" ]; then yuuji@447: offset=`getpar start`; offset=${offset%%[!0-9]*} yuuji@447: offset=$((offset-1)) yuuji@447: fi yuuji@0: offset=$((offset + 0)) # change to numeric forcibly yuuji@0: [ $offset -lt 0 ] && offset=0 yuuji@0: limit=30 yuuji@78: dir=`getcachedir "$1"` yuuji@0: if [ x"$1" = x"user" ]; then yuuji@0: hrb="$myname?home" yuuji@0: deficon=person-default.png yuuji@246: entity="ユーザ" tbl=user link=rowid nm=name # stage=mems yuuji@246: [ -n "$4" ] && hiddens=`cgi_hidden grid $4` yuuji@33: gcs=gecos yuuji@0: else # if group yuuji@0: hrb="$myname?grp" yuuji@22: deficon=group-default.png yuuji@16: entity="グループ" tbl=grp link=rowid nm=gname stage=grps yuuji@33: gcs=name yuuji@0: tagline=`grep :tag: $formdir/grp.def|cut -d: -f5-` yuuji@0: if [ -n "$tagline" ]; then yuuji@0: tagconv=`echo $tagline|sed 's/\([^= :]*\)=\([^= :]*\)/-D\2=\1/g'` yuuji@356: ## err tagconv=$tagconv yuuji@0: fi yuuji@0: fi yuuji@0: if [ ! -d $dir ]; then yuuji@0: mkdir -p $dir yuuji@131: fi yuuji@131: if [ ! -s $dir/$deficon ]; then yuuji@0: convert -geometry $thumbxy $imgdir/$deficon $dir/$deficon yuuji@0: fi yuuji@0: if [ -n "$2" ]; then yuuji@0: cond="where nick like '%$2%' or b.name like '%$2%'" yuuji@0: fi yuuji@0: yuuji@0: # XX: これ複雑すぎるかな。もっとシンプルにしたい。$3条件も。2015-07-08 yuuji@33: # grpは呼出し元の動的スコープ変数でよくないな... yuuji@33: ##qgrp=`sqlquote $grp` yuuji@33: getgrp="(select gname from grp where rowid=${rowid:--1})" yuuji@220: sql="select a.rowid, a.$link, yuuji@220: coalesce(b.$gcs, a.$nm) as nick, yuuji@388: quote(a.$nm) as qname, yuuji@388: (SELECT val FROM ${tbl}_s yuuji@388: WHERE $nm=a.$nm AND key='$iconcachekey') icon, yuuji@220: coalesce(b.gecos, a.$nm) /* If group, concat (Nusers) */ yuuji@220: || case when a.$nm in (select gname from grp) yuuji@220: then printf('(%d名)', yuuji@220: (select count(user) from grp_mem where gname=a.$nm)) yuuji@233: else ' <'||a.$nm||'>' yuuji@220: end yuuji@220: as name, yuuji@33: b.tag, yuuji@13: case when a.$nm in (select user from grp_adm yuuji@69: where gname=$getgrp) then '(管理者)' yuuji@13: when '$user' in (select user from grp_adm where gname=a.$nm) yuuji@13: then '(ADMIN)' yuuji@171: when '$user' in (select user from grp_mem where gname=a.$nm) yuuji@171: then '(Member)' yuuji@13: when '$iamowner' = '' then '' yuuji@259: else ',not='||a.rowid end as ownerlink, yuuji@259: CASE '$entity' yuuji@259: WHEN 'グループ' yuuji@259: THEN coalesce( yuuji@259: (SELECT val FROM grp_s WHERE gname=a.$nm AND key='regmode'), yuuji@259: 'open') yuuji@259: || yuuji@259: CASE WHEN '$user' yuuji@259: IN (SELECT user FROM grp_mem WHERE gname=a.$nm) yuuji@259: THEN ' ismember' yuuji@259: ELSE '' yuuji@259: END yuuji@259: ELSE 'user' yuuji@259: END regmode yuuji@0: from $tbl a left join yuuji@0: (select $nm as name, yuuji@0: max(case key when 'gecos' then val end) as gecos, yuuji@297: max(case key when 'tag' then val end) as tag, yuuji@387: max(case key when 'mtime' then val end) as mtime, yuuji@475: max(case key when 'wtime' then val end) as wtime, yuuji@474: max(case key when 'login' then val end) as login yuuji@0: from ${tbl}_s group by $nm) yuuji@0: b on a.$nm=b.name $cond $3 yuuji@474: order by b.wtime desc, b.login desc, yuuji@474: b.mtime desc, b.tag desc, a.rowid asc" yuuji@297: # Give precedence to newer maintained groups (2016-09-24) yuuji@297: # Note that mtime is stored only in grp_s. yuuji@356: ## err LE:sql.1="$sql" yuuji@0: total=`query "with x as ($sql) select count(*) from x;"` yuuji@61: echo "${entity} 一覧" | html h2 yuuji@0: if [ $total -gt $limit ]; then yuuji@0: echo '
' yuuji@0: cgi_form $stage <次の語を含む${entity}で検索: yuuji@0: `cgi_text kwd $kwd` yuuji@0: EOF yuuji@0: echo '
' yuuji@0: fi yuuji@246: hiddens="$hiddens yuuji@246: `cgi_hidden kwd \"$kwd\"` yuuji@246: `cgi_hidden stage \"$stage\"`" yuuji@0: cat< yuuji@447:

${total}件中の件めから${kwd:+" - 検索語: $kwd"}$hiddens yuuji@447:

yuuji@447: yuuji@0: EOF yuuji@0: if [ $((offset+limit)) -lt $total ]; then yuuji@235: nextbtn=$( yuuji@0: cat<
yuuji@0: `cgi_submit 次の${limit}件` yuuji@246: $hiddens yuuji@0: `cgi_hidden offset $((offset + limit))`
yuuji@0: EOF yuuji@235: ) yuuji@0: fi yuuji@0: if [ $offset -gt 0 ]; then yuuji@235: prevbtn=$( yuuji@0: cat< yuuji@0: `cgi_submit 前の${limit}件` yuuji@246: $hiddens yuuji@0: `cgi_hidden offset $((offset - limit))` yuuji@0: EOF yuuji@235: ) yuuji@0: fi yuuji@235: pnbtn="$nextbtn$prevbtn" yuuji@235: echo $pnbtn yuuji@0: yuuji@356: ## err ListEntry: `echo "$sql"\;` yuuji@391: # sq $db here??? 2016-11-28 yuuji@0: query "$sql limit $limit ${offset:+offset $offset};" \ yuuji@388: | while IFS='|' read id lnk name qname icon gecos tag ownerp type; do yuuji@16: err name=$name owner=$ownerp lnk=$lnk yuuji@259: err newlnk=$lnk regmode=$regmode yuuji@230: icondir=$dir/$id yuuji@332: # Pick up only last icon yuuji@259: echo "
yuuji@259:

$tag

" \ yuuji@187: | _m4 $tagconv yuuji@391: if [ -n "$NOSPEEDUP" ]; then yuuji@388: files=`getvalbyid $tbl profimg $id $icondir` yuuji@388: if [ -n "$files" ]; then yuuji@388: icon=`echo "$files"|tail -1` yuuji@388: iconhref2 "$icondir/$icon" "$hrb+$lnk" "$gecos" yuuji@388: else yuuji@388: iconhref "$dir/$deficon" "$hrb+$lnk" "$gecos" yuuji@388: fi yuuji@388: elif [ -n "$icon" -a -s "$icon" ]; then yuuji@474: iconhref2 "$icon" "$hrb+$lnk" "$gecos
$mt" yuuji@0: else yuuji@388: cond="$nm=$qname" yuuji@388: # err imgsrc_cache "$dir/list" ${tbl}_m "$cond" S yuuji@388: # err query "SELECT type FROM ${tbl}_m $cond LIMIT 1;" yuuji@388: img=`query "SELECT type FROM ${tbl}_m WHERE $cond AND key='profimg' LIMIT 1;"` yuuji@388: # err "img=[$img]" yuuji@388: if [ -n "$img" ]; then yuuji@390: echo "" yuuji@391: imgsrc_cache "$icondir" ${tbl}_m "$nm=$qname" S yuuji@390: echo "" yuuji@388: else yuuji@388: iconhref2 "$dir/$deficon" "$hrb+$lnk" "$gecos" yuuji@388: fi yuuji@0: fi yuuji@0: echo "
$name${ownerp:+
$ownerp}" yuuji@0: echo "
" yuuji@0: done yuuji@235: echo ${pnbtn:+"
$nextbtn$prevbtn"} yuuji@0: ) yuuji@0: listmember() { yuuji@0: listentry user "$@" yuuji@0: } yuuji@0: listgroup() { yuuji@0: listentry group "$@" yuuji@0: } yuuji@222: hexteams() { # $1=gname, $2(optional)=user yuuji@222: cond=${2:+" AND user='$2'"} yuuji@222: query "SELECT DISTINCT hex(val) FROM grp_mem_m yuuji@222: WHERE gname='$1' AND key='team'$cond;" yuuji@222: } yuuji@33: showgroup() { # $1=group-rowid yuuji@246: if [ -z "$1" ]; then yuuji@246: grid=`getpar grid` yuuji@246: grid=${grid%%[!0-9]*} yuuji@246: [ -n "$grid" ] && grp=`getgroupbyid $grid` yuuji@246: else yuuji@246: grid=$1 yuuji@246: fi yuuji@246: grp=`getgroupbyid $grid` yuuji@431: qgrp=`sqlquote "$grp"` yuuji@431: ## err showgroup2: grid=$grid grp=$grp qgrp="[$qgrp]" yuuji@13: if isgroup "$grp"; then yuuji@81: tf=$tmpd/title.$$ yuuji@418: sf=$tmpd/search.$$ yuuji@259: bodyclass=`query "SELECT val FROM grp_s yuuji@259: WHERE gname=$qgrp AND key='regmode';"` yuuji@259: if ismember "$user" "$grp"; then yuuji@259: ismember="ismember" yuuji@431: qgrp=`sqlquote "$grp"` yuuji@259: bodyclass="$bodyclass${bodyclass:+ }ismember" yuuji@259: else yuuji@259: ismember="" # bodyclass="group" yuuji@259: fi yuuji@311: bodyclass="$bodyclass grouphome" yuuji@418: echo "
`search_form grp=\"$grp\"`
"> $sf yuuji@81: echo "グループ $grp" > $tf yuuji@418: yuuji@246: showgroupsub $formdir/grp.def "$grid" | \ yuuji@418: _m4 -D_TITLE_="syscmd(\`cat $tf')" \ yuuji@187: -D_FORM_="syscmd(\`cat')" \ yuuji@259: -D_BODYCLASS_="$bodyclass" \ yuuji@187: -D_DUMPTABLE_="" \ yuuji@418: $htmlheader $sf $layout/form+dump.m4.html yuuji@418: # $htmlheader $layout/form+dump.m4.html yuuji@259: # $htmlheader is defined in grp() yuuji@13: else # if $grp is removed at par2table yuuji@13: listgroup yuuji@13: fi yuuji@0: } yuuji@0: showgroupsub() { yuuji@33: # $1=def-file $2=group-rowid yuuji@259: # Using $ismember yuuji@33: rowid=$2 yuuji@33: grp=`getgroupbyid $2` yuuji@431: qgrp=`sqlquote "$grp"` yuuji@311: td=`getcachedir grp/"$2"` yuuji@33: #rowid=`sq $db "select rowid from grp where gname=$qgrp"` yuuji@0: if [ -z "$rowid" ]; then yuuji@33: #rowid=`sq $db "select rowid from grp where rowid=$grp"` yuuji@33: #grp=`sq $db "select gname from grp where rowid=$grp"` yuuji@61: echo "showgroupsub: invalid argument($1 $2)" | html p yuuji@61: return yuuji@0: fi yuuji@0: val=`getvalbyid grp profimg $rowid $tmpd` yuuji@322: enticond="gname=$qgrp" yuuji@311: img=`query "SELECT type FROM grp_m WHERE $enticond LIMIT 1;"` yuuji@311: if [ -n "$img" ]; then yuuji@311: cat<<-EOF yuuji@311:

yuuji@322: `imgsrc_cache $td/main grp_m "$enticond" M`

yuuji@311: EOF yuuji@311: fi yuuji@319: echo "
" yuuji@0: viewtable $1 grp $rowid yuuji@319: echo "
" yuuji@13: if isgrpowner "$user" "$grp"; then yuuji@16: echo "

グループ情報の編集" yuuji@33: iamowner=$rowid yuuji@371: colmd=" mode" yuuji@0: fi yuuji@259: if [ -n "$ismember" ]; then yuuji@59: echo "${iamowner:+ / }グループの新規話題作成" yuuji@59: echo "/ メンバーを個別選択しての操作

" yuuji@26: # div.fold input[type="checkbox"]:checked ~ div {display: block;} yuuji@26: cat< yuuji@311:
yuuji@26: `cgi_checkbox send yes id="send"` yuuji@26:
yuuji@26: `cgi_textarea message "" "cols=60"` yuuji@26: `cgi_submit 送信` yuuji@26: `cgi_reset リセット` yuuji@26:
yuuji@26: `cgi_hidden grp $rowid` yuuji@26:
yuuji@26: EOF yuuji@0: fi yuuji@0: # 加入ボタン + 加入者リスト yuuji@259: if [ -n "$ismember" ]; then yuuji@259: ismem='checked' state="(参加中)" yuuji@259: else yuuji@259: nomem='checked' state="(現在非加入)" yuuji@259: fi yuuji@0: # このグループでの加入アドレス yuuji@222: eml=`query "select val from grp_mem_s where gname=$qgrp and user='$user' \ yuuji@0: and key='email';"` yuuji@356: ##err EML: "select val from grp_mem_s where gname='$2' and user='$user' \ yuuji@356: ## and key='email';" yuuji@356: ##err email=$eml yuuji@26: cat < yuuji@26: `cgi_checkbox reg yes id="reg"`$state yuuji@26:
yuuji@26: EOF yuuji@0: cgi_form grp <このグループに

yuuji@0: yuuji@0: yuuji@0: yuuji@0: yuuji@0:
メンバーとして yuuji@0: / yuuji@0:
参加する場合のメイルアドレス
yuuji@0: (メインのアドレスとは違うものにする場合に記入
yuuji@0: 同じでよい場合は空欄に)
`cgi_text email $eml`
yuuji@33: `cgi_hidden grp $rowid` yuuji@0: EOF yuuji@117: if [ x`getgroupattr $grp regmode` = x'moderated' -a -z "$ismem" ]; then yuuji@117: echo "moderated (承認加入の)グループなので実際に参加できるのは yuuji@117: グループ管理者が承認操作をした後になります。" | html p 'class="warn"' yuuji@117: fi yuuji@26: echo '
' yuuji@0: echo '

話題一覧

' yuuji@418: thelp="1ヶ月分のまとめには上部検索窓に @month と入れてください。" yuuji@418: cat<<-EOF yuuji@418:
yuuji@418: `cgi_hidden owner "$grp"` yuuji@418: `cgi_hidden kwd "@week"` yuuji@418: `cgi_hidden stage searchart` yuuji@418: `cgi_submit "一週間のまとめ"` yuuji@418:
yuuji@418: EOF yuuji@60: cond="where a.id in (select id from blog_s where key='owner' and val=$qgrp) order by ctime desc" yuuji@397: colstate="state:稼動状態:frozen=rowclass=凍結" yuuji@0: DT_CHLD=article:blogid \ yuuji@371: DT_VIEW=replyblog dumptable html blog \ yuuji@438: "ctime title heading team notify:通知$colmd $colstate" "$cond" yuuji@0: yuuji@33: getgname="(select gname from grp where rowid=$rowid)" yuuji@246: c="group by a.name having a.name in (select user from grp_mem where gname=$getgname)" yuuji@33: cm="?commission+$rowid" yuuji@246: thumbxy=50x50 listmember "" "$c" "$rowid" \ yuuji@153: |sed -e "s|\(
\),not=\(.*\)|\1|" # 間違って押しやすい yuuji@222: # team list yuuji@222: hexteams=`hexteams "$grp"` yuuji@222: if [ -n "$hexteams" ]; then yuuji@222: echo "チーム一覧" | html h2 yuuji@222: echo '
' yuuji@222: sq $db -html -header<<-EOF yuuji@222: SELECT val TEAM, yuuji@222: group_concat((SELECT gecos FROM gecoses WHERE name=user), ',') yuuji@222: MEMBERS yuuji@224: FROM grp_mem_m WHERE gname=$qgrp AND key='team' GROUP BY val; yuuji@222: EOF yuuji@222: echo '
' yuuji@222: fi yuuji@0: } yuuji@288: grp_getbodyclass() { yuuji@288: # Get css class name for document. yuuji@288: # `moderated' for moderated groups yuuji@288: # `ismember' for groups where user belongs yuuji@288: # $1=GroupName (w/o quote) yuuji@288: # $user=userNameCurrentlyLogin yuuji@356: ## err grp_getbodyclass: 1="$1" yuuji@288: qgrp=`sqlquote "$1"` yuuji@288: query<<-EOF yuuji@288: SELECT coalesce( yuuji@288: (SELECT val FROM grp_s WHERE gname=$qgrp AND key='regmode'), yuuji@288: 'open') yuuji@288: || yuuji@288: CASE WHEN '$user' yuuji@288: IN (SELECT user FROM grp_mem WHERE gname=$qgrp) yuuji@288: THEN ' ismember' yuuji@288: ELSE '' yuuji@288: END; yuuji@288: EOF yuuji@288: } yuuji@59: grpaction() { # $1=group-rowid yuuji@79: err GRP_ACTION:IN yuuji@79: grid=${1:-`getpar grp`} yuuji@79: grp=`getgroupbyid "$grid"` yuuji@79: if [ -z "$grp" ]; then yuuji@118: echo "無効な指定です。" | html p; return yuuji@118: fi yuuji@433: if ! ismember $user "$grp"; then yuuji@118: echo "加入者のみに許可された操作です。" | html p; return yuuji@79: fi yuuji@81: echo "グループ $grp 個別選択操作" \ yuuji@288: | _m4 -D_TITLE_="syscmd(\`cat')" \ yuuji@288: -D_BODYCLASS_="`grp_getbodyclass \"$grp\"`" \ yuuji@288: $layout/html.m4.html yuuji@79: yuuji@117: isowner="" yuuji@117: isgrpowner "$user" "$grp" && isowner="yes" yuuji@59: usel=`getpar usel` yuuji@59: if [ -n "$usel" ]; then yuuji@59: uids=$(echo `echo $usel`|tr ' ' ',') yuuji@356: ## err grpaction-1: grp=$grp, `echo $sql` yuuji@59: text=`getpar text` yuuji@59: yuuji@59: rm=`getpar rm` cfm=`getpar confirm` yuuji@356: ## err rm=$rm cfm=$cfm yuuji@59: if [ x"$rm" = x"yes" ]; then yuuji@117: if [ "$isowner" ]; then yuuji@59: if [ x"$rm$cfm" = x"yesyes" ]; then yuuji@59: # Eliminate yuuji@59: cond="where gname=(select gname from grp where rowid=$grid) and user in (select name from user where rowid in ($uids))" yuuji@59: for tbl in grp_mem grp_mem_s grp_mem_m; do yuuji@59: sql="delete from $tbl $cond;" yuuji@59: # echo "sql=$sql" yuuji@59: query "$sql" yuuji@59: err rmGRPuser "$sql" yuuji@59: done yuuji@59: num=`query "select count(*) from user where rowid in ($uids);"` yuuji@59: #err num=$num yuuji@59: if [ 0$num -gt 0 ]; then yuuji@59: sql="select coalesce(b.val,a.name) from user a left join \ yuuji@59: user_s b on a.name=b.name and key='gecos' where a.rowid in ($uids);" yuuji@59: # err `echo "$sql"` yuuji@59: html pre<@'` yuuji@300: myuid=`query "SELECT rowid FROM user WHERE name='$user';"` yuuji@300: fromad=`email4groupbyuid "$grp" "$myuid"` yuuji@300: mail_from="$safegc <$fromad>" yuuji@300: else yuuji@300: mail_from="$admin" yuuji@300: fi yuuji@300: MAIL_FROM=$mail_from \ yuuji@300: smail "`email4groupbyuid "$grp" $usel` $user" \ yuuji@300: "$gecos さんからのメッセージ" <" yuuji@490: to_input="" yuuji@492: fromtonote="

POST集計: $from_input - $to_input

" yuuji@59: # New entry yuuji@435: sql="WITH mems AS ( yuuji@435: SELECT g.rowid, name, gecos FROM grp_mem gm LEFT JOIN gecoses g yuuji@435: ON gm.user=g.name yuuji@435: WHERE gname=(SELECT gname FROM grp WHERE rowid=$grid) yuuji@490: ), target_article AS ( yuuji@490: SELECT id FROM article_s yuuji@490: WHERE key='ctime' AND val BETWEEN '${from:-0000}' AND '${to:-9999}' yuuji@435: ), posts AS ( yuuji@435: SELECT author, count(author) post yuuji@490: FROM article NATURAL JOIN article_s NATURAL JOIN target_article yuuji@435: WHERE blogid IN (SELECT id FROM blog_s yuuji@435: WHERE key='owner' yuuji@435: AND val=(SELECT gname FROM grp WHERE rowid=$grid)) yuuji@435: AND key='text' yuuji@435: GROUP BY author yuuji@435: ), teams AS ( yuuji@435: SELECT user, group_concat(val, ', ') team yuuji@435: FROM grp_mem_m yuuji@435: WHERE gname=(SELECT gname FROM grp WHERE rowid=$grid) yuuji@435: AND key='team' yuuji@435: GROUP BY user yuuji@435: ), user_post AS ( yuuji@435: SELECT m.rowid, name, m.gecos, coalesce(post, 0) as POST yuuji@435: FROM mems m LEFT JOIN posts yuuji@435: ON m.name=posts.author yuuji@435: GROUP by m.rowid yuuji@435: ) yuuji@435: SELECT yuuji@435: CASE yuuji@435: WHEN (SELECT user FROM grp_adm yuuji@435: WHERE gname=(SELECT gname FROM grp WHERE rowid=$grid) yuuji@435: AND user=up.name) IS NOT NULL yuuji@435: then 'k' yuuji@435: ELSE '' yuuji@435: END || rowid || ',' || gecos NAME, yuuji@435: post POST, team TEAM yuuji@435: FROM user_post up LEFT JOIN teams t yuuji@435: ON up.name=t.user yuuji@435: ORDER BY gecos;" yuuji@356: ## err grpaction: "`echo \"$sql\"`" yuuji@81: tf=$tmpd/title.$$ yuuji@291: echo "グループ[$grp]参加メンバーに対する操作" > $tf yuuji@291: cmmsg="`cgi_radio rm commission id=\"cmadmin\"` yuuji@153:

このグループでの全権を付与します。信頼できる人に託してください。 yuuji@291:

" yuuji@291: excmsg="`cgi_radio rm yes id=\"conf\"` yuuji@291:
本当に消します! `cgi_checkbox confirm yes` 確認 yuuji@117:

この操作による通知は本人に行きません。 yuuji@117: あらかじめ通知するか、登録解除してよい状況かしっかり確認してください。

yuuji@117:
" yuuji@222: # Get team list to which current user belongs into $hexteams yuuji@222: myhexteams=$(hexteams "$grp" "$user") yuuji@222: allhexteams=$(hexteams "$grp") yuuji@227: if [ -n "$myhexteams" ]; then yuuji@291: rmteammsg="`cgi_radio rm rmteam 'id=\"cmrmteam\"'` yuuji@228:
チーム属性:`cgi_select_h rmteam \"2d2d2d\" $myhexteams` yuuji@222: を除去します: `cgi_checkbox teamconfirm yes` 確認 yuuji@222:

この操作による通知は本人に行きません。 yuuji@222: あらかじめ通知するか、登録解除してよい状況かしっかり確認してください。

yuuji@228:
yuuji@222: " yuuji@222: fi yuuji@222: b1='' yuuji@222: # | sed -e "s|^\(\)k\([0-9]*\),\([^<]*\)|\1$ba\2$b2\3$b3|" \ yuuji@222: # -e "s|^\(\)\([0-9]*\),\([^<]*\)|\1$b1\2$b2\3$b3|" \ yuuji@222: lnk='"> \3 [HOME]' yuuji@59: cgi_form grpaction<\)k\([0-9]*\),\([^<]*\)|\1$ba\2$lnk|" \ yuuji@222: -e "s|^\(\)\([0-9]*\),\([^<]*\)|\1$b1\2$lnk|" \ yuuji@187: | _m4 -D_TITLE_="spaste(\`$tf')" \ yuuji@187: -D_SUBTITLE_="チェック後操作ボタン" \ yuuji@187: -D_FORM_="syscmd(cat)" -D_DUMPTABLE_="" \ yuuji@187: $layout/form+dump.m4.html yuuji@291:

下でチェックした人を対象として:

yuuji@291:
yuuji@222: `cgi_radio rm addteam 'id="cmteam"'` yuuji@222:
チーム名:`cgi_text team "" 'id="inteam" list="teams"'` yuuji@222: `cgi_datalist_h teams $allhexteams` yuuji@291:
yuuji@228: ${rmteammsg} yuuji@59: `cgi_radio rm send id="sendmsg"` yuuji@59:
yuuji@300: `cgi_checkbox mkfrom yes 'id="mkfrom" checked'`
yuuji@59: `cgi_textarea text "" cols=40` yuuji@59:
yuuji@291: ${isowner:+$cmmsg$excmsg} yuuji@291: `cgi_radio rm close id="x"` yuuji@59:
yuuji@490:

$grp 参加者一覧

$fromtonote yuuji@275: yuuji@222: `sq $db -header -html "$sql"` yuuji@207:
yuuji@59: `cgi_hidden grp $grid` yuuji@59: EOF yuuji@59: } yuuji@213: crview4article() { # $1=rowid of blog, $2(optional)=extra SQL yuuji@222: # Create TEMPORARY VIEW yuuji@213: query<owner) yuuji@300: cat< yuuji@213: `cgi_checkbox mv send id="mv"` yuuji@213:
yuuji@213:
yuuji@213: 移動先グループ: yuuji@213: yuuji@214:

(移動できるグループは、この「話題」に書き込んでいる人全てが yuuji@214: そのグループに加入しているものに限られます)

yuuji@213:

`cgi_checkbox cfm yes`

yuuji@213: `cgi_hidden blogrowid $rowid` yuuji@213: `cgi_submit 移動` yuuji@213: `cgi_reset Reset` yuuji@213:
yuuji@213:
yuuji@213: yuuji@213: EOF yuuji@213: fi yuuji@222: # end of isuser "$owner" yuuji@222: elif { hexteams=$(hexteams "$owner" ) # blog is of GROUP yuuji@222: [ -n "$hexteams" ];}; then yuuji@222: none="`echo なし|hexize`" yuuji@222: cat<<-EOF yuuji@222:
yuuji@222: `cgi_checkbox mv2team send id="mv2team"` yuuji@222:

現在の所属チーム設定: yuuji@222: `query "SELECT yuuji@222: coalesce((SELECT val FROM blog_s yuuji@222: WHERE id=(SELECT id FROM blog WHERE rowid=$rowid) yuuji@222: AND key='team'), yuuji@222: ':なし');"`

yuuji@222:
yuuji@222: 移動先チーム: `cgi_select_h mv2team $none $hexteams` yuuji@222:

`cgi_checkbox cfm yes`

yuuji@222: `cgi_hidden blogrowid $rowid`
yuuji@222: `cgi_submit 移動` yuuji@222: `cgi_reset Reset` yuuji@222:
yuuji@222: EOF yuuji@213: fi yuuji@213: } yuuji@222: mvart() { # move diary to some group or team yuuji@222: # or move blog of group to team which belong to the group yuuji@213: blogrowid=`getpar blogrowid` yuuji@213: cfm=`getpar cfm` yuuji@213: ##### echo move blog:$blogrowid to $mv2grp | html p yuuji@213: blogrowid=${blogrowid%%[!A-Z0-9a-z_]*} # Purify yuuji@213: . ./s4-blog.sh yuuji@222: if [ -z "$blogrowid" ]; then yuuji@213: echo "無効な指定です(mvart)。" | html p yuuji@213: return yuuji@213: elif [ x"$cfm" != x"yes" ]; then yuuji@213: echo "記事移動の確認にチェックがないので通常表示に戻ります。" | html p yuuji@222: elif { mv2grp=`getpar mv2grp` yuuji@222: mv2grp=${mv2grp%%[!A-Z0-9a-z_]*} # Purify yuuji@222: [ -n "$mv2grp" ]; }; then yuuji@213: crview4article $blogrowid yuuji@213: ########## TRANSACTION BEGIN yuuji@213: query "BEGIN;" yuuji@213: n=`query "SELECT count(*) FROM writeusers;"` yuuji@356: ## err Nwriteuser=$n yuuji@213: if [ $((n)) -gt 0 ]; then yuuji@213: query<<-EOF yuuji@213: UPDATE blog_s SET val=(SELECT gname FROM grp WHERE rowid=$mv2grp) yuuji@213: WHERE key='owner' yuuji@213: AND id=(SELECT id FROM blog WHERE rowid=$blogrowid) yuuji@213: AND $mv2grp IN (SELECT growid FROM movablegroups); yuuji@213: EOF yuuji@213: fi yuuji@213: query "END;" yuuji@213: ########## TRANSACTION END yuuji@222: elif { mv2team=`getpar mv2team|sed "s/'/''/g"` yuuji@222: [ -n "$mv2team" ];}; then yuuji@222: # blog owner can move it to ANY team yuuji@222: case "$mv2team" in yuuji@222: 'なし') yuuji@222: cat<<-EOF yuuji@222: DELETE FROM blog_s yuuji@222: WHERE id=(SELECT id FROM blog WHERE rowid=$blogrowid) yuuji@222: AND key='team'; yuuji@222: EOF yuuji@222: ;; yuuji@222: "") ;; yuuji@222: *)cat<<-EOF yuuji@222: BEGIN; yuuji@222: REPLACE INTO blog_s(id, key, val) yuuji@222: VALUES((SELECT id FROM blog WHERE rowid=$blogrowid), yuuji@222: 'team', '$mv2team'); yuuji@222: REPLACE INTO blog_s(id, key, val) yuuji@222: VALUES((SELECT id FROM blog WHERE rowid=$blogrowid), yuuji@222: 'notify', 'all'); -- Change notify to all yuuji@222: END; yuuji@222: EOF yuuji@222: esac | query yuuji@213: fi yuuji@213: blog_reply $blogrowid yuuji@213: echo yes | html p yuuji@79: } yuuji@79: editart() { # $1=article-rowid $2=blogrowid yuuji@79: rowid=${1%%[!A-Z0-9a-z_]*} yuuji@79: blogrowid=${2%%[!A-Z0-9a-z_]*} yuuji@79: if [ -z "$rowid" -o -z "$blogrowid" ]; then yuuji@79: echo "表示する記事番号が未指定です。" | html p yuuji@79: return yuuji@79: fi yuuji@79: owner=`getvalbyid blog owner $blogrowid` yuuji@79: title=`getvalbyid blog title $blogrowid` yuuji@79: author=`getvalbyid article author $rowid` yuuji@356: ## err EDITart: owner=$owner, author=$author yuuji@436: if isgrpowner "$user" "$owner"; then yuuji@79: : EDIT OK yuuji@79: elif [ x"$owner" != x"$user" -a x"$author" != x"$user" ]; then yuuji@79: echo "本人か所有者しか編集できません." | html p yuuji@79: return yuuji@79: fi yuuji@79: aid=`query "select id from article where rowid=$rowid;"` yuuji@81: tmpout=$tmpd/editart.$$.out yuuji@81: GF_ACTION="?replyblog+$blogrowid#$aid" \ yuuji@81: edittable $formdir/article.def article $rowid \ yuuji@81: > $tmpout yuuji@81: rm -f /tmp/editart.out yuuji@81: # Cannot use pipelining to m4 with genform() because of stdin stack yuuji@187: _m4 -D_TITLE_="コメントの修正" -D_DIARY_="" \ yuuji@187: -D_FORM_="syscmd(cat $tmpout)" \ yuuji@187: -D_SUBTITLE_="`gecos $owner`の「$title」" \ yuuji@187: -D_BLOGS_= -D_DUMPTABLE_= \ yuuji@187: $layout/html.m4.html $layout/form+dump.m4.html yuuji@79: } yuuji@79: send2mem() { yuuji@26: rowid=`getpar grp` yuuji@443: rowid=${rowid%%[!0-9]*} # Cleaning yuuji@26: if [ -z "$rowid" ]; then yuuji@61: echo "グループが未指定です。" | html p yuuji@26: return yuuji@26: fi yuuji@26: message=`getpar message` yuuji@117: if [ -z "$message" ]; then yuuji@61: echo "文章を入れてください。" | html p yuuji@26: return yuuji@26: fi yuuji@26: grp=`getgroupbyid $rowid` yuuji@26: members=`collectemail $grp` yuuji@26: # smail rcpt subj (file) yuuji@443: SMAIL_TO="`echo "$grp" | nkf -jM | tr -d '\n'` readers <$admin>" \ yuuji@443: smail "$members" "グループ $grp 宛メッセージ(from `gecos $user`)" <以下のユーザに送信しました。

yuuji@26:
yuuji@443: `collectgecosesbyid "$rowid" | sed 's/$/ さん/'`
yuuji@26: 
yuuji@26:

グループ $grpに戻る。

yuuji@26: EOF yuuji@26: } yuuji@117: joingrpadmit() { yuuji@117: # $1=yes/no $2=session-key yuuji@117: if [ -z "$2" ]; then yuuji@117: echo "bye bye" | html p; return yuuji@117: fi yuuji@117: t_usr=`session=$2 getpar user` yuuji@117: t_grp=`session=$2 getpar group` yuuji@356: ## err joingrpadmit: t_usr=$t_usr, t_grp=$t_grp yuuji@187: _m4 -D_TITLE_="joingrp" $layout/html.m4.html yuuji@117: if [ -z "$t_usr" -o -z "$t_grp" ]; then yuuji@117: echo "無効な加入依頼です。" | html p yuuji@117: echo "有効期限が切れたか、 yuuji@117: 他の管理者がいる場合は処理済みの可能性があります。" | html p yuuji@117: return yuuji@117: fi yuuji@436: if ! isgrpowner "$user" "$t_grp"; then yuuji@117: echo "グループ管理者のみの機能です。" | html p; return yuuji@117: fi yuuji@117: case $1 in yuuji@308: yes) joingrp "$t_grp" "$t_usr" yes ;; yuuji@308: no) joingrp "$t_grp" "$t_usr" no ;; yuuji@117: *) yuuji@117: echo "無効な指定です($1)。" | html p yuuji@117: return ;; yuuji@117: esac yuuji@431: gid=$(query "select rowid from grp where gname=`sqlquote \"$t_grp\"`;") yuuji@117: rcpts="`getgroupadminmails $t_grp` $user" yuuji@356: ## err admit: msgdir=$msgdir, rcpts="["$rcpts"]" yuuji@310: body="グループ $t_grp yuuji@117: に yuuji@117: $t_usr yuuji@117: `[ x$1 = xyes ] && echo 'を追加' || echo 'の解除操作を'` yuuji@117: しました。" yuuji@117: (echo "$body"; echo; echo "$url?grp+$gid") | smail "$rcpts" "joingrp $1" yuuji@117: query "delete from session where id='$2';" yuuji@117: echo "$body" | html p yuuji@117: } yuuji@117: yuuji@117: joingrprequest() { yuuji@117: # $1=group $2=user $3=yes/no $4=email(if any $5=AsAdmin) yuuji@117: jss="joingrp-`date +%s`-`genrandom 12`" yuuji@117: addsession $jss +${memoplimitdays}days yuuji@431: query "replace into par values('$jss', 'group', 'string', `sqlquote \"$1\"`), yuuji@431: ('$jss', 'user', 'string', `sqlquote \"$user\"`);" yuuji@117: smail "$(collectemail `getgroupadmins $1`)" "Join request to $1"< yuuji@397: # .... yuuji@397: # rowclass=foo yuuji@397: # yuuji@397: # To: ....foo yuuji@397: sed -e ' yuuji@397: /^/ { yuuji@397: :loop yuuji@397: s/\n// yuuji@397: N yuuji@397: /<\/TR>/ { yuuji@397: s/\n// yuuji@397: s,^\(.*\)rowclass=\(.*\)\(\),\1\2\3, yuuji@397: n yuuji@397: } yuuji@400: $q yuuji@397: b loop yuuji@397: }' yuuji@397: } yuuji@0: dumptable() { yuuji@13: # $1=mode $2=Table $3=column-list-of-*_s(defaults to *) $4=conditions(if any) yuuji@0: # textのフィールドだけ全てダンプにしたほうがいいか yuuji@0: # $DT_VIEW sets link yuuji@0: # 6/17の次: editリンクじゃなくてスレッドVIEWリンクでいいんちゃう? yuuji@0: ### elink="EDIT" yuuji@0: VIEW=${DT_VIEW-replyblog} yuuji@0: if [ -n "$VIEW" ]; then yuuji@362: dvlink=" VIEW" yuuji@0: fi yuuji@0: # $DT_CHLD=ChildTable:BindColumn yuuji@0: if [ -n "$DT_CHLD" ]; then yuuji@0: _t=${DT_CHLD%:*} _i=${DT_CHLD#*:} yuuji@0: cntall="(select count($_i) from $_t where $_i=a.id)" yuuji@281: # XXX: Dirty workaround for slow subquery of acclog yuuji@281: presql="CREATE TEMPORARY TABLE IF NOT EXISTS myacclog AS yuuji@281: SELECT * FROM acclog WHERE user='$user' and tbl='$2';" yuuji@0: cntnew="(select count(val) from ${_t}_s where key='ctime' \ yuuji@281: and id in (select id from $_t where $_i=a.id) \ yuuji@281: and val > coalesce((select time from myacclog where \ yuuji@281: tblrowid=a.rowid),\ yuuji@281: '1970-01-01'))" yuuji@60: cnt="$cntnew as '新着', $cntall as '総数'," yuuji@252: dt_class=" td2r td3r dumpblogs" yuuji@0: fi yuuji@0: # Construct join expression yuuji@0: eav="" scols="" yuuji@0: pk=`gettblpkey $2` yuuji@397: substr=${dumpcollen:+"substr(%s, 0, $dumpcollen)"} yuuji@397: substr=${substr:-%s} yuuji@0: for col in ${3:-`gettbl_s_cols $2`}; do yuuji@397: valvar=val yuuji@13: case $col in yuuji@60: gecos) scols="$scols${scols:+, }${col#}" yuuji@60: continue ;; # built-in column name yuuji@397: *:*) as=${col#*:} # as can be 稼動状態:frozen=凍結中 yuuji@397: col=${col%%:*} # stage:稼動状態:frozen=凍結中 -> stage yuuji@397: case "$as" in yuuji@397: *:*=*) cnd=${as#*:} yuuji@397: h=${cnd%%=*} v=${cnd#*=} yuuji@397: h=`sqlquotestr "$h"` yuuji@397: v=`sqlquotestr "$v"` yuuji@397: valvar="CASE val WHEN $h THEN $v END" yuuji@397: as=${as%%:*} ;; yuuji@397: esac yuuji@397: ;; yuuji@13: *) as=${col} ;; yuuji@13: esac yuuji@397: ss=`printf "$substr" "$valvar"` yuuji@397: eav=$eav${eav:+,}" max(case key when '$col' then $ss end) as $as" yuuji@13: scols="$scols${scols:+, }b.$as" yuuji@0: done yuuji@0: #case author when '$user' then a.rowid else '---' end as ID, yuuji@175: sql=${DT_SQL:-"select \ yuuji@203: a.rowid as LINK,\ yuuji@0: $cnt\ yuuji@60: $scols from $2 a left join\ yuuji@60: (select $pk,$eav, yuuji@60: max(case key when 'owner' yuuji@207: then (SELECT gecos FROM gecoses WHERE name=val) END) as gecos yuuji@175: from ${2}_s c group by $pk) b on a.$pk=b.$pk $4;"} yuuji@357: ## err dt:SQL="`echo \"$presql$sql\"|tr -d '\n'`" yuuji@397: cat<\)\([1-9][0-9]*\)\(#[0-9a-fxs]*\)*,\1$elink$dvlink," | dt_rowhack yuuji@200:
yuuji@0:
yuuji@0: yuuji@281: `sq -header -cmd ".mode $1" $db "$presql$sql"` yuuji@0:
yuuji@0:
yuuji@200:
yuuji@0: EOF yuuji@0: } yuuji@0: yuuji@0: par2table() ( yuuji@0: # copy current parameters of par into destination table yuuji@0: # $1=definition-file yuuji@0: # Using $user and $session yuuji@80: # Return value: yuuji@80: # 0: Stored successfully yuuji@80: # 1: Insufficient fillings yuuji@80: # 2: No permission to modify the record yuuji@80: # 3: Invalid rowid yuuji@80: # 4: SUCCESS to delete yuuji@80: # 5: Stop deletion for lack of confirm check yuuji@80: # 6: Password length too short yuuji@80: # 7: Password mismatch yuuji@80: # 8: Old password incorrect yuuji@0: rowid=`getpar rowid` yuuji@0: if [ ! -e $1 ]; then yuuji@61: echo "テーブル定義ファイルが見付かりません" | html p yuuji@0: exit 1 yuuji@0: fi yuuji@0: tbl=${1%.def} yuuji@0: tbl=${tbl##*/} yuuji@2: if [ -n "$rowid" ]; then # Modify existing entry yuuji@0: if [ x"$tbl" = x"user" ]; then yuuji@0: rowowner=`query "select name from $tbl where rowid=$rowid;"` yuuji@0: elif [ x"$tbl" = x"grp" ]; then yuuji@13: sql="select gname from $tbl where rowid=$rowid;" yuuji@13: ##err p2t:grp:q $sql yuuji@436: isgrpowner "$user" "`query $sql`" && rowowner=$user yuuji@0: else yuuji@394: # 2016-12-05 There's no owner column in $tbl (need confirmation) yuuji@394: rowowner=`query "SELECT author FROM $tbl WHERE rowid=$rowid;"` yuuji@0: fi yuuji@13: ### err rowowner=$rowowner yuuji@0: if [ x"$user" != x"$rowowner" ]; then yuuji@61: echo "他人のレコードはいじれないの" | html p yuuji@80: return 2 yuuji@0: elif [ -z "$rowowner" ]; then yuuji@61: echo "指定したレコードはないみたい" | html p yuuji@80: return 3 yuuji@0: fi yuuji@0: rm=`getpar rm` cfm=`getpar confirm` yuuji@0: # Editing existent entry yuuji@0: if [ x"$rm" = x"yes" ]; then yuuji@0: if [ x"$rm$cfm" = x"yesyes" ]; then yuuji@0: query "delete from $tbl where rowid=$rowid;" yuuji@80: return 4 yuuji@0: else yuuji@61: echo "消去確認のチェックがないので消さなかったの..." | html p yuuji@80: return 5 yuuji@0: fi yuuji@0: fi yuuji@0: fi yuuji@285: yuuji@285: ts=${tbl}_s tm=${tbl}_m val="" pval="" formaster="" yuuji@285: if [ -n "$rowid" ]; then yuuji@285: # Update of existing record yuuji@285: for col in `gettblcols $tbl`; do yuuji@285: val=`getparquote $col` yuuji@285: [ -z "$val" ] && continue yuuji@356: ## err query "update $tbl set $col=$val where rowid=$rowid" yuuji@285: ## XX: THIS IS DIRTY hack to ensure non-foreign key in blog_s yuuji@285: sql="update $tbl set $col=$val where rowid=$rowid;" yuuji@285: if [ x"$tbl" = x"grp" -a x"$col" = x"gname" \ yuuji@285: -o x"tbl" = x"user" -a x"$col" = x"name" ]; then yuuji@285: ## User name cannot be changed with interface provided with this yuuji@285: ## script. But we offer the trigger to change owner user yuuji@285: ## of blog_s table. yuuji@356: #err "select quote($col) from $tbl where rowid=$rowid;" yuuji@285: old=`query "select quote($col) from $tbl where rowid=$rowid;"` yuuji@285: cat<<-EOF | query yuuji@382: -- Here we cannot use BEGIN-COMMIT because groupupdate() yuuji@382: -- should use EXCLUSIVE transaction outside of this. yuuji@382: SAVEPOINT par2table; yuuji@180: $sql yuuji@180: update blog_s set val=$val yuuji@180: where key='owner' and val=$old; yuuji@382: RELEASE SAVEPOINT par2table; yuuji@180: EOF yuuji@285: ## XX: DIRTY Hack Ends here yuuji@285: ## We should keep blog's owner as a single column which has yuuji@285: ## foreign key constraint with primary key of grp/user. yuuji@180: else yuuji@180: query "$sql" yuuji@180: fi yuuji@0: done yuuji@0: # Then, set up $pval for further insertion of tbl_s and tbl_m yuuji@0: for col in `gettblpkey $tbl`; do yuuji@0: val=`query "select $col from $tbl where rowid=$rowid;"|sed -e 's/\"/\"\"/g'` yuuji@0: pval="$pval${pval:+, }\"$val\"" yuuji@0: done yuuji@285: else yuuji@285: # New entry yuuji@285: # Generate values() for primary keys yuuji@285: for col in `gettblpkey $tbl`; do yuuji@285: # Genuine primary keys for _m and _s yuuji@285: val=`getvalquote $tbl $col` yuuji@285: [ -z "$val" ] && continue yuuji@285: pval="$pval${pval:+, }$val" yuuji@285: done yuuji@356: ##err pval=$pval yuuji@285: for col in `gettblfkey $tbl`; do yuuji@285: # args for values() to insertion into master table yuuji@285: val=`getvalquote $tbl $col` yuuji@285: [ -z "$val" ] && continue yuuji@285: formaster=$formaster"${formaster:+, }$val" yuuji@285: done yuuji@285: formaster="$pval${formaster:+, }$formaster" yuuji@356: ## err formaster=$formaster yuuji@285: if [ -z "$formaster" ]; then yuuji@285: echo "項目を全て埋めてください" | html pre yuuji@285: return 1 yuuji@285: fi yuuji@356: ## err "replace into $tbl values($formaster);" yuuji@285: query "replace into $tbl values($formaster);" yuuji@285: ## Insertion to master table, done yuuji@285: fi yuuji@0: yuuji@285: for kt in s m; do yuuji@285: tb2=${tbl}_$kt yuuji@285: for col in `gettbl_${kt}_cols $tbl`; do yuuji@285: ptype=`getpartype $col "limit 1"` yuuji@0: yuuji@285: # First, check update of existing entries in _m yuuji@285: if [ $kt = m ]; then yuuji@285: # sessID|address.1.22|string|Somewhere-x.y.z yuuji@285: sql="" yuuji@356: ##err dots from query "select var from par where var like '$col.%';" yuuji@285: for v in `query "select var from par where var like '$col.%';"`; do yuuji@285: # v=address.1.22 yuuji@285: st_rowid=${v##*.} yuuji@285: origcol=${v%%.*} # original column derived from yuuji@356: ##err Updating for $v st_rowid=$st_rowid, partype=`getpartype $v` yuuji@285: ##case `getpartype $v` in yuuji@356: ## err CASE `gettbl_coltype $tbl/$origcol` in yuuji@356: ## err edit flag = `getpar action.$v` yuuji@285: case `getpar action.$v` in yuuji@285: rm) yuuji@285: if [ x`getpar confirm.$v` = x"yes" ]; then yuuji@285: newsql="delete from $tb2" yuuji@285: else yuuji@285: echo "削除確認未チェック" | html p yuuji@285: fi ;; yuuji@285: edit) yuuji@285: case `gettbl_coltype $tbl/$origcol` in yuuji@285: image|document|binary) yuuji@285: file=$tmpd/`getparfilename $v` yuuji@356: ## err type=file=$file yuuji@285: [ -z "$file" ] && continue yuuji@322: bn=`sqlquotestr "${file##*/}"` yuuji@326: bin="X'"$(hexize "$file")"'" yuuji@326: ct=`file --mime-type - < "$file" |cut -d' ' -f2` yuuji@285: type=\"file:$ct\" yuuji@322: newsql="update $tb2 set val=$bn, type=$type, bin=$bin" yuuji@285: cachedir=`getcachedir "$tbl/$rowid"` yuuji@285: err getcache tbl/rowid=$tbl/$rowid, rm -r $cachedir yuuji@326: rm -rf $cachedir yuuji@285: ;; yuuji@285: *) yuuji@285: newsql="update $tb2 set val=(select val from par where var \ yuuji@75: like '$col.%.$st_rowid')" yuuji@285: ;; yuuji@285: esac yuuji@285: ;; yuuji@285: *) # maybe "keep", do not modify value yuuji@285: continue yuuji@285: ;; yuuji@285: esac yuuji@285: # err newsql=$newsql yuuji@285: sql=$sql$nl"$newsql where rowid=$st_rowid;" yuuji@285: done yuuji@124: yuuji@285: if [ x"$bin" = x"NULL" ]; then yuuji@356: ## err repl:normal sql=`echo $sql` yuuji@285: query "$sql yuuji@113: delete from $tb2 where type='string' and val='';" yuuji@356: ## err repl:normal done yuuji@285: else yuuji@285: sqlfile="$tmpd/sqlf.$$" yuuji@285: echo "$sql" > $sqlfile yuuji@356: ## err repl:sqlfile=`ls -lF $sqlfile` yuuji@285: query ".read $sqlfile" yuuji@356: ## err repl:done yuuji@285: fi yuuji@285: # Rest of kt==m: set multiple mode yuuji@285: nr=`getparcount $col` yuuji@285: else yuuji@285: nr=1 # for kt==s, number of records is 1 yuuji@285: fi yuuji@0: yuuji@285: i=0 yuuji@285: while [ $i -lt $nr ]; do yuuji@285: limit="limit 1 offset $i" yuuji@285: i=$((i+1)) # increase beforehand against continue yuuji@285: val=`getvalquote $tbl $col "$limit"` yuuji@285: [ -z "$val" -o x"$val" = x'""' -o x"$val" = x"NULL" ] && continue yuuji@356: ## err $col=$val yuuji@356: bin=NULL yuuji@356: ## err partype$col=`getpartype $col "$limit"` yuuji@285: case $ptype in yuuji@285: file) file=$tmpd/`getparfilename $col "$limit"` yuuji@356: ## err parfile-$col=$file yuuji@285: [ -z "$file" ] && continue yuuji@326: bin="X'"$(hexize "$file")"'" yuuji@326: ct=`file --mime-type - < "$file"|cut -d' ' -f2` yuuji@285: type=\"file:$ct\" ;; yuuji@285: "*"*) continue ;; # foreign table yuuji@285: *) type=\"string\" ;; yuuji@285: esac yuuji@285: case `gettbl_coltype $tbl/$col` in yuuji@285: password) # special care for password yuuji@285: # name={password,pswd1,pswd2} yuuji@285: p1=`getpar pswd1 "$limit"` yuuji@285: if [ -z "$p1" ]; then yuuji@285: continue # SKIP password setting, if p1 is empty yuuji@285: else yuuji@285: pswd=`getpar pswd "$limit"` p2=`getpar pswd2 "$limit"` yuuji@0: ## err pswd=$pswd yuuji@285: if pwcheck "$pswd"; then yuuji@285: if [ x"$p1" = x"$p2" ]; then yuuji@285: case "$p1" in yuuji@285: ??????????*) ;; yuuji@285: *) echo "パスワードは10字以上にしてください。" | html p yuuji@285: return 6;; yuuji@285: esac yuuji@285: val="\"`echo $p1|mypwhash`\"" yuuji@285: else yuuji@285: echo "2つの新パスワード不一致" | html p yuuji@285: return 7 yuuji@285: fi yuuji@285: else yuuji@285: echo "旧パスワード違います" | html p yuuji@285: return 8 yuuji@285: fi yuuji@285: fi yuuji@285: ;; yuuji@285: esac yuuji@356: ## err p2t: "replace into $tb2 values($pval, \"$col\", $type, $val, bin...);" yuuji@285: #query "replace into $tb2 values($pval, \"$col\", $type, $val, $bin);" yuuji@285: sql="replace into $tb2 values($pval, \"$col\", $type, $val, $bin);" yuuji@285: if [ x"$bin" = x"NULL" ]; then yuuji@356: ## err Normal-query: `echo $sql` yuuji@285: query "$sql" yuuji@285: else yuuji@285: sqlfile="$tmpd/query.$$" yuuji@285: echo "$sql" > $sqlfile yuuji@356: ## err sqlfile=`ls -lF $sqlfile` yuuji@285: query ".read $sqlfile" yuuji@285: fi yuuji@356: ## err p2t done yuuji@285: done yuuji@285: done yuuji@285: done yuuji@285: return 0 yuuji@285: ##err donee yuuji@0: ) yuuji@0: genform() { yuuji@0: # $1 = form definition file yuuji@0: # $2, $3 (optional)= table name and ROWID yuuji@0: # If $GF_VIEWONLY set and nonNull, output values without form yuuji@219: # If $GF_ARGS set, use it as content-strings in the form yuuji@0: # If $GF_OWNER set, use it as value of name="owner" yuuji@0: # If $GF_STAGE set, use it as value of name="stage" yuuji@0: forms="" hiddens="" rowid=$3 yuuji@0: if [ ! -e "$1" ]; then yuuji@61: echo "そのようなデータベースはないようです($2)。" | html p yuuji@0: return yuuji@0: elif [ -n "$2" ]; then yuuji@0: rec=`query "select * from $2 where rowid='$rowid';"` yuuji@0: if [ -z "$rec" ]; then yuuji@0: pk=`gettblpkey $2` yuuji@0: ###rec=`sq $db "select rowid from $2 where $pk='$rowid'"` yuuji@0: rec=`query "select rowid from $2 where $pk='$rowid';"` yuuji@0: rowid=$rec yuuji@0: rec=$3 yuuji@0: fi yuuji@0: if [ -z "$rec" ]; then yuuji@61: echo "そんなレコードはないみたいね..." | html p yuuji@0: return yuuji@0: fi yuuji@0: fi yuuji@0: if [ -z "$GF_VIEWONLY" ]; then yuuji@0: rm=' yuuji@0: ほんとうに消しますよ(確認)! yuuji@0: はい' yuuji@0: fi yuuji@69: # Image Cache dir yuuji@356: ## err genform: getcache=$2/$rowid yuuji@77: td=`getcachedir "$2/$rowid"` yuuji@0: while IFS=: read prompt name keytype type args; do yuuji@0: [ -z "${prompt%%\#*}" ] && continue # skip comment line(#) yuuji@0: sp="${args:+ }" yuuji@0: form="" val="" yuuji@0: if [ -n "$rowid" ]; then yuuji@141: # err genform2a: Seeking for "$2.$name, type=$type" yuuji@322: rawval=`getvalbyid $2 $name $rowid $td` yuuji@322: val=`echo "$rawval"|htmlescape` yuuji@356: ## err genform3a: getvalbyid $2 $name $rowid $td yuuji@356: ## err genform3b: val="[$val]" type="$type" yuuji@0: fi yuuji@0: if [ -n "$GF_VIEWONLY" ]; then yuuji@0: is_hidden "$2" "$name" && continue yuuji@0: fi yuuji@0: case "$type" in yuuji@0: text*) yuuji@0: cgiform=cgi_multi_$type yuuji@141: if [ -s $td/$name.count -a -n "$val" ]; then yuuji@69: form=`$cgiform $name $td` yuuji@0: val=$(echo "$val"| yuuji@0: while read fn; do yuuji@208: echo "`cat $td/$fn|htmlescape|hreflink` yuuji@208: $nl" yuuji@0: done) yuuji@0: val="$nl$val$nl
" yuuji@0: else yuuji@0: #form="$nl" yuuji@361: form=`cgi_$type $name "$rawval" "$args"` yuuji@0: fi yuuji@0: ;; yuuji@0: [Rr][Aa][Dd][Ii][Oo]) yuuji@100: fh=",g\"`" yuuji@100: ;; yuuji@100: [Cc][Hh][Ee][Cc][Kk][Bb][Oo][Xx]) yuuji@101: form="" yuuji@0: ;; yuuji@0: [Ss][Ee][Ll][Ee][Cc][Tt]) yuuji@0: fh="" yuuji@0: ;; yuuji@0: [Ii][Mm][Aa][Gg][Ee]|[Dd][Oo][Cc][Uu][Mm][Ee][Nn][Tt]|[Bb]inary) yuuji@69: if [ -s $td/$name.count ]; then yuuji@69: form=`cgi_multi_file $name $td "$args"` yuuji@0: if [ -n "$val" ]; then yuuji@0: hrfb="$myname?showattc+$2_m" yuuji@322: val=$(echo "$rawval" \ yuuji@0: | while read fn; do yuuji@326: data=`percenthex "$td/$fn"` yuuji@69: #ct=`cat $td/$fn.content-type` yuuji@326: ct=`file --mime-type - < "$td/$fn"|cut -d' ' -f2` yuuji@326: ri=`cat "$td/$fn.rowid"` yuuji@356: ## err fn=$fn, name=$name, ri=$ri; ls -lF "$td/" 1>&3 yuuji@69: #imgsrc="" yuuji@69: #echo "$imgsrc
" yuuji@472: iconhref2 "$td/$fn" "$hrfb+$ri" "" yuuji@0: done) yuuji@0: fi yuuji@0: else yuuji@0: form="" yuuji@0: if [ -n "$val" ]; then yuuji@326: imgs=$(echo "$rawval"\ yuuji@0: |while read fn;do yuuji@326: data=`percenthex "$td/$fn"` yuuji@0: echo "$fn
" yuuji@0: done) yuuji@0: form=$form"
$imgs" yuuji@0: val=$imgs # 2015-06-15 yuuji@0: else yuuji@0: form="" yuuji@0: fi yuuji@0: fi yuuji@0: ;; yuuji@0: [Hh][Ii][Dd][Dd][Ee][Nn]) yuuji@0: if [ -n "$GF_STAGE" -a x"$name" = x"stage" ]; then yuuji@0: args="value=\"$GF_STAGE\"" yuuji@0: fi yuuji@0: form="" yuuji@0: prompt='' # Remove prompt yuuji@0: ;; yuuji@0: [Aa][Uu][Tt][Hh][Oo][Rr]) yuuji@391: [ -n "$GF_VIEWONLY" ] && continue yuuji@0: form="" yuuji@0: prompt="" ;; yuuji@0: [Oo][Ww][Nn][Ee][Rr]) yuuji@391: [ -n "$GF_VIEWONLY" ] && continue yuuji@0: val=${GF_OWNER:-$val} yuuji@0: val=${val:-$user} yuuji@0: form="" yuuji@0: prompt="" ;; yuuji@0: [Uu][Ss][Ee][Rr]) yuuji@0: # XXX: is null $user ok? yuuji@0: #form="" yuuji@0: [ -n "$GF_VIEWONLY" ] && continue yuuji@0: form="$user" yuuji@0: ;; yuuji@0: [Pp]assword) yuuji@0: [ -n "$GF_VIEWONLY" ] && continue yuuji@0: form="`cgi_passwd`" yuuji@0: val="" yuuji@0: ;; yuuji@0: [Ss][Ee][Rr][Ii][Aa][Ll]|[Ss][Tt][Aa][Mm][Pp]) yuuji@391: [ -n "$GF_VIEWONLY" ] && continue yuuji@127: if [ -z "$rowid" ]; then yuuji@268: val=`genserial` yuuji@127: fi yuuji@67: form="" yuuji@0: prompt="" ;; yuuji@0: [Ss][Ee][Ss][Ss][Ii][Oo][Nn]) yuuji@0: prompt="" yuuji@0: ;; yuuji@0: parent|path|blog*) yuuji@0: prompt="" yuuji@0: ;; yuuji@0: "*"*) yuuji@0: tail=$tail"``" yuuji@0: continue ;; yuuji@0: esac yuuji@0: if [ -n "$prompt" ]; then yuuji@0: if [ -n "${GF_VIEWONLY}" ]; then yuuji@0: form=$val yuuji@0: else yuuji@0: : yuuji@0: fi yuuji@0: forms=$forms" $prompt$form$nl" yuuji@0: else yuuji@0: hiddens=$hiddens$nl"$form" yuuji@0: fi yuuji@0: done < $1 yuuji@0: # enctype="multipart/form-data" yuuji@0: cat< yuuji@0: ${rowid:+$rm} yuuji@0: yuuji@0: $forms yuuji@0:
$hiddens yuuji@13: ${GF_STAGE:+`cgi_hidden stage $GF_STAGE`} yuuji@8: ${rowid:+} yuuji@0: EOF yuuji@0: if [ -z $GF_VIEWONLY ]; then yuuji@0: cat< yuuji@0: yuuji@0: EOF yuuji@0: fi yuuji@0: cat< yuuji@0: $tail yuuji@0: EOF yuuji@0: } yuuji@0: edittable() { yuuji@0: # $1=form-def $2=table $3 rowid yuuji@0: genform "$@" yuuji@0: } yuuji@0: viewtable() { yuuji@0: GF_VIEWONLY=1 genform "$@" yuuji@0: } yuuji@68: showattc() { yuuji@350: # $1=table_m $2=rowid &optional $3=RawFlag yuuji@356: ## err \$1=$1 \$2=$2 \$3=$3 yuuji@68: if ! isfilereadable $user $1 $2; then yuuji@68: contenttype; echo yuuji@68: echo "このファイルは管理者のみしか見られません" | html p yuuji@68: putfooter; exit yuuji@68: fi yuuji@68: idir=`umask 002; mktempd` || exit 1 yuuji@68: # tmpfiles=$tmpfiles"${tmpfiles+ }$idir" yuuji@68: bin=$idir/$myname-$$.bin yuuji@68: sql="select quote(bin) from $1 where rowid='$2';" yuuji@356: ## err showattc: sql: $sql yuuji@68: sq $db "$sql" | unhexize > $bin yuuji@326: tv=`query "select type||'//'||val from $1 where rowid='$2';"` yuuji@326: type=${tv%//*} fn=${tv#*//} yuuji@356: ## err tv=$tv type=$type fn=$fn, tp2=${tv%\|*} yuuji@68: ct=${type#file:} yuuji@68: case $ct in # all text/* changed to text/plain yuuji@68: text/*) yuuji@68: charset=`nkf -g $bin|cut -d' ' -f1` yuuji@68: case $charset in yuuji@68: ASCII*) charset="" ;; yuuji@68: esac yuuji@350: if [ -z "$3" ]; then yuuji@350: ct="text/html${charset:+; charset=$charset}" yuuji@350: link="?showattc+$1+$2+raw" yuuji@395: nkf -e $bin | htmlescape | nkf --oc="$charset" \ yuuji@350: | sed 's,^,,' \ yuuji@350: | _m4 -D_TITLE_="$fn" -D_CONTENT_TYPE_="$ct" \ yuuji@350: -D_LINK_="$link" \ yuuji@350: -D_BODY_="syscmd(\`cat')" $layout/pretty.m4.txt yuuji@350: exit $? yuuji@350: fi yuuji@350: ct="text/plain${charset:+; charset=$charset}" yuuji@68: ;; yuuji@68: esac yuuji@68: contenttype "$ct" yuuji@68: echo "Content-Disposition: filename=\"$fn\"" yuuji@68: echo "Content-Length: " `cat $bin | wc -c`; echo yuuji@68: #echo "Content-Type: " ${type#file:}; echo yuuji@68: cat $bin yuuji@68: } yuuji@78: # yuuji@78: # Some default stupid handler on CGI values yuuji@78: # yuuji@78: default_storedb() { yuuji@78: # ARG: $1=table-def-file yuuji@78: # RET: $tbl=table-name, $col=mail-column, $cols=columns yuuji@78: tbl=`basename $1` yuuji@78: tbl=${tbl%.def} yuuji@78: cols="`grep :text $1|cut -d: -f2`" yuuji@78: col=`echo "$cols"|head -1` yuuji@78: vcol=`getpar $col` yuuji@78: err default0: \$1=$1 col=$col cols="[$cols]" vcol=$vcol yuuji@78: if [ -n "$vcol" ]; then yuuji@78: par2table $1 yuuji@78: else yuuji@78: return 2 # No insertion occurred yuuji@78: fi yuuji@78: } yuuji@78: yuuji@78: default_view() { # $1=def-file yuuji@78: ### DT_VIEW="edittable+$tbl" dumptable html $tbl "$cols" \ yuuji@78: ## DT_VIEW="edittable+$tbl" dumptable html $tbl "name memo file" \ yuuji@78: default_storedb "$@" yuuji@78: query "select rowid from $tbl order by rowid desc;" \ yuuji@78: | while read rowid; do yuuji@78: viewtable $1 $tbl $rowid yuuji@187: done | _m4 -D_TITLE_="$tbl" \ yuuji@187: -D_FORM_="`genform $1`" \ yuuji@187: -D_DUMPTABLE_="syscmd(cat)" \ yuuji@187: $layout/html.m4.html $layout/form+dump.m4.html yuuji@78: } yuuji@78: default_viewtext() { # $1=def-file yuuji@78: ### DT_VIEW="edittable+$tbl" dumptable html $tbl "$cols" \ yuuji@78: default_storedb "$@" yuuji@78: DT_VIEW="viewtable+$tbl" dumptable html $tbl "name memo file" \ yuuji@187: | _m4 -D_TITLE_="$tbl" \ yuuji@187: -D_FORM_="`genform $1`" \ yuuji@187: -D_DUMPTABLE_="syscmd(cat)" \ yuuji@187: $layout/html.m4.html $layout/form+dump.m4.html yuuji@78: } yuuji@78: default_smail() { yuuji@78: default_storedb "$@" yuuji@78: if [ $? -eq 2 ]; then yuuji@187: _m4 -D_TITLE_="入力" \ yuuji@187: -D_FORM_="`genform $1`" \ yuuji@187: -D_DUMPTABLE_="" \ yuuji@187: $layout/html.m4.html $layout/form+dump.m4.html yuuji@78: return yuuji@78: fi yuuji@78: cond="" yuuji@78: for pk in `gettblpkey $tbl`; do yuuji@431: pv=$(sqlquote "$(getpar $pk)") yuuji@78: cond="$cond${cond:+ and }$pk=$pv" yuuji@78: done yuuji@78: sql="select rowid from $tbl where $cond;" yuuji@78: rowid=`query "$sql"` yuuji@356: ## err smail1 - "$sql" "-> rowid=$rowid" yuuji@78: yuuji@78: while IFS=: read prompt name keytype type args; do # Read from $1 yuuji@78: val=`getpar $name` yuuji@78: if [ -n "$val" ]; then yuuji@78: text="$text yuuji@78: $prompt yuuji@78: $name=$val yuuji@78: ---------------------------------------------------------" yuuji@78: fi yuuji@78: case "$type" in yuuji@78: image|document|file) yuuji@78: fn="`getvalbyid $tbl $name $rowid $tmpd`" yuuji@78: fns=$(echo "$fn"|while read fn; do yuuji@78: err mv $tmpd/$fn.orig $tmpd/$fn yuuji@78: mv $tmpd/$fn.orig $tmpd/$fn yuuji@78: rm $tmpd/$fn.rowid # Remove cache flag yuuji@356: ## err "`ls $tmpd/$fn`" yuuji@78: echo $fn yuuji@78: done) yuuji@78: files="$files $fns" yuuji@78: ;; yuuji@78: esac yuuji@78: done < $1 yuuji@356: ## err FILES=$files "`ls -lF $tmpd`" yuuji@78: subj="from ${REMOTE_ADDR}" yuuji@102: (echo "$url" yuuji@78: echo "への書き込みがありました。" yuuji@78: echo "------" yuuji@78: echo "$text" yuuji@78: ) | (cd $tmpd && yuuji@78: err LS="`ls -lF`" && yuuji@78: $mydir/sendmultipart.sh -t "$admin" -s "$subj" $files) yuuji@187: _m4 -D_TITLE_="入力完了" $layout/html.m4.html yuuji@78: echo "以下の内容で送信しました。" | html p yuuji@78: viewtable $1 $tbl \ yuuji@78: `query "select rowid from $tbl order by rowid desc limit 1;"` yuuji@78: echo "戻る" | html a "href=\"?\"" yuuji@78: }