POTI-boardのパスワードハッシュをpassword_hash()に

2018年のパスワードハッシュ - Qiita

ログイン認証と称してmd5とかsha1とか書いてあるソースはゴミなので投げ捨てましょう。
単純なMD5やSHA1ハッシュを元に戻す | Bamboo lath 日々の記録
ハッシュ値は非可逆なので元に戻す事ができない筈なのですが、「aiueo」や「12345」のような単純なパスワードはデーターベースと照合して元に戻す事ができるようです。

POTI-boardは md5() から途中の8文字を抽出してハッシュ化しているので、紹介されている逆引きサイトに8文字のハッシュ値をいれても何もでてきませんが、パスワードが同じならハッシュ値も同じである事に変わりはありません。
PHP: password_hash - Manual

password_hash − パスワードハッシュを作る
password_hash() という簡単に導入できるハッシュ化のための関数があるのに使わない手はない…ですね。

簡単なテストコード。
<?php
$h= password_hash("aiueo", PASSWORD_DEFAULT);
//パスワードは aiueo
echo $h."\n";//ハッシュ値が表示される
$v=password_verify("aiueo",$h);
//ハッシュ値とパスワードを照合
echo $v."\n";//1
var_dump($v);//true
同じパスワードなのにリロードする度にハッシュ値が入れ替わります。

しかし…。
$h= password_hash("aiueo", PASSWORD_DEFAULT);
ではcostが10になってしまいます。
<?php
/**
* このコードは、サーバーをベンチマークして、どの程度のコストに耐えられるかを判断します。
* サーバーに負荷をかけすぎない範囲で、できるだけ高めのコストを設定したいものです。
* 基準として 8 から 10 程度からはじめ、サーバーが十分に高速なら、できるだけ上げていきましょう。
* 以下のコードでは、ストレッチングの時間を 50 ミリ秒以内にすることを狙っています。
* 対話形式のログインを扱う際の許容時間としては、このあたりが妥当なところでしょう。
*/
$timeTarget = 0.05; // 50 ミリ秒

$cost = 8;
do {
$cost++;
$start = microtime(true);
password_hash("test", PASSWORD_BCRYPT, ["cost" => $cost]);
$end = microtime(true);
} while (($end - $start) < $timeTarget);

echo "Appropriate Cost Found: " . $cost . "\n";
?>
さくらのレンタルサーバ ライトでこのテストコードを実行してみたところ最適なcostは9でした。

一番安いライトプランではありますが有料のサーバでもcost10ではサーバに負荷がかかるという事です。
costを10から9に下げると処理時間が半分に。
8にしたらさらに半分…。costが1下がると処理時間が半分になるようです。

ログイン認証を一度だけ行ってログインしたらそのまま…という想定ならcostが10でも耐えられるのかもしれませんが何か一言書き込むだけでパスワードのハッシュ化が行われる掲示板でcost10で運用するとサーバの負荷が高くなってしまうかもしれません。
$pass = $pwd ? password_hash($pwd,PASSWORD_BCRYPT,['cost' => 5]) : "*";
costを5に引き下げました。

cost5では低すぎるのでは?と思ったりもしましたが、コメントを書き込むたびにパスワードをハッシュ化する掲示板なのでこれぐらい下げないと無料のレンタルサーバでは高負荷になる…という判断です。

それでも同じパスワードなら同じハッシュ値という従来のmd5の8文字のハッシュ値とは比べ物にならないぐらい安全性を向上できた…と思うのですが。

この変更は、lot.190823に反映されました。

POTI-board改のダウンロードはこちらから。

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

file_exists() is_file() 速度比較

ファイルの存在確認をするときに使う関数 file_exists() 、 is_file() の速度を比較するため簡単なコードを書いてテスト。
<?php
$time_start = microtime(true);//計測開始
$img='img/hoge.png';
for($i=0; $i<100000;++$i){//10万回繰り返す
file_exists($img);
}
$time = microtime(true) - $time_start; echo "{$time} 秒";
//計測結果
$time_start = microtime(true);//計測開始
$img='img/hoge.png';
for($i=0; $i<100000;++$i){
is_file($img);
}
$time = microtime(true) - $time_start; echo "{$time} 秒";
//計測結果

