Cannot modify header information の原因を突き止める

php.iniを
display_errors=on
error_reporting = E_ERROR | E_WARNING | E_PARSE
にして、Warningは表示するけれど、Noticeは表示しないように設定し、以下のようにページが切り替わる秒数を15秒に書き換えて確認しました。
$str = "<html><head><META HTTP-EQUIV=\"refresh\" content=\"15;URL=".PHP_SELF2."\">\n";
1秒で切り替わる設定のままだと何が表示されているのかわからない…。

POTI-board Warning

コメントを送信した直後の「画面を切り替えます」の時に表示されるエラーメッセージ。
Cannot modify header informationが6箇所。

POTI-board Warning

投稿直後に表示されるWarning。

POTI-board WarningPOTI-board Warning

POTI-boardのエラーを減らすために 数値以外の値編: STP^3の、数値が入るべきところに文字列が入っていた問題を解消すると…。Warningがでなくなりました。

POTI-boardのエラーを減らすために header編: STP^3を書いた時は、もしかしたら…という感じだったのですが、
Warning: Cannot modify header information
が出ていた原因は、phpのエラーメッセージがheaderより先に出力されていたから…だったようです。

Cannot modify header informationが出る原因を一生懸命調べても解決しなかったのに、きれいにエラーが消えたので思わず笑ってしまいました。

一箇所気になるところがあるといえばあるのですが…。さくらのレンタルサーバのphp7.1で確認した限りでは…POTI-board改のWarningはこれで解消されたような…気がします。

POTI-boardのエラーを減らすために 数値以外の値編

Warning: A non-numeric value encountered
警告:数値以外の値が発生しました
一体何が…。
数値以外の値がなんなのか中身をechoで表示してみる事に…。
echo $ltime; //問題の変数
echo '|'; //区切り
if(RENZOKU && $time - $ltime < RENZOKU){error(MSG020,$dest);}
if(RENZOKU2 && $time - $ltime < RENZOKU2 && $upfile_name){error(MSG021,$dest);}
出力された値とエラーメッセージ。
1528807931|1528805950|1528544331|1528530938|1528527552|1528520321|1528512258|
1528508742|1528505146|1528502788|OB1528490148|
Warning: A non-numeric value encountered in C:\xampp\hoge\potiboard.php on line 946
お絵かき機能を使って投稿するとログファイルの13桁のUNIX timeの先頭にKASIRAで設定したOBが入りOB1528490148799となる事が原因でした。

現在の時間からOB1528490148を引いても数字ではないので…。
if(strlen($ltime)>10){$ltime=substr($ltime,0,-3);}
でOB1528490148799の後ろからマイクロ秒の3桁を取り除いてもOB1528490148になりますが
if(strlen($ltime)>10){$ltime=substr($ltime,-13,-3);}
とすれば10桁のUNIX time、1528490148になりになります。
(Tips)これから100年のunix時間は10桁数字。5桁の固定長文字列でも表現できる。

21世紀ののUnix時間はほぼ10桁で表せる
10桁なら…という前提付きですが、これから先100年は大丈夫…という事で。
KASIRAを廃止すれば従来の
if(strlen($ltime)>10){$ltime=substr($ltime,0,-3);}
で、問題ないんですけどね。
futaba.phpがPOTI-boardになった時点で、
//連続投稿秒数
define('RENZOKU', '10');
//画像連続投稿秒数
define('RENZOKU2', '20');
の計算が正しくできなくなっていた可能性が高い…です。
例えば、画像連続投稿秒数を60秒に設定して、お絵かきだけを繰り返すとOBの付いた数字ではないものでは引き算ができないので、60秒経過しなくても投稿できていた筈です。
しかし、画像アップロードと、テキストの投稿の時には正常に動作していたので誰も困っていなかった…のかもしれません。

この問題は、POTI-board改 v1.42.2 lot.180614で修正されました。

お絵かき掲示板はこちら。

POTI-boardのエラーを減らすために header編

headerのWarningを検証するため、正常に動作するとgoogleが表示されるように該当箇所を書き換えてみました。
// header("Content-type: text/html; charset=".CHARSET_HTML);
header("Location: http://google.com/");
XAMPPでphpのエラー表示ありで試してみると…。
Warning: Cannot modify header information - headers already sent by (output started at C:\xampp\htdocs\hoge\potiboard.php:459) in C:\xampp\htdocs\hoge\potiboard.php on line 1123
になり、googleに推移しません。
しかし、phpのエラーを表示しない設定のサーバ上ではgoogleに推移します。
Warning: Cannot modify header information
というWarningがほかにも出ていましたが、headerの出力の前にNoticeが表示された事が原因でした。

POTI-boardのログファイルの上限を5MBに

簡単なテストしかできていないため、各自自己責任で…。
ぷち的ココロ♪

総レス数がまだ2800を超えた程度なのに、親記事のナンバーの低いスレが消えてしまっていました。
親記事ナンバー+5000レスをスレの消える寿命に設定するにはどうしたらいいのでしょうか?

バッファに1000000byte読み込む処理があったので
logファイルの上限がおそらく約1Mbyteだと思います。
その上限を超えたので2800でレスが消えたのではないでしょうか
調べてみると…。

$buf=fread($fp,1000000);
となっているところが7箇所
$buf=fread($tp,1000000);
1箇所

合計8箇所にログファイルに関するものと思われる1000000byteの指定がありました。
試しにここを

$buf=fread($fp,2000000);

つまり2倍にしてみたところ

POTI-boardのログファイルの上限

1.961kbまでログを保存する事ができるようになりました。

XAMPPでテストしたので、ログファイルのファイルサイズの確認がエクスプローラーになりましたが…。
2000000byte=1953kbなのでだいたいあってますね…。

