s4

view s4-blog.sh @ 570:9328392f7c55

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