//0.37799286842346 秒 0.038822174072266 秒 さくらのレンタルサーバライト
is_file() のほうが、10倍速いという結果がでました。

テストしたコードが単純すぎてキャッシュを確認しているだけだとしても…。
速度差が10倍…なら is_file() で構わないところは is_file() を使ったほうが。

動作の違いは…。
$img='img/';
var_dump(is_file($img));//bool(false)
var_dump(file_exists($img));//bool(true)
$img='img/hoge.png';
var_dump(is_file($img));//bool(true)
var_dump(file_exists($img));//bool(true)
file_exists()は、ディレクトリしかなくても bool(true) を返します。 is_file() では bool(false) になります。

POTI-boardで使用されている file_exists() の該当箇所をしらべてみると…。
ディレクトリの確認をしているかもしれない箇所はほとんどなく逆にディレクトリしかなくても bool(true) では意図した動作にならないところに file_exists() が使用されている事がわかりました。

POTI-boardは一言書いて投稿するだけでもすべてのログを解析してHTMLファイルに書き出します。
そのためログが肥大化すると処理速度が遅くなってしまうのですが…さらに投稿するたびにすべての画像ファイルにアニメファイルがあるかどうか確認しているのでそこに重い関数を使うと…。

投稿時にアニメファイルの存在確認を行う回数が一目でわかるようにdumpしてみました。

file_exists()をis_file()に

アニメファイルの存在確認を file_exists() から is_file() に書き換えたところ8秒かかっていた投稿処理時間が1秒に短縮。

運営している絵板は設置件数が多くログ保持件数が多いのに一番安いさくらのレンタルサーバ ライトのライトプランなので、遅くても仕方がないのかな?と思っていたのですがどうにか…。

この変更は、POTI-board改 v1.52.9 lot.190812に反映されました。
(最新版は v1.53.2 lot.190831)

POTI-board改のダウンロードはこちらから。

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

phpのOpenSSL関数で暗号化 復号化

phpでpasswordを暗号化して復号化…。
password_hash()は暗号化ではなくハッシュ化なので元のpasswordに戻す事はできません。
ではどうしたら…。
PHPで文字列を暗号化 - Qiita
なんか複雑なコードが書いてある…。これは私には手におえない?
phpのマニュアルは…。

PHP: OpenSSL 関数 - Manual

PHP マニュアル 関数リファレンス 暗号 OpenSSL
目次が…。
という事でできてみればたったこれだけ…のコードに1時間以上…。
<?php
$pwd = 'hogefuga';
define('crypt_pass','VNCLiX9BaeuzfaR');//暗号鍵
define('crypt_method','aes-128-cbc');//method
define('crypt_iv','FpXe2VNEVwLhJa8a');//iv 16バイト
$pwd=openssl_encrypt ($pwd,crypt_method, crypt_pass, true, crypt_iv);//暗号化
$pwd=bin2hex($pwd);//16進数に
var_dump($pwd);
//string(32) "9427c68b3e6ba3468c773d1b8f54359a"
$pwd=hex2bin($pwd);//バイナリに
$pwd=openssl_decrypt($pwd,crypt_method, crypt_pass, true, crypt_iv);
var_dump($pwd);// string(8) "hogefuga"
ivは半角16文字(16バイト)で。
暗号鍵は暗号化復号化のための固有の文字列。
methodは aes-128-cbc。

暗号化したpasswordをバイナリから16進数に変換したものをGETで取得して、16進数をバイナリに戻して復号化。

続きから描く時にペイント画面に入るpasswordを暗号化する事ができました。

この変更は、POTI-board改 v1.53.0 lot.190823 に反映されました。

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

$_POST $_GET から filter_input()へ

POTI-boardの$delに不正な値が入らないようにする: STP^3
でこう書きました。
$del = ( isset($_POST["del"]) === true ) ? ($_POST["del"]): "";

if(is_array($del)){
$countdel=count($del);
for($i = 0; $i < $countdel; $i++){
if(!ctype_digit($del[$i])){//数字のみ
$del="";
}
}
}
else{
$del="";
}
数字しか入らなくする工夫だったのですが…。
foreachを使ったほうが的確だったかも。そして…。
$_GET, $_POST じゃなくて filter_input 使えとのこと - Qiita
$del = filter_input(INPUT_POST,'del',FILTER_VALIDATE_INT,FILTER_REQUIRE_ARRAY);//$del は配列
配列にもfilter_input() を使う事ができるので FILTER_VALIDATE_INT で整数以外入らなくなりました。とてもスマートです。