XAMPPの次は、さくらのレンタルサーバで5MB保存できるかテスト。

$buf=fread($fp,5242880);
$buf=fread($tp,5242880);

に設定。

POTI-boardのログファイルの上限POTI-boardのログファイルの上限

テキストファイルのサイズが1MB〜3MBのものを数回投稿。
数発言で5MBを超える投稿を行ってみたところ…。

9601969byte…。
5MBを超えてしまいました。

ログファイルが4MBの時に、1発言5MBの投稿を行うと4+5=9MBとなるようです。
追加で短く一言書いてみると…。

5242824byte=4.999946594MBになりました。

$buf=fread($fp,5242880);
$buf=fread($tp,5242880);

この2つは、ログファイルを読み込む時の設定…なんでしょうね。
5MBしか読み込まなかったので9MBあったログが5MBに…。

ログファイルがどうなっているのか調べてみたところ、コメントが途中で切れて必要なログの形式もなくなっていました。
スレッドやレス単位ではなくファイルサイズの上限で切れるようです。

他のログはどうなるのかというと…。
途中で切れてしまったログ以外は問題なさそうな感じでした。

POTI-boardのログファイルの上限

ログファイルをダウンロードしてファイルサイズを確認してみたところ…。
ぴったり5MB…。

ログが5MBまで溜まった状態で書き込むと5MB読み込む処理が入る…。どの程度の負荷になるのかよくわからないのですが…。
5MBだと大きすぎるのかもしれないので…。

$buf=fread($fp,2097152);
$buf=fread($tp,2097152);

2MBなら…。どうなんでしょうね…。

お絵かき掲示板はこちら。

POTI-boardの頁リンクが増え続けるのを制御(その2)

POTI-boardの現在の仕様だと、300ページ分ログがあると、300ページ全部表示してしまうので、長く運用してログをストックしていくタイプの掲示板だと厳しい…。

だから、最新から19ページまでは古いログを表示しない、20ページになったら、21ページ以後のページがすべて表示される。20ページ分のログが存在しない時は、存在しているログの分だけ表示するようにプログラムを書き直して終わり…の筈だったのですが。

それだとログが20ページまでしか存在していないと思う人がでてくるという指摘がありました。

ログが21ページ分より多くかつ最新から20ページまで表示している時は、21ページを
[0][1][2](中略)[20][>>]
のように表示する事ができれば…。

直接テンプレートに[>>]といれて、21ページへのリンクを貼る事もできますが…。
それだと…ログファイルが少ない時と多い時とでテンプレートを書き直さなければならなくなるのでプログラムで対応したい…と思いました。

POTI-board

こんな感じになりました。
//下段ページリンクの出力をifで分岐
//0-21まで表示する事を想定
//カウントツリーが指定した数値より小さい場合は全件表示

if(220 > count($tree)){
for($i = 0; $i < count($tree) ; $i+=PAGE_DEF){
if($st==$i){
$pformat = str_replace("<PAGE>", $i/PAGE_DEF, NOW_PAGE);
}else{
if($i==0){
$pno = str_replace("<PAGE>", "0", OTHER_PAGE);
$pformat = str_replace("<PURL>", PHP_SELF2, $pno);
}else{
$pno = str_replace("<PAGE>", $i/PAGE_DEF, OTHER_PAGE);
$pformat = str_replace("<PURL>", ($i/PAGE_DEF).PHP_EXT, $pno);
}
}
$paging.=$pformat;
}
}

//下段ページリンクの出力をifで分岐
//スレッド数が指定した数値より大きな時は全件表示
//数値を-1小さく設定しないとリンクが表示されないページができるかも。

elseif($i > 219 ){
for($i = 0; $i < count($tree) ; $i+=PAGE_DEF){
if($st==$i){
$pformat = str_replace("<PAGE>", $i/PAGE_DEF, NOW_PAGE);
}else{
if($i==0){
$pno = str_replace("<PAGE>", "0", OTHER_PAGE);
$pformat = str_replace("<PURL>", PHP_SELF2, $pno);
}else{
$pno = str_replace("<PAGE>", $i/PAGE_DEF, OTHER_PAGE);
$pformat = str_replace("<PURL>", ($i/PAGE_DEF).PHP_EXT, $pno);
}
}
$paging.=$pformat;
}
}

//下段ページリンクの出力をifで分岐
//スレッド数が指定した数値より小さい時は任意の数値でページを表示

elseif($i < 220 ){
for($i = 0; $i < 220 ; $i+=PAGE_DEF){
if($st==$i){
$pformat = str_replace("<PAGE>", $i/PAGE_DEF, NOW_PAGE);
}else{
if($i==0){
$pno = str_replace("<PAGE>", "0", OTHER_PAGE);
$pformat = str_replace("<PURL>", PHP_SELF2, $pno);
}else{
if($i==210){
$pno = str_replace("<PAGE>", ">>", OTHER_PAGE);
// $pformat = str_replace("<PURL>", PHP_SELF2, $pno);
$pformat = str_replace("<PURL>", ($i/PAGE_DEF).PHP_EXT, $pno);
}else{
$pno = str_replace("<PAGE>", $i/PAGE_DEF, OTHER_PAGE);
$pformat = str_replace("<PURL>", ($i/PAGE_DEF).PHP_EXT, $pno);
}
}}
$paging.=$pformat;
}
}
//ここまで
21ページ目なら、[>>]にという記述が増えただけなんですけどね。
ページ番号20を表示させたかったので、ひとつ前の記事で書いたものより、+10スレッド数が多くなっています。
1ページ10件表示用なので、例えば5件表示で使うと [>>] が横並びの最後にならず、ひとつ手前に出てしまいます。

