s4

view s4-blog.sh @ 592:a50e83239b51

Add "enquete" mode
author HIROSE Yuuji <yuuji@gentei.org>
date Tue, 03 Dec 2019 11:41:39 +0900
parents 1e40019d1bb1
children 874e1f59263f
line source
1 #
2 type cgiinit >/dev/null 2>&1 || . ./s4-funcs.sh
4 # Global error flags
5 BLOG_NOTMEM=1
6 BLOG_FROZEN=2
7 FROZEN_TAG='<span class="frozen">[凍結]</span>'
9 blog_genform() {
10 #
11 t=$1
12 }
14 blog_writable() (
15 # $1=articleid $2=user
16 # Return: $?=0 - Writable
17 # =1 - NOT Writable because user is not a member
18 # =2 - NOT Writable because blog is frozen
19 blogowner=`getvalbyid blog owner "$1"`
20 state=`getvalbyid blog state "$1"`
21 rc=0
22 [ x"$blogowner" = x"$2" ] || isuser "$blogowner" || ismember "$2" "$blogowner" || rc=$((rc+$BLOG_NOTMEM))
23 [ "$state" = "frozen" ] && rc=$((rc+$BLOG_FROZEN))
24 return $rc
25 )
26 blog_readable() {
27 # $1=articleid $2=user
28 mode=`getgroupattr $grp regmode`
29 }
30 blog_getteam() {
31 # $1=rowid of blog
32 blogid="${1%%[!A-Z0-9a-z_]*}"
33 # team cannot get `getvalbyid blog team "$blogid"` because it's not
34 # defined in blog.def. Yes, it is Illegal USE!!
35 query "SELECT val FROM blog_s
36 WHERE id=(SELECT id FROM blog WHERE rowid=$blogid)
37 AND key='team';"
38 }
39 blog_notify_reply() (
40 # $1=blogid $2=ReplyingUser $3=WrittenText $4(optional)=Action
41 blogid="${1%%[!A-Z0-9a-z_]*}"
42 blogowner=`getvalbyid blog owner "$blogid"`
43 blogtitle=`getvalbyid blog title "$blogid"`
44 blogurl="$urlbase?replyblog+$blogid"
45 action=${4:-書き込み}
46 mode=`getvalbyid blog notify "$blogid"`
47 isgroup "$blogowner" && _isgroup=true || _isgroup=false
48 ### EXCEPT=`sqlquote "$user"` ## User should receive to feal some annoyance
49 case $mode in
50 admin)
51 if $_isgroup; then
52 emails=`getgroupadminmails $blogowner`
53 else
54 emails=`collectemail $blogowner`
55 fi
56 notifyto=`getpar notifyto`
57 if [ -n "$notifyto" ]; then
58 emails=$emails" `email4groupbyuid \"$blogowner\" $notifyto`"
59 fi
60 ;;
61 no) emails="" ;;
62 *) team=`blog_getteam "$blogid"`
63 # team cannot get by `getvalbyid blog team "$blogid"`
64 emails=`TEAM=$team collectemail $blogowner` ;;
65 esac
66 ## 2017-0210 Respond to the direct reply mark such as: >#1234
67 replymark=`echo "$3"|nkf -w -Z0|grep '^ *>#'`
68 authgecos=`gecos $2`
69 if [ -z "$4" -a -n "$replymark" ]; then
70 # If the action is new subscription($4="") and has ">#123" marks...
71 ids=`echo "$replymark"|sed 's/[^#0-9]*#\([0-9]*\)[^#0-9]*/\1 /g'`
72 ids=`echo $ids|tr -dc '[0-9 ]'|tr ' ' ','`
73 # -> 123,345,347
74 unames=`query "SELECT distinct author FROM article \
75 WHERE rowid in ($ids)\
76 AND blogid=(SELECT id FROM blog WHERE rowid=$blogid);"`
77 if [ -n "$unames" ]; then
78 e4g=$(if $_isgroup; then
79 email4group "$blogowner" $unames
80 else
81 for u in $unames; do
82 collectemail $u
83 done
84 fi)
85 emails=$emails" $e4g"
86 for e in $unames; do
87 g=`gecos $e`
88 whom=$whom"${whom:+,}${g:-$e}さん"
89 done
90 action="${whom}への返信"
91 fi
92 else
93 [ x"$2" = x"$blogowner" ] && return # If author=blogowner, unnecessary
94 fi
95 test -z "$emails" && return
96 err notify: user=$user Admins=`getgroupadmins $blogowner` Mode=$mode Emails="[$emails]"
97 SMAIL_TO="`echo "$blogowner" | nkf -jM | tr -d '\n'` readers <$admin>" \
98 smail "$emails" "${action}通知 $urlbase"<<EOF
99 [$blogtitle]板に${action}がありました。
100 ※このメイルに返信しても通知者には伝わりません(管理者宛になる)。
101 場所: $blogurl (返信先)
102 所有: $blogowner
103 題目: $blogtitle
104 筆者: $authgecos
105 内容:
106 `echo "$3"|sed 's/^/> /'`
107 EOF
108 )
110 blog_showentry() {
111 # $1=table $2=rowid
112 # if [ -n "$2" ]; then
113 # if [ -n "$imgcached" ]; then
114 # bstmpdir=$tmpdir/$imgcached/$thumbxy
115 # else
116 # bstmpdir=$tmpd
117 # # tmpd=`mktempd`
118 # # tmpfiles=$tmpfiles" $tmpd"
119 # fi
120 # fi
121 td=`getcachedir "article/$2"`
122 [ -d "$td" ] || mkdir -p $td
123 tbl=${1%%[!A-Z0-9a-z_]*} rowid=${2%%[!A-Z0-9a-z_]*}
124 err blow_showentry: rowid=$rowid, '$2'=$2 user=$user
125 ts=${tbl}_s tm=${tbl}_m
126 at=article as=article_s am=article_m
127 serial=$(($(date +%s)-1420038000))s$$
128 cannotread='<div class="relative"><img class="overlap" src="img/key.png" alt="(読み取り不可)"></div>'
129 blog_writable $rowid $user
130 rc=$?
131 if [ $rc = 0 ]; then
132 iswritable=true
133 ismem=true
134 else
135 iswritable=false
136 if [ $((rc & $BLOG_NOTMEM)) -gt 0 ]; then
137 ismem=false
138 else
139 ismem=true
140 fi
141 fi
142 # This function grasps blog entry definiton directly.
143 # blog: id
144 # blog_s: title,ctime,heading
145 # blog_m: *article
147 blogowner=`getvalbyid blog owner "$2"`
148 isgroup "$blogowner" && isgroup=true || isgroup=false
149 isgrpadmin=false # Reversed later (*1)
151 # 2015-10-05 check readable
152 if ! $iswritable; then
153 # err blogowner=$blogowner
154 if $isgroup; then
155 regmode=`getgroupattr $blogowner regmode`
156 # err regmode=$regmode
157 if [ x"$regmode" = x"moderated" ]; then
158 # if ! ismember $user $blogowner; then
159 if ! $ismem; then
160 echo "加入してからどうぞ" | html p
161 return
162 fi
163 fi
164 fi
165 else # if writable
166 isgrpowner "$user" "$blogowner" && isgrpadmin=true # (*1)
167 fi
168 blog_notify=`getvalbyid blog notify "$rowid"`
169 blog_team=`blog_getteam "$rowid"`
170 blog_mode=`getvalbyid blog mode "$rowid"`
171 case "$blog_notify" in # "all", "admin" or "no" (or NULL)
172 admin) notifyto=adm ;;
173 *) notifyto="" ;;
174 esac
175 case $blog_mode in
176 *quiz*|*close*|*euquete*) f_exclusive=1 ;;
177 *) f_exclusive='' ;;
178 esac
180 # err "SELECT id from $tbl where rowid=$rowid"
181 id=`query "select id from $tbl where rowid=$rowid;"`
182 #err id=$id
183 #err "select val from $ts where key='title' and id='$id';"
185 #(1)Display root article
186 cat<<EOF
187 <form class="replyblog" action="$myname?replyblog+${rowid}#bottom" method="POST" enctype="multipart/form-data">
188 <table class="bloghead">
189 EOF
191 href="<a href=\"?editheading+$rowid\" accesskey=\"e\" title=\"E\"> 編集 </a>"
192 if $ismem; then
193 case $blog_mode in
194 *report*|*quiz*|*euquete*)
195 href2="<a href=\"?lshandout+$rowid\" accesskey=\"l\" title=\"L\"> 提出状況 </a>"
196 ;;
197 esac
198 if $isgrpadmin; then
199 href3="(<a href=\"?gethandout+$rowid\" accesskey=\"f\" title=\"F\">ファイル取得</a>)"
200 fi
201 fi
202 href4='<a href="#bottom" accesskey="b" title="B"> 末尾へ</a>'
203 $isgrpadmin &&
204 href5="<a href=\"?blogseen+$rowid\" accesskey=\"s\" title=\"S\"> 読刻</a>"
205 quizmodefile=$td/quiz; rm -f "$quizmodefile" # XXX: Global state
207 query<<-EOF |
208 SELECT coalesce((SELECT "yes" FROM blog
209 -- GrpAdmin CAN EDIT heading since 2019-08-15
210 WHERE '$isgrpadmin' = 'true'
211 OR (rowid=$rowid AND author='$user')),
212 ''),
213 max(CASE key WHEN 'ctime' THEN val END) ctime,
214 max(CASE key WHEN 'heading' THEN hex(val) END) heading,
215 CASE (SELECT val FROM $ts WHERE key="mode" AND id="$id")
216 WHEN 'report-closed' THEN 'レポート提出用(closed)'
217 WHEN 'report-open' THEN 'レポート提出用(open)'
218 WHEN 'quiz' THEN 'クイズ'
219 WHEN 'enquete' THEN '集計'
220 ELSE ''
221 END
222 FROM $ts WHERE id='$id' GROUP BY id;
223 EOF
224 { IFS='|' read edit ctime hexhead blogtype
225 cat<<-EOF
226 <tr><td>${edit:+$href }$ctime $blogtype $href2$href3 $href4 $href5</td></tr>
227 <tr class="preface${frozen_class:+ }$frozen_class">
228 <td>`echo "$hexhead"|unhexize|hreflink|minitbl`</td></tr>
229 </table>
230 EOF
231 case "$blogtype" in
232 "クイズ"|"集計")
233 echo "${blogtype}モードは本人と管理者の書き込みのみが表示されます。"
234 ;;
235 esac | html p 'class="warn"'
236 echo '<table class="blog_replies"> <!-- blog:blog_showentry() main table -->'
237 if [ x"$blogtype" = x"クイズ" -o x"$blogtype" = x"集計" ]; then
238 if $isgroup; then
239 if ! isgrpowner "$user" "$blogowner"; then
240 qgrp=`sqlquote "$blogowner"`
241 cat<<-EOF > $quizmodefile
242 AND (author IN (SELECT user FROM grp_adm WHERE gname=$qgrp)
243 OR
244 author='$user')
245 EOF
246 fi
247 else # if user's blog
248 if [ x"$user" != x"$blogowner" ]; then
249 cat<<-EOF > $quizmodefile
250 AND author IN ('$blogowner', '$user')
251 EOF
252 fi
253 fi
254 fi
255 }
256 lkhome="<a href=\"$myname?home" lke='">'
257 lkedit="<a href=\"$myname?editart"
258 hlink="$myname?home" elink="$myname?editart"
259 catlink="$myname?showattc+article_m"
260 deficon="img/file-icon.png"
261 # 2016-08-15 Newer flag introduced
262 atime=`query "SELECT time FROM acclog
263 WHERE tbl='blog' AND tblrowid=$rowid AND user='$user';"`
264 iconcleaner=$tmpd/iconcleaner.$$
265 [ -s $quizmodefile ] && cond_qz=`cat $quizmodefile`
266 # *** DO NOT USE query(), use "sq $db" instead here ***
267 # because the next block in pipe line uses query() repeatedly.
268 sq $db<<EOF |
269 WITH a_s AS (
270 SELECT id,
271 max(CASE key WHEN 'ctime' THEN val END) TIME,
272 max(CASE key WHEN 'text' THEN val END) TEXT
273 FROM article_s
274 GROUP by id
275 )
276 SELECT a.id,
277 CASE author
278 WHEN '$user' THEN a.rowid||'+'||$rowid
279 ELSE ''
280 END edit,
281 CASE -- 「通知送信」ボタンの有無
282 WHEN '$notifyto' = '' THEN '' -- 不要モードならなし
283 WHEN '$user' = author THEN '' -- 筆者自身ならなし
284 ELSE "yes"
285 END notify,
286 (SELECT rowid FROM user WHERE name=author) user_rid,
287 author,
288 coalesce((SELECT val FROM user_s
289 WHERE name=author AND key='gecos'),
290 author) uname,
291 (SELECT val FROM user_s WHERE name=author AND key='$iconcachekey')
292 icon,
293 a.rowid,
294 s.TIME,
295 CASE WHEN s.TIME < '2019-05'
296 THEN printf('平成%d年%d月%d日%s',
297 substr(s.TIME, 1, 4)-1988,
298 substr(s.TIME, 6, 2),
299 substr(s.TIME, 9, 2),
300 substr(s.TIME, 12)
301 )
302 WHEN s.TIME < '2020'
303 THEN printf('令和元年%d月%d日%s',
304 substr(s.TIME, 6, 2),
305 substr(s.TIME, 9, 2),
306 substr(s.TIME, 12))
307 WHEN s.TIME < '2050'
308 THEN printf('令和%d年%d月%d日%s',
309 substr(s.TIME, 1, 4)-2018,
310 substr(s.TIME, 6, 2),
311 substr(s.TIME, 9, 2),
312 substr(s.TIME, 12))
313 ELSE s.TIME
314 END reki,
315 CASE WHEN s.TIME > '$atime' THEN 'new' ELSE '' END newer,
316 hex(s.TEXT),
317 CASE -- File Accessibility to attached file
318 WHEN '$f_exclusive' = '' THEN ''
319 WHEN '$isgrpadmin' = 'true' THEN ''
320 WHEN '$user' = author THEN ''
321 ELSE 'Unreadable'
322 END cannotread,
323 (SELECT group_concat(rowid||':'||length(bin)||':'||hex(val), ' ')
324 FROM article_m
325 WHERE id=a.id AND key='image') imxgids
326 FROM (select rowid,id,author from article
327 where blogid in
328 (select id from blog where rowid=$rowid)
329 $cond_qz) a
330 LEFT JOIN
331 a_s s
332 ON a.id=s.id;
333 EOF
334 while IFS='|' read id edit notify uid author uname icon aid \
335 tm reki new hte fa imgids
336 do
337 cachefile="$td/$id.row.html"
338 stampfile="$td/$id.row.stamp"
339 editlink="${edit:+<a href="$elink+$edit">編集</a> }"
340 nt="<label style=\"font-size: 70%;\"><input type=\"checkbox\"\
341 name=\"notifyto\" value=\"$uid\">返信通知送信</label>"
342 # fa is file accessibility flag # err "----r=$aid fa=[$fa]----"
344 # First, check the availability of user-icon.
345 # If not existent, clear and reset row cache by rm $stampfile
346 if [ ! -s "$icon" ]; then
347 rm -f "$stampfile"; unset stampfile
348 fi
349 if test -s "$stampfile" &&
350 test -s "$cachefile" &&
351 { ts=`cat "$stampfile"`; test -n "$ts"; } &&
352 test "$ts" '>' "$tm" && # Cache timestamp is newer
353 test "$stampfile" -nt "$icon"; then # UserIcon is older
354 : Nothing to do
355 else
356 { ######## New ROW creation begins here ######## >$cachefile
357 tdcls="__NEWCLS__repatt"
358 if [ -s "$icon" ]; then
359 icfn=`echo "$icon"|htmlescape`
360 picon="<p class=\"proficon\"><a href=\"$hlink+$uid\" title=\"${author%@*}\"><img src=\"$icfn\"></a></p>"
361 else
362 echo "DELETE FROM user_s WHERE key='$iconcachekey' AND
363 val=`sqlquotestr \"$icon\"`;" >> $iconcleaner
364 picon=""
365 fi
367 cat<<EOF
368 <tr id="$id">
369 <td class="$tdcls">${picon}__EDIT__<a href="#$aid">#$aid</a>
370 <a href="$hlink+$uid" title="${author%@*}">$uname</a>
371 <span title="$tm">${reki:-$tm}</span>
372 <__NOTIFY__></td>
373 EOF
374 echo -n "<td id=\"$aid\" class=\"repl\">"
375 echo "$hte"|unhexize|htmlescape|hreflink|minitbl
376 usecache='' tsfile=$td/$id.stamp
377 for i in $imgids; do
378 mrid=${i%%:*}; i=${i#*:}; sz=`size_h ${i%%:*}`
379 fn=`echo "${i#*:}"|unhexize`
380 fnb=$fn"(${sz})"
381 case "$fn" in
382 *.[Pp][Nn][Gg]|*.[Jj][Pp][Gg]|*.[Jj][Pp][Ee][Gg]|*.[GgTt][Ii][Ff])
383 # fmt=${fn##*.} # convert - jpg:- is slow...why
384 case "$fn" in
385 *.[Pp][Nn][Gg]) fmt=png ;;
386 *.[Gg][Ii][Ff]) fmt=gif ;;
387 *) fmt=jpeg ;;
388 esac
389 outfile=$td/$mrid-${fn%.*}.$fmt
390 #err fn=$fn outfile=$outfile
391 #err "usecache=$usecache `ls -l $outfile`"
392 #err tm=$tm
393 #err tsfile=$tsfile=`cat $tsfile`
394 if [ -s "$outfile" ] && # $outfile should be > 0
395 { [ "$usecache" ] || # And usecache flag is true, or...
396 { [ -s "$tsfile" ] && [ x"`cat $tsfile`" = x"$tm" ]
397 };}; then
398 usecache=1 # Set usecache flag on
399 cat<<-EOF
400 <a href="$catlink+$mrid"><img src="$outfile">
401 $fnb</a>
402 EOF
403 # !!NOTE!! Create row stamp ONLY WHEN imgcache is active
404 else
405 query "SELECT hex(bin) FROM article_m WHERE rowid=$mrid;" \
406 | unhexize \
407 | convert -define ${fmt}:size=100x100 -resize 100x100'>' \
408 - ${fmt}:- \
409 | tee "$outfile" \
410 | hexize \
411 | sed -e 's/\(..\)/%\1/g' \
412 -e "s|^|<a href=\"$catlink+$mrid\"><img src=\"data:image/$fmt,|" \
413 -e "s|\$|\">$fnb</a>|"
414 unset stampfile # img data stream is not suitable to cache
415 echo $tm > $tsfile
416 fi
417 ;;
418 *)
419 echo "<__UNREADABLE__><a href=\"$catlink+$mrid\"><img src=\"$deficon\">$fnb</a>"
420 ;;
421 esac
422 done
423 echo "</td></tr>"
424 } > "$cachefile" ######## New ROW Creation Ends here ########
425 test -n "$stampfile" && date "+%F %T" > $stampfile
426 fi
427 # Printing a cached row
428 sed -e "/^<td class=/s/__NEWCLS__/$new${new:+ }/" \
429 -e "/^<td class=/s,__EDIT__,$editlink," \
430 -e "/^<__NOTIFY__>/s,,${notify:+$nt}," \
431 -e "/<__UNREADABLE__>/s,,${fa:+$cannotread}," \
432 $cachefile
433 done
435 help="=== コメントに使用できる特殊記法 ===
436 行頭に href=URL でURLへのリンク
437 行頭に iframe=URL でURL先を開く iframe
438 [[#記事番号]] でs4内の記事番号に飛ぶリンク
439 [[#検索キーワード]] でs4内の記事検索(記号はいくつか使えない)
440 [[URL]] でURLへのリンク、 [[URL|文字列]]でアンカー文字列指定
441 {{画像URL}} でインライン画像、 {{画像URL|幅}} でピクセル幅指定
442 {{{URL}}} でURL先を開く iframe、 {{{URL|高さ}}} ピクセル高さ指定
443 行頭: ## 大見出し, ### 中見出し, #### 小見出し
444 行末の2連続スペースで強制改行(<br>)
445 |*見出し列|列2|列3… と行頭から始まる縦棒区切り行を続けて表
446 ' *語群* ' で強調(両側の空白必要、** でもっと強調。*の代わりに _ でも可)
447 - [ ] と - [x] でチェックボックス"
448 touchhelp="${touchpanel:+<p class=\"help\">$help</p>}"
449 filehelp="《添付の注意》
450 $file_accept_help"
451 ntmode="通知モード=$blog_notify${blog_team:+ (team=$blog_team)}"
452 textform='<div class="fold">
453 <input type="checkbox" id="cmt" checked><label
454 accesskey="c" title="C" for="cmt">コメントする</label><div>
455 <table class="b">
456 <tr><td><textarea id="text" name="text" cols="72" rows="4" title="'"$help"'">
457 </textarea>'"$touchhelp</td></tr>
458 <tr><td>添付ファイル(${filesize_max_MB}以下):"'
459 <input type="file" name="image"'" $file_accept title=\"$filehelp\" multiple></td></tr>"'
460 </table>
461 <input type="submit" value="送信"'" class=\"$blog_notify\" title=\"$ntmode\""'>
462 <input type="reset" value="リセット"></div></div>
463 '
464 cat<<-EOF
465 </table> <!-- end of s4-blog:blog_showentry() main table -->
466 <p class="update_link"><a
467 href="?reload/$rowid" accesskey="r" title="R">再読込</a> / <a
468 href="#title" id="bottom" accesskey="t" title="T">先頭へ</a></p>
469 EOF
470 $iswritable && cat<<-EOF
471 <div class="blogcomment">
472 <input type="hidden" name="blogid" value="$id">
473 <input type="hidden" name="id" value="`genserial`">
474 <input type="hidden" name="stage" value="replyblog">
475 $textform
476 </div>
477 </form> <!-- End of s4-blog:blog_showentry() main form -->
478 EOF
479 # Clean up orphaned icon cache
480 [ -s $iconcleaner ] && query ".read '$iconcleaner'"
481 # Record access log
482 acclog blog $rowid
483 }
485 lshandout() {
486 # $1=rowid of blog
487 blog_writable $1 $user
488 rc=$? # =0: writable, $BLOG_NOTMEM bit set => not member
489 if [ $((rc & $BLOG_NOTMEM)) -gt 0 ] ; then
490 echo "メンバー以外は利用できません。" | html p; return
491 fi
492 time=`getvalbyid blog ctime $1|colrm 11`
493 owner=`getvalbyid blog owner $1`
494 title=`getvalbyid blog title $1`
495 ge=`gecos $owner`
496 fh=$tmpd/formhead
497 echo "$time [$title]@${ge:-$owner}" > $fh
498 lshandoutsub $owner "$@" \
499 |_m4 -D_TITLE_="提出状況" \
500 -D_FORMHEAD_="syscmd(cat $fh)" \
501 -D_FORM_="syscmd(cat)" -D_DUMPHEAD_= -D_DUMPTABLE_= \
502 $layout/html.m4.html $layout/form+dump-whead.m4.html
503 gn=`echo $owner|htmlescape`
504 echo "<p><a href=\"?lshandoutall+$1\">グループ $gn すべてのレポート板集計</a></p>"
505 }
506 gethandoutcsv() {
507 # contenttype; echo
508 CATCSV=1 lshandoutall "$1"
509 }
510 gethandoutcsv2() {
511 # contenttype; echo
512 SQL=$(cat<<-EOF
513 WITH this_blog_articles AS (
514 SELECT rtb.id bid, rtb.brid, a.id aid, author, title, ctime
515 FROM report_type_blogs rtb JOIN article a ON rtb.id=a.blogid
516 ), text_or_file AS (
517 SELECT bid, author, title, ctime, 'text' shu, count(val) cnt
518 FROM this_blog_articles tba, article_s s
519 ON tba.aid=s.id
520 WHERE key='text'
521 GROUP by bid, author
522 UNION
523 SELECT bid, author, title, ctime, 'file' shu, count(val) cnt
524 FROM this_blog_articles tba, article_m m
525 ON tba.aid=m.id
526 WHERE key='image'
527 GROUP by bid, author
528 ), count_list AS (
529 SELECT author,
530 substr(ctime, 1, 10)||upper(substr(shu, 1, 1)) unit,
531 cnt
532 FROM text_or_file
533 )
534 SELECT gecos "名前",
535 substr(author, 1, instr(author, '@')-1) "uname",
536 unit,
537 cnt "post"
538 FROM count_list cl JOIN gecoses g ON cl.author=g.name;
539 EOF
540 ) gethandoutcsv "$1"
541 }
542 lshandout_ulink_table() {
543 # NO Args. Read stdin as SQL
544 echo '<table class="b td3rr td3evw">'
545 hrb="<a href=\"?home+"
546 # echo "$sql" | sq -header -html $db \ # Formerly, this is called via sq()
548 printf ".mode html\n.header ON\n" | query
549 cat | query \
550 | sed -e "s,\(<TR><TD>\)\([^ ]*\) \(.*\)</TD>,\1$hrb\2\">\3</TD>," -e 's,<TD>0</TD>,<TD class="warn">0</TD>,'
551 echo '</table>'
552 printf ".mode list\n.header OFF\n" | query
553 }
554 lshandoutall() {
555 # $1=rowid of blog
556 blog_writable $1 $user
557 rc=$? # =0: writable, $BLOG_NOTMEM bit set => not member
558 if [ $((rc & $BLOG_NOTMEM)) -gt 0 ] ; then
559 echo "メンバー以外は利用できません。" | html p; return
560 fi
561 rowid=$(($1 + 0))
562 owner=`getvalbyid blog owner $1`
563 qowner=`sqlquotestr "$owner"`
565 query<<-EOF
566 CREATE TEMPORARY TABLE IF NOT EXISTS report_type_blogs AS
567 WITH blog_owner_mode AS (
568 SELECT id,
569 blog.rowid brid,
570 max(CASE key WHEN 'owner' THEN val END) owner,
571 max(CASE key WHEN 'mode' THEN val END) mode,
572 max(CASE key WHEN 'title' THEN val END) title,
573 max(CASE key WHEN 'ctime' THEN val END) ctime
574 FROM blog NATURAL JOIN blog_s
575 GROUP BY id
576 )
577 SELECT id, brid, title, ctime FROM blog_owner_mode
578 /* WHERE owner=$qowner AND mode LIKE '%report%'; */
579 WHERE owner=$qowner
580 AND
581 (mode LIKE '%report%' OR mode LIKE '%quiz%'
582 OR mode LIKE '%enquete%');
583 /* ↑これでレポート形式の blogid 一覧を得る */
584 EOF
585 if [ -z "$CATCSV" ]; then
586 _m4 -D_TITLE_="提出状況" $layout/html.m4.html
587 ge=`gecos "$owner"`
588 tbls=""
589 grptxt=`echo "${ge:-$owner}"|htmlescape`
590 echo "<h1>$grptxt 書き込み状況一覧</h1>"
591 fi
592 if [ -z "$SQL" ]; then
593 bridlist=`query "SELECT brid FROM report_type_blogs;"`
594 for brid in $bridlist; do # Skip this loop if $SQL set
595 brid=$(($brid + 0)) # Ensure to be a number
596 [ $brid = 0 ] && continue
597 time=`getvalbyid blog ctime $brid|colrm 11`
598 title=`getvalbyid blog title $brid|htmlescape`
599 state=`getvalbyid blog state $brid|htmlescape`
600 tt="handout_$brid"
601 [ "$state" = "frozen" ] && frozen=" $FROZEN_TAG" || frozen=""
602 if [ -z "$CATCSV" ]; then
603 echo "<h2>$time - <a href=\"?replyblog+$brid\">$title</a>$frozen</h2>"
604 lshandoutsub "$owner" $brid "$tt"
605 else
606 lshandoutsub "$owner" $brid "$tt" >/dev/null # Only create temp.table
607 fi
608 tbls="$tbls${tbls:+ NATURAL JOIN }$tt"
609 done
610 fi
611 sql=${SQL:-"SELECT * FROM $tbls;"}
612 if [ -z "$CATCSV" ]; then
613 echo "<hr><h2>総合</h2>"
614 echo "$sql" | lshandout_ulink_table
615 echo "<h2>総合(<a href=\"?gethandoutcsv+$rowid\">CSV</a>)</h2>"
616 printf ".mode csv\n.header ON\n" | query
617 echo '<pre class="list">'
618 echo "$sql" | query | sed 's/^"[0-9]* /"/'
619 echo "</pre>"
620 echo "<pre><a href=\"?gethandoutcsv2+$rowid\">縦持ちCSV</a></pre>"
621 else
622 contenttype "Application/CSV"
623 printf ".mode csv\n.header ON\n" | query >/dev/null
624 fn=report-count.csv
625 printf 'Content-Disposition: filename="%s"\n' "$fn"
626 outfile=$tmpd/out-$$.csv
627 echo "$sql" | query | sed 's/^"[0-9]* /"/' > $outfile
628 echo "Content-Length: " `cat $outfile | wc -c`; echo
630 cat $outfile
631 exit 0
632 fi
633 printf ".mode list\n.header OFF\n.separator |\n" | query
634 }
635 lshandoutsub() {
636 # $1=owner $2=rowid of blog &optional $3=temp_table name
637 qgname=`sqlquote "$1"`
638 if isgroup "$1"; then
639 sample="(select user from grp_mem where gname=$qgname)"
640 else
641 sample="(select distinct author as user from arts)"
642 echo "(集計は板への投稿者のみ)" | html p
643 fi
644 tmpname="${3:-handout_$2}"
645 sql="CREATE TEMPORARY TABLE IF NOT EXISTS $tmpname AS
646 with arts as (select id,author from article \
647 where blogid=(select id from blog where rowid=$2))\
648 select (select rowid from user where name=c0.user)||' '|| \
649 (select gecos from gecoses where name=c0.user) as 'メンバー',\
650 substr(c0.user, 1, instr(c0.user, '@')-1) 'uname',\
651 sum(case when c1.key is not null then 1 else 0 end)\
652 as '[$title] コメント記入',\
653 sum(case when c2.key is not null then 1 else 0 end)\
654 as '[$title] ファイルの提出'\
655 from $sample c0 \
656 left join (select id,author from arts) a\
657 on c0.user=a.author\
658 left join (select id,key from article_s where key='text') c1\
659 on a.id=c1.id left join (select id,key from article_m ) c2\
660 on c1.id=c2.id group by c0.user order by c0.user;\
661 \
662 SELECT * FROM $tmpname;"
663 err ishandoutsub: sql="$sql"
664 echo "$sql" | lshandout_ulink_table
665 }
666 gethandout() {
667 # $1=rowid of blog
668 rid=`numericalize "$1"`
669 blog_writable $rid $user
670 rc=$? # =0: writable, $BLOG_NOTMEM bit set => not member
671 if [ $((rc & $BLOG_NOTMEM)) -gt 0 ] ; then
672 contenttype; echo
673 echo "メンバー以外は利用できません。" | html p; return
674 fi
675 # Here, this blog is writable by $user
676 owner=`getvalbyid blog owner $1`
677 if [ x"$user" = x"$owner" ]; then
678 : OK
679 elif isgrpowner "$user" "$owner"; then
680 : OK
681 else
682 contenttype; echo
683 echo "板の所有者以外は利用できません。" | html p; return
684 fi
685 mode=`getvalbyid blog mode $1`
686 copy2csv=false
687 blogid=`getvalbyid blog id $1`
688 isgroup "$owner" && isgroup=true || isgroup=false
689 isgrpowner "$user" "$owner" && isgrpadmin=true || isgrpadmin=false
691 i=0
692 bd=$tmpd/archive.$$
693 mkdir $bd
694 case "$mode" in
695 *enquete*)
696 copy2csv=true
697 csvline=`getvalbyid blog heading $1 | grep "..*,." | head -1`
698 # Create CSV-base table for questionnaire
699 # If heading in blog_s has at least 1 CSV line,
700 # we take the line as column list.
701 # Otherwise we produce two column CSV as below:
702 # USER,ANSWER
703 if [ -n "$csvline" ]; then
704 :
705 else
706 query <<-EOF
707 DROP TABLE IF EXISTS tmp_q;
708 CREATE TEMPORARY TABLE tmp_q(user text PRIMARY KEY, answer);
709 EOF
710 fi
711 esac
712 query <<-EOF |
713 SELECT a.rowid, a.id artid, a.author, s.val
714 FROM article a JOIN article_s s ON a.id=s.id
715 WHERE blogid=(SELECT id FROM blog WHERE rowid=$rid);
716 EOF
717 while IFS='|' read rowid artid author text; do
718 isfilereadable $user article_s $rowid || continue
719 dir=`printf $bd/%d/%06d "$rid" "$rowid"`
720 mkdir -p $dir
721 echo "$author" > $dir/Author
722 echo "$text" > $dir/Text
723 if $copy2csv; then
724 query "REPLACE INTO tmp_q SELECT author, val
725 FROM article a NATURAL JOIN article_s s
726 WHERE blogid='$blogid' AND key='text';"
727 fi
728 i=0
729 query "SELECT m.rowid, m.val FROM article_m m \
730 WHERE id='$artid' AND m.key IN ('image', 'document', 'binary');" \
731 | while IFS='|' read mrowid filename; do
732 outfile=`printf "%s/%02d-%s" "$dir" $((++i)) "$filename"`
733 query "SELECT quote(bin) FROM article_m WHERE rowid=$mrowid;" \
734 | unhexize > $outfile
735 done
736 done
737 # query "select m.rowid,a.id,author,m.val from article a join article_m m\
738 # on a.id=m.id where blogid=(select id from blog where rowid=$rid)\
739 # and m.key in ('image', 'document', 'binary');" \
740 # | while IFS='|' read rowid artid author filename; do
741 # err isfilereadable $user article_m $rowid
742 # isfilereadable $user article_m $rowid || continue
743 # err ok
744 # i=$((i+1))
745 # dir=`printf $bd/%03d $i`
746 # mkdir $dir
747 # echo "$author" > $dir/author
748 # query "select val from article_s where id=$artid;" > $dir/text
749 # query "select quote(bin) from article_m where rowid=$rowid;" \
750 # | unhexize > $dir/$filename
751 # done
752 if [ ! -d $bd/$rid ]; then
753 contenttype; echo
754 echo "取得できるファイルがありませんでした。" | html p
755 return
756 fi
758 if $copy2csv; then
759 query <<-EOF > $bd/$rid/all-text-$rid.csv
760 .mode csv
761 .head 1
762 SELECT * FROM tmp_q;
763 .mode list
764 .head 0
765 EOF
766 fi
767 err "BDLIST: `ls -l $bd`"
768 arcname=archive-$rid.tar.gz
769 (cd $bd
770 # query() CANNOT BE used in this subshell
771 tar zcf .archive.tar.gz $rid && mv .archive.tar.gz "$arcname"
772 err Creating tar archive "`ls -l "$arcname"`"
773 )
774 arcfile=$bd/$arcname
775 echo "Content-type: application/x-gzip"
776 echo "Content-Length: `cat $arcfile|wc -c`"
777 echo "Content-Disposition: filename=\"$arcname\""
778 echo
779 cat $arcfile
780 }
781 blogseen() { # $1 = blogid
782 blogid=${1%%[!0-9]*}
783 if [ -z "$blogid" ]; then
784 echo "Invalid blog id" | html p; exit
785 fi
786 blog_writable "$blogid" "$user"
787 rc=$? # =0: writable, $BLOG_NOTMEM bit set => not member
788 if [ $((rc & $BLOG_NOTMEM)) -gt 0 ] ; then
789 echo "メンバー以外は利用できません。" | html p; return
790 fi
791 owner=`getvalbyid blog owner $rowid`
792 qowner=`sqlquotestr "$owner"`
793 grprowid=`query "SELECT rowid FROM grp WHERE gname=$qowner;"`
794 ge=`gecos "$owner" | htmlescape`
795 title=`getvalbyid blog title $rowid | htmlescape`
796 h1="アクセス時刻"
797 link2board="<a href=\"?replyblog+$rowid\">$title</a>"
798 link2group="<a href=\"?grp+$grprowid\">$ge</a>"
799 _m4 -D_TITLE_="$h1" $layout/html.m4.html
800 echo "$h1" | html h1
801 echo "[$link2board]@$link2group" | html h2
802 warn=' class="warn"'
803 cat <<-EOF
804 <table class="b">
805 <tr><th>メンバー</th><th>uname</th><th>最終閲覧時刻</th></tr>
806 EOF
807 query <<-EOF |
808 WITH grpmem as (
809 SELECT user, (SELECT gecos FROM gecoses WHERE name=user) gecos
810 FROM grp_mem
811 WHERE gname=(SELECT val FROM blog_s
812 WHERE id=(select id from blog where rowid=$blogid)
813 AND key='owner')
814 ), acctime AS (
815 SELECT user, max(time) atime
816 FROM tblaccesses
817 WHERE tbl='blog' AND tblrowid=$blogid
818 GROUP BY user
819 )
820 SELECT g.user,
821 (SELECT rowid FROM user u WHERE u.name=g.user),
822 hex(gecos),
823 atime
824 FROM grpmem g LEFT JOIN acctime t
825 ON g.user = t.user
826 GROUP BY g.user
827 ORDER BY atime DESC;
828 EOF
829 while IFS='|' read u uid hexge time; do
830 td=${time:+"<td>"} # If the variable time is set, td=<td>
831 td=${td:-"<td$warn>"} # else td=<td class="warn">
832 cat <<-EOF
833 <tr>
834 <td><a href="?home+$uid">`echo "$hexge"|unhexize|htmlescape`</a></td>
835 <td>`echo ${u%%@*}|htmlescape`</td>
836 $td${time:----}</td></tr>
837 EOF
838 done
839 cat <<-EOF
840 </table>
841 <p><a href="?replyblog+$rowid">[$title]に戻る</a></p>
842 </html>
843 EOF
844 }
845 lsmyfile() { # $1(optional)=SortBy
846 case "$1" in
847 ""|CTIME-DESC)
848 by="CTIME" ord="DESC" ;;
849 CTIME*) by="CTIME" ;;
850 FILE*) by="FILE" ;;
851 OWNER*) by="OWNER" ;;
852 TITLE*) by="TITLE" ;;
853 esac
854 case "$1" in
855 *DESC) ord="DESC" ;;
856 esac
857 case "$ord" in
858 DESC) lkod="" jord="降順" ;;
859 *) lkod="-DESC" jord="昇順" ;;
860 esac
861 sql="select m.val||'/'||m.rowid FILE,
862 coalesce(
863 case when (select name from user where name=bs.owner)
864 is not null
865 then (select val from user_s where name=bs.owner
866 and key='gecos')
867 when (select gname from grp where gname=bs.owner)
868 is not null
869 then (select val from grp_s where gname=bs.owner
870 and key='gecos')
871 else
872 null
873 end,
874 bs.owner
875 ) OWNER,
876 a_s.val CTIME,
877 ',t,'||bs.title||':'||b.rowid||'#'||a.id TITLE
878 from (select rowid,id,val from article_m where id
879 in (select id from article where author='$user')
880 and type like 'file:%')
881 m left join article a on m.id=a.id
882 left join article_s a_s on a.id=a_s.id and a_s.key='ctime'
883 left join (select id,
884 max(case key when 'owner' then val end) as owner,
885 max(case key when 'title' then val end) as title
886 from blog_s group by id)
887 bs on a.blogid=bs.id
888 left join blog b on bs.id=b.id
889 where m.val is not null order by $by $ord;"
890 err lshandoutbyauthor: sql=`echo "$sql"`
891 title="個人提出ファイル"
892 _m4 -D_TITLE_=$title $layout/html.m4.html
893 hra="<a href=\"?lsmyfile+"
894 hrb="<a href=\"?showattc+article_m+"
895 hrc="<a href=\"?replyblog+"
896 (echo '<table class="b">'
897 echo "$sql"|sq -html -header $db ) \
898 | sed -e "s|\(<TR><TD>\)\([^/]*\)/\([0-9]*\)|\1$hrb\3\">\2</a>|" \
899 -e "s|,t,\(.*\):\([^<]*\)\(</TD>\)|$hrc\2\">\1</a>\3|" \
900 -e "s|\(<TH>\)\([A-Z]*\)\(</TH>\)|\1$hra\2$lkod\">\2</a>|" \
901 | _m4 -D_TITLE_=$title -D_FORM_="<p>($by$jord)</p>" \
902 -D_DUMPTABLE_="syscmd(cat)" $layout/form+dump.m4.html
903 echo '</table>'
904 }
905 searchart() {
906 kwd=`getpar kwd|nkf -wZ1` # Convert Zenkaku-SPC to ASCII-SPC
907 bloglist=`getpar bloglist|sed 's/[^0-9,]//g'`
908 kwdgrp=""
909 authcond=""
910 if [ -z "$kwd" ]; then
911 echo "検索語を指定してください" | html p; return
912 fi
913 if logstart "$searchlog"; then
914 { echo "kwd=$kwd"
915 test -n "$bloglist" && echo "bloglist=$bloglist"
916 } >> $searchlog
917 logend "$searchlog"
918 fi
919 if expr x"$kwd" : 'x#[1-9][0-9]*$' >/dev/null 1>&2; then
920 # Like '#1234', assume as artID
921 rowid=$((${kwd#\#} + 0)) # Force to be a number
922 kc="ar.rowid = $rowid"
923 else
924 for k in `echo "$kwd" | sed "s/'/''/g"`; do # With wrap quotes
925 ctime=""
926 if expr x"$k" : 'x@[><= ]*[1-9][][0-9]*-[][0-9:-]*$' >/dev/null >&2; then
927 # '@<2016-10-10' -> ctime < '2016-10-10'
928 # '@>=2016-10-10' -> ctime >= '2016-10-10'
929 # '@2016-10-10' -> ctime GLOB '@2016-10-10'
930 k=${k#@}
931 case "$k" in
932 [\<\>]*) op=${k%%[!<>=]*}; ctime=${k##*[><= ]} ;;
933 *) op='GLOB'; ctime="${k##*[><= ]}*" ;;
934 esac
935 kc=$kc${kc:+" AND "}"ctime $op '${ctime}'"
936 # Not sure GROUP BY a.blogid is comfortable for searchers...?
937 ##### kwdgrp=" GROUP BY a.blogid" ## Add this to lessen results
938 elif [ x"$k" = x"@today" -o x"$k" = x"@今日" ]; then
939 ctime=`date +%F`
940 elif n=`expr x"$k" : 'x@\([0-9]*\)days*'` >/dev/null >&2; then
941 ctime=`query "SELECT datetime('now', 'localtime', '-$n days');"`
942 elif [ x"$k" = x"@week" ]; then
943 ctime=`query "SELECT datetime('now', 'localtime', '-7 days');"`
944 elif n=`expr x"$k" : 'x@\([0-9]*\)weeks*'` >/dev/null >&2; then
945 n=$((n * 7))
946 ctime=`query "SELECT datetime('now', 'localtime', '-$n days');"`
947 elif [ x"$k" = x"@month" ]; then
948 ctime=`query "SELECT datetime('now', 'localtime', '-1 month');"`
949 elif n=`expr x"$k" : 'x@\([0-9]*\)months*'` >/dev/null >&2; then
950 ctime=`query "SELECT datetime('now', 'localtime', '-$n month');"`
951 elif [ x"$k" = x"@year" ]; then
952 ctime=`query "SELECT datetime('now', 'localtime', '-1 year');"`
953 elif n=`expr x"$k" : 'x@\([0-9]*\)years*'` >/dev/null >&2; then
954 ctime=`query "SELECT datetime('now', 'localtime', '-$n year');"`
955 fi
956 if [ -n "$ctime" ]; then
957 kc=$kc${kc:+" AND "}"ctime > '${ctime}'"
958 else
959 e=""
960 case "$k" in
961 *${likeesc}*) e="" ;; # Giving up char-escaping
962 *%*|*_*) k=`echo "$k"|sed "s/\([%_]\)/${likeesc}\1/g"`
963 e=" ESCAPE '$likeesc'" ;;
964 esac
965 kc=$kc${kc:+" AND "}"content LIKE '%$k%'$e"
966 fi
967 done
968 fi
969 kwd=`echo "$kwd"|htmlescape`
970 owner=`getpar owner`
971 owner=${owner:-$1}
972 msg=""
973 if [ -n "$owner" ]; then
974 cond="where key='owner' and val='$owner'"
975 if isuser $owner; then
976 msg="(`linkhome $owner` さんの記録から)"
977 else
978 linkhome $owner 1>&3
979 msg="(`linkhome $owner` グループから)"
980 fi
981 elif { author=`getpar author`; test -n "$author"; }; then
982 atptn=`sqlquotestr $author`
983 #kc="$kc${kc:+ AND }author=$atptn"
984 authcond="WHERE author=$atptn"
985 if isuser $author; then
986 msg="(`linkhome $author` さんの書き込みから)"
987 fi
988 fi
989 if [ -n "$bloglist" ]; then
990 blogcond="AND bl.rid IN ($bloglist)"
991 fi
993 sf=`search_form "$search_form_args" "$kwd" | sed '1d;$d'` # rm <div></div>
994 echo "$sf" | sed -e "/POST SENTENCE/s/.*/__PS__/" -e "/EOF/q" \
995 | _m4 -D__PS__="による検索結果$msg"
996 echo "(上記入力窓で再検索すると下記の掲示板のみに絞って再検索します)" \
997 | html p 'class="small"'
998 # article_s: id=article-id, key='text', val='TEXT'
999 # article: id=article-id, blogid=blogkd
1000 # blog: id=blog-id, author=LeaderAuthor
1001 # blog_s: id=blog-id, key='title', val='BLOG-TITLE'
1002 # WANT: blog-ROWid,article-id,val(TEXT)
1003 sql2="`sql4readableblogs` -- Extract user-readable blogs
1004 -- 0.3sec
1005 WITH artsm AS (
1006 SELECT a.id,ctime, text || ' ' || coalesce(files, '') content
1007 FROM article a
1008 LEFT JOIN
1009 (SELECT ars.id, ctime, text, coalesce(files, '') files
1010 FROM (SELECT id,
1011 max(CASE key WHEN 'ctime' THEN val END) ctime,
1012 max(CASE key WHEN 'text' THEN val END) text
1013 FROM article_s
1014 GROUP BY id) ars
1015 LEFT JOIN
1016 (SELECT id, group_concat(val) files
1017 FROM article_m
1018 WHERE type LIKE 'file:%'
1019 GROUP BY id) arm
1020 ON ars.id=arm.id
1021 ) ar
1022 ON a.id=ar.id
1023 ), ar AS (
1024 SELECT a.rowid, a.blogid, a.id, a.author, ctime, content
1025 FROM article a JOIN artsm ON a.id=artsm.id
1026 $authcond
1027 ), bl AS (
1028 SELECT blg.rid, blg.*, blog_s.val TITLE
1029 FROM readableblogs blg JOIN blog_s ON blg.id=blog_s.id AND blog_s.key='title'
1031 SELECT bl.rid||'#'||ar.id '',
1032 bl.title TITLE,
1033 (SELECT gecos FROM gecoses WHERE name=ar.author) AUTHOR,
1034 substr(ctime, 0, 11) DATE,
1035 substr(content, 0, 78) TEXT
1036 FROM ar JOIN bl
1037 ON ar.blogid=bl.id
1038 WHERE $kc AND bl.id IN (SELECT id FROM blog_s $cond) $blogcond
1039 ORDER by DATE DESC, TITLE, ctime;"
1040 sedopt="s,<TR><TD>\([^<]*\)</TD>,<TR><TD><a\
1041 href=\"?replyblog+\1\">VIEW</a></TD>,"
1042 # echo "$sql2" > tmp/sql.out
1043 result=$tmpd/result.$$
1044 cat<<EOF
1045 <table class="b searchart">
1046 `sq -header -html $db "$sql2"|sed "$sedopt"|tee $result`
1047 </table>
1048 EOF
1049 if [ -s "$result" ]; then
1050 found=$((`grep "^<TR><TD>" $result | wc -l` + 0)) # Cast to INT
1051 one=${found%1}
1052 echo "$found match${one:+es} found"
1053 # <a href="?replyblog+39#12345">VIEW</a>
1054 # -> 39,49,55, -> 39,49,55
1055 # -> <input type="hidden" name="bloglist" value="39,49,55">
1056 sed -n "/.*href=.*replyblog\+\([0-9][0-9]*\).*/s//\1/p" "$result" \
1057 | sort | uniq | tr '\n' ',' \
1058 | sed -e 's/,$//' \
1059 -e 's/^/<input type="hidden" name="bloglist" value="/' \
1060 -e 's/$/">/'
1061 else
1062 echo orz...
1063 fi
1064 echo "$sf" | sed "1,/-- EOF/d" # Close <form>
1066 listblog() (
1067 # $1={user,group}
1068 qow=`sqlquote $1`
1069 cond="where a.id in (select id from blog_s where key='owner' and val=$qow) order by ctime desc"
1070 cgi_form searchart<<EOF
1071 <label>`cgi_text kwd`という語を含む記事をこの一覧から検索</label>
1072 `cgi_hidden owner $user`
1073 EOF
1074 DT_CHLD=article:blogid DT_QOWNER=$qow \
1075 dumptable html blog 'ctime title heading' "$cond"
1078 blog_addentry() {
1079 # $1=GRPname(if it is a group)
1080 grprowid=`numericalize $1`
1081 rowid=`getpar rowid`
1082 ## err blog_addentry0: rowid=$rowid
1083 if [ -n "$grprowid" ]; then
1084 owner=`getgroupbyid $grprowid`
1085 else
1086 owner=`getpar owner`
1087 fi
1088 err blog-add: \$1=$grprowid rowid=$rowid owner=$owner
1089 if isgroup "$owner"; then
1090 groupmode=1 listing=$owner guide="[${owner}]" GF_OWNER=$owner
1091 else
1092 usermode=1 listing=$user guide="[個人]"
1093 fi
1095 if [ -n "`getpar title`" ]; then
1096 if [ "$usermode" ]; then
1097 err usermode: user=$user owner=$owner
1098 if [ x"$user" != x"$owner" ]; then
1099 echo "他人の日記は書けません" | html p
1100 return 2
1101 fi
1102 elif [ "$groupmode" ]; then # if write to group log
1103 grp=$owner #\`getpar grp\`
1104 err ismember: $user $grp
1105 if ! ismember "$user" "$grp"; then
1106 echo "(話題作成はこのグループに加入してから)" | html p
1107 return 3
1108 fi
1109 fi
1110 par2table $formdir/blog.def
1111 serial=`getpar serial`
1112 ## err SERIAL: $serial ROWID=$rowid listing=$listing
1113 id=""
1114 if [ -n "$rowid" ]; then
1115 # Here, id becomes NULL when removal of entries at par2table
1116 id=`query "select rowid from blog where rowid=$rowid;"`
1117 elif [ -n "$serial" ]; then
1118 # If new blog leader created, traverse to its head.
1119 id=`query "select rowid from blog where id='$serial';"`
1120 ## err new-Leader: "select rowid from blog where id='$serial';" id=$id
1121 fi
1122 if [ -n "$id" ]; then
1123 ## If new aritcle is entered, JUMP to blog_reply
1124 blog_reply $id
1125 return
1126 fi
1127 fi
1128 echo "${guide}新規話題作成" > $tmpd/title.$$
1129 listblog $listing > $tmpd/listblog.$$
1130 genform $formdir/blog.def \
1131 | _m4 -D_TITLE_="spaste(\`$tmpd/title.$$')" \
1132 -D_FORMHEAD_="序文は簡単に詳しくはコメントに" \
1133 -D_DUMPHEAD_="これまでの蓄積" \
1134 -D_FORM_="syscmd(\`cat')" \
1135 -D_DUMPTABLE_="spaste(\`$tmpd/listblog.$$')" \
1136 $layout/html.m4.html \
1137 $layout/form+dump-whead.m4.html
1140 blog_reply() { # Posting to blog article
1141 rowid=`numericalize $1` # Ensure (already purified in s4.cgi)
1143 if [ -z "$rowid" ]; then
1144 echo "表示する日記番号が未指定です。" | html p
1145 return
1146 fi
1147 title=`getvalbyid blog title $rowid`
1148 owner=`getvalbyid blog owner $rowid`
1149 qowner=`sqlquotestr "$owner"`
1150 if [ -z "$title" ]; then
1151 echo "日記番号指定が無効です。" | html p
1152 return
1153 fi
1154 blog_writable $rowid $user; rc=$?
1155 if [ $rc = 0 ]; then
1156 iswritable=true
1157 else
1158 iswritable=false
1159 if [ $((rc & $BLOG_FROZEN)) -gt 0 ]; then
1160 isfrozen=true
1161 frozen_class='frozen"'
1162 frozen_flag=$FROZEN_TAG
1163 fi
1164 fi
1165 if isuser "$owner"; then
1166 subtitle="`gecos $owner` さんの話題"
1167 else
1168 grprowid=`query "select rowid from grp where gname=$qowner;"`
1169 subtitle="グループ
1170 <a href=\"?grp+$grprowid\" accesskey=\"h\" title=\"H\">$owner</a> での話題
1171 `query \"SELECT printf('(チーム:%s)', val)\
1172 FROM blog_s
1173 WHERE id=(SELECT id FROM blog WHERE rowid=$rowid)
1174 AND key='team';
1175 \"|htmlescape`"
1176 memclass=`grp_getbodyclass "$owner"`
1177 fi
1179 text=`getpar text`
1180 if [ -n "$text" ]; then
1181 if $iswritable; then
1182 par2table $formdir/article.def
1183 st=$?
1184 case $st in
1185 0|4)
1186 [ "$st" = "4" ] && act="書込削除"
1187 blog_notify_reply $rowid $user "$text" $act
1188 if [ -n "$grprowid" ]; then
1189 qgrp=$(sqlquote "$owner")
1190 dbsetbyid grp $owner wtime "`date '+%F %T'`"
1191 else
1192 dbsetbyid user "$user" wtime "`date '+%F %T'`"
1193 fi
1194 ;;
1195 esac
1196 else
1197 if $isfrozen; then
1198 title="$title(凍結板につき書き込み不可)"
1199 else
1200 title="$title(加入してないので書き込み不可)"
1201 fi
1202 fi
1203 fi
1204 def=$formdir/article.def
1205 echo "$title" > $tmpd/title.$$
1206 echo "$subtitle$frozen_flag" > $tmpd/subtitle.$$
1207 ${BLOG_SHOW:-blog_showentry} blog $rowid \
1208 | _m4 -D_TITLE_="spaste(\`$tmpd/title.$$')" \
1209 -D_BODYCLASS_=general"${memclass:+ $memclass}" \
1210 -D_FORMHEAD_="spaste(\`$tmpd/subtitle.$$')" \
1211 -D_FORM_='' \
1212 -D_DUMPTABLE_="syscmd(cat)" -D_DUMPHEAD_="" \
1213 $layout/html.m4.html $layout/form+dump-whead.m4.html
1216 blog_reply_article() { # Direct link to article in some blog
1217 arid=${1:-0} # Already sanitized to digits
1218 brid=`query "SELECT rowid FROM blog WHERE \
1219 id=(SELECT blogid FROM article WHERE rowid=$arid);"`
1220 if [ -n "$brid" ]; then
1221 newurl="?replyblog+$brid#$arid"
1222 echo "Refresh: 0; $newurl"; echo
1223 exit 0
1224 else
1225 contenttype; echo
1226 echo "無効な記事番号です." | html p
1227 fi