# HG changeset patch # User HIROSE Yuuji # Date 1437281501 -32400 # Node ID 6822f4362bf915e1ff8c20c87e0b1276e6dd78be # Parent 95cebd686c97f4b265b708360fe1c0ee49be63d5 New system name declared as yas4 diff -r 95cebd686c97 -r 6822f4362bf9 se-blog.sh --- a/se-blog.sh Sat Jul 18 23:44:21 2015 +0900 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,382 +0,0 @@ -# -type cgiinit >/dev/null 2>&1 || . ./se-funcs.sh - -blog_genform() { - # - t=$1 -} - -blog_writable() ( - # $1=articleid $2=user - blogowner=`getvalbyid blog owner "$1"` - [ x"$blogowner" = x"$2" ] || isuser "$blogowner" || ismember "$2" "$blogowner" -) -blog_notify_reply() { - # $1=articleid $2=ReplyingUser $3=WrittenText - blogowner=`getvalbyid blog owner "$1"` - blogtitle=`getvalbyid blog title "$1"` - blogurl="$urlbase?replyblog+$1" - emails=`collectemail $blogowner` - smail "$emails" "書込通知 $urlbase"< /'` -EOF -} -blog_showentry() { - # $1=table $2=rowid - if [ -n "$2" ]; then - if [ -n "$imgcached" ]; then - tmpd=$tmpdir/$imgcached/$thumbxy - else - tmpd=`mktempd` - tmpfiles=$tmpfiles" $tmpd" - fi - fi - tbl=${1%%[!A-Z0-9a-z_]*} rowid=${2%%[!A-Z0-9a-z_]*} -err rowid=$rowid, '$2'=$2 - ts=${tbl}_s tm=${tbl}_m - at=article as=article_s am=article_m - serial=$(($(date +%s)-1420038000))s$$ - # This function grasps blog entry definiton directly. - # blog: id - # blog_s: title,ctime,heading - # blog_m: *article - - err "SELECT id from $tbl where rowid=$rowid" - id=`query "select id from $tbl where rowid=$rowid;"` -err id=$id -err "select val from $ts where key='title' and id='$id';" - - - #(1)Display root article - cat< - -EOF - - href=" 編集 " - href2=" 提出状況 " - href3="(ファイル取得)" - cat<\)|$href2$href3\1|" --- select val from $ts where key="title" and id="$id"; -select - coalesce((select ",e," from blog where rowid=$rowid and author='$user'),'') -||val||" " -||case (select val from $ts where key="mode" and id="$id") - when 'report-closed' then "レポート提出用(自身のファイルのみ参照可),s," - when 'report-open' then "レポート提出用,s," - else "" - end - from $ts where key="ctime" and id="$id"; -select val from $ts where key="heading" and id="$id"; -EOF - cat< -
\),e,|\1 $href |" \ - -e "s|,s,\(
-EOF - - #(2)Display following articles -textform='
- - -
添付ファイル:
- - -' - ## 6/11の次: articleを出して行く -: <&3 - #case $ct in - # [Ii]mage*) anch="$fn" ;; - # *) anch=$fn ;; - # esac - # Should not contain newlines for sed argument - # echo -n "$anch" - iconhref $td/$fn "$hrfb+$ri" "$fn" "$fn" - done) - fi - fi - - ### number=$((number+1)) -# reply="" - getgecos="(select rowid from user where name='$author')||':'||\ - coalesce((select val from user_s \ - where name='$author' and key='gecos'), '$author')||',[/a],'" - href="$myname?editart+$arid+$rowid" - link="編集" - cat<|" \ - -e 's|,\[/a\],||' \ - -e 's/,n,/
/g' -e "s|,i,|$imgs|" \ - -e "s|\(\)|\1|" \ - -e "s|\(\)\(\),e,|\1\2$link|" -select - coalesce((select ",e," from article where id='$aid' and author='$user'),"") - || - max(case key when 'ctime' then ",n,"||val|| - ",n,"||$getgecos end) as TIME, --- max(case key when 'parent' then val||"への返信" end) as REPLYTO, - max(case key when 'text' then val||",i," end) as TEXT - from article_s where id = '$aid' - group by id order by TIME; -EOF - done - echo "" - - - blog_writable $rowid $user && cat< -

コメント記入

- - - -$textform - -EOF - echo "" - - # Record access log - acclog blog $rowid -} - -lshandout() { - # $1=rowid of blog - time=`getvalbyid blog ctime $1|colrm 11` - owner=`getvalbyid blog owner $1` - title=`getvalbyid blog title $1` - ge=`gecos $owner` - lshandoutsub $owner "$@" \ - |m4 -D_TITLE_="提出状況" \ - -D_SUBTITLE_="$time [$title]@${ge:-$owner}" -D_DIARY_="" \ - -D_FORM_="syscmd(cat)" -D_BLOGS_= -D_DUMPTABLE_= \ - $layout/html.m4.html $layout/diary.m4.html -} -lshandoutsub() { - # $1=owner $2=rowid of blog - if isgroup $1; then - sample="(select user from grp_mem where gname='$1')" - else - sample="(select distinct author as user from arts)" - echo "

(集計は板への投稿者のみ)

" - fi - sql="with arts as (select id,author from article \ - where blogid=(select id from blog where rowid=$2))\ - select (select rowid from user where name=c0.user)||' '|| \ - coalesce((select val from user_s where name=c0.user \ - and key='gecos'),\ - c0.user) as 'メンバー',\ - sum(case when c1.key is not null then 1 else 0 end)\ - as 'コメント記入',\ - sum(case when c2.key is not null then 1 else 0 end)\ - as 'ファイルの提出'\ - from $sample c0 \ - left join (select id,author from arts) a\ - on c0.user=a.author\ - left join (select id,key from article_s where key='text') c1\ - on a.id=c1.id left join (select id,key from article_m ) c2\ - on c1.id=c2.id group by c0.user order by c0.user;" - err ishandoutsub: sql="$sql" - echo '' - hrb=",\1$hrb\2\">\3," -e 's,,,' - echo '
\)\([^ ]*\) \(.*\)00
' -} -gethandout() { - # $1=rowid of blog - i=0 - bd=$tmpd/archive.$$ - mkdir $bd - query "select m.rowid,author,m.val from article a join article_m m\ - on a.id=m.id where blogid=(select id from blog where rowid=$1)\ - and m.key in ('image', 'document', 'binary');" \ - | while IFS='|' read rowid author filename; do - # err isfilereadable $user article_m $1 - isfilereadable $user article_m $1 || continue - err ok - i=$((i+1)) - dir=`printf $bd/%03d $i` - mkdir $dir - query "select quote(bin) from article_m where rowid=$rowid;" \ - | xxd -r -p > $dir/$filename - done - if [ ! -d $bd/001 ]; then - contenttype; echo - echo "

取得できるファイルがありませんでした。