$_POST $_GET から filter_input()へ
$anime = filter_input(INPUT_POST, 'anime',FILTER_VALIDATE_BOOLEAN);
bool型以外受け付けないので、入る値はtrueまたはfalseのみ。
取得する値がないときは変数にNULLがセットされるので未定義になりません。
【PHP入門講座】 NULLと未定義の違い - Qiita
$_POST[]は書き換える事ができるので意図しない値が入る可能性…。スクリプトの先頭で取得するだけなら問題ないのかもしれませんが途中で他の値を代入しているスクリプトも存在していて…httpからPOSTされたデータなのか、代入して書き換えられた値なのかわからなくなるケースもあるようです。
PHP - スーパーグローバル変数に直接アクセスしない方がいい理由|teratail

filter_input()を使った場合、スーパーグローバルの$_GETや$_POSTではなく、本当にHTTPで投げられた値を元に結果を返します。
この変更はPOTI-board改 v1.51.9 lot.190612に反映されました。
注意:2019年8月29日現在の最新版は POTI-board改 v1.53.1 lot.190827です。

POTI-board改の最新版のダウンロードはこちらから。
お絵かき掲示板はこちら。

お絵かき掲示板交流サイトのトップページの負荷削減

お絵かき掲示板交流サイトのトップページの新着画像の表示に使っていたスクリプト…。
foreach(glob('cgi/{foo,bar,baz}/src/{*.png,*.jpg}', GLOB_BRACE) as $filename) {
//$arr[$filename] = filemtime($filename);
$arr[$filename] = substr($filename,-17,-4);
}
unset($filename);
//連想配列を値でソート
arsort($arr);
?>
お絵かき掲示板の画像が保存されているディレクトリに入っている画像をすべて呼び出して新着画像順になるようにソート。

以前はファイルのタイムスタンプで並び替えていましたがもしひとつのディレクトリに2000枚の画像があったらディレクトリ3つで合計6000枚。

それを配列にいれるだけでなくサーバにタイムスタンプを問い合わせる処理もはいって…となるのでその処理が負荷になっていました。

それをファイル名でソートするようにすると0.09秒かかっていた処理が0.03秒に短縮。
//$arr[$filename] = filemtime($filename);
$arr[$filename] = substr($filename,-17,-4);
POTI-boardの画像ファイルのファイル名には10桁のユニックスタイムと小数点以下のマイクロタイム3桁分、合計13桁の数字が入っているのでその箇所とりだしてファイル名でソートしても同じ結果を得ることができました。

しかし、表示する画像が新着の1枚でも12枚でもglobでディレクトリ内の画像を検索して6000枚画像があったら配列の数も6000…。

あれ?ログファイルから画像のファイルのパスを取得したら?とひらめいて…。
$i=1;
$fp = fopen($val, "r");
while ($line = fgets($fp ,4096)) {
list($no,,$name,,$sub,,,
,,$ext,,,$time,,,,) = explode(",", $line);
if ($ext){
$dir=explode('/',$val);
$files[]=$no.','.$name.','.$sub.','.$dir[1].',cgi/'.$dir[1].'/src/'.$time.$ext;
// var_dump($val);
if($i>=12){break;}
++$i;
}
}
fclose($fp);
各ディレクトリの新着12枚をもとにして全ディレクトリ分の配列を作成してファイル名でソートすれば…。

12x3=36で配列の数36。

結果処理時間を0.09秒から0.006秒に短縮することができました。

従来の1/15の処理時間でほぼ同じ結果を得ることができました。
いろいろとやってみるものですね。

お絵かき掲示板交流サイトはこちら。

わかると便利なforeach

あんまりにもあんまりなコードを書いていたので、少しは進歩している事をおしらせすべく、お絵かき掲示板交流サイトのトップページで使っているphpのソースの一部を…。

<?php
$arr = array();
foreach(glob('cgi/{foo,bar,baz}/index.html', GLOB_BRACE) as $filename) {
$arr[$filename] = $filename;
}
$i = 1;
foreach($arr as $key => $value){
var_dump($key);
if($i >= 3){break;}
$i++;
}
?>

