Engineering

AWSでロードバランサー(ELB)を使っている環境で「.htaccess」を使って一時的に「メンテナンス中」表示をするが、特定IPアドレスを除外したい(特定IPアドレスからは普通に見えるようにしたい)、というお話。
...
RewriteCond %{REMOTE_ADDR} !=192.168.0.123
...

としても効かない。
なぜ?と思って環境変数を調べると…うん。$_SERVER['REMOTE_ADDR']に自分のIPアドレスは入らない。
探してみると$_SERVER['HTTP_X_FORWARDED_FOR']の中に入っている。
じゃあ、と思って先の.htaccessを書き換えたがやっぱり効かない。
教えてグーグル先生!
…見つかった。
php:$_SERVER[“REMOTE_ADDR”]

.htaccess:RewriteCond %{REMOTE_ADDR} !^××.××.××.××

ELBの場合

PHP:$_SERVER[“HTTP_X_FORWARDED_FOR”]

.htaccess:RewriteCond %{HTTP:X-Forwarded-For} !^××.××.××.××

ありがとうryoさん。コメント機能がなかったのでここでお礼を言わせていただきます。
環境変数名が違ったんだね…。
サーバでは「HTTP:X-Forwarded-For」だったのが、PHPでは「HTTP_X_FORWARDED_FOR」に変換されちゃってたんだー、そういうものなのか知らなかったなー。
summernote でも画像挿入時とかに modal を使っている。
つまり modal 内で summernote を使うと画像挿入時とかに modal の入れ子が発生することになる。

bootstrap modal って、意外と入れ子のことは考えられていないようで、皆さん苦労されているようです。そもそも入れ子にすべきじゃないってことなの?

というわけで、公式な対応ではなく無理矢理ここだけ対応、ということになる。
ニッチ対応とでも言うのか…こんなことに命名するのも馬鹿げているが。
まあなんとなくカッコいいほうが良いよねー、的な。
ニッチやなくてリッチになりたいでほんま。

さて、愚痴を吐いて少しスッキリしたところで本題。

summernote で画像挿入した場合、挿入した時に画像選択用モーダルが閉じる。
その閉じた際にbodyタグが操作されて親モーダルも閉じた状態になってしまう。
具体的には'modal-open'クラスが無くなって、style属性も変更される。
そこでそれを元に戻そう、というのが下記コード。
    var body_style;
$('#parent-modal').on('show.bs.modal', function (e) {
if (e.target.id !== 'parent-modal') {
body_style = $('body').attr('style');
return;
}
// 親モーダル用処理
}).on('hidden.bs.modal', function (e) {
if (e.target.id !== 'parent-modal') {
if (body_style) $('body').attr('style', body_style).addClass('modal-open');
body_style = null;
return;
}
// 親モーダル用処理
});

子モーダルが開く時に親モーダルの「show」イベントも発火する。
まあそれはそれで不具合の元なのだが…今回はそれを利用して、、
子モーダルが開いた(と思わしき)時にbodyタグのstyle属性値を保存しておいて、子モーダルが閉じた(と思わしき)時に保存しておいたモノを戻す。そして'modal-open'クラスも付与。
ということをしてまーす。

そうそう。画像選択用モーダルのバツボタンを押して閉じた時、親モーダルまで閉じてしまうことにはワタクシメは気づいておりませんので。
もし気づいた方がいらっしゃったらご対応くださいませ\(^o^)/
echo date('Y/m/d', strtotime('2000/0/0')); // 1999/11/30

「ゼロ月」は1月の前の月だから、前年の12月。
「ゼロ日」は1日の前の日だから、前月の末日。
つまり「ゼロ月ゼロ日」は前年の12月の前月の末日。つまり前年の11月の末日。
よって2000年0月0日は1999年11月30日となる。

ちなみに、下記のように0年0月0日としても同じ1999年11月30日が出力される。
echo date('Y/m/d', strtotime('0/0/0')); // 1999/11/30

これは、「0年」は年の短い表現と解釈されて2000年となるため。
…と思ったけど違うかも。

echo date('Y/m/d', strtotime('1/0/0')); // 1999/12/31

echo date('Y/m/d', strtotime('2/0/0')); // 2000/01/31

あー、mm/dd/yy形式と判定されるのねー。
「1/0/0」 → 「01/00/2000」 → 2000年1月0日 → 1999年12月31日
「2/0/0」 → 「02/00/2000」 → 2000年2月0日 → 2000年1月31日
「mysql concat null」でググると、
引数にNULLが含まれると返り値はNULLになる
という至極当たり前のことをさも大発見かのように語る記事が多く、「どうしたらいいか」について触れられていないものばかりを開いてしまった。
おそらくワタクシメのヒキが悪かったせいで、ちゃんと対処法も書いてある記事もあったに違いない。
まーでも対処法を書いた記事が多くなったほうが良いであろうと考え、本記事を執筆することにした。

なんて偉そうなことを言っているんでしょうか私は…。
『CONCAT_WSも知らないくせに』とか思われるのかな。
ま、いっか。

しかし、掲題に結論を書いてしまったので、もう書くこと無いね。
まあ一応結果でも書きますか。
SELECT CONCAT('hoge', null, 'fuga');
 ↓
NULL
SELECT CONCAT_WS('', 'hoge', null, 'fuga');
 ↓
hogefuga

CONCAT_WS() では、空の文字列がスキップされません。 ただし、区切り文字引数のあとの NULL 値はすべてスキップされます。

今回のように区切り文字を空文字にしていると同じになるけど、区切り文字を指定した場合に違いが出る。
SELECT CONCAT_WS('&', 'hoge', '', 'fuga', 'CHAKE', null, 'YASUKA');
 ↓
hoge&&fuga&CHAKE&YASUKA

引数のhogeとfugaの間に空文字が入っているのに対し、CHAKEとYASUKAの間にはnullが入っています。
すると返り値では、hogeとfugaの間には「&&」と&が2つ重なってしまっています。
対してCHAKEとYASUKAの間は&が1つで「CHAKE&YASUKA」となっていますね。

eval関数を使います。
いや多分、掲題のようなことをしたくて探している人にとっては「そんなの知っとるわい!」なんでしょうけど、違うんです、、、多分。
多分私と同じであれば、PHPタグ外の文字列も含めて出力したい。
イメージ的には、文字列を一度PHPファイルに出力して、それを実行する、という感じです。
そんな話なんです。違ったらすみません。

答えは↓です。
eval('?>' . $str);

これで、例えば$strの中身が
1 + 1 = <?php echo 1 + 1; ?>

だったとすると、出力は
1 + 1 = 2

となります。

こんなことできるんですね。全く盲点でした。
なぜできるのかを考えると、おそらく、evalに渡す文字列はPHPタグに囲まれているものと想定されているため、こんな感じで処理されるのでしょう。
'<?php' + evalに渡された文字列 + '?>'

上の例で言うと、
<?php?>1 + 1 = <?php echo 1 + 1; ?>?>

なにかに似ていると思ったら、SQLインジェクションだね。。

これ、たまたま見つけたんだけど、あまり知られてないよね?
もしかして、広めないほうがいいってやつ?

あれ、こんな夜中に誰か来