" - return - fi - (cd $bd - err cdto$bd; (pwd; ls -lFa) 1>&3 - tar zcf .archive.tar.gz * && mv .archive.tar.gz archive.tar.gz - ) - arc=$bd/archive.tar.gz - echo "Content-type: application/x-gzip" - echo "Content-Length: `cat $arc|wc -c`" - echo "Content-Disposition: filename=\"archive.tar.gz\"" - echo - cat $arc -} - -listblog() ( - # $1=user - cond="where a.id in (select id from blog_s where key='owner' and val='$1') order by ctime desc" - DT_CHLD=article:blogid - cgi_form searchart<`cgi_text kwd`という語を含む記事を検索 -`cgi_hidden owner $user` -EOF - dumptable html blog 'ctime title heading' "$cond" -) - -blog_addentry() { - # $1=GRPname(if it is a group) - grp=$1 - rowid=`getpar rowid` -err ba: rowid=$rowid - #if [ -z "$rowid" ]; then - # When rowid is SET, it is updation of existing entry - if [ -z "$1" ]; then - listing=$user guide="[個人]" -#listing代入は rowid 時でもするべき - else - if isgroup $1; then - listing=$1 guide="[${1}]" GF_OWNER=$1 - else - echo "

無効なグループ指定です。

" - return - fi - fi - #fi - if [ -n "`getpar title`" ]; then - owner=`getpar owner` - if isuser $owner; then - if [ x"$user" != x"$owner" ]; then - echo "

他人の日記は書けません

" - return - fi - elif isgroup $owner; then # if write to group log - grp=$owner #\`getpar grp\` - err ismember: $user $grp - if ! ismember "$user" "$grp"; then - echo "

(話題作成はこのグループに加入してから)

" - return - fi - fi - par2table $formdir/blog.def - serial=`getpar serial` - err SERIAL: $serial ROWID=$rowid listing=$listing - id="" - if [ -n "$rowid" ]; then - # Here, id becomes NULL when removal of entries at par2table - id=`query "select rowid from blog where rowid=$rowid;"` - elif [ -n "$serial" ]; then - # If new blog leader created, traverse to its head. - id=`query "select rowid from blog where id='$serial';"` - fi - if [ -n "$id" ]; then - ## If new aritcle is entered, JUMP to blog_reply - blog_reply $id - return - fi - fi - m4 -D_TITLE_="${guide}新規話題作成" -D_DIARY_="新規話題の記入" \ - -D_SUBTITLE_="序文は簡単に詳しくはコメントに" \ - -D_BLOGS_="これまでの蓄積" \ - -D_FORM_="`genform $formdir/blog.def`" \ - -D_DUMPTABLE_="`listblog $listing`" \ - $layout/html.m4.html \ - $layout/diary.m4.html -} - -blog_reply() { - rowid=$1 -err rowid=$1 - - if [ -z "$rowid" ]; then - echo "

表示する日記番号が未指定です。

" - return - fi - title=`getvalbyid blog title $rowid` - owner=`getvalbyid blog owner $rowid` - if isuser "$owner"; then - subtitle="`gecos $owner` さんの話題" - else - subtitle="
$owner での話題" - fi - if [ -z "$title" ]; then - echo "

日記番号指定が無効です。

" - return - fi - - text=`getpar text` - if [ -n "$text" ]; then - if blog_writable $rowid $user; then - if par2table $formdir/article.def; then - blog_notify_reply $rowid $user "$text" - fi - else - title="$title(加入してないので書き込み不可)" - fi - fi - def=$formdir/article.def - cat $layout/html.m4.html $layout/diary.m4.html \ - | sed '/_DIARY_/q' \ - | m4 -D_TITLE_="$title" -D_DIARY_="" -D_BODYCLASS_=general \ - -D_SUBTITLE_="$subtitle" - blog_showentry blog $rowid - sed '1,/_DIARY_/d' $layout/diary.m4.html | m4 -D_FORM_= -D_DUMPTABLE_= -} diff -r 95cebd686c97 -r 6822f4362bf9 se-cgi.sh --- a/se-cgi.sh Sat Jul 18 23:44:21 2015 +0900 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,108 +0,0 @@ -# -# cgi functions -# -cgi_form() { - # $1=stage - : ${myname:?'Sure to set $myname to this script name'} - cont=`cat` - cat< -$cont - - - - -EOF -} -cgi_submit() { - cat< -EOF -} -cgi_radio() { - echo "" -} -cgi_hidden() { - echo "" -} -cgi_passwd() { - cat< - 現パスワード - 新パスワード - 新パスワード(確認) - -EOF -} -cgi_text() { - echo "" -} -cgi_textarea() { - cat<$2 -EOF -} -cgi_file() ( # In a subshell - # $1=name $2=val(as filename) $3=args(if any) - # Using global variable $dir - if [ -s $dir/$2 -a -s $dir/$2.content-type ]; then - file=$dir/$2 - bn=${file##*/} - ct=`cat $dir/$2.content-type` - data=`percenthex $file` - icon="" - fi - cat< -EOF -) -cgi_multi() ( - # $1=name $2=dir $3=func $4=args... - # `dir' should contain $name.count and $name.N where N is 1 upto N - i=1 name=$1 dir=$2 func=$3 - n=`cat $dir/$name.count` - echo '' - while [ $i -le $n ]; do - file=$name.$i ctf=$dir/$name.content-type - vname=$file.`cat $dir/$file.rowid` - if [ -s $ctf ]; then - case `cat $ctf` in - *:[Ii]mage:*) - - ;; - - esac - fi - val="`cat $dir/$file`" - cat< -EOF - i=$((i+1)) - done - cat< -
($i) - - - -
-`$func $vname "$val" "$4"`$val -
(新規)`$func $name "" "$4"`
-EOF -) -# In these functions, $2 should be quoted because it can be null -cgi_multi_text() { - cgi_multi $1 "$2" cgi_text "$3" -} -cgi_multi_textarea() { - cgi_multi $1 "$2" cgi_textarea "$3" -} -cgi_multi_file() { - # $1=name $2=val(filename) - cgi_multi $1 "$2" cgi_file "$3" -} diff -r 95cebd686c97 -r 6822f4362bf9 se-funcs.sh --- a/se-funcs.sh Sat Jul 18 23:44:21 2015 +0900 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1805 +0,0 @@ -#!/bin/sh -# Here's global variable table. Do not use this names. -# $HGid$ -myname=`basename ${SCRIPT_NAME:-$0}` -mydir=`dirname ${SCRIPT_FILENAME:-$0}` -myargs="$@" -#bindir=`(cd $mydir/bin; pwd)` -# :$bindir -PATH=/usr/local/sqlite3/bin:/usr/local/vim7/bin:/usr/local/ImageMagick/bin:$PATH -tmpdir=${TMPDIR:-tmp} -dbdir=${DBDIR:-db} -tmpfiles="" -db=${DB:-$dbdir/cgi.sq3} -admin=wwwadmin@gentei.org -templ=${TEMPL:-templ} -layout=$templ/default -formdir=$templ/form -imgdir=img -url=${URL:-"${REQUEST_SCHEME}://$HTTP_HOST$REQUEST_URI"} -urlbase=${url%%\?*} -msg=$templ/msg -timeout="+2 days" -conftbl=_tblconf -dumpcollen=20 -thumbxy=120x120 -thumbxy=96x96 -maximagexy=1600x1600 -### maximagexy=400x400 -tconfs="" -imgcached=imgcache.`date +%Y/%m` -nl=" -" -. ./se-cgi.sh - -: < "hoge", "owner" => "yuuji", "date" => "2015-04-27", - "text" => "hogehoge ..", - "reply" => [ {"serial" => 1, - "author" => "taro", - "date" => "2015-04-28", - "parent" => "/", - "path" => "/1", - "text" => "blah, blah, ....", - "image" => ["a.jpg", "b.jpg"] }, - {"serial" => 2, - "author" => "hanako", - "date" => "2015-04-29", - "parent" => "/", - "path" => "/2", - "text" => "blah, blah, ....", - "image" => [] }]}, - {"title" => "buha", ...} ] - - -user:= - ユーザ名(英数字):name:p:text:length="20" maxlength="40" - パスワード:pswd:s:password:length="20" maxlength="40" - 説明(日本語OK):gecos:s:text:length="20" maxlength="40" - セッションキー:skey:s:session - メイルアドレス:email:m:text:length="20" maxlength="40" - 住所:address:m:textarea:maxlength="400" - プロフィール画像:profimg:m:image:maxlength="400K" - 履歴書:profpdf:m:document:maxlength="4M" - -変換表 -/user/email=m - -blog:= - シリアル:id:p:serial - タイトル:title:s:text: - 所有者:owner:s:owner: - 時刻:ctime:s:stamp: - リード文:heading:s:textarea: - リプライ:reply:m:*article: - -article:= - シリアル:id:p:serial - 筆者:author:s:owner - 時刻:ctime:s:stamp: - 参照元:parent:s:parent: - パス:path:s:path: - 本文:text:s:textarea: - 画像:image:m:image: - -履歴書:profpdf:m:document:maxlength="4M" - - -EOF - -sq() { - # ./args.rb -cmd ".timeout 3000" "$@" - sqlite3 -cmd 'PRAGMA foreign_keys=ON' -cmd ".timeout 3000" "$@" -} -####XXXXXXXXXXXXXXXXXXXXXX 場所移動 -sqi=/tmp/sqi.$$ -sqo=/tmp/sqo.$$ -mkfifo $sqi $sqo -tail -f $sqi | sq $db & -sq3pid="`jobs -p` $!" - -query() { - cat< $sqi -.once $sqo -$@ -EOF - cat $sqo -} -exec 3>> $tmpdir/debug.out -exec 2>> $tmpdir/error.out -err() { - echo "$@" 1>&3 -} - -_m4() { - -} -ismember() { - # $1=user, $2=group -err ismem: "select user from grp_mem where gname='$2' and user='$1';" - test -n "`query \"select user from grp_mem where gname='$2' and user='$1';\"`" -} -isuser() { # Check if $1 is a valid user - test -n "`query \"select name from user where name='$1';\"`" -} -isgroup() { # Check if $1 is a valid group - test -n "`query \"select gname from grp where gname='$1';\"`" -} -isgrpowner() { - # $1=user, $2=group - test -n "`query \"select user from grp_adm - where gname='$2' and user='$1';\"`" -} -isfilereadable() { # $1=user $2=tbl $3=rowid - # Return true if user($1) can read attachment files in tbl($2):rowid($3) - [ -z "$1" -o -z "$2" -o -z "$3" ] && return 1 # invalid argument - - # case `getvalbyid blog mode $2` in - # normal|*open*|"") return 0 ;; - # *closed*) - # owner=`getvalbyid blog owner $2` - # if isgrp $owner; then - # isgrpowner $1 $owner && return 0 || return 1 - # elif isuser $owner; then - # [ x"$1" = x"$owner" ] && return 0 || return 1 - # fi - # esac - # ↑ 要はこういう処理を↓で一気にやっている - sql="with getblog as (\ - select key,val from blog_s where id=(\ - select blogid from article where id in\ - (select id from $2 where rowid=$3))),\ - getowner as (select val from getblog where key='owner'),\ - getmode as (select val from getblog where key='mode')\ - select case\ - when (select author from article where\ - id=(select id from $2 where rowid=$3))='$1' \ - then 'author'\ - when (select val from getmode) in ('report-open', 'normal')\ - then 'open'\ - when (select val from getmode) is null \ - then 'open' - when (select val from getowner) in (select gname from grp)\ - then (select user from grp_adm where \ - gname=(select val from getowner) and \ - user='$1')\ - else 'user' end;" - err isfilereadable: sql="$sql" - # caseのネストで内側のcaseがスカラーtrueを返しても外側はtrue扱いにならない - result=`query "$sql"` - [ -n "$result" ] && return 0 - return 2 -} -linkhome() { - # $1=UserOrGroup - echo -n '`gecos $1`" -} -acclog() { - # $1=table, $2=rowid - if [ -n "$2" ]; then - now=`date +"%F %T"` - query "replace into acclog values('$user', '$1', '$2', '$now');" - fi -} -gecos() ( - u=${1:-$user} - #gecos=`query "select val from user_s where name='$u' and key='gecos';"` - sql="select case when (select name from user where name='$u') is not null - then (select val from user_s where name='$u' and key='gecos') - when (select gname from grp where gname='$u') is not null - then (select val from grp_s where gname='$u' and key='gecos') - else '$u' - end;" - query "$sql" -) -getpar() { -err getpar: "select val from par where var='$1' and sessid='$session' $2;" - val=`query "select val from par where var='$1' and sessid='$session' $2;"` - if [ -z "$val" ]; then - val=`query "select val from cookie where var='$1' and sessid='$session' $2;"` - fi - case "$var" in - owner) - if [ x"$user" = x"$val" ]; then - echo $user; return - elif ismember $user $val; then - echo $val; return - fi ;; - esac - echo "$val" -} - -getpartype() { - query "select type from par where var='$1' and sessid='$session' $2;" -} -getparcount() { - query "select count(*) from par where var='$1' and sessid='$session' $2;" -} -getparfilename() { - # null if type of $1 is not file - (f=`query "select val from par where var='$1' and sessid='$session' and type='file' $2;"` - [ -n "$f" ] && echo $tmpdir/$f) -} -sqlquote() { - (v="$1" - case "$v" in - "") return ;; # null - "X'"*) # quoted hex string - echo $1 ;; - *\"*) # string including dbl-quote" - v=`echo "$v"|sed -e 's/\"/\"\"/g'` - echo "\"$v\"" - return ;; - *.*.*|*-*-*|*[Ee]*[Ee]*|[Ee]*|*[\ -,:-df-~]*) # string - echo "\"$v\"" - return ;; - *) - if expr "$v" : '[-0-9.Ee][-0-9.Ee]*$' >/dev/null 2>&1; then - echo $v # MAYBE numeric, maybe... - else - echo "\"$v\"" - fi ;; - esac) -} -mktempd() { - mktemp -d -p $tmpdir/ -t $session -} -getval() { - # $1=table $2=col $3(optional)=condition - case `gettbl_coltype "/$1/$2"` in - user|author) # author added 2015-06-18 for article(author) - echo "$user" ;; - stamp|datetime) - date "+%F %T" ;; - serial) - (s=`getpar serial` - if [ -n "$s" ]; then echo $s; else echo "`date +%s`x$$"; fi) ;; - *) - getpar "$2" "$3";; - esac -} - -getvalquote() { - # $1=table $2=col $3(optional)=condition - (v=`getval "$@"` - case "$v" in - "") echo NULL ;; - *) sqlquote "$v" ;; - esac) -} -getparquote() { - sqlquote `getpar $1` -} -getvalbyid() { - # $1=tbl $2=col $3=rowid $4=tmpdirForBinary - # If two or more values found, save them to $tmpd/${column}.$N and - # store the number of files into $tmpd/${column}.count and - # their each rowid stored into $tmpd/${column}.$N.rowid. - ### err gtb-$1=`gettblcols $1`, tbl=$1, col=$2, '$3'=$3 - (for c in `gettblcols $1`; do - if [ x"$2" = x"$c" ]; then - err "select $2 from $1 where rowid=$3" - ###sq $db "select $2 from $1 where rowid=$3" - query "select $2 from $1 where rowid=$3;" - return - fi - done - pk=`gettblpkey $1` -# key=`sq $db "select $pk from $1 where rowid=$3"` - key=`query "select $pk from $1 where rowid=$3;"` - ### err "select $pk from $1 where rowid=$3" - key=$key '$4(tmp)'=$4 - for kt in s m; do - td=${4:-$tmpdir} - [ -d $td ] || mkdir -p $td - t=${1}_$kt - for c in `gettbl_${kt}_cols $1`; do - vcount=1 # count(val) - if [ x"$2" = x"$c" ]; then - cond="$t where $pk=\"$key\" and key=\"$c\"" - ###val=`query "select val from $cond;"` - val=`query "select val from $cond limit 1;"` - ###type=`query "select type from $cond;"` - type=`query "select type from $cond limit 1;"` - if [ $kt = m ]; then - ###vcount=`sq $db "select count(val) from $cond"` - # Reset val to store filenames if type is string - val=`query "select val from $cond and type like 'file:%' order by rowid;"` - vcount=`query "select count(val) from $cond;"` - echo $vcount > $td/$c.count - i=0 - while [ $i -lt $vcount ]; do - slice="order by rowid limit 1 offset $i" - i=$((i+1)) - fn=$c.$i -##err td=$td, fn=$fn, type=$type, val="[$val]" - case $type in - file:*) - #file=$td/$val - file=$td/`query "select val from $cond $slice;"` -####tmp [ -s $file -a -s $td/$fn.rowid ] && continue - sq $db< $file -.output $td/$fn.rowid -select rowid from $cond $slice; -.output $td/$fn -select val from $cond $slice; -.output $file.content-type -select substr(type, 6) from $cond $slice; -.output stdout -select quote(bin) from $cond $slice; -EOF - ## err i=$i - file=$file rowid=`cat $td/$fn.rowid` - ln $td/$fn.rowid $file.rowid 2>&3 # for convenience - case $type in - *:[Ii]mage*) mogrify -geometry $thumbxy $file ;; - ### ここのアイコンを増やしたい - *|*:[Aa]pplication*) - convert -geometry $thumbxy $imgdir/file-icon.png \ - png:- > $file - ;; - esac - ;; - *) - sq $db< $file - echo ${type#file:} > $file.content-type -# err TTTTTTTTTTTTTTTT: $type - case $type in - *:[Ii]mage*) mogrify -geometry $thumbxy $file ;; - *:[Aa]pplication*) - convert -geometry $thumbxy $imgdir/file-icon.png \ - png:- > $file ;; - esac - fi - done - ;; - esac - fi - echo "$val" # Keep newlines by "" - return - fi - done - done) -} -getvalbypkey() ( - # $1=tbl $2=col $3=pkey $4=tmpdirForBinary - pk=`gettblpkey $1` - rowid=`query "select rowid from $1 where $pk='$3';"` - getvalbyid "$1" "$2" $rowid $4 -) -getvalbycond() { - # $1=tbl $2=col $3=SQL-Condition - ###rowid=`sq $db "select rowid from $1 where $3"` - rowid=`query "select rowid from $1 where $3;"` - if [ -n "$rowid" ]; then - getvalbyid "$1" "$2" $rowid "$4" - fi -} -getpwfield() { - # getpwfield user column -# val=`sqlite3 $db "select $2 from passwd where name='$1' $3"` - val=`getvalbycond user $2 "name='$1'"` - if [ -n "$val" ]; then - echo "$val" - return 0 - else - return 1 - fi -} -encode() { - if [ -z "$sha1" ]; then - if type sha1 >/dev/null 2>&1; then - sha1=sha1 - elif type sha1sum >/dev/null 2>&1; then - sha1=sha1sum - elif type gsha1sum >/dev/null 2>&1; then - sha1=gsha1sum - fi - fi - $sha1 "$@" | cut -d' ' -f1 -} -mycrypt() ( - key=$1 salt=$2 -err \$2=$2 - case $2 in - '$'*'$'*) salt=${salt#\$4\$} - salt=${salt%\$*} ;; - esac - echo -n '$4$'"$salt"'$' - echo "$salt$key" | encode -) -hexize() { - if [ -z "$hexize" ]; then - if type xxd >/dev/null 2>&1; then - hexize="xxd -p" - else - hexize="hexdump -ve '1/1 \"%.2x\"'" - fi - fi - cat $1 | $hexize | tr -d '\n' -} -percenthex() { - hexize $1 | sed 's/\(..\)/%\1/g' -} -enascii() { - if [ -z "$enascii" ]; then - if type kakasi >/dev/null 2>&1; then - enascii="kakasi -Ha -Ka -Ja -Ea -ka" - else - enascii_now=`date +%FT%T` - enascii_sed() { - nkf -Z0Z1Z2 \ - | sed -e "s/^/$enascii_now/" -e "s|[^-0-9.A-z/,()_=]|x|g" - } - enascii="enascii_sed" - fi - fi - cat "$@" | $enascii -} -gettblconf() { - if [ -z "$tconfs" ]; then -## tconfs=`sq $db \ - tconfs=`query \ - "select tbl||'/'||col||'='||keytype||'/'||objtype from $conftbl;"` - fi - # /tb1/col1=p/text /tb1/col2=s/text /tb1/col3=m/image /tb2/col1=p/text ... -} -gettblkeys() { - # $1=tbl - gettblconf - echo "$tconfs" | fgrep "/$1/" | \ - (type="" keys="" fks="" cols="" scols="" mcols="" hcols="" - while IFS='=' read tc conf; do # tc=/tb1/col1 conf=s/text - col=${tc##*/} type=${conf%%/*} - case $type in - *p*) - cols=$cols"${cols:+:}$col" - keys=$keys"${keys:+:}$col" ;; - *f*) cols=$cols"${cols:+:}$col" - fks=$fks"${fks:+:}$col" ;; - *m*) mcols=$mcols"${mcols:+:}$col" ;; - *s*) scols=$scols"${scols:+:}$col" ;; - esac - case $type in - *h*) hcols=$hcols"${hcols:+:}$col" ;; - esac - done - echo "_keys=$keys _fks=$fks _cols=$cols _scols=$scols _mcols=$mcols _hcols=$hcols") -} -gettblpkey() { - # $1=tbl - gettblkeys $1 | cut -d ' ' -f 1 | sed -e 's/.*=//' -e 's/:/ /g' -} -gettblfkey() { - (x=`gettblkeys $1` - x=${x#*_fks=} # cut before "_fks=" including - echo ${x%% *} | tr ':' ' ') -} -gettblcols() { - (x=`gettblkeys $1` - x=${x#*_cols=} # cut before "_cols=" including - echo ${x%% *} | tr ':' ' ') -} -gettbl_s_cols() { - (x=`gettblkeys $1` - x=${x#*_scols=} # cut before "_scols=" including - echo ${x%% *} | tr ':' ' ') -} -gettbl_m_cols() { - (x=`gettblkeys $1` - x=${x#*_mcols=} # cut before "_mcols=" including - echo ${x%% *} | tr ':' ' ') -} -gettbl_h_cols() { - (x=`gettblkeys $1` - x=${x#*_hcols=} # cut before "_hcols=" including - echo ${x%% *} | tr ':' ' ') -} -gettbl_coltype() ( - gettblconf - x=`echo "$tconfs"|fgrep $1=` - x=${x#*=} # cut before = - echo ${x#*/} # cut before p/ including -) -is_hidden() { - # $1=Tbl $2=col - gettblconf - x=`echo "$tconfs"|fgrep /$1/$2=` - x=${x#*=} # cut before = - x=${x%%/*} # cut after / - case $x in - *h*) return 0 ;; - *) return 1 ;; - esac -} - -dbsetbyid() { - # $1=tbl $2=id $3=col $4=val/filename - &optional - $5=content-type - (t0=$1 t=$1 p=$2 c=$3 - tsc=$t/$c val=$4 - unset primary update - gettblconf -#err tsc=$tsc, tconfs="$tconfs" - conf=`echo "$tconfs"|fgrep "$tsc"=` -#err conf=$conf - case ${conf#*=} in - p*) primary=1 ;; - f*) update=1 ;; - u*) ;; - m*) t=${t}_m;; - s*) t=${t}_s;; - esac -#err t=$t - type=text fn="" - case $conf in - */password) - type=encoded ### val=`echo $val|encode` - ;; - */image*|*/document*) - type=`file --mime-type $val` - bin="X'`hexize $val`'" - ;; - esac - pkey=`echo "$tconfs"|grep "${t0}/.*=p"|sed 1q` - pkey=${pkey#/*/} # cut $tbl/ - pkey=${pkey%=p/*} # cut =p/... -> primary key - if [ "$primary" ]; then - nulls=`echo "$tconfs"|grep "$t/.*=[fu]/"|sed 's/^.*/, NULL/'|tr -d '\n'` - ###sq $db "replace into $t values(\"$val\"$nulls)" - query "replace into $t values(\"$val\"$nulls);" - elif [ "$update" ]; then - ###sq $db "update $1 set $c=\"$val\" where $pkey=\"$p\"" - query "update $1 set $c=\"$val\" where $pkey=\"$p\";" - else -#err "replace into $t values(\"$p\", \"$c\", \"$type\", \"$val\", \"$bin\")" - ###sq $db "replace into $t values(\"$p\", \"$c\", \"$type\", \"$val\", \"$bin\")" - query "replace into $t values(\"$p\", \"$c\", \"$type\", \"$val\", \"$bin\");" - fi - ) -} -expire() ( - at="${1:-$timeout}" - FMT="${2:-%F %T}" - TZ=GMT date -d "$at" +"$FMT" -) -addsession() { - # expireをセット - # loginの先にどの画面に行くかの状態遷移表書式を決める - expire=`expire ${2:-"+1min"}` -err addsession "$1" exp=$expire - sq $db "replace into session values('$1', '$expire')" - # Remove old session parameters - now=`expire now` - sq $db "delete from session where expire < '$now'" -} -gencookie() ( - for kv; do - expire="`expire '' '%a, %d-%b-%Y %H:%M:%S GMT'`" - echo "Set-Cookie: $kv; expires=$expire" - done -) -contenttype() { - echo "Content-type: ${1:-text/html; charset=utf-8}" - contenttype() {} # Only need to work once -} -putheader() { - -} -putfooter() { - m4 -D_TITLE_="${TITLE:-$myname}" $layout/footer.m4.html -} -getcookie() ( - for kv in `echo $HTTP_COOKIE|sed 's/[;, ]/ /g'`; do - k="${kv%%=*}" - v="`echo ${kv#*=}|nkf -Ww -mQ|sed -e 's/\"/\"\"/g'`" - query "replace into cookie values('$session', '$k', 'string', \"$v\");" - done -) -genrandom() { - # $1=columns (default: 10) - dd if=/dev/urandom count=1 2>/dev/null|nkf -MB|fold -w${1:-10}|sed -n 10p -} -smail() { - # smail rcpt subj (file) - rcpt=`echo $1` # strip newlines - subj="`echo $2|nkf -jM`" - # echo rcpt=$rcpt - (m4 -D_RCPT_="$rcpt" -D_SUBJ_="$subj" -D_FROM_=$admin $msg/mail-header.m4 - cat $3 | nkf -jd ) | sendmail -f $admin $rcpt -} -setviastring() { - table=$1 - oifs="$IFS" - IFS="&" - for us in $2; do - k=${us%%=*} - v="`echo ${us#*=}|tr '%+' '= '|nkf -Ww -mQ|sed -e 's/\"/\"\"/g'`" - sq $db "replace into $table values('$session', '$k', 'string', \"$v\")"; - #echo $k=$v - done - IFS="$oifs" -} -checkdomain() ( - # Check the validity of domain by referring DNS - item=$1 - host ${item#@*} >/dev/null 2>&1 -) -pwcheck() { - # $1=passwd - dbpswd=`getpwfield $user pswd` - encpswd=`mycrypt "$1" "$dbpswd"` - err user=$user, pswd=$1, db=$dbpswd, enc=$encpswd - [ x"$dbpswd" = x"$encpswd" ] -} -mypwhash() { - mycrypt `cat` `genrandom 5` -} -wasureta() { - user=$1 - if checkdomain $user; then - echo "ユーザ名には正しいメイルアドレスが必要です。" - exit 0 - fi - newpswd=`genrandom` # newsalt=`genrandom 5` - #encpswd=`mycrypt "$newpswd" "$newsalt"` - encpswd=`echo $newpswd|mypwhash` - dbsetbyid user $user pswd "$encpswd" - m4 -D_USER_="$user" -D_PSWD_="$newpswd" -D_URL_="$url" \ - $msg/mail-newaccount.m4 \ - | smail $user "New Account" -} -checkauth() { - user=`getpar user` - skc=`getpar skey` # from cookie - [ -z "$user" ] && return 3 - skey="`getpwfield $user skey`" -err user=$user skey=$skey - if [ -n "$skey" ]; then - if [ x"$skey" = x"$skc" ]; then - return 0 - fi - fi - pswd=`getpar pswd` - if [ x"$pswd" = x"wasureta" ]; then - wasureta $user - return 1 # wasureta error - fi - # dbpswd="`sq $db \"select pswd from passwd where name='$user'\"`" - # putheader; echo; echo user=$user, db=$dbpswd, enc=$encpswd - if pwcheck "$pswd"; then - newsession=`genrandom 50` - dbsetbyid user $user skey "$newsession" - gencookie "user=$user" "skey=$newsession" - return 0 - fi - return 2 # Password mismatch -} -showlogin() { - args=`echo $myargs|tr ' ' '+'` - m4 -D_SYSNAME_="Welcome" -D_MYNAME_="$myname${args+?}$args" \ - $layout/login.m4.html - exit 0 -} -dologin() { - checkauth - st=$? - if [ $st != 0 ]; then - contenttype; echo - m4 -D_USER_="$user" -D_URL_="$url" -D_ADMIN_="$admin" \ - $msg/login-fail-$st.m4.html - showlogin # and EXIT - fi -} -cleanup() { - echo .quit > $sqi - kill $sq3pid - rm -f $sqo $sqi - rm -rf $tmpfiles -} -trap cleanup INT HUP EXIT -# trap cleanup INT HUP -cgiinit() { - session=`date +%F-$$` - tmpf=tmp/stream - tmpd=`mktempd` - tmpfiles=$tmpfiles" $tmpd" - addsession $session - getcookie - case "$REQUEST_METHOD" in - get|GET) s="$QUERY_STRING" ;; - post|POST) dd count=$CONTENT_LENGTH bs=1 of=$tmpf 2>/dev/null - # cat > $tmpf - s="`cat tmp/stream`" - tmpfiles=$tmpfiles"${tmpfiles+ }$tmpf" - ;; - esac - case "$CONTENT_TYPE" in - *boundary*) - bndry=${CONTENT_TYPE#*boundary=} - for us in `LC_CTYPE=C ./mpsplit.rb "$bndry" $tmpdir < $tmpf` - do - k=${us%%\=*} - #echo u=$us - # v="`echo ${us#*=}|nkf -Ww -mQ|sed -e 's/=/=3d/g' -e 's/\"/=22/g'`" - v="`echo ${us#*=}|nkf -Ww -mQ|sed -e 's/\"/\"\"/g'`" - # err k=$k v=$v - case "$k" in - *:filename) - type='file'; k=${k%:filename} - case `file --mime-type $tmpdir/$v|cut -d' ' -f2` in - [Ii]mage/*) - mogrify -resize $maximagexy'>' $tmpdir/$v - ;; - esac - ;; - *) - type='string' - ;; - esac - sq $db "replace into par values('$session', '$k', '$type', \"$v\")" - done - ;; - *) - setviastring par "$s" - ;; - esac -} -collectemail() { - # Collect email addresses for group $1 - if isuser "$1"; then - em=`query "select val from user_m where name='$1' and key='email';"` - [ -n "$em" ] && echo "$em" || echo "$1" - else - query "with recursive allmem as - (select gname,val from grp_m where gname='$1' - union all select grp_m.gname,grp_m.val from grp_m,allmem - where allmem.val=grp_m.gname) - select coalesce(b.val,a.val) - from allmem a left join grp_mem_s b - on a.gname=b.gname and a.val=b.user and b.key='email' - where a.val in (select name from user) limit 10000;" - fi -} -sendinvitation() ( - # $1=email - iss="invite-`date +%s`-$(genrandom 10)" - addsession $iss +7days # 1 week due date - query "replace into par values('$iss', 'invite', 'string', \"$1\");" - gecos=`gecos` - name=$user"${gecos:+($gecos)}" - regist="$urlbase?reg+$iss" - m4 -D_URL_="$urlbase" \ - -D_USER_="$name" \ - -D_EMAIL_="$1" \ - -D_REGIST_="$regist" \ - -D_ADMIN_="$admin" \ - $msg/mail-invite.m4 \ - | smail $1 "BBSへの御招待" - return 0 -) -emaildomaincheck() { - case "$1" in - *@*@*) echo "無効なアドレスです"; return 1 ;; - *@*) - local=${1%@*} domain=${1#*@} - if ! host $domain >/dev/null 2>&1; then - echo "ドメイン($domain)が見付かりません。" - return 2 - fi - return 0 - ;; - *) echo "正しいメイルアドレスをいれてください"; return 3 ;; - esac -} -invite() { - email=`getpar email` - case $email in - *@*@*) repo="無効なアドレスです" ;; - *@*) - local=${email%@*} domain=${email#*@} - if ! repo=`emaildomaincheck $email`; then - repo="招待アドレスのエラー: $repo" - elif [ -n "`query \"select * from user where name='$email';\"`" ]; then - repo="$email さんは既に加入しています。" - elif sendinvitation $email; then - repo="アドレス($email)宛に案内を送信しました。" - fi ;; - "") repo="招待したい人のメイルアドレスを入力してください。" ;; - *) repo="無効なアドレスです" ;; - esac - m4 -D_REPORT_="$repo" -D_ACTION_="$myname?invite" \ - $layout/html.m4.html $layout/invite.m4.html -} -regist() { - # $1=session-id-for-invitation - m4 -D_TITLE_="Invitation" $layout/html.m4.html - if [ -z "$1" ]; then - echo "