よくわからないけれど動いていたもの。

foreachは配列の数だけループするのでもし3ならbreakという処理は必要ありませんでした。

globで配列に入れる必要もありませんでした。その配列を別の配列に入れる必要もありませんでした。

<?php
$arr=array('cgi/foo/index.html','cgi/bar/index.html','cgi/baz/index.html');
for($i = 0; $i <= 2; $i++){
$filename = $arr[$i];
var_dump($filename);
}
?>

foreachがよくわからなかったので、forで記述。
しかしやや煩雑なコード…。

<?php
$arr=array('cgi/foo/index.html','cgi/bar/index.html','cgi/baz/index.html');
foreach($arr as $filename){
var_dump($filename);
}
?>

foreachが便利な事がわかったので書き直し。
配列の数だけループ。

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

配列の最後の値を取得するコードの速度を比較

サーバの負荷が気になるので、お絵かき掲示板交流サイトのトップページのphpのコードを書き直しているところです…。

ディレクトリ内の画像から最新の画像を1枚表示したいだけなのに、ディレクトリ内に1000枚画像があったら配列の数が1000個…それをタイムスタンプで逆順でソートしてまた配列に格納…。

ファイル名の数字が同じ桁数で新しいほど数値が増えるのなら、globでディレクトリ内の画像を呼びした時点でソートがかかっているのでタイムスタンプを使った処理をしなくても…。

その処理を省略するだけで、少なくとも00.1秒は速くなるようですね。サーバの処理速度にもよりますが…。

ふと思ったのですが…。

ディレクトリに1000枚の画像が存在していたらglobで古い画像から順番に配列に格納されるので、最新の画像は1000番目になりますね…。

foreach(glob('cgi/poti/src/{*.png,*.jpg}', GLOB_BRACE) as $filename) {
}

foreachで配列の数だけループするけれど何もしない。しかしループが終わったあとに残る$filenameは配列の最後の値…。(必ずそうなる訳では無いようですが…)

$filenameに1000枚の画像のファイル名が入るので処理速度は期待できない…。

そこで…
$filename=glob("cgi/poti/src/{*.jpg,*.png}", GLOB_BRACE);
$filename=$filename[count($filename)-1];

最新の画像が表示されるので結果は同じ。ループしていないのでforeachを使うより軽い…はずだったのですがcountが重いのか…。

配列の最後の値を取得するコードの処理速度 php

$filename=glob("cgi/poti/src/{*.jpg,*.png}", GLOB_BRACE);
$filename=array_slice($filename, -1)[0];

foreach(glob('cgi/poti/src/{*.png,*.jpg}', GLOB_BRACE) as $filename) {
}

の処理速度がほぼ同じ…。

むしろforeachでループして最後に残った値を取得する下側の書き方のほうが処理時間が短くて…。

$filename=$filename[count($filename)-1];

が一番遅い…。

$filename=glob("cgi/poti/src/{*.jpg,*.png}", GLOB_BRACE);
$filename=end($filename);

配列の最後の値を取得したいのならendという関数が…と思いましたがなぜかあまり速くない。

配列の最後の値を取得するコードの処理速度 php

一番速かったのは…。一番遅いと思っていたforeachで配列を最後まで読み込んで最後に残った値…でした。

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

配列の数だけループ

foreachで配列の数だけループできたんですね。試しに簡略化したプログラムを書いて実行…。
<?php
$arr = array('Apple', 'Google', 'Microsoft');
foreach($arr as $filename) {
var_dump($filename);//配列の値
}
foreach($arr as $kye => $filename) {
var_dump($kye);//配列のキー
}
結果。
string(5) "Apple" string(6) "Google" string(9) "Microsoft" int(0) int(1) int(2)
単純化してみてやっと理解できたような…。
という事は…。
さくらのレンタルサーバのOSのバージョンアップでphpの動作が変わった: STP^3
お絵かき掲示板交流サイトのトップページのコードを書きましたが…。
<?php
$arr = array();
foreach(glob('cgi/{foo,bar,baz}/index.html', GLOB_BRACE) as $filename) {
$arr[$filename] = $filename;
}
$i = 1;
foreach($arr as $key => $value){
var_dump($key);
if($i >= 3){break;}
$i++;
}
?>
配列の数が3でカウンターが3になったらbreak…。
エラーメッセージはでないし実行結果も問題ないのですが、この人配列の数だけループする事を知らないんじゃない?とphpの基礎がわかっている方は思ったでしょうね。

