s4

view s4-blog.sh @ 619:7af908a22128

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