bye bye

" - reutrn - fi - email=`session=$1 getpar invite` - if [ -z "$email" ];then - cat<無効な招待状チケットです。

-

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

-EOF - reutrn - fi - echo "

$email さんようこそ

" - query "replace into user values('$email');" - # Fake login password to wasureta - query "replace into par values('$session', 'pswd', 'string', 'wasureta'), -('$session', 'user', 'string', '$email');" - wasureta $email - m4 -D_SYSNAME_="Initial Login" -D_MYNAME_="$myname?userconf" \ - $layout/login.m4.html - return -} -userconf() { - m4 -D_BODYCLASS_=userconf -D_TITLE_="ユーザ情報編集" $layout/html.m4.html - GF_ACTION="?home" edittable "$formdir/user.def" "user" "$user" -} -groupconf() { - m4 -D_BODYCLASS_=groupconf -D_TITLE_="グループ情報編集" $layout/html.m4.html - rowid=`query "select rowid from grp where gname='$1';"` -err gcon \$1=$1 rowid=$rowid - GF_ACTION="?grp+$1" edittable "$formdir/grp.def" "grp" "$rowid" -} -showhome() { - # $1=userRowIdToShow -err showhome \$1=$1 - case "$1" in - *@*) uname=`getvalbypkey user name "$1"` ;; - *) uname=`getvalbyid user name $1` ;; - esac -err ShowHome: uname=$uname - gecos=`gecos "$uname"` - GF_VIEWONLY=1 - cond="gname in (select gname from grp_mem where user='$uname')" - if [ x"$user" = x"$uname" ]; then - conflink="プロフィールの編集 / - 新規話題の作成" - fi - . ./se-blog.sh - - m4 -D_BODYCLASS_=home -D_TITLE_="$gecos さん" \ - -D_PROFILE_="`viewtable $formdir/user.def user $1`$conflink" \ - -D_BLOGS_="`listblog $uname`" \ - -D_GROUPS_="`listgroupbytable $formdir/grp.def $cond`" \ - $layout/html.m4.html $layout/home.m4.html - - # - # Record access log - [ -n "$1" ] && [ x"$1" != x"$user" ] && acclog user $1 -} - -listgroupbytable() { - # $1=deffile - tagline=`grep :tag: $1`; shift - and="${1:+and }" - href="' -err ListGRP: query "select val from grp_s where key='tag' $and$* group by val;" - for tag in `query "select val from grp_s where key='tag' $and$* group by val;"` - do -err ListGrp: tag=$tag - tn=${tagline%%=${tag}*} - tn=${tn##*[ :]} - sql="select gname as 'グループ名',説明 from (select gname,max(case key when 'gecos' then val end) as '説明',max(case key when 'tag' then val end) as 'tag' from grp_s group by gname having tag='$tag');" - err PersonalGroupList= `echo $sql` - echo "

$tn

" - echo '' - sq -header -html $db "$sql" \ - | sed "s,\(,\1$href\2\">\2," - echo '
\)\([-_A-z0-9]*\)
' - done - echo '' -} -iconhref() ( - # $1=icon-file, $2=Href $3=title $4...=anchor - data=`percenthex $1` - ct=`file --mime-type $1|cut -d' ' -f2` -err iconhref: \$1=$1 \$2=$2 \$3="$@" - href=$2; title=$3; shift 3 - echo "
$@" -) -iconhref2() ( - # $1=icon-file, $2=Href $3=title $4...=anchor - src=$1 - href=$2; title=$3; shift 3 - echo "$@" -) -listentry() ( - # $1=user/group $2=SearchKeyword $3=condition(if any) - # Referring variable $iamowner=$grp to attach owner-request links -err listentry: \$1=$1 \$2=$2 \$3=$3 - cond= - offset=`getpar offset` - offset=${offset%%[!0-9]*} - offset=$((offset + 0)) # change to numeric forcibly - [ $offset -lt 0 ] && offset=0 - limit=30 - dir=$tmpdir/$imgcached/$thumbxy.`echo $1|md5` - if [ x"$1" = x"user" ]; then - hrb="$myname?home" - deficon=person-default.png - entity="ユーザ" tbl=user link=rowid nm=name stage=mems - else # if group - hrb="$myname?grp" - deficon=person-default.png - entity="グループ" tbl=grp link=gname nm=gname stage=grps - tagline=`grep :tag: $formdir/grp.def|cut -d: -f5-` - if [ -n "$tagline" ]; then - tagconv=`echo $tagline|sed 's/\([^= :]*\)=\([^= :]*\)/-D\2=\1/g'` -err tagconv=$tagconv - fi - fi - if [ ! -d $dir ]; then - mkdir -p $dir - convert -geometry $thumbxy $imgdir/$deficon $dir/$deficon - fi - if [ -n "$2" ]; then - cond="where nick like '%$2%' or b.name like '%$2%'" - fi - - # XX: これ複雑すぎるかな。もっとシンプルにしたい。$3条件も。2015-07-08 - sql="select a.rowid, a.$link, coalesce(b.gecos, a.$nm) as nick, b.tag, - case when '$iamowner' = '' then '' - when a.$nm in (select user from grp_adm - where gname='$grp') then '(管理者)' - else ',not='||a.rowid end as ownerlink - from $tbl a left join - (select $nm as name, - max(case key when 'gecos' then val end) as gecos, - max(case key when 'tag' then val end) as tag - from ${tbl}_s group by $nm) - b on a.$nm=b.name $cond $3 - order by b.tag desc, a.rowid asc" - total=`query "with x as ($sql) select count(*) from x;"` - echo "

${entity} 一覧

" - if [ $total -gt $limit ]; then - echo '
' - cgi_form $stage <次の語を含む${entity}で検索: -`cgi_text kwd $kwd` -EOF - echo '
' - fi - cat<${total}件中の${offset}件めから${kwd:+" - 検索語: $kwd"}

-EOF - if [ $((offset+limit)) -lt $total ]; then - cat<
-`cgi_submit 次の${limit}件` -`cgi_hidden kwd "$kwd"` -`cgi_hidden stage "$stage"` -`cgi_hidden offset $((offset + limit))`
-EOF - fi - if [ $offset -gt 0 ]; then - cat< -`cgi_submit 前の${limit}件` -`cgi_hidden stage "$stage"` -`cgi_hidden kwd "$kwd"` -`cgi_hidden offset $((offset - limit))` -EOF - fi - - err `echo $sql\;` - - query "$sql limit $limit ${offset:+offset $offset};" \ - | while IFS='|' read id lnk name tag ownerp; do -err name=$name owner=$ownerp - files=`getvalbyid $tbl profimg $id $dir` - # Pick up only first icon - echo "

$tag

" \ - | m4 $tagconv - if [ -n "$files" ]; then - icon=`echo "$files"|head -1` - iconhref $dir/$icon "$hrb+$lnk" "$name" - else - iconhref $dir/$deficon "$hrb+$lnk" "$name" - fi - echo "
$name${ownerp:+
$ownerp}" - echo "
" - done -) -listmember() { - listentry user "$@" -} -listgroup() { - listentry group "$@" -} -showgroup() { - grp=$1 - - showgroupsub $formdir/grp.def $grp | \ - m4 -D_TITLE_="グループ $grp" \ - -D_FORM_="syscmd(\`cat')" \ - -D_DUMPTABLE_="" \ - $layout/groupman.m4.html -} -showgroupsub() { - # $1=def-file $2=group - grp=$2 - rowid=`sq $db "select rowid from grp where gname='$grp'"` - if [ -z "$rowid" ]; then - rowid=`sq $db "select rowid from grp where rowid=$grp"` - grp=`sq $db "select gname from grp where rowid=$grp"` - fi - val=`getvalbyid grp profimg $rowid $tmpd` - # 6/14の次グループのHOMEで出す情報を作る Done - viewtable $1 grp $rowid - if isgrpowner $user $grp; then - echo "

グループ情報の編集" - iamowner=$grp - fi - if ismember $user $grp; then - echo "${iamowner:+ / }グループの新規話題作成

" - fi - # 加入ボタン + 加入者リスト -err ismember $user $grp - ismember $user $grp && ismem='checked' || nomem='checked' - # このグループでの加入アドレス - eml=`query "select val from grp_mem_s where gname='$2' and user='$user' \ - and key='email';"` -err EML: "select val from grp_mem_s where gname='$2' and user='$user' \ - and key='email';" -err email=$eml - echo '

このグループに

' - cgi_form grp < -メンバーとして - / - -参加する場合のメイルアドレス
-(メインのアドレスとは違うものにする場合に記入
-同じでよい場合は空欄に)
-`cgi_text email $eml` - -`cgi_hidden grp $grp` -EOF - - echo '

話題一覧

' - cgi_form searchart<`cgi_text kwd`という語を含むコメントを検索 -`cgi_hidden owner $grp` -EOF - cond="where a.id in (select id from blog_s where key='owner' and val='$grp') order by ctime desc" - DT_CHLD=article:blogid \ - DT_VIEW=replyblog dumptable html blog 'ctime title heading' "$cond" - - c="group by b.name having b.name in (select user from grp_mem where gname='$grp')" - cm="?commission+$grp" - thumbxy=50x50 listmember "" "$c" \ - |sed -e "s|\(
\),not=\(.*\)|\1管理者委託|" -} -joingrp() { - # $1=group $2=user $3=yes/no $4=email(if any) -err joingrp: \$1=$1 \$2=$2 \$3=$3 \$4=$4 - if [ x"$2" != x"$user" ]; then # if user is not login user - if ! isgrpowner $user $1; then - echo "

本人か、グループ管理者しか加入操作はできません。

" - return - fi - fi - cond="where gname='$1' and user='$2'" - if [ x"$3" = x"yes" ]; then - query "replace into grp_mem values('$1', '$2');" - if [ -n "$4" ]; then - if msg=`emaildomaincheck "$4"`; then -err "replace into grp_mem_s values('$1', '$user', 'email', \ - 'string', '$4', NULL);" - query "replace into grp_mem_s values('$1', '$user', 'email', \ - 'string', '$4', NULL);" - else - echo $msg - fi - else - query "delete from grp_mem_s $cond and key='email';" - fi - else - query "delete from grp_mem $cond; -delete from grp_mem_s $cond; -delete from grp_mem_m $cond;" - fi -} -grp_reg_adm() { - # $1=grp $2=user-rowid - if ! isgrpowner $user $1; then - echo "

$1 グループの管理者しかこの操作はできません。"; return - fi - newadm=`query "select name from user where rowid=$2;"` - if [ -z "$newadm" ]; then - echo "

指定ユーザIDがおかしいようです。

"; return - fi -err GRP_reg_adm: "replace into grp_adm values('$1', '$newadm');" -err ismember $newadm $1 - if ismember $newadm $1; then - # OK, go ahead - query "replace into grp_adm values('$1', '$newadm');" - # confirm insertion - sql="select * from grp_adm where gname='$1' and user='$newadm'" - if [ -n "`query \"$sql;\"`" ]; then - echo "

追加完了

" - else - echo "

追加失敗($1 $2)

