s4

view s4-blog.sh @ 593:874e1f59263f

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