カウンターを回してbreakする必要があるとしたら例えば配列の数が30で上位3件でループを終了したい時ですね…。

他にも…。

php Brackets 変数 シングルクオート

書き間違いがあればエラーになるから文法がわからなくても何とかなる…ではまずいのでコードを調べて無駄な動作を減らし、メモリを消費する変数がループ外に残らないようにunset。

お絵かき掲示板交流サイトのトップページの負荷がこれで軽く?
<?php
$time_start = microtime(true);
(ここに処理が入る)
$time = microtime(true) - $time_start;
echo "{$time} 秒";
?>
書き直し前の速度を計測するのを忘れていました…。
書き直し後に計測してみたところ、0.097969055175781 秒…でした。

POTI-board用テンプレートPINKの動的パレットを修正しました。

動的パレットスクリプトのMatrix関連の不具合を修正しました。

発生していた問題。

お絵かき掲示板 POTI−board 動的パレットスクリプト

モノクロを「現在」で「取得」。

お絵かき掲示板 POTI−board 動的パレットスクリプト

「取得」した書式が正しくないので正しく色が「セット」されない。

お絵かき掲示板 POTI−board 動的パレットスクリプト

書式を修正して「セット」すれば正しく色が入るが「あいうえお」というパレット名が「あいうえ」になる。
14番目のパレットの色が正しくセットされない。

POTI-boardの動的パレットスクリプトはテンプレートに組み込まれているので、修正されたテンプレートに入れ替えればこれらの不具合は解消します。

POTI-board用テンプレート PINKは、lot.190516で対応しました。

お絵かき掲示板交流サイトの動的パレットの不具合も解消していますのでMatrix機能をぜひ使ってみてください。
パレットをインポートしたり、エクスポートしたりする事ができる便利な機能です。

さくらのレンタルサーバのOSのバージョンアップでphpの動作が変わった

サーバのOSのバージョンがあがっただけなのにお絵かき掲示板交流サイトの掲示板の並び方が変わってしまいました。
phpのバージョンは7.2のままです。
XAMPPでは意図通りの動作をするし、さくらのレンタルサーバでも昨日まで問題ありませんでした。
メンテナンスの内容。
FreeBSDのアップデートに伴う変更点 (2019/4/9 更新) – さくらのサポート情報

レンタルサーバのOSである「FreeBSD」のバージョンを9.x系から11.x系へ変更します。
問題が発生したプログラム。
<?php
$arr = array();
foreach(glob('cgi/{foo,bar,baz}/index.html', GLOB_BRACE) as $filename) {
$arr[$filename] = $filename;
}
$i = 1;
foreach($arr as $key => $value){
var_dump($key);
if($i >= 3){break;}
$i++;
}
?>
これまでは、
string(18) "cgi/foo/index.html" string(18) "cgi/bar/index.html" string(18) "cgi/baz/index.html"
foo,bar,baz だったのに、

string(18) "cgi/bar/index.html" string(18) "cgi/baz/index.html" string(18) "cgi/foo/index.html"
bar,baz,foo の順になってしまいました。
foreach(glob('cgi/{foo,bar,baz}/index.html', GLOB_BRACE) as $filename) {
$arr[$filename] = $filename;
}
このコードでは期待通りに並ばないので書き直す事にしました。
<?php
$arr = array('cgi/foo/index.html', 'cgi/bar/index.html', 'cgi/baz/index.html');
for($i = 0; $i <= 2; $i++){
$filename = $arr[$i];
var_dump($filename);
}
?>
XAMPPでも、さくらのレンタルサーバでも、
string(18) "cgi/foo/index.html" string(18) "cgi/bar/index.html" string(18) "cgi/baz/index.html"
が返ってくるようになりました。

POTI-board改のメンテナンスに参加した経験が無かったら書き直せなかったかも…。

お絵かき掲示板 ネコ娘 paintBBS NEO
お絵かき掲示板はこちら。