" - fi - fi - showgroup $1 -} -dumptable() { - # $1=mode $2=Table $3=column-list(defaults to *) $4=conditions(if any) - # textのフィールドだけ全てダンプにしたほうがいいか - # $DT_VIEW sets link - # 6/17の次: editリンクじゃなくてスレッドVIEWリンクでいいんちゃう? - ### elink="EDIT" - VIEW=${DT_VIEW-replyblog} - if [ -n "$VIEW" ]; then - dvlink=" VIEW" - fi - # $DT_CHLD=ChildTable:BindColumn - if [ -n "$DT_CHLD" ]; then - _t=${DT_CHLD%:*} _i=${DT_CHLD#*:} - cntall="(select count($_i) from $_t where $_i=a.id)" - cntnew="(select count(val) from ${_t}_s where key='ctime' \ - and id in (select id from $_t where $_i=a.id) \ - and val > coalesce((select time from acclog where \ - user='$user' and tbl='$2' and rowid=a.rowid),\ - '1970-01-01'))" - cnt="$cntnew||'/'||$cntall as '新着/総数'," - dt_class=" td2r" - fi - # Construct join expression - eav="" scols="" - pk=`gettblpkey $2` - substr=${dumpcollen:+"substr(val, 0, $dumpcollen)"} - substr=${substr:-val} - for col in ${3:-`gettbl_s_cols $2`}; do - eav=$eav${eav:+,}" max(case key when '$col' then $substr end) as $col" - scols="$scols${scols:+, }b.$col" - done -#case author when '$user' then a.rowid else '---' end as ID, - sql="select \ -a.rowid as ID,\ -$cnt\ -$scols from $2 a left join (select $pk,$eav from ${2}_s group by $pk) b on a.$pk=b.$pk $4;" -err SQL="$sql" - cat<\)\([1-9][0-9]*\),\1$elink$dvlink," -
- -`sq -header -cmd ".mode $1" $db "$sql"` -
-
-EOF -} - -par2table() ( - # copy current parameters of par into destination table - # $1=definition-file - # Using $user and $session - rowid=`getpar rowid` - if [ ! -e $1 ]; then - echo "

テーブル定義ファイルが見付かりません

" - exit 1 - fi - tbl=${1%.def} - tbl=${tbl##*/} - if [ -n "$rowid" ]; then # Modify existing entry - if [ x"$tbl" = x"user" ]; then - rowowner=`query "select name from $tbl where rowid=$rowid;"` - elif [ x"$tbl" = x"grp" ]; then - isgrpowner $user `query "select gname from $tbl where rowid=$rowid;"` \ - && rowowner=$user - else - rowowner=`query "select owner from $tbl where rowid=$rowid;"` - rowowner=${rowowner:-`query "select author from $tbl - where rowid=$rowid;"`} - fi - if [ x"$user" != x"$rowowner" ]; then - echo "

他人のレコードはいじれないの

" - return - elif [ -z "$rowowner" ]; then - echo "

指定したレコードはないみたい

" - return - fi - rm=`getpar rm` cfm=`getpar confirm` - # Editing existent entry - if [ x"$rm" = x"yes" ]; then - if [ x"$rm$cfm" = x"yesyes" ]; then - query "delete from $tbl where rowid=$rowid;" - return - else - echo "

消去確認のチェックがないので消さなかったの...

" - return - fi - fi - fi - # XX: Subshelling here is unnecessary 2015-07-05 - (ts=${tbl}_s tm=${tbl}_m val="" pval="" formaster="" getrow="" - if [ -n "$rowid" ]; then - # Update of existing record - for col in `gettblcols $tbl`; do - val=`getparquote $col` - [ -z "$val" ] && continue - err sq $db "update $tbl set $col=$val where rowid=$rowid" - query "update $tbl set $col=$val where rowid=$rowid;" - done - # Then, set up $pval for further insertion of tbl_s and tbl_m - for col in `gettblpkey $tbl`; do - val=`query "select $col from $tbl where rowid=$rowid;"|sed -e 's/\"/\"\"/g'` - pval="$pval${pval:+, }\"$val\"" - done - else - # New entry - # Generate values() for primary keys - for col in `gettblpkey $tbl`; do - # Genuine primary keys for _m and _s - val=`getvalquote $tbl $col` - [ -z "$val" ] && continue - pval="$pval${pval:+, }$val" - done -err pval=$pval - for col in `gettblfkey $tbl`; do - # args for values() to insertion into master table - val=`getvalquote $tbl $col` - [ -z "$val" ] && continue - formaster=$formaster"${formaster:+, }$val" - done - formaster="$pval${formaster:+, }$formaster" -err formaster=$formaster - if [ -z "$formaster" ]; then - echo "
項目を全て埋めてください
" - return 1 - fi - err "replace into $tbl values($formaster);" - echo "replace into $tbl values($formaster); $getrow" | sq $db - ## Insertion to master table, done - fi - - for kt in s m; do - tb2=${tbl}_$kt - for col in `gettbl_${kt}_cols $tbl`; do - ptype=`getpartype $col "limit 1"` - - # First, check update of existing entries in _m - if [ $kt = m ]; then - # sessID|address.1.22|string|Somewhere-x.y.z - sql="" -err dots from query "select var from par where var like '$col.%';" - for v in `query "select var from par where var like '$col.%';"`; do - # v=address.1.22 - rowid=${v##*.} - origcol=${v%%.*} # original column derived from -err Updating for $v rowid=$rowid, partype=`getpartype $v` - ##case `getpartype $v` in - err CASE `gettbl_coltype $tbl/$origcol` in - err edit flag = `getpar action.$v` - case `getpar action.$v` in - rm) - if [ x`getpar confirm.$v` = x"yes" ]; then - newsql="delete from $tb2" - else - echo "

削除確認未チェック

" - fi ;; - edit) - case `gettbl_coltype $tbl/$origcol` in - image|document|binary) - file=`getparfilename $v` - err type=file=$file - [ -z "$file" ] && continue - bn=${file##*/} - bin="X'"$(hexize $file)"'" - ct=`file --mime-type $file|cut -d' ' -f2` - type=\"file:$ct\" - newsql="update $tb2 set val='$bn', type=$type, bin=$bin" - ;; - *) - newsql="update $tb2 set val=(select val from par where var \ -like '$col.%.$rowid')" - ;; - esac - ;; - *) # maybe `keep', do not modify value - continue - ;; - esac -# err newsql=$newsql - sql=$sql$nl"$newsql where rowid=$rowid;" - done - echo "$sql -delete from $tb2 where type='string' and val='';" | sq $db - # Rest of kt==m: set multiple mode - nr=`getparcount $col` - else - nr=1 # for kt==s, number of records is 1 - fi - - i=0 - while [ $i -lt $nr ]; do - limit="limit 1 offset $i" - i=$((i+1)) # increase beforehand against continue - val=`getvalquote $tbl $col "$limit"` - [ -z "$val" -o x"$val" = x'""' -o x"$val" = x"NULL" ] && continue -err $col=$val - bin=NULL -err partype$col=`getpartype $col "$limit"` - case $ptype in - file) file=`getparfilename $col "$limit"` -err parfile-$col=$file - [ -z "$file" ] && continue - bin="X'"$(hexize $file)"'" - ct=`file --mime-type $file|cut -d' ' -f2` - type=\"file:$ct\" ;; - "*"*) continue ;; # foreign table - *) type=\"string\" ;; - esac - case `gettbl_coltype $tbl/$col` in - password) # special care for password - # name={password,pswd1,pswd2} - p1=`getpar pswd1 "$limit"` - if [ -z "$p1" ]; then - continue # SKIP password setting, if p1 is empty - else - pswd=`getpar pswd "$limit"` p2=`getpar pswd2 "$limit"` -## err pswd=$pswd - if pwcheck "$pswd"; then - if [ x"$p1" = x"$p2" ]; then - case "$p1" in - ????????*) ;; - *) echo "

8字以上にしてください。

" - return ;; - esac - val="\"`echo $p1|mypwhash`\"" - else - echo "

2つの新パスワード不一致

" - return - fi - else - echo "

旧パスワード違います

" - return - fi - fi - ;; - esac - #err "replace into $tb2 values($pval, \"$col\", $type, $val, $bin);" - echo "replace into $tb2 values($pval, \"$col\", $type, $val, $bin);" \ - | sq $db - done - done - done - return 0 - err donee) -) -par2table_old() { - # copy current parameters of par into destination table - # $1=dst-table $2=definition-file - # Using $user and $session - rowid=`getpar rowid` - if [ -n "$rowid" ]; then - rm=`getpar rm` cfm=`getpar confirm` - if [ x"$rm$cfm" = x"yesyes" ]; then - sq $db "delete from $1 where rowid=$rowid and owner=\"$user\"" - return - fi - fi - cat $2 \ - | (cols="" - while IFS=: read prompt name type args; do - [ x"$name" = x"stage" ] && continue - if [ -n "$rowid" ]; then - val=`getpar $name|sed -e 's/\"/\"\"/g'` - sq $db "update $1 set $name=\"$val\" where rowid=$rowid and owner=\"$user\"" - else - eav=$eav${eav+,}" max(case var when '$name' then val end)" - fi - done - [ -n "$rowid" ] && return - cond="where sessid='$session' group by sessid" - sq $db "replace into $1 select $eav,\"$user\" from par $cond" - # Think over again about putting $user - ) -} -genform() { - # $1 = form definition file - # $2, $3 (optional)= table name and ROWID - # If $GF_VIEWONLY set and nonNull, output values without form - # If $GF_HIDDEN set, use it hidden values - # If $GF_OWNER set, use it as value of name="owner" - # If $GF_STAGE set, use it as value of name="stage" - forms="" hiddens="" rowid=$3 - if [ ! -e "$1" ]; then - echo "

そのようなデータベースはないようです($2)。

" - return - elif [ -n "$2" ]; then -err genform1: "select * from $2 where rowid='$rowid'" - rec=`query "select * from $2 where rowid='$rowid';"` - if [ -z "$rec" ]; then - pk=`gettblpkey $2` - ###rec=`sq $db "select rowid from $2 where $pk='$rowid'"` -err "select rowid from $2 where $pk='$rowid';" - rec=`query "select rowid from $2 where $pk='$rowid';"` -err rec-rowid=$rec - rowid=$rec - rec=$3 - fi - if [ -z "$rec" ]; then - echo "

そんなレコードはないみたいね...

" - return - fi - fi - if [ -z "$GF_VIEWONLY" ]; then - rm=' -ほんとうに消しますよ(確認)! -はい' - fi - while IFS=: read prompt name keytype type args; do - [ -z "${prompt%%\#*}" ] && continue # skip comment line(#) - sp="${args:+ }" - form="" val="" - if [ -n "$rowid" ]; then - val=`getvalbyid $2 $name $rowid $tmpd` - fi - if [ -n "$GF_VIEWONLY" ]; then - is_hidden "$2" "$name" && continue - fi - case "$type" in - text*) - cgiform=cgi_multi_$type - if [ -s $tmpd/$name.count ]; then - form=`$cgiform $name $tmpd` - val=$(echo "$val"| - while read fn; do - echo "`cat $tmpd/$fn`$nl" - done) - val="$nl$val$nl
" - else - #form="$nl" -err genform: cgi_$type $name $val "$args" - form=`cgi_$type $name "$val" "$args"` - fi - ;; - [Rr][Aa][Dd][Ii][Oo]) - fh="\1,g\"`" - ;; - [Ss][Ee][Ll][Ee][Cc][Tt]) - fh="" - ;; - [Ii][Mm][Aa][Gg][Ee]|[Dd][Oo][Cc][Uu][Mm][Ee][Nn][Tt]|[Bb]inary) - if [ -s $tmpd/$name.count ]; then - form=`cgi_multi_file $name $tmpd "$args"` - if [ -n "$val" ]; then - hrfb="$myname?showattc+$2_m" - val=$(echo "$val" \ - | while read fn; do - data=`percenthex $tmpd/$fn` - #ct=`cat $tmpd/$fn.content-type` - ct=`file --mime-type $tmpd/$fn|cut -d' ' -f2` - ri=`cat $tmpd/$fn.rowid` -## err fn=$fn, name=$name, ri=$ri; ls -lF $tmpd 1>&3 - imgsrc="" - echo "$imgsrc
" - done) - fi - else - form="" - if [ -n "$val" ]; then - imgs=$(echo "$val"\ - |while read fn;do - data=`percenthex $tmpd/$fn` - echo "$fn
" - done) - form=$form"
$imgs" - val=$imgs # 2015-06-15 - else - form="" - fi - fi - ;; - [Hh][Ii][Dd][Dd][Ee][Nn]) - if [ -n "$GF_STAGE" -a x"$name" = x"stage" ]; then - args="value=\"$GF_STAGE\"" - fi - form="" - prompt='' # Remove prompt - ;; - [Aa][Uu][Tt][Hh][Oo][Rr]) - form="" - prompt="" ;; - [Oo][Ww][Nn][Ee][Rr]) - val=${GF_OWNER:-$val} - val=${val:-$user} - form="" - prompt="" ;; - [Uu][Ss][Ee][Rr]) - # XXX: is null $user ok? - #form="" - [ -n "$GF_VIEWONLY" ] && continue - form="$user" - ;; - [Pp]assword) - [ -n "$GF_VIEWONLY" ] && continue - form="`cgi_passwd`" - val="" - ;; - [Ss][Ee][Rr][Ii][Aa][Ll]|[Ss][Tt][Aa][Mm][Pp]) - val=$((($(date +%s)-1433084400)/10))c$$ - form="" - prompt="" ;; - [Ss][Ee][Ss][Ss][Ii][Oo][Nn]) - prompt="" - ;; - parent|path|blog*) - prompt="" - ;; - "*"*) - tail=$tail"``" - continue ;; - esac - if [ -n "$prompt" ]; then - if [ -n "${GF_VIEWONLY}" ]; then - form=$val - else - : - fi - forms=$forms" $prompt$form$nl" - else - hiddens=$hiddens$nl"$form" - fi - done < $1 - # enctype="multipart/form-data" - cat< -${rowid:+$rm} - -$forms -
$hiddens - ${rowid:+} -EOF - if [ -z $GF_VIEWONLY ]; then - cat< - -EOF - fi - cat< -$tail -EOF -} -edittable() { - # $1=form-def $2=table $3 rowid - genform "$@" -} -viewtable() { - GF_VIEWONLY=1 genform "$@" -} diff -r 95cebd686c97 -r 6822f4362bf9 se-init.sh --- a/se-init.sh Sat Jul 18 23:44:21 2015 +0900 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,101 +0,0 @@ -#!/bin/sh -. `dirname $0`/se-funcs.sh - -create() { - # $1=type $2=obj $3=defs... - target=$1; shift - name=$1; shift - [ "$debug" ] && echo "create $target if not exists $name $@" - sq $db "create $target if not exists $name $@" -} -create table passwd '(name primary key, pswd, gecos, skey);' -: </dev/null 2>&1 || . ./y4-funcs.sh + +blog_genform() { + # + t=$1 +} + +blog_writable() ( + # $1=articleid $2=user + blogowner=`getvalbyid blog owner "$1"` + [ x"$blogowner" = x"$2" ] || isuser "$blogowner" || ismember "$2" "$blogowner" +) +blog_notify_reply() { + # $1=articleid $2=ReplyingUser $3=WrittenText + blogowner=`getvalbyid blog owner "$1"` + blogtitle=`getvalbyid blog title "$1"` + blogurl="$urlbase?replyblog+$1" + emails=`collectemail $blogowner` + smail "$emails" "書込通知 $urlbase"< /'` +EOF +} +blog_showentry() { + # $1=table $2=rowid + if [ -n "$2" ]; then + if [ -n "$imgcached" ]; then + tmpd=$tmpdir/$imgcached/$thumbxy + else + tmpd=`mktempd` + tmpfiles=$tmpfiles" $tmpd" + fi + fi + tbl=${1%%[!A-Z0-9a-z_]*} rowid=${2%%[!A-Z0-9a-z_]*} +err rowid=$rowid, '$2'=$2 + ts=${tbl}_s tm=${tbl}_m + at=article as=article_s am=article_m + serial=$(($(date +%s)-1420038000))s$$ + # This function grasps blog entry definiton directly. + # blog: id + # blog_s: title,ctime,heading + # blog_m: *article + + err "SELECT id from $tbl where rowid=$rowid" + id=`query "select id from $tbl where rowid=$rowid;"` +err id=$id +err "select val from $ts where key='title' and id='$id';" + + + #(1)Display root article + cat< + +EOF + + href=" 編集 " + href2=" 提出状況 " + href3="(ファイル取得)" + cat<\)|$href2$href3\1|" +-- select val from $ts where key="title" and id="$id"; +select + coalesce((select ",e," from blog where rowid=$rowid and author='$user'),'') +||val||" " +||case (select val from $ts where key="mode" and id="$id") + when 'report-closed' then "レポート提出用(自身のファイルのみ参照可),s," + when 'report-open' then "レポート提出用,s," + else "" + end + from $ts where key="ctime" and id="$id"; +select val from $ts where key="heading" and id="$id"; +EOF + cat< +
\),e,|\1 $href |" \ + -e "s|,s,\(
+EOF + + #(2)Display following articles +textform='
+ + +
添付ファイル:
+ + +' + ## 6/11の次: articleを出して行く +: <&3 + #case $ct in + # [Ii]mage*) anch="$fn" ;; + # *) anch=$fn ;; + # esac + # Should not contain newlines for sed argument + # echo -n "$anch" + iconhref $td/$fn "$hrfb+$ri" "$fn" "$fn" + done) + fi + fi + + ### number=$((number+1)) +# reply="" + getgecos="(select rowid from user where name='$author')||':'||\ + coalesce((select val from user_s \ + where name='$author' and key='gecos'), '$author')||',[/a],'" + href="$myname?editart+$arid+$rowid" + link="編集" + cat<|" \ + -e 's|,\[/a\],||' \ + -e 's/,n,/
/g' -e "s|,i,|$imgs|" \ + -e "s|\(\)|\1|" \ + -e "s|\(\)\(\),e,|\1\2$link|" +select + coalesce((select ",e," from article where id='$aid' and author='$user'),"") + || + max(case key when 'ctime' then ",n,"||val|| + ",n,"||$getgecos end) as TIME, +-- max(case key when 'parent' then val||"への返信" end) as REPLYTO, + max(case key when 'text' then val||",i," end) as TEXT + from article_s where id = '$aid' + group by id order by TIME; +EOF + done + echo "" + + + blog_writable $rowid $user && cat< +

コメント記入

+ + + +$textform + +EOF + echo "" + + # Record access log + acclog blog $rowid +} + +lshandout() { + # $1=rowid of blog + time=`getvalbyid blog ctime $1|colrm 11` + owner=`getvalbyid blog owner $1` + title=`getvalbyid blog title $1` + ge=`gecos $owner` + lshandoutsub $owner "$@" \ + |m4 -D_TITLE_="提出状況" \ + -D_SUBTITLE_="$time [$title]@${ge:-$owner}" -D_DIARY_="" \ + -D_FORM_="syscmd(cat)" -D_BLOGS_= -D_DUMPTABLE_= \ + $layout/html.m4.html $layout/diary.m4.html +} +lshandoutsub() { + # $1=owner $2=rowid of blog + if isgroup $1; then + sample="(select user from grp_mem where gname='$1')" + else + sample="(select distinct author as user from arts)" + echo "

(集計は板への投稿者のみ)

" + fi + sql="with arts as (select id,author from article \ + where blogid=(select id from blog where rowid=$2))\ + select (select rowid from user where name=c0.user)||' '|| \ + coalesce((select val from user_s where name=c0.user \ + and key='gecos'),\ + c0.user) as 'メンバー',\ + sum(case when c1.key is not null then 1 else 0 end)\ + as 'コメント記入',\ + sum(case when c2.key is not null then 1 else 0 end)\ + as 'ファイルの提出'\ + from $sample c0 \ + left join (select id,author from arts) a\ + on c0.user=a.author\ + left join (select id,key from article_s where key='text') c1\ + on a.id=c1.id left join (select id,key from article_m ) c2\ + on c1.id=c2.id group by c0.user order by c0.user;" + err ishandoutsub: sql="$sql" + echo '' + hrb=",\1$hrb\2\">\3," -e 's,,,' + echo '
\)\([^ ]*\) \(.*\)00
' +} +gethandout() { + # $1=rowid of blog + i=0 + bd=$tmpd/archive.$$ + mkdir $bd + query "select m.rowid,author,m.val from article a join article_m m\ + on a.id=m.id where blogid=(select id from blog where rowid=$1)\ + and m.key in ('image', 'document', 'binary');" \ + | while IFS='|' read rowid author filename; do + # err isfilereadable $user article_m $1 + isfilereadable $user article_m $1 || continue + err ok + i=$((i+1)) + dir=`printf $bd/%03d $i` + mkdir $dir + query "select quote(bin) from article_m where rowid=$rowid;" \ + | xxd -r -p > $dir/$filename + done + if [ ! -d $bd/001 ]; then + contenttype; echo + echo "