お絵かき掲示板はこちら。

POTI-boardの頁リンクが増え続けるのを制御

POTI-boardは、1ページ10件表示で3000スレッドあったら300ページ分のリンクができる仕様…。

しかし、そんなに多くの古いログを見たい訳ではない時のほうが多いので…。
テンプレートで最初の20件だけ表示して、あとは頁へのリンク無しでもいいか…と思いましたが、それはそれで、古いログを見る時に…。

というわけで、以下の仕様になるようにPOTI-boardを改造してみました。

0から19ページまでは、
ページ番号0から20(0から20なので210スレッド分)までしか表示しない。
20ページになったら21ページ以後も表示。
3000スレッドあったら300ページ表示。
また、スレッドが210件未満の時は、存在しないページへのリンクができないように最初の条件分岐でログのカウントツリーをチェックして全件表示。
その場合は210スレッド未満なので、20ページ以下になります。

POTI-board

0-20ページまで表示。

POTI-board

20ページ以後を表示しているので、0-21ページまで表示。
もし300ページ分ログがあれば、0-300ページまで表示。

プログラムを書き換えた箇所
// for($i = 0; $i < count($tree) ; $i+=PAGE_DEF){
// if($st==$i){
// $pformat = str_replace("<PAGE>", $i/PAGE_DEF, NOW_PAGE);
// }else{
// if($i==0){
// $pno = str_replace("<PAGE>", "0", OTHER_PAGE);
// $pformat = str_replace("<PURL>", PHP_SELF2, $pno);
// }else{
// $pno = str_replace("<PAGE>", $i/PAGE_DEF, OTHER_PAGE);
// $pformat = str_replace("<PURL>", ($i/PAGE_DEF).PHP_EXT, $pno);
// }
// }
// $paging.=$pformat;
// }

コメントアウトしてあります。
//下段ページリンクの出力をifで分岐
//0-20まで表示する事を想定
//カウントツリーが指定した数値より小さい場合は全件表示

if(210 > count($tree)){
for($i = 0; $i < count($tree) ; $i+=PAGE_DEF){
if($st==$i){
$pformat = str_replace("<PAGE>", $i/PAGE_DEF, NOW_PAGE);
}else{
if($i==0){
$pno = str_replace("<PAGE>", "0", OTHER_PAGE);
$pformat = str_replace("<PURL>", PHP_SELF2, $pno);
}else{
$pno = str_replace("<PAGE>", $i/PAGE_DEF, OTHER_PAGE);
$pformat = str_replace("<PURL>", ($i/PAGE_DEF).PHP_EXT, $pno);
}
}
$paging.=$pformat;
}
}

//スレッド数が指定した数値より大きな時は全件表示
//数値を-1小さく設定しないとリンクが表示されないページができるかも

elseif($i > 209 ){
for($i = 0; $i < count($tree) ; $i+=PAGE_DEF){
if($st==$i){
$pformat = str_replace("<PAGE>", $i/PAGE_DEF, NOW_PAGE);
}else{
if($i==0){
$pno = str_replace("<PAGE>", "0", OTHER_PAGE);
$pformat = str_replace("<PURL>", PHP_SELF2, $pno);
}else{
$pno = str_replace("<PAGE>", $i/PAGE_DEF, OTHER_PAGE);
$pformat = str_replace("<PURL>", ($i/PAGE_DEF).PHP_EXT, $pno);
}
}
$paging.=$pformat;
}
}

//スレッド数が指定した数値より小さい時は任意の数値でページを表示

elseif($i < 210 ){
for($i = 0; $i < 210 ; $i+=PAGE_DEF){
if($st==$i){
$pformat = str_replace("<PAGE>", $i/PAGE_DEF, NOW_PAGE);
}else{
if($i==0){
$pno = str_replace("<PAGE>", "0", OTHER_PAGE);
$pformat = str_replace("<PURL>", PHP_SELF2, $pno);
}else{
$pno = str_replace("<PAGE>", $i/PAGE_DEF, OTHER_PAGE);
$pformat = str_replace("<PURL>", ($i/PAGE_DEF).PHP_EXT, $pno);
}
}
$paging.=$pformat;
}
}
//ここまで

書き換えた内容。

ちゃんとプログラムが書ける人なら、スマートにまとめる事ができる筈なのですが…。
とりあえず動いているからいいか…という…。

まともにプログラムが書ける方が見たら、うわっ…というプログラムになっていますのでご注意ください。
カタログページも対応させる場合は、該当箇所を同じように分岐させる事になります。

お絵かき掲示板はこちら。

合作ができるようにPOTI-boardを改造しました

BBSNoteや、relmには、新規投稿ならパスワードがなくても続きを描く事ができる機能があります。合作の時に使う機能です。
もとの投稿を編集・削除する時はパスワードが必要なので、第三者による編集・削除を防ぐ事ができます。

POTI-boardでも似たような事ができるんだろうな…と思ったのですが…。

POTI-board 続きから描くPOTI-board 続きから描く
//コンティニュー時、削除キーを必要とする 必要:1 不要:0
define('CONTINUE_PASS', '0');
に設定すると、削除キーの入力欄が無くなり誰でも続きを描く事ができるようになりました。
しかし…。

POTI-board 続きから描くPOTI-board 続きから描く

差し換えなのにパスワードが無くても続きが描けるのはおかしい…と思ったら投稿エラーになりました。
これでエラーにならなかったら、知らないうちに投稿したイラストが別の何かになっていてもおかしくない…。

POTI-board 続きから描く