POTI-boardのエラーを減らすために 1のログの書式の見直し

POTI-board改のエラーを根絶できた…と思っていたのですが…。

POTI-board 1のログの書式の見直し

続きから描く時に番号を1にするとWarningが出ました。
if(file_exists(IMG_DIR.$ctim.$cext)){//画像が無い時は処理しない
$dat['picfile'] = IMG_DIR.$ctim.$cext;
$size = getimagesize($dat['picfile']);
中略
}
file_exists()で、画像が無い時は処理しないようにした筈…。
var_dump(IMG_DIR.$ctim.$cext); //string(4) "src/"
あるのはディレクトリだけのようです…。
var_dump(file_exists(IMG_DIR.$ctim.$cext)); //bool(true)
画像が無い時はfalseの筈…。
PHP: file_exists - Manual

file_exists − ファイルまたはディレクトリが存在するかどうか調べる
src/というディレクトリが存在しているかどうか調べていた…ようです。

パターンを変えてみると…。

POTI-board 1のログの書式の見直し
string(17) "src/1547552231446" bool(false)
falseになりました。
src/1547552231446というファイルは存在しないので…。

自動生成される1のログにタイムスタンプが入っていないので、ディレクトリがあるかどうかのチェックになり、ディレクトリがあるので画像がなくてもtrueになって処理続行。ディレクトリは画像ではないのでWarningがでる…。
POTI-boardのエラーを減らすためにE_NOTICE削減編: STP^3

設置時にできる[1]を編集すると、その後の書き込みでWarningが発生するので修正しました。
//文字列を整数に
$ltime = (int)$ltime;
(int)をつければエラーはでなくなるかもしれませんが、こちらも1のログにタイムスタンプが入っていない事が原因で発生していたWarningなので、この作業の時に1のログの書式を修正していれば良かったのですが…。
$time = time();
$tim = $time.substr(microtime(),2,3);
$testmes="1,".$now.",".DEF_NAME.",,".DEF_SUB.",".DEF_COM.",,,,,,,".$tim.",,,\n";
他のログ番号と同じ形式のタイムスタンプが1のログに入るように書き換えました。
(int)で整数にしなくても、Warningが発生しない事を確認しました。
続きから描くの番号を1にしてもWarningが発生しない事を確認しました。

この変更は、POTI-board改 v1.51.1 に反映されました。

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

extract()の使用を全廃

poti-boardというPHPスクリプトをサイトに設置したいのですが、設置手順通... - Yahoo!知恵袋

このスクリプトはPHP5であるにも関わらず extract($_POST); extract($_GET); extract($_COOKIE); と、register_globals同等のことを自らやっているので、相変わらず脆弱性はあります。
extract($_POST); extract($_GET); extract($_COOKIE);による変数の取得をやめて、個別に変数を取得するようにしました。
POTI-board改 v1.50.0で対応ずみです。

残るはextract($_SERVER);でしたが…。
var_dump(count($_SERVER));で確認すると存在している配列の数47…。

変数として使っていれば配列のキーが変数名になっているはずなので1個ずつgrepで確認。
extract()を使っているのに、POSTかどうか調べているだけでした。
$REQUEST_METHOD = ( isset($_SERVER["REQUEST_METHOD"]) === true ) ? ($_SERVER["REQUEST_METHOD"]): "";
に書き直しました。

外部から取得する変数の取得方法を三項演算子に統一。
変数が未定義なら空文字列になるようになりました。
POTI-boardのエラーを減らすために $mode編: STP^3