取得できるファイルがありませんでした。

" + return + fi + (cd $bd + err cdto$bd; (pwd; ls -lFa) 1>&3 + tar zcf .archive.tar.gz * && mv .archive.tar.gz archive.tar.gz + ) + arc=$bd/archive.tar.gz + echo "Content-type: application/x-gzip" + echo "Content-Length: `cat $arc|wc -c`" + echo "Content-Disposition: filename=\"archive.tar.gz\"" + echo + cat $arc +} + +listblog() ( + # $1=user + cond="where a.id in (select id from blog_s where key='owner' and val='$1') order by ctime desc" + DT_CHLD=article:blogid + cgi_form searchart<`cgi_text kwd`という語を含む記事を検索 +`cgi_hidden owner $user` +EOF + dumptable html blog 'ctime title heading' "$cond" +) + +blog_addentry() { + # $1=GRPname(if it is a group) + grp=$1 + rowid=`getpar rowid` +err ba: rowid=$rowid + #if [ -z "$rowid" ]; then + # When rowid is SET, it is updation of existing entry + if [ -z "$1" ]; then + listing=$user guide="[個人]" +#listing代入は rowid 時でもするべき + else + if isgroup $1; then + listing=$1 guide="[${1}]" GF_OWNER=$1 + else + echo "

無効なグループ指定です。

" + return + fi + fi + #fi + if [ -n "`getpar title`" ]; then + owner=`getpar owner` + if isuser $owner; then + if [ x"$user" != x"$owner" ]; then + echo "

他人の日記は書けません

" + return + fi + elif isgroup $owner; then # if write to group log + grp=$owner #\`getpar grp\` + err ismember: $user $grp + if ! ismember "$user" "$grp"; then + echo "

(話題作成はこのグループに加入してから)

" + return + fi + fi + par2table $formdir/blog.def + serial=`getpar serial` + err SERIAL: $serial ROWID=$rowid listing=$listing + id="" + if [ -n "$rowid" ]; then + # Here, id becomes NULL when removal of entries at par2table + id=`query "select rowid from blog where rowid=$rowid;"` + elif [ -n "$serial" ]; then + # If new blog leader created, traverse to its head. + id=`query "select rowid from blog where id='$serial';"` + fi + if [ -n "$id" ]; then + ## If new aritcle is entered, JUMP to blog_reply + blog_reply $id + return + fi + fi + m4 -D_TITLE_="${guide}新規話題作成" -D_DIARY_="新規話題の記入" \ + -D_SUBTITLE_="序文は簡単に詳しくはコメントに" \ + -D_BLOGS_="これまでの蓄積" \ + -D_FORM_="`genform $formdir/blog.def`" \ + -D_DUMPTABLE_="`listblog $listing`" \ + $layout/html.m4.html \ + $layout/diary.m4.html +} + +blog_reply() { + rowid=$1 +err rowid=$1 + + if [ -z "$rowid" ]; then + echo "

表示する日記番号が未指定です。

" + return + fi + title=`getvalbyid blog title $rowid` + owner=`getvalbyid blog owner $rowid` + if isuser "$owner"; then + subtitle="`gecos $owner` さんの話題" + else + subtitle="
$owner での話題" + fi + if [ -z "$title" ]; then + echo "

日記番号指定が無効です。

" + return + fi + + text=`getpar text` + if [ -n "$text" ]; then + if blog_writable $rowid $user; then + if par2table $formdir/article.def; then + blog_notify_reply $rowid $user "$text" + fi + else + title="$title(加入してないので書き込み不可)" + fi + fi + def=$formdir/article.def + cat $layout/html.m4.html $layout/diary.m4.html \ + | sed '/_DIARY_/q' \ + | m4 -D_TITLE_="$title" -D_DIARY_="" -D_BODYCLASS_=general \ + -D_SUBTITLE_="$subtitle" + blog_showentry blog $rowid + sed '1,/_DIARY_/d' $layout/diary.m4.html | m4 -D_FORM_= -D_DUMPTABLE_= +} diff -r 95cebd686c97 -r 6822f4362bf9 y4-cgi.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/y4-cgi.sh Sun Jul 19 13:51:41 2015 +0900 @@ -0,0 +1,108 @@ +# +# cgi functions +# +cgi_form() { + # $1=stage + : ${myname:?'Sure to set $myname to this script name'} + cont=`cat` + cat< +$cont + + + + +EOF +} +cgi_submit() { + cat< +EOF +} +cgi_radio() { + echo "" +} +cgi_hidden() { + echo "" +} +cgi_passwd() { + cat< + 現パスワード + 新パスワード + 新パスワード(確認) + +EOF +} +cgi_text() { + echo "" +} +cgi_textarea() { + cat<$2 +EOF +} +cgi_file() ( # In a subshell + # $1=name $2=val(as filename) $3=args(if any) + # Using global variable $dir + if [ -s $dir/$2 -a -s $dir/$2.content-type ]; then + file=$dir/$2 + bn=${file##*/} + ct=`cat $dir/$2.content-type` + data=`percenthex $file` + icon="" + fi + cat< +EOF +) +cgi_multi() ( + # $1=name $2=dir $3=func $4=args... + # `dir' should contain $name.count and $name.N where N is 1 upto N + i=1 name=$1 dir=$2 func=$3 + n=`cat $dir/$name.count` + echo '' + while [ $i -le $n ]; do + file=$name.$i ctf=$dir/$name.content-type + vname=$file.`cat $dir/$file.rowid` + if [ -s $ctf ]; then + case `cat $ctf` in + *:[Ii]mage:*) + + ;; + + esac + fi + val="`cat $dir/$file`" + cat< +EOF + i=$((i+1)) + done + cat< +
($i) + + + +
+`$func $vname "$val" "$4"`$val +
(新規)`$func $name "" "$4"`
+EOF +) +# In these functions, $2 should be quoted because it can be null +cgi_multi_text() { + cgi_multi $1 "$2" cgi_text "$3" +} +cgi_multi_textarea() { + cgi_multi $1 "$2" cgi_textarea "$3" +} +cgi_multi_file() { + # $1=name $2=val(filename) + cgi_multi $1 "$2" cgi_file "$3" +} diff -r 95cebd686c97 -r 6822f4362bf9 y4-funcs.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/y4-funcs.sh Sun Jul 19 13:51:41 2015 +0900 @@ -0,0 +1,1807 @@ +#!/bin/sh +# Here's global variable table. Do not use this names. +# $HGid$ +myname=`basename ${SCRIPT_NAME:-$0}` +mydir=`dirname ${SCRIPT_FILENAME:-$0}` +myargs="$@" +#bindir=`(cd $mydir/bin; pwd)` +# :$bindir +PATH=/usr/local/sqlite3/bin:/usr/local/vim7/bin:/usr/local/ImageMagick/bin:$PATH +tmpdir=${TMPDIR:-tmp} +dbdir=${DBDIR:-db} +tmpfiles="" +db=${DB:-$dbdir/cgi.sq3} +admin=wwwadmin@gentei.org +templ=${TEMPL:-templ} +layout=$templ/default +formdir=$templ/form +imgdir=img +url=${URL:-"${REQUEST_SCHEME}://$HTTP_HOST$REQUEST_URI"} +urlbase=${url%%\?*} +msg=$templ/msg +timeout="+2 days" +dumpcollen=20 +thumbxy=120x120 +thumbxy=96x96 +maximagexy=1600x1600 +### maximagexy=400x400 +tconfs="" +imgcached=imgcache.`date +%Y/%m` +conftbl=_tblconf +nl=" +" +. ./y4-cgi.sh + +: < "hoge", "owner" => "yuuji", "date" => "2015-04-27", + "text" => "hogehoge ..", + "reply" => [ {"serial" => 1, + "author" => "taro", + "date" => "2015-04-28", + "parent" => "/", + "path" => "/1", + "text" => "blah, blah, ....", + "image" => ["a.jpg", "b.jpg"] }, + {"serial" => 2, + "author" => "hanako", + "date" => "2015-04-29", + "parent" => "/", + "path" => "/2", + "text" => "blah, blah, ....", + "image" => [] }]}, + {"title" => "buha", ...} ] + + +user:= + ユーザ名(英数字):name:p:text:length="20" maxlength="40" + パスワード:pswd:s:password:length="20" maxlength="40" + 説明(日本語OK):gecos:s:text:length="20" maxlength="40" + セッションキー:skey:s:session + メイルアドレス:email:m:text:length="20" maxlength="40" + 住所:address:m:textarea:maxlength="400" + プロフィール画像:profimg:m:image:maxlength="400K" + 履歴書:profpdf:m:document:maxlength="4M" + +変換表 +/user/email=m + +blog:= + シリアル:id:p:serial + タイトル:title:s:text: + 所有者:owner:s:owner: + 時刻:ctime:s:stamp: + リード文:heading:s:textarea: + リプライ:reply:m:*article: + +article:= + シリアル:id:p:serial + 筆者:author:s:owner + 時刻:ctime:s:stamp: + 参照元:parent:s:parent: + パス:path:s:path: + 本文:text:s:textarea: + 画像:image:m:image: + +履歴書:profpdf:m:document:maxlength="4M" + + +EOF + +sq() { + # ./args.rb -cmd ".timeout 3000" "$@" + sqlite3 -cmd 'PRAGMA foreign_keys=ON' -cmd ".timeout 3000" "$@" +} +####XXXXXXXXXXXXXXXXXXXXXX 場所移動 +sqi=/tmp/sqi.$$ +sqo=/tmp/sqo.$$ +mkfifo $sqi $sqo +tail -f $sqi | sq $db & +sq3pid="`jobs -p` $!" + +query() { + cat< $sqi +.once $sqo +$@ +EOF + cat $sqo +} +exec 3>> $tmpdir/debug.out +exec 2>> $tmpdir/error.out +err() { + echo "$@" 1>&3 +} + +_m4() { + +} +ismember() { + # $1=user, $2=group +err ismem: "select user from grp_mem where gname='$2' and user='$1';" + test -n "`query \"select user from grp_mem where gname='$2' and user='$1';\"`" +} +isuser() { # Check if $1 is a valid user + test -n "`query \"select name from user where name='$1';\"`" +} +isgroup() { # Check if $1 is a valid group + test -n "`query \"select gname from grp where gname='$1';\"`" +} +isgrpowner() { + # $1=user, $2=group + test -n "`query \"select user from grp_adm + where gname='$2' and user='$1';\"`" +} +isfilereadable() { # $1=user $2=tbl $3=rowid + # Return true if user($1) can read attachment files in tbl($2):rowid($3) + [ -z "$1" -o -z "$2" -o -z "$3" ] && return 1 # invalid argument + + # case `getvalbyid blog mode $2` in + # normal|*open*|"") return 0 ;; + # *closed*) + # owner=`getvalbyid blog owner $2` + # if isgrp $owner; then + # isgrpowner $1 $owner && return 0 || return 1 + # elif isuser $owner; then + # [ x"$1" = x"$owner" ] && return 0 || return 1 + # fi + # esac + # ↑ 要はこういう処理を↓で一気にやっている + sql="with getblog as (\ + select key,val from blog_s where id=(\ + select blogid from article where id in\ + (select id from $2 where rowid=$3))),\ + getowner as (select val from getblog where key='owner'),\ + getmode as (select val from getblog where key='mode')\ + select case\ + when (select author from article where\ + id=(select id from $2 where rowid=$3))='$1' \ + then 'author'\ + when (select val from getmode) in ('report-open', 'normal')\ + then 'open'\ + when (select val from getmode) is null \ + then 'open' + when (select val from getowner) in (select gname from grp)\ + then (select user from grp_adm where \ + gname=(select val from getowner) and \ + user='$1')\ + else 'user' end;" + err isfilereadable: sql="$sql" + # caseのネストで内側のcaseがスカラーtrueを返しても外側はtrue扱いにならない + result=`query "$sql"` + [ -n "$result" ] && return 0 + return 2 +} +linkhome() { + # $1=UserOrGroup + echo -n '`gecos $1`" +} +acclog() { + # $1=table, $2=rowid + if [ -n "$2" ]; then + now=`date +"%F %T"` + query "replace into acclog values('$user', '$1', '$2', '$now');" + fi +} +gecos() ( + u=${1:-$user} + #gecos=`query "select val from user_s where name='$u' and key='gecos';"` + sql="select case when (select name from user where name='$u') is not null + then (select val from user_s where name='$u' and key='gecos') + when (select gname from grp where gname='$u') is not null + then (select val from grp_s where gname='$u' and key='gecos') + else '$u' + end;" + query "$sql" +) +getpar() { +err getpar: "select val from par where var='$1' and sessid='$session' $2;" + val=`query "select val from par where var='$1' and sessid='$session' $2;"` + if [ -z "$val" ]; then + val=`query "select val from cookie where var='$1' and sessid='$session' $2;"` + fi + case "$var" in + owner) + if [ x"$user" = x"$val" ]; then + echo $user; return + elif ismember $user $val; then + echo $val; return + fi ;; + esac + echo "$val" +} + +getpartype() { + query "select type from par where var='$1' and sessid='$session' $2;" +} +getparcount() { + query "select count(*) from par where var='$1' and sessid='$session' $2;" +} +getparfilename() { + # null if type of $1 is not file + (f=`query "select val from par where var='$1' and sessid='$session' and type='file' $2;"` + [ -n "$f" ] && echo $tmpdir/$f) +} +sqlquote() { + (v="$1" + case "$v" in + "") return ;; # null + "X'"*) # quoted hex string + echo $1 ;; + *\"*) # string including dbl-quote" + v=`echo "$v"|sed -e 's/\"/\"\"/g'` + echo "\"$v\"" + return ;; + *.*.*|*-*-*|*[Ee]*[Ee]*|[Ee]*|*[\ -,:-df-~]*) # string + echo "\"$v\"" + return ;; + *) + if expr "$v" : '[-0-9.Ee][-0-9.Ee]*$' >/dev/null 2>&1; then + echo $v # MAYBE numeric, maybe... + else + echo "\"$v\"" + fi ;; + esac) +} +mktempd() { + mktemp -d -p $tmpdir/ -t $session +} +getval() { + # $1=table $2=col $3(optional)=condition + case `gettbl_coltype "/$1/$2"` in + user|author) # author added 2015-06-18 for article(author) + echo "$user" ;; + stamp|datetime) + date "+%F %T" ;; + serial) + (s=`getpar serial` + if [ -n "$s" ]; then echo $s; else echo "`date +%s`x$$"; fi) ;; + *) + getpar "$2" "$3";; + esac +} + +getvalquote() { + # $1=table $2=col $3(optional)=condition + (v=`getval "$@"` + case "$v" in + "") echo NULL ;; + *) sqlquote "$v" ;; + esac) +} +getparquote() { + sqlquote `getpar $1` +} +getvalbyid() { + # $1=tbl $2=col $3=rowid $4=tmpdirForBinary + # If two or more values found, save them to $tmpd/${column}.$N and + # store the number of files into $tmpd/${column}.count and + # their each rowid stored into $tmpd/${column}.$N.rowid. + ### err gtb-$1=`gettblcols $1`, tbl=$1, col=$2, '$3'=$3 + (for c in `gettblcols $1`; do + if [ x"$2" = x"$c" ]; then + err "select $2 from $1 where rowid=$3" + ###sq $db "select $2 from $1 where rowid=$3" + query "select $2 from $1 where rowid=$3;" + return + fi + done + pk=`gettblpkey $1` +# key=`sq $db "select $pk from $1 where rowid=$3"` + key=`query "select $pk from $1 where rowid=$3;"` + ### err "select $pk from $1 where rowid=$3" - key=$key '$4(tmp)'=$4 + for kt in s m; do + td=${4:-$tmpdir} + [ -d $td ] || mkdir -p $td + t=${1}_$kt + for c in `gettbl_${kt}_cols $1`; do + vcount=1 # count(val) + if [ x"$2" = x"$c" ]; then + cond="$t where $pk=\"$key\" and key=\"$c\"" + ###val=`query "select val from $cond;"` + val=`query "select val from $cond limit 1;"` + ###type=`query "select type from $cond;"` + type=`query "select type from $cond limit 1;"` + if [ $kt = m ]; then + ###vcount=`sq $db "select count(val) from $cond"` + # Reset val to store filenames if type is string + val=`query "select val from $cond and type like 'file:%' order by rowid;"` + vcount=`query "select count(val) from $cond;"` + echo $vcount > $td/$c.count + i=0 + while [ $i -lt $vcount ]; do + slice="order by rowid limit 1 offset $i" + i=$((i+1)) + fn=$c.$i +##err td=$td, fn=$fn, type=$type, val="[$val]" + case $type in + file:*) + #file=$td/$val + file=$td/`query "select val from $cond $slice;"` +####tmp [ -s $file -a -s $td/$fn.rowid ] && continue + sq $db< $file +.output $td/$fn.rowid +select rowid from $cond $slice; +.output $td/$fn +select val from $cond $slice; +.output $file.content-type +select substr(type, 6) from $cond $slice; +.output stdout +select quote(bin) from $cond $slice; +EOF + ## err i=$i - file=$file rowid=`cat $td/$fn.rowid` + ln $td/$fn.rowid $file.rowid 2>&3 # for convenience + case $type in + *:[Ii]mage*) mogrify -geometry $thumbxy $file ;; + ### ここのアイコンを増やしたい + *|*:[Aa]pplication*) + convert -geometry $thumbxy $imgdir/file-icon.png \ + png:- > $file + ;; + esac + ;; + *) + sq $db< $file + echo ${type#file:} > $file.content-type +# err TTTTTTTTTTTTTTTT: $type + case $type in + *:[Ii]mage*) mogrify -geometry $thumbxy $file ;; + *:[Aa]pplication*) + convert -geometry $thumbxy $imgdir/file-icon.png \ + png:- > $file ;; + esac + fi + done + ;; + esac + fi + echo "$val" # Keep newlines by "" + return + fi + done + done) +} +getvalbypkey() ( + # $1=tbl $2=col $3=pkey $4=tmpdirForBinary + pk=`gettblpkey $1` + rowid=`query "select rowid from $1 where $pk='$3';"` + getvalbyid "$1" "$2" $rowid $4 +) +getvalbycond() { + # $1=tbl $2=col $3=SQL-Condition + ###rowid=`sq $db "select rowid from $1 where $3"` + rowid=`query "select rowid from $1 where $3;"` + if [ -n "$rowid" ]; then + getvalbyid "$1" "$2" $rowid "$4" + fi +} +getpwfield() { + # getpwfield user column +# val=`sqlite3 $db "select $2 from passwd where name='$1' $3"` + val=`getvalbycond user $2 "name='$1'"` + if [ -n "$val" ]; then + echo "$val" + return 0 + else + return 1 + fi +} +encode() { + if [ -z "$sha1" ]; then + if type sha1 >/dev/null 2>&1; then + sha1=sha1 + elif type sha1sum >/dev/null 2>&1; then + sha1=sha1sum + elif type gsha1sum >/dev/null 2>&1; then + sha1=gsha1sum + fi + fi + $sha1 "$@" | cut -d' ' -f1 +} +mycrypt() ( + key=$1 salt=$2 +err \$2=$2 + case $2 in + '$'*'$'*) salt=${salt#\$4\$} + salt=${salt%\$*} ;; + esac + echo -n '$4$'"$salt"'$' + echo "$salt$key" | encode +) +hexize() { + if [ -z "$hexize" ]; then + if type xxd >/dev/null 2>&1; then + hexize="xxd -p" + else + hexize="hexdump -ve '1/1 \"%.2x\"'" + fi + fi + cat $1 | $hexize | tr -d '\n' +} +percenthex() { + hexize $1 | sed 's/\(..\)/%\1/g' +} +enascii() { + if [ -z "$enascii" ]; then + if type kakasi >/dev/null 2>&1; then + enascii="kakasi -Ha -Ka -Ja -Ea -ka" + else + enascii_now=`date +%FT%T` + enascii_sed() { + nkf -Z0Z1Z2 \ + | sed -e "s/^/$enascii_now/" -e "s|[^-0-9.A-z/,()_=]|x|g" + } + enascii="enascii_sed" + fi + fi + cat "$@" | $enascii +} +gettblconf() { + if [ -z "$tconfs" ]; then +## tconfs=`sq $db \ + tconfs=`query \ + "select tbl||'/'||col||'='||keytype||'/'||objtype from $conftbl;"` + fi + # /tb1/col1=p/text /tb1/col2=s/text /tb1/col3=m/image /tb2/col1=p/text ... +} +gettblkeys() { + # $1=tbl + gettblconf + echo "$tconfs" | fgrep "/$1/" | \ + (type="" keys="" fks="" cols="" scols="" mcols="" hcols="" + while IFS='=' read tc conf; do # tc=/tb1/col1 conf=s/text + col=${tc##*/} type=${conf%%/*} + case $type in + *p*) + cols=$cols"${cols:+:}$col" + keys=$keys"${keys:+:}$col" ;; + *f*) cols=$cols"${cols:+:}$col" + fks=$fks"${fks:+:}$col" ;; + *m*) mcols=$mcols"${mcols:+:}$col" ;; + *s*) scols=$scols"${scols:+:}$col" ;; + esac + case $type in + *h*) hcols=$hcols"${hcols:+:}$col" ;; + esac + done + echo "_keys=$keys _fks=$fks _cols=$cols _scols=$scols _mcols=$mcols _hcols=$hcols") +} +gettblpkey() { + # $1=tbl + gettblkeys $1 | cut -d ' ' -f 1 | sed -e 's/.*=//' -e 's/:/ /g' +} +gettblfkey() { + (x=`gettblkeys $1` + x=${x#*_fks=} # cut before "_fks=" including + echo ${x%% *} | tr ':' ' ') +} +gettblcols() { + (x=`gettblkeys $1` + x=${x#*_cols=} # cut before "_cols=" including + echo ${x%% *} | tr ':' ' ') +} +gettbl_s_cols() { + (x=`gettblkeys $1` + x=${x#*_scols=} # cut before "_scols=" including + echo ${x%% *} | tr ':' ' ') +} +gettbl_m_cols() { + (x=`gettblkeys $1` + x=${x#*_mcols=} # cut before "_mcols=" including + echo ${x%% *} | tr ':' ' ') +} +gettbl_h_cols() { + (x=`gettblkeys $1` + x=${x#*_hcols=} # cut before "_hcols=" including + echo ${x%% *} | tr ':' ' ') +} +gettbl_coltype() ( + gettblconf + x=`echo "$tconfs"|fgrep $1=` + x=${x#*=} # cut before = + echo ${x#*/} # cut before p/ including +) +is_hidden() { + # $1=Tbl $2=col + gettblconf + x=`echo "$tconfs"|fgrep /$1/$2=` + x=${x#*=} # cut before = + x=${x%%/*} # cut after / + case $x in + *h*) return 0 ;; + *) return 1 ;; + esac +} + +dbsetbyid() { + # $1=tbl $2=id $3=col $4=val/filename - &optional - $5=content-type + (t0=$1 t=$1 p=$2 c=$3 + tsc=$t/$c val=$4 + unset primary update + gettblconf +#err tsc=$tsc, tconfs="$tconfs" + conf=`echo "$tconfs"|fgrep "$tsc"=` +#err conf=$conf + case ${conf#*=} in + p*) primary=1 ;; + f*) update=1 ;; + u*) ;; + m*) t=${t}_m;; + s*) t=${t}_s;; + esac +#err t=$t + type=text fn="" + case $conf in + */password) + type=encoded ### val=`echo $val|encode` + ;; + */image*|*/document*) + type=`file --mime-type $val` + bin="X'`hexize $val`'" + ;; + esac + pkey=`echo "$tconfs"|grep "${t0}/.*=p"|sed 1q` + pkey=${pkey#/*/} # cut $tbl/ + pkey=${pkey%=p/*} # cut =p/... -> primary key + if [ "$primary" ]; then + nulls=`echo "$tconfs"|grep "$t/.*=[fu]/"|sed 's/^.*/, NULL/'|tr -d '\n'` + ###sq $db "replace into $t values(\"$val\"$nulls)" + query "replace into $t values(\"$val\"$nulls);" + elif [ "$update" ]; then + ###sq $db "update $1 set $c=\"$val\" where $pkey=\"$p\"" + query "update $1 set $c=\"$val\" where $pkey=\"$p\";" + else +#err "replace into $t values(\"$p\", \"$c\", \"$type\", \"$val\", \"$bin\")" + ###sq $db "replace into $t values(\"$p\", \"$c\", \"$type\", \"$val\", \"$bin\")" + query "replace into $t values(\"$p\", \"$c\", \"$type\", \"$val\", \"$bin\");" + fi + ) +} +expire() ( + at="${1:-$timeout}" + FMT="${2:-%F %T}" + TZ=GMT date -d "$at" +"$FMT" +) +addsession() { + # expireをセット + # loginの先にどの画面に行くかの状態遷移表書式を決める + expire=`expire ${2:-"+1min"}` +err addsession "$1" exp=$expire + sq $db "replace into session values('$1', '$expire')" + # Remove old session parameters + now=`expire now` + sq $db "delete from session where expire < '$now'" +} +gencookie() ( + for kv; do + expire="`expire '' '%a, %d-%b-%Y %H:%M:%S GMT'`" + echo "Set-Cookie: $kv; expires=$expire" + done +) +contenttype() { + echo "Content-type: ${1:-text/html; charset=utf-8}" + contenttype() {} # Only need to work once +} +putheader() { + +} +putfooter() { + m4 -D_TITLE_="${TITLE:-$myname}" $layout/footer.m4.html +} +getcookie() ( + for kv in `echo $HTTP_COOKIE|sed 's/[;, ]/ /g'`; do + k="${kv%%=*}" + v="`echo ${kv#*=}|nkf -Ww -mQ|sed -e 's/\"/\"\"/g'`" + query "replace into cookie values('$session', '$k', 'string', \"$v\");" + done +) +genrandom() { + # $1=columns (default: 10) + dd if=/dev/urandom count=1 2>/dev/null|nkf -MB|fold -w${1:-10}|sed -n 10p +} +smail() { + # smail rcpt subj (file) + rcpt=`echo $1` # strip newlines + subj="`echo $2|nkf -jM`" + # echo rcpt=$rcpt + (m4 -D_RCPT_="$rcpt" -D_SUBJ_="$subj" -D_FROM_=$admin $msg/mail-header.m4 + cat $3 | nkf -jd ) | sendmail -f $admin $rcpt +} +setviastring() { + table=$1 + oifs="$IFS" + IFS="&" + for us in $2; do + k=${us%%=*} + v="`echo ${us#*=}|tr '%+' '= '|nkf -Ww -mQ|sed -e 's/\"/\"\"/g'`" + sq $db "replace into $table values('$session', '$k', 'string', \"$v\")"; + #echo $k=$v + done + IFS="$oifs" +} +checkdomain() ( + # Check the validity of domain by referring DNS + item=$1 + host ${item#@*} >/dev/null 2>&1 +) +pwcheck() { + # $1=passwd + dbpswd=`getpwfield $user pswd` + encpswd=`mycrypt "$1" "$dbpswd"` + err user=$user, pswd=$1, db=$dbpswd, enc=$encpswd + [ x"$dbpswd" = x"$encpswd" ] +} +mypwhash() { + mycrypt `cat` `genrandom 5` +} +wasureta() { + user=$1 + if checkdomain $user; then + echo "ユーザ名には正しいメイルアドレスが必要です。" + exit 0 + fi + newpswd=`genrandom` # newsalt=`genrandom 5` + #encpswd=`mycrypt "$newpswd" "$newsalt"` + encpswd=`echo $newpswd|mypwhash` + dbsetbyid user $user pswd "$encpswd" + m4 -D_USER_="$user" -D_PSWD_="$newpswd" -D_URL_="$url" \ + $msg/mail-newaccount.m4 \ + | smail $user "New Account" +} +checkauth() { + user=`getpar user` + skc=`getpar skey` # from cookie + [ -z "$user" ] && return 3 + skey="`getpwfield $user skey`" +err user=$user skey=$skey + if [ -n "$skey" ]; then + if [ x"$skey" = x"$skc" ]; then + return 0 + fi + fi + pswd=`getpar pswd` + if [ x"$pswd" = x"wasureta" ]; then + wasureta $user + return 1 # wasureta error + fi + # dbpswd="`sq $db \"select pswd from passwd where name='$user'\"`" + # putheader; echo; echo user=$user, db=$dbpswd, enc=$encpswd + if pwcheck "$pswd"; then + newsession=`genrandom 50` + dbsetbyid user $user skey "$newsession" + gencookie "user=$user" "skey=$newsession" + return 0 + fi + return 2 # Password mismatch +} +showlogin() { + args=`echo $myargs|tr ' ' '+'` + m4 -D_SYSNAME_="Welcome" -D_MYNAME_="$myname${args+?}$args" \ + $layout/login.m4.html + exit 0 +} +dologin() { + checkauth + st=$? + if [ $st != 0 ]; then + contenttype; echo + m4 -D_USER_="$user" -D_URL_="$url" -D_ADMIN_="$admin" \ + $msg/login-fail-$st.m4.html + showlogin # and EXIT + fi +} +cleanup() { + echo .quit > $sqi + kill $sq3pid + rm -f $sqo $sqi + rm -rf $tmpfiles +} +trap cleanup INT HUP EXIT +# trap cleanup INT HUP +cgiinit() { + session=`date +%F-$$` + tmpf=tmp/stream + tmpd=`mktempd` + tmpfiles=$tmpfiles" $tmpd" + addsession $session + getcookie + case "$REQUEST_METHOD" in + get|GET) s="$QUERY_STRING" ;; + post|POST) dd count=$CONTENT_LENGTH bs=1 of=$tmpf 2>/dev/null + # cat > $tmpf + s="`cat tmp/stream`" + tmpfiles=$tmpfiles"${tmpfiles+ }$tmpf" + ;; + esac + case "$CONTENT_TYPE" in + *boundary*) + bndry=${CONTENT_TYPE#*boundary=} + for us in `LC_CTYPE=C ./mpsplit.rb "$bndry" $tmpdir < $tmpf` + do + k=${us%%\=*} + #echo u=$us + # v="`echo ${us#*=}|nkf -Ww -mQ|sed -e 's/=/=3d/g' -e 's/\"/=22/g'`" + v="`echo ${us#*=}|nkf -Ww -mQ|sed -e 's/\"/\"\"/g'`" + # err k=$k v=$v + case "$k" in + *:filename) + type='file'; k=${k%:filename} + case `file --mime-type $tmpdir/$v|cut -d' ' -f2` in + [Ii]mage/*) + mogrify -resize $maximagexy'>' $tmpdir/$v + ;; + esac + ;; + *) + type='string' + ;; + esac + sq $db "replace into par values('$session', '$k', '$type', \"$v\")" + done + ;; + *) + setviastring par "$s" + ;; + esac +} +collectemail() { + # Collect email addresses for group $1 + if isuser "$1"; then + em=`query "select val from user_m where name='$1' and key='email';"` + [ -n "$em" ] && echo "$em" || echo "$1" + else + query "with recursive allmem as + (select gname,val from grp_m where gname='$1' + union all select grp_m.gname,grp_m.val from grp_m,allmem + where allmem.val=grp_m.gname) + select coalesce(b.val,a.val) + from allmem a left join grp_mem_s b + on a.gname=b.gname and a.val=b.user and b.key='email' + where a.val in (select name from user) limit 10000;" + fi +} +sendinvitation() ( + # $1=email + iss="invite-`date +%s`-$(genrandom 10)" + addsession $iss +7days # 1 week due date + query "replace into par values('$iss', 'invite', 'string', \"$1\");" + gecos=`gecos` + name=$user"${gecos:+($gecos)}" + regist="$urlbase?reg+$iss" + m4 -D_URL_="$urlbase" \ + -D_USER_="$name" \ + -D_EMAIL_="$1" \ + -D_REGIST_="$regist" \ + -D_ADMIN_="$admin" \ + $msg/mail-invite.m4 \ + | smail $1 "BBSへの御招待" + return 0 +) +emaildomaincheck() { + case "$1" in + *@*@*) echo "無効なアドレスです"; return 1 ;; + *@*) + local=${1%@*} domain=${1#*@} + if ! host $domain >/dev/null 2>&1; then + echo "ドメイン($domain)が見付かりません。" + return 2 + fi + return 0 + ;; + *) echo "正しいメイルアドレスをいれてください"; return 3 ;; + esac +} +invite() { + email=`getpar email` + case $email in + *@*@*) repo="無効なアドレスです" ;; + *@*) + local=${email%@*} domain=${email#*@} + if ! repo=`emaildomaincheck $email`; then + repo="招待アドレスのエラー: $repo" + elif [ -n "`query \"select * from user where name='$email';\"`" ]; then + repo="$email さんは既に加入しています。" + elif sendinvitation $email; then + repo="アドレス($email)宛に案内を送信しました。" + fi ;; + "") repo="招待したい人のメイルアドレスを入力してください。" ;; + *) repo="無効なアドレスです" ;; + esac + m4 -D_REPORT_="$repo" -D_ACTION_="$myname?invite" \ + $layout/html.m4.html $layout/invite.m4.html +} +regist() { + # $1=session-id-for-invitation + m4 -D_TITLE_="Invitation" $layout/html.m4.html + if [ -z "$1" ]; then + echo "