エラーになった画像が、アップロード途中の画像に残っていました。
コメントを入力すれば新規投稿になります。

という事は、削除キーがなくても続きを描く事ができる設定にすると、続きを描いて差し換える事ができなくなる仕様…という事になります。

投稿したあとでちょっとだけ直したくなった…という事があるので困ります。

差し換えと新規投稿で、異なる動作になるようにプログラムを書き変える事ができれば…。
//コンティニュー時のパスワード
// if(CONTINUE_PASS) usrchk($no,$pwd);
//パスワードが必要なのは差し換えの時だけ
if($type=='rep') usrchk($no,$pwd);
思ったより簡単だったというか…。差し換えの時はパスワードをチェックするけど、それ以外はパスワードをチェックしない。
新規投稿ならパスワードなしで、差し換えならパスワードが必要。
ここを書き直すだけで期待通りの動作をするようになりました。

ただし、削除キー不要の設定のところを、必要にしないと削除キーの入力欄が表示されなくなりますから、必要にしておかなければいけません。

config.phpで設定できるようにしてみました。
テンプレートの仕様変更も…。従来のテンプレートでも対応テンプレートで改造前のプログラムでもどちらでも問題がでないように何とか…。

config.php
//コンティニュー時、削除キーを必要とする 必要:1 不要:0
define('CONTINUE_PASS', '1');
の設定をそのまま使います。
説明文だけ変更して
//新規投稿でコンティニューする時にも削除キーが必要 必要:1 不要:0
define('CONTINUE_PASS', '0');
potiboard.phpの
1855行目付近
// if(CONTINUE_PASS) $dat['passflag'] = true;
//コンティニュー時はパスワード欄を常に表示
//従来のテンプレートとの互換性を保つため
//passflag を常に true にする。
$dat['passflag'] = true;
//ペイント画面のテンプレートで使う変数を追加
//新規投稿でパスワード不要の時 true
if(! CONTINUE_PASS) $dat['newpost_nopassword'] = true;
2680行目付近。
case 'contpaint':
//コンティニュー時のパスワード
// if(CONTINUE_PASS) usrchk($no,$pwd);
//パスワードが必要なのは差し換えの時だけ
if(CONTINUE_PASS||$type=='rep') usrchk($no,$pwd);
CONTINUE_PASSが 1 または、差し換えの時はパスワードが必要→差し換えでも、新規投稿でもパスワードが必要。

CONTINUE_PASSが 0 なら、パスワードが必要なのは差し換えの時だけになるので、新規投稿を選択すれば誰でもパスワード無しで続きを描く事ができる→合作可能。

お絵かき テンプレート
<!--{def newpost_nopassword}-->
<li>新規投稿なら削除キーがなくても続きを描く事ができます。</li>
<!--{/def}-->
<!--{ndef newpost_nopassword}-->
<li>続きを描くには描いたときの削除キーが必要です。</li>
<!--{/ndef}-->
従来のテンプレートを使う場合は
// passflag…削除キー入力を促す場合 true が入る
の箇所が、常に true となるので、
<li>続きを描くには描いたときの削除キーが必要です。</li>
という表示になる。

続きから描く時の挙動が、POTI-board、BBSNote、relmですべて同じになり設置しているすべてのお絵かき掲示板で合作が可能になりました。

P.S
この仕様はPOTI-board改 v1.42 lot.180507に組み込まれました。

コメントスパム対策のための.htaccess POTI-board用

長い間、掲示板へのコメントスパムをcgiの設定で防いで来ました。
「半角英数のみの投稿を許可しない」「NGワード機能を使用」「特定のIPをアクセスできないようにする」
BBSNotev8.0b19のモジュール、filter.cgi、ngword.cgi、security.cgiでフィルタリング。
それで十分…と思っていましたがBBSNoteはPerl5.12以上では動作しない事がわかり…。

他の掲示板には、BBSNoteのモジュールのような機能があるような、無いような…。
.htaccessによるアクセス制御 – さくらのサポート情報

特定のドメイン名やIPアドレスからの閲覧を【拒否】したい
設定ファイルの作成

メモ帳等のテキストエディタで、設定ファイルを作ります。

Order allow,deny
allow from all
deny from remote.host.com
deny from 192.168.0.
home/cgi/ のようなディレクトリ構成で、複数ある掲示板は cgi/ 以下にしか無いのであれば、cgiというディレクトリに.htaccessを設置すれば、cgi/ 以下の下位ディレクトリすべてへのアクセスを許可したり拒否したりできますから、掲示板が10種類あってもまとめて制御する事ができます。

こっちのほうが簡単…という事で.htaccessによる掲示板へのアクセス制限を使い始めて、約1年…。

コメントスパムのIPアドレス、ホスト名の記録を15年近く続けていましたから、それを.htaccessで拒否するように設定しました。
今のところコメントスパムを排除する事に成功しています。

しかし、拒否しなくてもいい人まで拒否してしまっている可能性も…。
登録しているIPアドレスが古すぎて、日本国内のIPアドレスになっていたら?
定期的に調べ直さなければならないのかもしれません。
それでも蓄積したブラックリストがあるのなら公開して欲しいという方のために、6800行あるファイルから必要最小限のものをピックアップしてzipファイルにまとめてみました。

POTI-boardと同じディレクトリに設置する事を想定したものですから、その他の掲示板にはそのままでは使えないかもしれません。

HTMLファイルをキャッシュさせないようにする設定と、POTI-boardの設定ファイルとログファイルへのアクセスを拒否する設定も入っているからです。

.htaccessの中を見て、何が書いてあるのかわかる方なら、IP、ホスト名だけコピペしていただければ…。
order allow,deny
allow from all