//未定義エラー対策
if (isset($mode)){
switch($mode){
と書けば未定義エラーはでなくなると書きましたが…。
$modeが未定義にならなくなったので、isset()で確認する必要がなくなりました。
かなりの数のisset()を削減する事ができました。

この変更はPOTI-board改 v1.51.0に反映されました。

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

php7.3のcompact()のエラーを修正

Notice、Warning、Deprecatedのエラーを少しずつ減らし…、ついにエラーのでないPOTI-boardができた…と思ったら、php7.3でcompact()のエラーがでてしまいました。

compact()に未定義変数が入るとNoticeが発生…。

compact()の手前でisset()で判定して空文字列にすればエラーはでなくなりますが、isset()だらけになるので、変数取得時のif文を見直す事に…。
if(USE_ANIME){
if(file_exists(PCH_DIR.$time.'.pch')){
$pch = $time.$ext;
}
elseif(file_exists(PCH_DIR.$time.'.spch')){
$pch = $time.$ext.'&amp;shi=1';
}
else{
$pch="";
}
}
else{
$pch="";
}
もしアニメを保存しない設定の時は、$pchを空文字列に。.pchファイルがなくて.spchファイルも無い時は、$pchを空文字列に。

値が入らない時は空文字列になるので、compact()に未定義変数が入るのを回避できます。
if文とelseを組み合わせれば未定義変数を減らす事ができるという基本的な事がやっとわかりました。

この変更はPOTI-board改 v1.50.6に反映されました。

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

POTI-boardのエラーを減らすために 1のログファイルの書式編

POTI-boardの設置時にできる1のログファイルのコンマ数不足がが原因でNoticeが発生していたので…。
$testmes="1,".$now.",".DEF_NAME.",,".DEF_SUB.",".DEF_COM.",,,,,,,,,,\n";
コンマを8つ付け足しました。

お絵かき掲示板 POTI-board Notice削減

これだけでていたNoticeが…。

お絵かき掲示板 POTI-board Notice削減

でなくなりました。

記事を削除するとNoticeがでるので…。
for($i = 0; $i < $countline; $i++){
if($line[$i]){
list($no,,,,,,,$dhost,$pass,$ext,,,$tim,,) = explode(",",$line[$i]);

}
else{
$no=$dhost=$pass=$ext=$tim="";
}
$line[$i]が空文字の時には処理しないようにしました。

お絵かき掲示板 POTI-board Notice削減

記事を削除した時に発生していたNoticeが…。

お絵かき掲示板 POTI-board Notice削減

でなくなりました。

この変更はPOTI-board改 v1.50.5 lot.190101に反映されました。

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

formの入れ子を回避する

<input>: 入力欄 (フォーム入力) 要素 | MDN

form 属性によって、入力欄を文書内のどこに置いても、文書内の他の場所にあるフォームと関連付けることができます。
formの入れ子になりそうなところは、早めにformのタグを閉じてformにidをつけて、inputにformのidを入れてやれば…。
<form id="foo" action="hoge" method="POST">
中略
</form>
<!--formのタグを閉じる-->
<!--別のformここから-->
<form action="fuga" method="POST">
中略
</form>
<!--別のformここまで-->
<!--最初のformのinput-->
<input form="foo" type="text">

id fooのformのinput。
ただしIE11では動作しないようです。

POTI-board改のテンプレート、POTI-board用テンプレート PINKの管理画面のセキュリティ対策のため、GETで管理者パスワードを取得していたテキストリンクをjavaScriptでPOSTに書き換えて、formの入れ子回避のためformにidを付けたのですが…。

やはりIE非対応…。
管理者が記事を削除するときに、Chrome・Firefox・Edgeを使えばすむ事なので、セキュリティリスクの回避を優先しました。

ブラウザのアドレスバーに管理者パスワードが表示されている状態で、著作表示のurlをクリックしたら…。
アクセスログに管理者パスワードが入ったurlが残るかもしれません。

noreferrerタグをいれてあるので、Chromeなら大丈夫かもしれないのですが…。IEはどうだったか…。
POTI-boardに限った問題ではなくて、relmにも同じ問題がありました。

テンプレートで対応できるのであれば、フタをしておいたほうがいいのでIE非対応でも…。

ゲストが投稿を編集・削除するときに使うメンテナンスフォームはIEでも問題なく動作するので、管理者が管理画面を操作する時にChrome・Firefox・Edgeを使えばすむことです。

formの入れ子を回避する

変更前のformタグの範囲。

formの入れ子を回避する

その中にjavaScriptを使ったform。

formの入れ子を回避する

formの入れ子になってしまうので、早めにformのタグを閉じて、idを付ける。

formの入れ子を回避する

inputにform属性を指定してformタグの範囲外から入力。
POTI-board用テンプレート PINK を配布します。: STP^3

セキュリティ対策済みのPOTI-board用テンプレート。

NEOを使うのチェックを外すとしぃペインター標準版が起動するテンプレートの配布も開始しましたので、よろしくお願いいたします。