bye bye

" + reutrn + fi + email=`session=$1 getpar invite` + if [ -z "$email" ];then + cat<無効な招待状チケットです。

+

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

+EOF + reutrn + fi + echo "

$email さんようこそ

" + query "replace into user values('$email');" + # Fake login password to wasureta + query "replace into par values('$session', 'pswd', 'string', 'wasureta'), +('$session', 'user', 'string', '$email');" + wasureta $email + m4 -D_SYSNAME_="Initial Login" -D_MYNAME_="$myname?userconf" \ + $layout/login.m4.html + return +} +userconf() { + m4 -D_BODYCLASS_=userconf -D_TITLE_="ユーザ情報編集" $layout/html.m4.html + GF_ACTION="?home" edittable "$formdir/user.def" "user" "$user" +} +groupconf() { + m4 -D_BODYCLASS_=groupconf -D_TITLE_="グループ情報編集" $layout/html.m4.html + rowid=`query "select rowid from grp where gname='$1';"` +err gcon \$1=$1 rowid=$rowid + GF_ACTION="?grp+$1" edittable "$formdir/grp.def" "grp" "$rowid" +} +showhome() { + # $1=userRowIdToShow +err showhome \$1=$1 + case "$1" in + *@*) uname=`getvalbypkey user name "$1"` ;; + *) uname=`getvalbyid user name $1` ;; + esac +err ShowHome: uname=$uname + gecos=`gecos "$uname"` + GF_VIEWONLY=1 + cond="gname in (select gname from grp_mem where user='$uname')" + if [ x"$user" = x"$uname" ]; then + conflink="プロフィールの編集 / + 新規話題の作成" + fi + . ./y4-blog.sh + + m4 -D_BODYCLASS_=home -D_TITLE_="$gecos さん" \ + -D_PROFILE_="`viewtable $formdir/user.def user $1`$conflink" \ + -D_BLOGS_="`listblog $uname`" \ + -D_GROUPS_="`listgroupbytable $formdir/grp.def $cond`" \ + $layout/html.m4.html $layout/home.m4.html + + # + # Record access log + [ -n "$1" ] && [ x"$1" != x"$user" ] && acclog user $1 +} + +listgroupbytable() { + # $1=deffile + tagline=`grep :tag: $1`; shift + and="${1:+and }" + href="' +err ListGRP: query "select val from grp_s where key='tag' $and$* group by val;" + for tag in `query "select val from grp_s where key='tag' $and$* group by val;"` + do +err ListGrp: tag=$tag + tn=${tagline%%=${tag}*} + tn=${tn##*[ :]} + sql="select gname as 'グループ名',説明 from (select gname,max(case key when 'gecos' then val end) as '説明',max(case key when 'tag' then val end) as 'tag' from grp_s group by gname having tag='$tag');" + err PersonalGroupList= `echo $sql` + echo "