deny from .ru
deny from .ua
deny from .broadband.kyivstar.net
コメントスパムで埋まったお絵かき掲示板の投稿者のIP、ホストを調べてみた限りでは…。
.ua
.ru
.broadband.kyivstar.net
の3つを拒否するだけで海外からのコメントスパムの大半は拒否できるような気がします…。

配布するファイルにはもうちょっといろいろ入れてあります。

zipファイルには別の.htaccessも入れておきましたが…。
そのまま使うのは危険です。

何名かの国内の友人、そして全世界の友人を失っても構わない、とにかく海外からのコメントスパムを防ぎたい…という方のための設定になっています。
#phpファイルにアクセスできるのは.jpと.bbtec.netだけ
#そのほかの国内からのアクセスも弾いてしまうので
#実際に運用する場合は
#http://www.cgis.biz/tools/access/
#の日本国外からのアクセスを制限する.htaccessの内容を以下に追加

<Files ~ "\.php$">
order deny,allow
deny from all
allow from .jp
allow from .bbtec.net
</files>
海外からでも掲示板の投稿を読む事ができて、イラストを見る事もできるように、拡張子.phpのファイルへのアクセスだけ拒否するように設定してみました。
.jp
.bbtec.net
からのアクセスしか許可しない設定になりますから、学校の施設からアクセスしたら拒否されたとか…、国内で使っているけれど回線は米国の場合は書き込む事ができなくなります。
アクセス制限のかかっていない領域にメールフォームを設置して、書き込めないから許可する設定にしてください…という連絡をもらって許可するIP、ホストを追加していけばいいのかもしれませんが…。
IPアドレスで日本国外(海外/外国)からのアクセスを制限する.htaccess CGI's
ここから.htaccessをダウンロードして、そのまま設置すれば、国内からしかアクセスできなくなる筈なので、こんな小さな個人サイトのブログが配布しているファイルよりよほど確実かもしれません。

しかし、日本以外からのアクセスを禁止するという事はGoogleからのアクセスも禁止する事になるようなので、いつまでたってもGoogleの検索結果に反映されないといった問題が起きるかもしれません。

アクセス制限は、できるだけ狭い範囲にかけるものだと思っています…。
たとえば、ただのHTMLファイルへのアクセスはできるけれど、掲示板の拡張子、cgi、phpにアクセスできるのは日本国内からだけといった設定をする事もできます。
上位ディレクトリへの設置ではなく、掲示板が設置されているディレクトリに設置すれば、掲示板以外へのアクセスは制限されないのでトップページも見る事ができないといった問題を回避する事ができると思います。
htaccess_for_POTI_board_181425.zip
二種類の.htaccessが入っています。あくまでもサンプルです。
実際に運用する場合は、記述されている内容をご自身で確認してくださいますようお願い致します。
また、サーバによってはうまく動作しないかもしれません。
そういった事も含めて、あくまでもサンプルであり無保証です。

お絵かき掲示板のキャッシュを.htaccessで制御

お絵かき掲示板、POTI-boardは投稿後の画面をHTMLファイルで表示します。
そのため、更新される前のキャッシュを表示する事があります。
Ctrl+R、F5、またはブラウザの更新のアイコンをクリックすれば、投稿したコメントやイラストが表示されるので問題ないといえば問題ないのですが…。
ちょっと面倒…というか…。
どうにかならないのかな?と思って調べてみると…。
HTML5における no-cache - Qiita

本記事の投稿当時に紹介したアプリケーションキャッシュは、現在では廃止予定の機能となりました。
HTML5でもキャッシュを制御する方法が…と思ったら廃止…。その代わりになるものは?
サービスワーカーの使用 - Web API インターフェイス | MDN

コードは HTTPS を通して提供する必要があります。サービスワーカーはセキュリティ上の理由から HTTPS を通して実行されるよう制限されています。
どのようにすれば使う事ができるのか、よくわからない上、HTTPS…。
.htaccess の書き方(アクセス制御編) - Qiita

キャッシュの有効期限を過去にする
<Files ~ "\.html?$">
<IfModule mod_headers.c>
Header set Pragma no-cache
Header set Cache-Control no-cache
Header set Expires "Thu, 01 Dec 1994 16:00:00 GMT"
</IfModule>
</Files>
Qiitaの記事を参考に拡張子 .html または .htm のファイルのキャシュの有効期限を
Thu, 01 Dec 1994 16:00:00 GMT に設定。

POTI-board

デベロッパーツールでHTMLファイルのキャッシュの有効期限を確認。
Expires: Thu, 01 Dec 1994 16:00:00 GMT
リロードしなくても反映されるようになりました。
キャッシュしないファイルはHTMLだけで、ファイルサイズが大きな画像はキャッシュしますから表示速度への影響も最小限…だと思います。

relm

続きを描いた筈なのに以前の画像のまま…というトラブルが発生していたrelmのための設定。
<Files ~ "\.(html?|jpg|png)$">
<IfModule mod_headers.c>
Header set Pragma no-cache
Header set Cache-Control no-cache
Header set Expires "Thu, 01 Dec 1994 16:00:00 GMT"
</IfModule>
</Files>
pngファイルのキャッシュの有効期限は
Expires: Thu, 01 Dec 1994 16:00:00 GMT
リロードしなくても反映されるようになりました。

ただし、画像をキャッシュしない訳ですから、1ページに画像が10枚あって1枚あたり100kbとして1MB…。
回線が高速化しているのでで1MBなんて大した事ないんじゃないか…という気もしますが…。