$tn

" + echo '' + sq -header -html $db "$sql" \ + | sed "s,\(,\1$href\2\">\2," + echo '
\)\([-_A-z0-9]*\)
' + done + echo '' +} +iconhref() ( + # $1=icon-file, $2=Href $3=title $4...=anchor + data=`percenthex $1` + ct=`file --mime-type $1|cut -d' ' -f2` +err iconhref: \$1=$1 \$2=$2 \$3="$@" + href=$2; title=$3; shift 3 + echo "
$@" +) +iconhref2() ( + # $1=icon-file, $2=Href $3=title $4...=anchor + src=$1 + href=$2; title=$3; shift 3 + echo "$@" +) +listentry() ( + # $1=user/group $2=SearchKeyword $3=condition(if any) + # Referring variable $iamowner=$grp to attach owner-request links +err listentry: \$1=$1 \$2=$2 \$3=$3 + cond= + offset=`getpar offset` + offset=${offset%%[!0-9]*} + offset=$((offset + 0)) # change to numeric forcibly + [ $offset -lt 0 ] && offset=0 + limit=30 + dir=$tmpdir/$imgcached/$thumbxy.`echo $1|md5` + if [ x"$1" = x"user" ]; then + hrb="$myname?home" + deficon=person-default.png + entity="ユーザ" tbl=user link=rowid nm=name stage=mems + else # if group + hrb="$myname?grp" + deficon=person-default.png + entity="グループ" tbl=grp link=gname nm=gname stage=grps + tagline=`grep :tag: $formdir/grp.def|cut -d: -f5-` + if [ -n "$tagline" ]; then + tagconv=`echo $tagline|sed 's/\([^= :]*\)=\([^= :]*\)/-D\2=\1/g'` +err tagconv=$tagconv + fi + fi + if [ ! -d $dir ]; then + mkdir -p $dir + convert -geometry $thumbxy $imgdir/$deficon $dir/$deficon + fi + if [ -n "$2" ]; then + cond="where nick like '%$2%' or b.name like '%$2%'" + fi + + # XX: これ複雑すぎるかな。もっとシンプルにしたい。$3条件も。2015-07-08 + sql="select a.rowid, a.$link, coalesce(b.gecos, a.$nm) as nick, b.tag, + case when '$iamowner' = '' then '' + when a.$nm in (select user from grp_adm + where gname='$grp') then '(管理者)' + else ',not='||a.rowid end as ownerlink + from $tbl a left join + (select $nm as name, + max(case key when 'gecos' then val end) as gecos, + max(case key when 'tag' then val end) as tag + from ${tbl}_s group by $nm) + b on a.$nm=b.name $cond $3 + order by b.tag desc, a.rowid asc" + total=`query "with x as ($sql) select count(*) from x;"` + echo "

${entity} 一覧

" + if [ $total -gt $limit ]; then + echo '
' + cgi_form $stage <次の語を含む${entity}で検索: +`cgi_text kwd $kwd` +EOF + echo '
' + fi + cat<${total}件中の${offset}件めから${kwd:+" - 検索語: $kwd"}

+EOF + if [ $((offset+limit)) -lt $total ]; then + cat<
+`cgi_submit 次の${limit}件` +`cgi_hidden kwd "$kwd"` +`cgi_hidden stage "$stage"` +`cgi_hidden offset $((offset + limit))`
+EOF + fi + if [ $offset -gt 0 ]; then + cat< +`cgi_submit 前の${limit}件` +`cgi_hidden stage "$stage"` +`cgi_hidden kwd "$kwd"` +`cgi_hidden offset $((offset - limit))` +EOF + fi + + err `echo $sql\;` + + query "$sql limit $limit ${offset:+offset $offset};" \ + | while IFS='|' read id lnk name tag ownerp; do +err name=$name owner=$ownerp + files=`getvalbyid $tbl profimg $id $dir` + # Pick up only first icon + echo "

$tag

" \ + | m4 $tagconv + if [ -n "$files" ]; then + icon=`echo "$files"|head -1` + iconhref $dir/$icon "$hrb+$lnk" "$name" + else + iconhref $dir/$deficon "$hrb+$lnk" "$name" + fi + echo "
$name${ownerp:+
$ownerp}" + echo "
" + done +) +listmember() { + listentry user "$@" +} +listgroup() { + listentry group "$@" +} +showgroup() { + grp=$1 + + showgroupsub $formdir/grp.def $grp | \ + m4 -D_TITLE_="グループ $grp" \ + -D_FORM_="syscmd(\`cat')" \ + -D_DUMPTABLE_="" \ + $layout/groupman.m4.html +} +showgroupsub() { + # $1=def-file $2=group + grp=$2 + rowid=`sq $db "select rowid from grp where gname='$grp'"` + if [ -z "$rowid" ]; then + rowid=`sq $db "select rowid from grp where rowid=$grp"` + grp=`sq $db "select gname from grp where rowid=$grp"` + fi + val=`getvalbyid grp profimg $rowid $tmpd` + # 6/14の次グループのHOMEで出す情報を作る Done + viewtable $1 grp $rowid + if isgrpowner $user $grp; then + echo "

グループ情報の編集" + iamowner=$grp + fi + if ismember $user $grp; then + echo "${iamowner:+ / }グループの新規話題作成

" + fi + # 加入ボタン + 加入者リスト +err ismember $user $grp + ismember $user $grp && ismem='checked' || nomem='checked' + # このグループでの加入アドレス + eml=`query "select val from grp_mem_s where gname='$2' and user='$user' \ + and key='email';"` +err EML: "select val from grp_mem_s where gname='$2' and user='$user' \ + and key='email';" +err email=$eml + echo '

このグループに

' + cgi_form grp < +メンバーとして + / + +参加する場合のメイルアドレス
+(メインのアドレスとは違うものにする場合に記入
+同じでよい場合は空欄に)
+`cgi_text email $eml` + +`cgi_hidden grp $grp` +EOF + + echo '

話題一覧

' + cgi_form searchart<`cgi_text kwd`という語を含むコメントを検索 +`cgi_hidden owner $grp` +EOF + cond="where a.id in (select id from blog_s where key='owner' and val='$grp') order by ctime desc" + DT_CHLD=article:blogid \ + DT_VIEW=replyblog dumptable html blog 'ctime title heading' "$cond" + + c="group by b.name having b.name in (select user from grp_mem where gname='$grp')" + cm="?commission+$grp" + thumbxy=50x50 listmember "" "$c" \ + |sed -e "s|\(
\),not=\(.*\)|\1管理者委託|" +} +joingrp() { + # $1=group $2=user $3=yes/no $4=email(if any) +err joingrp: \$1=$1 \$2=$2 \$3=$3 \$4=$4 + if [ x"$2" != x"$user" ]; then # if user is not login user + if ! isgrpowner $user $1; then + echo "

本人か、グループ管理者しか加入操作はできません。

" + return + fi + fi + cond="where gname='$1' and user='$2'" + if [ x"$3" = x"yes" ]; then + query "replace into grp_mem values('$1', '$2');" + if [ -n "$4" ]; then + if msg=`emaildomaincheck "$4"`; then +err "replace into grp_mem_s values('$1', '$user', 'email', \ + 'string', '$4', NULL);" + query "replace into grp_mem_s values('$1', '$user', 'email', \ + 'string', '$4', NULL);" + else + echo $msg + fi + else + query "delete from grp_mem_s $cond and key='email';" + fi + else + query "delete from grp_mem $cond; +delete from grp_mem_s $cond; +delete from grp_mem_m $cond;" + fi +} +grp_reg_adm() { + # $1=grp $2=user-rowid + if ! isgrpowner $user $1; then + echo "

$1 グループの管理者しかこの操作はできません。"; return + fi + newadm=`query "select name from user where rowid=$2;"` + if [ -z "$newadm" ]; then + echo "

指定ユーザIDがおかしいようです。

"; return + fi +err GRP_reg_adm: "replace into grp_adm values('$1', '$newadm');" +err ismember $newadm $1 + if ismember $newadm $1; then + # OK, go ahead + query "replace into grp_adm values('$1', '$newadm');" + # confirm insertion + sql="select * from grp_adm where gname='$1' and user='$newadm'" + if [ -n "`query \"$sql;\"`" ]; then + echo "

追加完了

" + else + echo "

追加失敗($1 $2)

" + fi + fi + showgroup $1 +} +dumptable() { + # $1=mode $2=Table $3=column-list(defaults to *) $4=conditions(if any) + # textのフィールドだけ全てダンプにしたほうがいいか + # $DT_VIEW sets link + # 6/17の次: editリンクじゃなくてスレッドVIEWリンクでいいんちゃう? + ### elink="EDIT" + VIEW=${DT_VIEW-replyblog} + if [ -n "$VIEW" ]; then + dvlink=" VIEW" + fi + # $DT_CHLD=ChildTable:BindColumn + if [ -n "$DT_CHLD" ]; then + _t=${DT_CHLD%:*} _i=${DT_CHLD#*:} + cntall="(select count($_i) from $_t where $_i=a.id)" + cntnew="(select count(val) from ${_t}_s where key='ctime' \ + and id in (select id from $_t where $_i=a.id) \ + and val > coalesce((select time from acclog where \ + user='$user' and tbl='$2' and rowid=a.rowid),\ + '1970-01-01'))" + cnt="$cntnew||'/'||$cntall as '新着/総数'," + dt_class=" td2r" + fi + # Construct join expression + eav="" scols="" + pk=`gettblpkey $2` + substr=${dumpcollen:+"substr(val, 0, $dumpcollen)"} + substr=${substr:-val} + for col in ${3:-`gettbl_s_cols $2`}; do + eav=$eav${eav:+,}" max(case key when '$col' then $substr end) as $col" + scols="$scols${scols:+, }b.$col" + done +#case author when '$user' then a.rowid else '---' end as ID, + sql="select \ +a.rowid as ID,\ +$cnt\ +$scols from $2 a left join (select $pk,$eav from ${2}_s group by $pk) b on a.$pk=b.$pk $4;" +err SQL="$sql" + cat<\)\([1-9][0-9]*\),\1$elink$dvlink," +
+ +`sq -header -cmd ".mode $1" $db "$sql"` +
+
+EOF +} + +par2table() ( + # copy current parameters of par into destination table + # $1=definition-file + # Using $user and $session + rowid=`getpar rowid` + if [ ! -e $1 ]; then + echo "

テーブル定義ファイルが見付かりません

" + exit 1 + fi + tbl=${1%.def} + tbl=${tbl##*/} + if [ -n "$rowid" ]; then # Modify existing entry + if [ x"$tbl" = x"user" ]; then + rowowner=`query "select name from $tbl where rowid=$rowid;"` + elif [ x"$tbl" = x"grp" ]; then + isgrpowner $user `query "select gname from $tbl where rowid=$rowid;"` \ + && rowowner=$user + else + rowowner=`query "select owner from $tbl where rowid=$rowid;"` + rowowner=${rowowner:-`query "select author from $tbl + where rowid=$rowid;"`} + fi + if [ x"$user" != x"$rowowner" ]; then + echo "

他人のレコードはいじれないの

" + return + elif [ -z "$rowowner" ]; then + echo "

指定したレコードはないみたい

" + return + fi + rm=`getpar rm` cfm=`getpar confirm` + # Editing existent entry + if [ x"$rm" = x"yes" ]; then + if [ x"$rm$cfm" = x"yesyes" ]; then + query "delete from $tbl where rowid=$rowid;" + return + else + echo "

消去確認のチェックがないので消さなかったの...

" + return + fi + fi + fi + # XX: Subshelling here is unnecessary 2015-07-05 + (ts=${tbl}_s tm=${tbl}_m val="" pval="" formaster="" getrow="" + if [ -n "$rowid" ]; then + # Update of existing record + for col in `gettblcols $tbl`; do + val=`getparquote $col` + [ -z "$val" ] && continue + err sq $db "update $tbl set $col=$val where rowid=$rowid" + query "update $tbl set $col=$val where rowid=$rowid;" + done + # Then, set up $pval for further insertion of tbl_s and tbl_m + for col in `gettblpkey $tbl`; do + val=`query "select $col from $tbl where rowid=$rowid;"|sed -e 's/\"/\"\"/g'` + pval="$pval${pval:+, }\"$val\"" + done + else + # New entry + # Generate values() for primary keys + for col in `gettblpkey $tbl`; do + # Genuine primary keys for _m and _s + val=`getvalquote $tbl $col` + [ -z "$val" ] && continue + pval="$pval${pval:+, }$val" + done +err pval=$pval + for col in `gettblfkey $tbl`; do + # args for values() to insertion into master table + val=`getvalquote $tbl $col` + [ -z "$val" ] && continue + formaster=$formaster"${formaster:+, }$val" + done + formaster="$pval${formaster:+, }$formaster" +err formaster=$formaster + if [ -z "$formaster" ]; then + echo "
項目を全て埋めてください
" + return 1 + fi + err "replace into $tbl values($formaster);" + echo "replace into $tbl values($formaster); $getrow" | sq $db + ## Insertion to master table, done + fi + + for kt in s m; do + tb2=${tbl}_$kt + for col in `gettbl_${kt}_cols $tbl`; do + ptype=`getpartype $col "limit 1"` + + # First, check update of existing entries in _m + if [ $kt = m ]; then + # sessID|address.1.22|string|Somewhere-x.y.z + sql="" +err dots from query "select var from par where var like '$col.%';" + for v in `query "select var from par where var like '$col.%';"`; do + # v=address.1.22 + rowid=${v##*.} + origcol=${v%%.*} # original column derived from +err Updating for $v rowid=$rowid, partype=`getpartype $v` + ##case `getpartype $v` in + err CASE `gettbl_coltype $tbl/$origcol` in + err edit flag = `getpar action.$v` + case `getpar action.$v` in + rm) + if [ x`getpar confirm.$v` = x"yes" ]; then + newsql="delete from $tb2" + else + echo "

削除確認未チェック

" + fi ;; + edit) + case `gettbl_coltype $tbl/$origcol` in + image|document|binary) + file=`getparfilename $v` + err type=file=$file + [ -z "$file" ] && continue + bn=${file##*/} + bin="X'"$(hexize $file)"'" + ct=`file --mime-type $file|cut -d' ' -f2` + type=\"file:$ct\" + newsql="update $tb2 set val='$bn', type=$type, bin=$bin" + ;; + *) + newsql="update $tb2 set val=(select val from par where var \ +like '$col.%.$rowid')" + ;; + esac + ;; + *) # maybe `keep', do not modify value + continue + ;; + esac +# err newsql=$newsql + sql=$sql$nl"$newsql where rowid=$rowid;" + done + echo "$sql +delete from $tb2 where type='string' and val='';" | sq $db + # Rest of kt==m: set multiple mode + nr=`getparcount $col` + else + nr=1 # for kt==s, number of records is 1 + fi + + i=0 + while [ $i -lt $nr ]; do + limit="limit 1 offset $i" + i=$((i+1)) # increase beforehand against continue + val=`getvalquote $tbl $col "$limit"` + [ -z "$val" -o x"$val" = x'""' -o x"$val" = x"NULL" ] && continue +err $col=$val + bin=NULL +err partype$col=`getpartype $col "$limit"` + case $ptype in + file) file=`getparfilename $col "$limit"` +err parfile-$col=$file + [ -z "$file" ] && continue + bin="X'"$(hexize $file)"'" + ct=`file --mime-type $file|cut -d' ' -f2` + type=\"file:$ct\" ;; + "*"*) continue ;; # foreign table + *) type=\"string\" ;; + esac + case `gettbl_coltype $tbl/$col` in + password) # special care for password + # name={password,pswd1,pswd2} + p1=`getpar pswd1 "$limit"` + if [ -z "$p1" ]; then + continue # SKIP password setting, if p1 is empty + else + pswd=`getpar pswd "$limit"` p2=`getpar pswd2 "$limit"` +## err pswd=$pswd + if pwcheck "$pswd"; then + if [ x"$p1" = x"$p2" ]; then + case "$p1" in + ????????*) ;; + *) echo "

8字以上にしてください。

" + return ;; + esac + val="\"`echo $p1|mypwhash`\"" + else + echo "

2つの新パスワード不一致

" + return + fi + else + echo "

旧パスワード違います

" + return + fi + fi + ;; + esac + #err "replace into $tb2 values($pval, \"$col\", $type, $val, $bin);" + echo "replace into $tb2 values($pval, \"$col\", $type, $val, $bin);" \ + | sq $db + done + done + done + return 0 + err donee) +) +par2table_old() { + # copy current parameters of par into destination table + # $1=dst-table $2=definition-file + # Using $user and $session + rowid=`getpar rowid` + if [ -n "$rowid" ]; then + rm=`getpar rm` cfm=`getpar confirm` + if [ x"$rm$cfm" = x"yesyes" ]; then + sq $db "delete from $1 where rowid=$rowid and owner=\"$user\"" + return + fi + fi + cat $2 \ + | (cols="" + while IFS=: read prompt name type args; do + [ x"$name" = x"stage" ] && continue + if [ -n "$rowid" ]; then + val=`getpar $name|sed -e 's/\"/\"\"/g'` + sq $db "update $1 set $name=\"$val\" where rowid=$rowid and owner=\"$user\"" + else + eav=$eav${eav+,}" max(case var when '$name' then val end)" + fi + done + [ -n "$rowid" ] && return + cond="where sessid='$session' group by sessid" + sq $db "replace into $1 select $eav,\"$user\" from par $cond" + # Think over again about putting $user + ) +} +genform() { + # $1 = form definition file + # $2, $3 (optional)= table name and ROWID + # If $GF_VIEWONLY set and nonNull, output values without form + # If $GF_HIDDEN set, use it hidden values + # If $GF_OWNER set, use it as value of name="owner" + # If $GF_STAGE set, use it as value of name="stage" + forms="" hiddens="" rowid=$3 + if [ ! -e "$1" ]; then + echo "

そのようなデータベースはないようです($2)。

" + return + elif [ -n "$2" ]; then +err genform1: "select * from $2 where rowid='$rowid'" + rec=`query "select * from $2 where rowid='$rowid';"` + if [ -z "$rec" ]; then + pk=`gettblpkey $2` + ###rec=`sq $db "select rowid from $2 where $pk='$rowid'"` +err "select rowid from $2 where $pk='$rowid';" + rec=`query "select rowid from $2 where $pk='$rowid';"` +err rec-rowid=$rec + rowid=$rec + rec=$3 + fi + if [ -z "$rec" ]; then + echo "

そんなレコードはないみたいね...

" + return + fi + fi + if [ -z "$GF_VIEWONLY" ]; then + rm=' +ほんとうに消しますよ(確認)! +はい' + fi + while IFS=: read prompt name keytype type args; do + [ -z "${prompt%%\#*}" ] && continue # skip comment line(#) + sp="${args:+ }" + form="" val="" + if [ -n "$rowid" ]; then + val=`getvalbyid $2 $name $rowid $tmpd` + fi + if [ -n "$GF_VIEWONLY" ]; then + is_hidden "$2" "$name" && continue + fi + case "$type" in + text*) + cgiform=cgi_multi_$type + if [ -s $tmpd/$name.count ]; then + form=`$cgiform $name $tmpd` + val=$(echo "$val"| + while read fn; do + echo "`cat $tmpd/$fn`$nl" + done) + val="$nl$val$nl
" + else + #form="$nl" +err genform: cgi_$type $name $val "$args" + form=`cgi_$type $name "$val" "$args"` + fi + ;; + [Rr][Aa][Dd][Ii][Oo]) + fh="\1,g\"`" + ;; + [Ss][Ee][Ll][Ee][Cc][Tt]) + fh="" + ;; + [Ii][Mm][Aa][Gg][Ee]|[Dd][Oo][Cc][Uu][Mm][Ee][Nn][Tt]|[Bb]inary) + if [ -s $tmpd/$name.count ]; then + form=`cgi_multi_file $name $tmpd "$args"` + if [ -n "$val" ]; then + hrfb="$myname?showattc+$2_m" + val=$(echo "$val" \ + | while read fn; do + data=`percenthex $tmpd/$fn` + #ct=`cat $tmpd/$fn.content-type` + ct=`file --mime-type $tmpd/$fn|cut -d' ' -f2` + ri=`cat $tmpd/$fn.rowid` +## err fn=$fn, name=$name, ri=$ri; ls -lF $tmpd 1>&3 + imgsrc="" + echo "$imgsrc
" + done) + fi + else + form="" + if [ -n "$val" ]; then + imgs=$(echo "$val"\ + |while read fn;do + data=`percenthex $tmpd/$fn` + echo "$fn
" + done) + form=$form"
$imgs" + val=$imgs # 2015-06-15 + else + form="" + fi + fi + ;; + [Hh][Ii][Dd][Dd][Ee][Nn]) + if [ -n "$GF_STAGE" -a x"$name" = x"stage" ]; then + args="value=\"$GF_STAGE\"" + fi + form="" + prompt='' # Remove prompt + ;; + [Aa][Uu][Tt][Hh][Oo][Rr]) + form="" + prompt="" ;; + [Oo][Ww][Nn][Ee][Rr]) + val=${GF_OWNER:-$val} + val=${val:-$user} + form="" + prompt="" ;; + [Uu][Ss][Ee][Rr]) + # XXX: is null $user ok? + #form="" + [ -n "$GF_VIEWONLY" ] && continue + form="$user" + ;; + [Pp]assword) + [ -n "$GF_VIEWONLY" ] && continue + form="`cgi_passwd`" + val="" + ;; + [Ss][Ee][Rr][Ii][Aa][Ll]|[Ss][Tt][Aa][Mm][Pp]) + val=$((($(date +%s)-1433084400)/10))c$$ + form="" + prompt="" ;; + [Ss][Ee][Ss][Ss][Ii][Oo][Nn]) + prompt="" + ;; + parent|path|blog*) + prompt="" + ;; + "*"*) + tail=$tail"``" + continue ;; + esac + if [ -n "$prompt" ]; then + if [ -n "${GF_VIEWONLY}" ]; then + form=$val + else + : + fi + forms=$forms" $prompt$form$nl" + else + hiddens=$hiddens$nl"$form" + fi + done < $1 + # enctype="multipart/form-data" + cat< +${rowid:+$rm} + +$forms +
$hiddens + ${rowid:+} +EOF + if [ -z $GF_VIEWONLY ]; then + cat< + +EOF + fi + cat< +$tail +EOF +} +edittable() { + # $1=form-def $2=table $3 rowid + genform "$@" +} +viewtable() { + GF_VIEWONLY=1 genform "$@" +} diff -r 95cebd686c97 -r 6822f4362bf9 y4-init.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/y4-init.sh Sun Jul 19 13:51:41 2015 +0900 @@ -0,0 +1,101 @@ +#!/bin/sh +. `dirname $0`/y4-funcs.sh + +create() { + # $1=type $2=obj $3=defs... + target=$1; shift + name=$1; shift + [ "$debug" ] && echo "create $target if not exists $name $@" + sq $db "create $target if not exists $name $@" +} +create table passwd '(name primary key, pswd, gecos, skey);' +: <"; gencookie "user=$user" "skey=$skey"; echo "" + # echo "
`env|sort -u`
" + ;; + "diary") + contenttype; echo + title=`getpar title` #diary=`getpar diary` wday=`getpar wday` + [ -n "$title" ] && par2table $formdir/diary.def + m4 -D_TITLE_="$title" -D_DIARY_="$diary" \ + -D_FORM_="`genform templ/form/diary.def`" \ + -D_FORM2_="syscmd(\`genform templ/form/diary.def')" \ + -D_DUMPTABLE_="`dumptable html diary title,wday,diary`" \ + $layout/html.m4.html $layout/diary.m4.html + ;; + "invite") + contenttype; echo + invite + ;; + "home") + contenttype; echo + [ -n "`getpar rowid`" ] && par2table $formdir/user.def + showhome ${2:-$user} + ;; + "groupman") + contenttype; echo + gname=`getpar gname` + [ -n "$gname" ] && par2table $formdir/grp.def + m4 -D_TITLE_="グループ作成" \ + -D_FORM_="`genform $formdir/grp.def`" \ + -D_DUMPTABLE_="`DT_VIEW=grp dumptable html grp 'gname gecos'`" \ + $layout/html.m4.html $layout/groupman.m4.html + ;; + "edittable") + contenttype; echo + m4 -D_TITLE_="グループ編集/削除" $layout/html.m4.html + edittable "$formdir/$2.def" "$2" "$3" + ;; + "userconf") + contenttype; echo + [ -n "`getpar rowid`" ] && par2table $formdir/user.def + userconf + ;; + "groupconf") + contenttype; echo + [ -n "`getpar rowid`" ] && par2table $formdir/grp.def + groupconf "$2" + ;; + "mems") + contenttype; echo + m4 -D_TITLE_="参加者一覧" -D_BODYCLASS_=listmember $layout/html.m4.html + kwd=`getpar kwd` + listmember $kwd | tee tmp/listmem.out + ;; + "grps") + contenttype; echo + m4 -D_TITLE_="グループ一覧" -D_BODYCLASS_=listgroup $layout/html.m4.html + kwd=`getpar kwd` + listgroup $kwd \ + | m4 -D_DUMPTABLE_="syscmd(\`cat')" \ + -D_TITLE_="グループ関連操作" \ + -D_FORM_="新規グループ作成" \ + $layout/groupman.m4.html + + ;; + "grps2") + contenttype; echo + m4 -D_TITLE_="グループ一覧" \ + -D_FORM_="`listgroup2 $formdir/grp.def`" -D_DUMPTABLE_= \ + $layout/html.m4.html \ + $layout/groupman.m4.html + ;; + "grp") # $2=group + contenttype; echo + gpg=`getpar grp` + grp=${2:-$gpg} + ## . ./y4-blog.sh + jg=`getpar joingrp` + if [ -n "$jg" ]; then + err jg=$jg, grp=$grp + [ -n "$jg" -a -n "$grp" ] && + joingrp "$grp" "$user" "$jg" "`getpar email`" + fi + m4 -D_TITLE_="グループ $grp" \ + $layout/html.m4.html + showgroup $grp + + ;; + "commission") + # $2=grp $3=user-rowid + contenttype; echo +err commission: "$@" + m4 -D_TITLE_="グループ $2 管理者委任" $layout/html.m4.html + shift # $1=grp $2=user-rowid + if [ -n "$2" ]; then + grp_reg_adm "$@" + else + echo "

無効な指定です。普通のアクセスならここに来ないはず。

" + fi + ;; + "blog") + contenttype; echo + . ./y4-blog.sh + blog_addentry $2 + ;; + "replyblog") + contenttype; echo + rowid=${2%%[!A-Z0-9a-z_]*} + ## err ROWid=$rowid, '$2'=$2 + . ./y4-blog.sh +err blog_reply $rowid + blog_reply $rowid + ;; + "editheading") + contenttype; echo + rowid=${2%%[!A-Z0-9a-z_]*} + # blogrowid=${3%%[!A-Z0-9a-z_]*} + if [ -z "$rowid" ]; then + echo "

話題番号が未指定です。

" + return + fi + owner=`getvalbyid blog owner $2` + title=`getvalbyid blog title $2` + m4 -D_TITLE_="修正" \ + -D_SUBTITLE_="[$title]@$owner" -D_DIARY_="" \ + -D_BLOGS_="" -D_DUMPTABLE_="" \ + -D_FORM_="`GF_ACTION=\"?blog\" edittable $formdir/blog.def blog $rowid`" \ + $layout/html.m4.html $layout/diary.m4.html + ;; + "editart") + contenttype; echo + rowid=${2%%[!A-Z0-9a-z_]*} + blogrowid=${3%%[!A-Z0-9a-z_]*} + if [ -z "$rowid" -o -z "$blogrowid" ]; then + echo "

表示する記事番号が未指定です。

" + return + fi + owner=`getvalbyid blog owner $blogrowid` + title=`getvalbyid blog title $blogrowid` + author=`getvalbyid article author $rowid` + err EDITart: owner=$owner, author=$author + if isgrpowner $user $owner; then + : EDIT OK + elif [ x"$owner" != x"$user" -a x"$author" != x"$user" ]; then + echo "

本人か所有者しか編集できません.

" + return + fi + aid=`query "select id from article where rowid=$rowid;"` + # title=`getvalbyid blog title $2` + m4 -D_TITLE_="コメントの修正" -D_DIARY_="" \ + -D_FORM_="`GF_ACTION=\"?replyblog+$blogrowid#$aid\" edittable $formdir/article.def article $rowid`" \ + -D_SUBTITLE_="`gecos $owner`の「$title」" \ + -D_BLOGS_= -D_DUMPTABLE_= \ + $layout/html.m4.html $layout/diary.m4.html + ;; + "lshandout") + contenttype; echo + rowid=${2%%[!A-Z0-9a-z_]*} + if [ -z "$rowid" ]; then + echo "

話題番号が未指定です。

" + return + fi + . ./y4-blog.sh + lshandout $rowid + ;; + "gethandout") + rowid=${2%%[!A-Z0-9a-z_]*} + if [ -z "$rowid" ]; then + echo "

話題番号が未指定です。

" + return + fi + . ./y4-blog.sh + gethandout $rowid + ;; + "searchart") # $2=blogowner + contenttype; echo + m4 -D_TITLE_="検索結果" $layout/html.m4.html + kwd=`getpar kwd` + if [ -z "$kwd" ]; then + echo "

検索語を指定してください

" + else + owner=`getpar owner` + owner=${owner:-$2} + echo "

「$kwd」による検索結果

" + if [ -n "$owner" ]; then + cond="where key='owner' and val='$owner'" + if isuser $owner; then + echo "

(`linkhome $owner` さんの記録からの検索)

" + else + linkhome $owner 1>&3 + echo "

(`linkhome $owner` グループからの検索)

" + fi + fi + # article_s: id=article-id, key='text', val='TEXT' + # article: id=article-id, blogid=blogkd + # blog: id=blog-id, author=LeaderAuthor + # blog_s: id=blog-id, key='title', val='BLOG-TITLE' + # WANT: blog-ROWid,article-id,val(TEXT) + sql="select b.rowid||'#'||x.id as '', + b.title as TITLE, + substr(x.val, 0, 80) as TEXT + from (select blog.rowid,blog.*,bs.val as title from blog join blog_s bs + on blog.id=bs.id and bs.key='title') b + join + (select a.id,a.blogid,s.val from article a join article_s s + on a.id=s.id where s.val like '%$kwd%') + x on b.id=x.blogid + where b.id in (select id from blog_s + $cond);" + sedopt="s,\([^<]*\),VIEW," + cat< +`sq -header -html $db "$sql"|sed "$sedopt"` + +EOF + fi + ;; + "showattc") + # $2=table_m $3=rowid $4=val + if ! isfilereadable $user $2 $3; then + contenttype; echo + echo "

このファイルは管理者のみしか見られません

" + putfooter; exit + fi + idir=`umask 002; mktemp -d -p $tmpdir -t $myname` || exit 1 + tmpfiles=$tmpfiles"${tmpfiles+ }$idir" + bin=$idir/$myname-$$.bin + ##sql="select quote(bin) from $2 where id='$3' and val='$4'" + sql="select quote(bin) from $2 where rowid='$3'" + sq $db "$sql" | xxd -r -p > $bin + # type=`sq $db "select type from $2 where id='$3' and val='$4'"` + tv=`sq $db "select type,val from $2 where rowid='$3'"` + type=${tv%|*} fn=${tv#*|} + err tv=$tv type=$type fn=$fn + ct=${type#file:} + case $ct in # all text/* changed to text/plain + text/*) + charset=`nkf -g $bin|cut -d' ' -f1` + case $charset in + ASCII*) charset="" ;; + esac + ct="text/plain${charset:+; charset=$charset}" + ;; + esac + contenttype "$ct" + echo "Content-Disposition: filename=\"$fn\"" + echo "Content-Length: " `cat $bin | wc -c`; echo + #echo "Content-Type: " ${type#file:}; echo + cat $bin + exit 0 + ;; + "gallery") + ## contenttype "Image/jpeg" + sql="select quote(b) from te where a='${2:-mikan.jpg}'" + idir=`umask 002; mktemp -d -p $tmpdir -t $myname` || exit 1 + tmpfiles=$tmpfiles"${tmpfiles+ }$idir" + img=$idir/$myname-$$.bin + db=b.sq3 + sqlite3 $db "$sql" | xxd -r -p > $img + len=`cat $img | wc -c` + echo "Content-Length: $len" + type=`file --mime-type $img | cut -d' ' -f2` + echo 'Content-type: $type'; echo + cat $img + ;; +esac + + +putfooter