relmのディレクトリに画像のキャッシュの有効期限を過去にした.htaccessを設置するだけなら、そのほかのページへの影響はありませんが上位ディレクトリに設置してしまうと…。
.htaccessを上位ディレクトリに設置すると下位ディレクトリでも設定が有効となり、下位ディレクトリに設置すると下位ディレクトリのみ有効になるようです。
.htaccess の書き方(アクセス制御編) - Qiita

見られたくないファイルへのアクセスを拒否
キャッシュから話しがそれますが…。
もっと早く知っていれば、あちこちいじりまわさなくても良かったのかも…という設定。
<files ~ "\.(ini|log|dat)$">order allow,deny
deny from all
</files>
.htaccessで文法を間違えると下位ディレクトリを含むすべての範囲でエラーが発生し、何も表示されなくなってしまいます。

テスト用のディレクトリに.htaccessを設置して問題ない事を確認してから設置が必要なディレクトリに設置するようにしていますが…。

なぜエラーになるのかわからなくて数十分というケースも…。

お絵かき掲示板はこちら。

POTI-boardのURL欄の文字列をチェックしてフィルタリングする

POTI-boardの
//拒絶する文字列
$badstring = array("foo","bar");
は、URL欄をチェックしていません。
URL欄の文字列をチェックして拒絶する設定項目を作る事もできますが…。
config.phpの設定項目が増えて、乱雑になるのはあまり好ましい事ではないのかもしれません。
しかし、お絵かき掲示板のURL欄に
.ru
と入力しているのはコメントスパム位なので、設定で弾く事ができたほうがいいような気もします。
設定項目を増やしたくない…だったら設定したい人は本体を改造して…。
POTI-board改とテンプレートシリーズ
から、php7と、PaintBBS NEOに対応したPOTI-boardをダウンロードし、potiboard.phpの860行目付近の
//本文へのURLの書き込みを禁止
if(DENY_COMMENTS_URL && preg_match('/:\/\/|\.co|\.ly|\.gl|\.net|\.org|\.cc|\.ru|\.su|\.ua|\.gd/i', $com)) error(MSG036,$dest);
の下に
//URL欄で拒絶する文字列
if(preg_match('/\.ru$|\.su$|\.ua$/i',$url)) error(MSG037,$dest);
を追加すると…。
.ru
.su
.ua
で終わるURLを拒絶します。
cheapautoinsurancefoo.pw
autoinsurancebar.pw
autoinsurancebaz.top

コメントスパムのURLの一部を変更したサンプルです。
autoinsurance.*\.(top|pw)$
で3パターンすべて拒絶。実際に使うとしたら
//URL欄で拒絶する文字列
if(preg_match('/\.ru$|\.su$|\.ua$|autoinsurance.*\.(top|pw)$/i',$url)) error(MSG037,$dest);
でしょうか。

POTI-boardで水素水を拒絶する

水素水のコメントスパムが連日投稿されている場合の考えられる設定。
//拒絶する文字列
$badstring = array("水( | ?)素( | ?)水","\[\/URL\]");
[/URL]も拒絶する設定に入っていますが…。

POTI-boardの拒絶する文字列には、正規表現を使う事ができます。

サルにもわかる正規表現入門

いつも参考にさせて頂いているサイト様。
正規表現全般については他のより詳しいサイトを参考にしていただくとして…。

水素水という文字列を拒絶したとします。
すると、コメントスパムを投稿する業者は、
水 素 水
水 素 水
水素 水
のように、全角スペース、半角スペースを入れて規制をすり抜けようとします。
正規表現が使えるので
水( | ?)素( | ?)水
全角スペースあるいは半角スペースあるいは半角スペースが無いかもしれないという指定になりました。
実際に試してみると、
水素水
水 素 水
水 素 水
水素 水
どのパターンでも拒絶する事ができました。
水素水の素の部分の一文字が変わる場合は?
水.水
でいい筈なのですが…。.の部分が半角英数であれば拒絶…しかし、全角1文字の場合はなぜか動作しません。
水.*水
にすると、今度は、水寿限無水、でも拒絶されて…。
弾きたくない長い文字列でも拒絶されてしまいました。
[/URL]
を拒絶したい場合は…。
POTI-boardの拒絶する文字列では、/ をエスケープする必要があります。
[ ] は正規表現のメタ文字ですから、[ ] そのものを指定したい場合はエスケープする必要があります。
\[\/URL\]
なぜ日本円の通貨の記号が…と思われるかもしれませんが、本来はバックスラッシュです。
POTI-board改とテンプレートシリーズ

POTI-board改 v1.41.1 lot.180423 18/04/23 up
かなり無理を言って、
//指定文字列+本文へのURLの書き込みで拒絶(正規表現)
$badstring_and_url = array("ブランド","偽物","財布","\[\/URL\]");
という設定項目を作っていただきました。
デフォルトの設定で、本文にURLが記入されていて、かつ、ブランド、偽物、財布、[/URL]の文字列があると拒絶します。

しかし、知らなかったのですが、従来の拒絶する文字列でも結果的に同じになる書き方が…。
//拒絶する文字列
$badstring = array("HOGE","(:\/\/[\s\S]+(財布|偽物)|(財布|偽物)[\s\S]+:\/\/)");
この場合は、URL+拒絶する文字列の前後が入れ替わる事を想定して同じ文字列を二度指定しなければならなくなるので、面倒といえば面倒なのですが…。

正規表現に詳しい人なら、従来のままでも弾く事ができる内容だったようです。
でも、この書き方だとタイトルに偽物、本文にURLの場合は弾かれない…のかな。

お絵かき掲示板の入力フォームにautocomplete属性を設定

設置しているお絵かき掲示板のコメント欄の入力フォームにautocomplete属性を設定しました。

Chromeのパスワード保存機能に対応させるためです。

autocomplete属性 お絵かき掲示板autocomplete属性 お絵かき掲示板

右、BBSNote。左、relm。

autocomplete属性を設定したので、名前+パスワードで保存できるようになりました。

これまでは、URL+パスワードでした。
URLを変更するとその組み合わせて再度パスワードを記憶…というおかしな事になっていました。

POTI-board、は題名+パスワードで、題名を書き換えるたびにパスワードを記憶していました。

<input type="text" name="name" class="post_input_text" autocomplete="username">

名前のところにautocomplete="username"といれただけですが…。

autocomplete属性 お絵かき掲示板

こちらも、名前+パスワードで記憶できるようになりました。

autocomplete属性 お絵かき掲示板

続きから描く時にも名前を選択すればパスワードが入ります。

input 要素 - HTML | MDN

username
new-password: 新しいパスワード (例: アカウントの新規作成やパスワード変更のとき)
current-password

他の絵板と同じパスワードが入っても問題ないはずなので、記憶したいパスワードはcurrent-password、自動的に入力されると困る記事番号+パスワードはnew-password。
フォームのオートコンプリートを無効にするには - Web セキュリティ | MDN

パスワードフィールドのオートフィルを抑止したい場合、autocomplete="new-password" を指定するべきです。ただし、この機能はどのブラウザでもまだ実装されていません。
どのブラウザでもまだ実装されていないとありますが、Chrome64はautocomplete="new-password"で対応可能でした。

Chromeには有効な設定だったのですが、IE11でパスワードを記憶させるとPOTI-boardでは題名+パスワードの組み合わせに…。
Firefoxは…何が変わったのかよくわかりませんでした。

P.S
この記事には後日談があります。

Chrome68 オートフィルを抑止したいだけなのに新規パスワード生成メニューが出る

Chrome68から、autocomplete="new-password"が指定されている箇所をクリックすると新規パスワード生成メニューがでるようになりました。
パスワードを記憶しないようにするための工夫のつもりでしたが、この記事の通りに設定してもうまくいかないかもしれません。

POTI-board用テンプレート PINK を配布します。

Chrome、FirefoxともにJavaのサポートを終了。
Windows10のアクセサリに入っているIE11を使えば、とりあえずJavaを使う事ができますが…。

描くたびにJavaのセキュリティの警告…。

これでは、しぃちゃんお絵描き掲示板PaintBBSはすたれてしまう、と思ったら…。
GitHub - funige/neo: PaintBBS NEO

お絵描きしぃ掲示板 PaintBBS ((C)2000-2004しぃちゃん) をhtml5化するプロジェクトです。
Flashやhtml5のお絵描きサイトはいっぱいあるんだけど、そうじゃないんだ。
おじさんは昔のjavaアプレットそっくりの環境が欲しいんだ。
かなりの再現度です。

HTML5ですから、Chromeでお絵かきできます。

PaintBBS NEOは、既存のお絵かき掲示板に組み込む事が可能なので、BBSNote、relm、らくがきひろばでも使えるのですが…。
新規設置をするなら、POTI-boardがいいのかなぁ…と思います。

BBSNoteはPerl5.12以上では動作しない、relmは管理パスワードがURLに出るので、リファラを返す設定で使うと…。

しかし、POTI-boardにも問題があります。
php7では動作しない、と思ったら…。
POTI-board改とテンプレートシリーズ

Punyu NetのPOTI-boardを、php7で使えるように改造したものです。 使いやすさの観点から1.33のベータ版ではなく安定版の1.32から作りました。
さくらのレンタルサーバの一番安いライトプランで、phpのバージョンを7.1にして動作確認。

今のところ問題ありません。

でも、レス送信時のコメント欄の位置が、と思ったら…。
ドラ☆クロウ! - オリジナルイラスト中心よろずサイト -

POTI-boardテンプレート Cool Solid
POTI-board v1.32以降向けのテンプレートです。
SakaQさん作のMONO WHITEを元にHTML5とCSS3で大幅にアレンジしました。
BBSNoteのスキンsiberiaの作者れいさんzero(配布サイト)の、POTI-board版siberiaのデザインを取り入れているのでBBSNoteと見た目が近い。

コメント欄はスレッドの下。

これをベースにすれば、BBSNoteに近いテンプレートを作る事ができると思いました。

作ってみました。

POTI-board テンプレート PINKPOTI-board テンプレート PINK

タブレット。
iPadとiPad ProをChromeでエミュレート。

POTI-board テンプレート PINKPOTI-board テンプレート PINKPOTI-board テンプレート PINK

スマートフォン。
Galaxy S5、iPhone8をChromeでエミュレート。

配布したくなったので、配布します。

画像アップロードができない仕様。
お絵かき掲示板として使いたいという方向けのテンプレートです。

管理画面からの画像アップロードには対応しています。
設置方法、注意事項はreadmeにまとめておきました。

たまに、readmeを読まない方がいますが、読まないといろいろと…。

キャンバスサイズを選択式にしましたが、
セレクトボックスを貼り付けあるだけなので、変更するにはテンプレートを…。

そのあたりの事も、書いてありますので目を通していただけたらと思います。

POTI-board用テンプレート PINK 設置サンプル

設置サンプル。
POTI-board用テンプレート PINK
pink181031.zip

テンプレートのダウンロードはこちらから。

BBSNote8.0にPaintBBS NEOを組み込む

HTML5版 PaintBBS NEO 起動画面
以下はBBSNote8.0b19でHTML5版のPaintBBS NEOを使うための設定方法です。

何かのお役に立てればと思いながら書いていますが、この記事を参考にした事によりトラブルが起きても何もしてあげる事ができません。
私はなんら責任を負いません。無保証です。

BBSNoteb8.0はPerlのバージョンが5.12以上の場合動作しません。

いまのところ、さくらのレンタルサーバではPerlのバージョンを5.8.9、5.10.1に切り替える事ができるため動作します。しかし、いつ使えなくなってもおかしくありません。
以下はそれでも、NEO化したいという方向けの情報です。

BBSNoteは配布が終了していて、再配布も禁止されているため新規に入手する事ができません。
作業する前にバックアップを取り、さらに、動作確認のためのテスト用の掲示板を別途設置します。

テスト用の掲示板を設置して問題がないことを確認してから実際に使う掲示板に転送すれば、すでに動作しているお絵かき掲示板をトラブルに巻き込む事なく作業をすすめる事ができます。

NEOを使えるようにする。

GitHub - funige/neo: PaintBBS NEO

から必要なファイルをダウンロードしてヘッダに2行追加します。
neo/README.md at master ・ funige/neo ・ GitHub

1. 基本的には<head>に2行追加するだけです

<head>
<link rel="stylesheet" href="neo.css" type="text/css" />
<script src="neo.js" charset="UTF-8"></script>
...
</head>

neo.jsとneo.cssの2つのファイルを/dist からダウンロードしてください。
最新版のPaintBBS-x.x.x.(css|js)とneo.(css|js)は同じものです。
問題はどこに追加するかですが、Javaのしぃペインターも使いたいのであれば、PaintBBSの設定のところに追加するのが適当だと思います。

paint.cgiの

#=== ★ ShiPaintBBS の設定 ===================================================

以下の箇所に2行追加します。
#-------< ヘッダ内テキスト >--------------------------------------------------
'TxtHead' => <<_TXT_
<link rel="stylesheet" href="PaintBBS-1.2.3.css" type="text/css" />
<script src="PaintBBS-1.2.3.js" charset="UTF-8"></script>
_TXT_
_TXT_を消すと500エラーになるため注意が必要です。

PaintBBS-1.2.3.css
PaintBBS-1.2.3.js

上記の2つのファイルがbbsnote.cgiと同じディレクトリに転送されていることを想定しています。

転送したファイルの名称が

neo.css
neo.js

の場合は、ファイル名をそれに合わせます。

PaintBBS-1.2.3.js

という記述は特定のバージョンのNEOを動作させるためのものです。
<link rel="stylesheet" href="neo.css" type="text/css" />
<script src="neo.js" charset="UTF-8"></script>
としておいて、
バージョンアップしたら

neo.css
neo.js

を上書きする形でも運用できます。

まとめると、paint.cgiのShiPaintBBS の設定のヘッダ内テキストに2行追加して、指定したファイル名と同じファイルをbbsnote.cgiと同じディレクトリに転送するだけです。

PaintBBSを選択した時にはHTML5のPaintBBS NEOが起動し、しぃペインター選択を選択した時にはJavaのしぃペインターが起動します。

Java版のPaintBBSと共存させる事もできますが、書き直す箇所が多くなるため割愛します。

ここから先は、ちょっと難しい設定になります。

PaintBBS NEOで投稿できるのはPNG形式だけです。
BBSNote8.0はPNG形式の画像から続きを描く事ができません。

つまり、NEOで投稿した画像からは続きを描く事ができません。

それでは不便なのでPNG形式の画像から続きを描けるようにします。

paint.cgi
3751行付近の
$fmt_png = 1 if($Data{ ImageSrc } =~ /\.png$/);
$ok_image = 1 if($Data{ ImageSrc } =~ /\.png$/);
に書き換えます。
これだけでは続きから描くためのリンクが出てこないので、skin.cgiの続き表示関係の該当箇所を
$Data{ImageSrc} =~ /\.(jpg|gif|png)$/i) &&
とします。

JPEGでもGIFでもPNGでも続きから描くリンクが出るようになります。

PaintBBS NEOが使えてPNGから続きを描く事ができるBBSNoteのお絵かき掲示板。

気軽にお絵かき PaintBBS/しぃペインター

お絵かき掲示板をスマートフォン対応にする

<meta name="viewport" content="width=device-width,initial-scale=1">

viewportを指定します。PC用の解像度で表示しなくなるので、文字が小さすぎて読めない、クリック可能な要素が近すぎるといった問題を回避する事ができます。
ビューポートを設定する  |  PageSpeed Insights  |  Google Developers

ビューポートは携帯端末でのウェブページの表示方法を制御します。ビューポートがない場合、携帯端末は一般的なデスクトップ画面の幅でページをレンダリングします。ビューポートを設定すると、ページの幅やさまざまな端末での拡大縮小を制御できるようになります。

お絵かき掲示板をスマートフォン対応にする

ブラウザの幅をせまくすると文字が縦並びになって読みにくいので…。

お絵かき掲示板をスマートフォン対応にする

ここからブラウザの幅をせまくすると…。

お絵かき掲示板をスマートフォン対応にする

コメントが画像の下に回り込むように設定。
<div class="message">
蒼の六郷の昴さん。
</div>

.messageの幅が200pxより小さくならないようにして、それよりブラウザの幅がせまい時はカラム落ちさせます。
.message {
min-width:200px;
display: table;
}

コメントの横幅が200pxより小さくならないように指定。
min-width:200px;だけではうまくいかないので、display: table;を使いました。

お絵かき掲示板をスマートフォン対応にする

ブラウザの横幅にあわせて画像を縮小。
img {
max-width: 100%;
height: auto;
}

お絵かき掲示板をスマートフォン対応にする

ChromeでiPhoneをエミュレート。

スマートフォンに対応させたお絵かき掲示板はこちら。