独学!Webサイト構築日誌

37日目:布団の中で覚醒。

8:00

おはようございます!
昨晩布団に入ってからもモンモンと考えて、もう少しでデジモンになるところでしたが、その前に良いことを思いつきました。



画像の数字をそのまま取って来たら良いだけじゃね?...と。



ただ、そのまま取ってくるとなると正規表現やら使ってややこしくなるので、hidden使って値取って来ちゃいましょう。



あ、目標は故知覧。
  1. 画像認証を含めたお問い合わせフォームの完成。
  2. OS コマンドインジェクション対策をする。
  3. グローバル変数乱用状態なので、functionでまとめる。

1.画像認証を含めたお問い合わせフォームの完成。

10:00

出来たぞコラァアアアアアアアアアアアアアアアア!

            
html ※htmlは変更無いですが、念のため載せておきます。
<?php $textTitle = "お問い合わせフォーム"; $title = $textTitle. " | 独学!Webサイト構築日誌"; ?>
<?php include("../php/header.php"); ?>
<div class="middle-body">
    <div id="main">
        <h1>お問い合わせフォーム</h1>
        <br>
        <form id="contactForm" action="../php/contact.php" method="post">
            <label class="messageInfo">氏名</label>
            <input class="messageInput" id="mName" type="text" name="mName" placeholder="気楽 太郎" onchange="reCheck()"><br>
            <br>
            <label class="messageInfo">メールアドレス</label>
            <input class="messageInput" id="mMail" type="email" name="mMail" placeholder="abc@xxx.yy.zzz" onchange="reCheck()"><br>
            <br>
            <label class="messageInfo">メッセージ本文</label>
            <textarea  class="messageText" id="mComment" name="mComment" placeholder="ここにメッセージを1000字以内で記載してください。" onchange="reCheck()"></textarea><br>
            <br>
            <label class="messageInfo">認証確認文字</label>
            <?php include("../php/hiraganaCheck.php"); ?><input id="mHiragana" type="text" name="mHiragana" placeholder="ひらがなで入力" onchange="reCheck()"><br>
            <br>
            <div class="checkArea">
                ※「<a href="/other/privacy-policy.html">プライバシーポリシー, 免責事項</a>」をお読みいただき、予め同意の上、お問い合わせください。<br>
                <input id="mPrivacy" type="checkbox" name="mPrivacy" onclick="privacyCheck()">
                <label>個人情報の取り扱いについてに同意する。</label><br>
            </div>
            <br>
            <div class="btnArea">
                <input class="messageBtn" id="mCheck" type="button" value="入力内容確認" onclick="inputCheck()" disabled>
                <input class="messageBtn" id="mSend" type="submit" value="送信する" disabled>
            </div>
        </form>
    </div>
    <script src="../js/contact.js"></script>
</div>
<?php include("../php/footer.php"); ?>
            
        

            
php ※hiraganaCheck.php全文
<?php
    $im = imagecreatefromjpeg('../◆保存先/passBase.jpg');//ベース画像設定
    $textColor= imagecolorallocate( $im, 0, 0, 0);
    $font = '../◆保存先/HGRSMP.TTF';
    $textR = '../◆保存先/pass.txt';
    $fileP = '../◆保存先/pass';
    $textHiragana='あいうえおかがきぎくぐけげこごさざしじすずせぜそぞただちぢつづてでとどなにぬねのはばぱひびぴふぶぷへべぺほぼぽまみむめもやゆよらりるれろわをん';
    $textP = '';
    $passT = '';
    for($i=0; $i<5; $i++){ //5文字入れる
        $textP = mb_substr($textHiragana, mt_rand(0, mb_strlen($textHiragana) - 1), 1,"UTF-8");
        $kakudo = mt_rand(-15, 15);
        imagettftext($im, 25, $kakudo, 25+(40*$i), 35, $textColor, $font, $textP);//画像に文字書き込む
        $passT = $passT. $textP;
    }
    
    for($mugen=0;$mugen<10000;$mugen++){
        $filename = $fileP. $mugen. '.jpg';
        if($mugen==9999) {//最大値まで行ったら
            unlink($filename);//.jpg削除
            $filename = $fileP. '0.jpg';//ファイル名初期化
            imagejpeg($im, $filename);
            echo '<img class="passT" src="'. $filename. '" alt="check"><input name="passNum" type="hidden" value="0">';

            unlink($textR);//.txt削除
            file_put_contents($textR, $passT. "\n", FILE_APPEND | LOCK_EX); //判定用
            break;
        } else if (file_exists($filename)) {//見つかるまで回す
            unlink($filename);
            $filename = $fileP. ($mugen+1). '.jpg';//ファイル名更新
            imagejpeg($im, $filename);
            echo '<img class="passT" src="'. $filename. '" alt="check"><input name="passNum" type="hidden" value="'. ($mugen+1). '">';
            
            file_put_contents($textR, $passT. "\n", FILE_APPEND | LOCK_EX); //判定用
            break;
        }
    }
    imagedestroy( $im ); // 後始末
?>
            
        

            
php ※contact.php全文
<?php
    $mName = htmlspecialchars($_POST['mName'],ENT_QUOTES);
    $mMail = htmlspecialchars($_POST['mMail'],ENT_QUOTES);
    $mComment = htmlspecialchars($_POST['mComment'],ENT_QUOTES);
    $mPrivacy = htmlspecialchars($_POST['mPrivacy'],ENT_QUOTES);
    $mHiragana = htmlspecialchars($_POST['mHiragana'],ENT_QUOTES);
    $mPass = htmlspecialchars($_POST['passNum'],ENT_QUOTES);
    $failureTime = htmlspecialchars(file_get_contents('../◆保存先/failureTime.txt'),ENT_QUOTES);
    $newip = ip2long($_SERVER['REMOTE_ADDR']);
    $failureIP = htmlspecialchars(file_get_contents('../◆保存先/ipAdress.txt'),ENT_QUOTES);
    $passT = file('../◆保存先/pass.txt'); //配列に格納。
    $passT[$mPass] = trim($passT[$mPass]);//空白削除。これ無いと文字列不一致でエラー吐く

    $error = '';
    if ($mName == '') {
        $error = '氏名が入力されていません。';
    }else if ($mMail == '') {
        $error = 'メールアドレスが入力されていません。';
    }else if ($mComment == '') {
        $error = 'メッセージ本文が入力されていません。';
    }else if ($mPrivacy == '') {
        $error = '個人情報の取り扱いについて、同意されていません。';
    }else if ($mHiragana != $passT[$mPass]) {
        $error = '認証文字が違います。';
    }

    if($newip == $failureIP){//IPアドレスと時間チェック
        if(time()-$failureTime < 30){
            file_put_contents('../◆保存先/ipAdress.txt', $newip, LOCK_EX); //判定用
            file_put_contents('../◆保存先/failureTime.txt', time(), LOCK_EX); //判定用
            $error = '現在送信機能を制限させていただいております。\n時間を置いて再度お試しください。';
            echo '<script> alert("'. htmlspecialchars($error,ENT_QUOTES). '"); location.href="https://ki-luck.info/"; </script>';
        }else{
            goto mainMove;
        }
    }

    mainMove:
    if ($error != '') {
        file_put_contents('../◆保存先/ipAdress.txt', $newip, LOCK_EX); //判定用
        file_put_contents('../◆保存先/failureTime.txt', time(), LOCK_EX); //判定用
        $error = $error. '\nお手数をおかけしますが、最初から入力してください。';
        echo '<script> alert("'. htmlspecialchars($error,ENT_QUOTES). '"); location.href="https://ki-luck.info/other/contact.html"; </script>';
    } else {
        $mailBody .= "以下の内容が送信されました。\n\n";
        $mailBody .= "【氏名】\n";
        $mailBody .= $mName."\n\n";
        $mailBody .= "【メールアドレス】\n";
        $mailBody .= $mMail."\n\n";
        $mailBody .= "【メッセージ本文】\n";
        $mailBody .= $mComment."\n\n";
        
        //日本語設定を行う
        mb_language("Japanese");
        mb_internal_encoding("UTF-8");
    
        $mailTo = "◆◆◆"; //送信先メールアドレス
        $mailSubject = "◆◆◆ より送信されました"; //メールの件名
        $mailHeader = "from:".$mMail; //フォームで入力されたメールアドレスを送信元として表示する
        
        $mailsend = mb_send_mail($mailTo, $mailSubject, $mailBody, $mailHeader);
        
        if($mailsend == true) {
            echo '<script> alert("お問い合わせを受け付けました。"); location.href="https://ki-luck.info/"; </script>';
        } else {
            echo '<script> alert("エラーが発生しました。"); location.href="https://ki-luck.info/"; </script>';
        }
    }
?>
            
        




2.OS コマンドインジェクション対策をする。

ココを参考にやっていきましょう。
既にhtmlspecialcharsを使って簡易的な対策をしているので、それに追加する形で実装していく。

12:00

正規表現が難しくてやる気ブレイクされそうなので、先にお昼食べます。



15:00

3つほどサイトを読んで分かったこと。
・正規表現 = 様々な文字列を一つの文字列で表現する表記法。
・未確定の文字列を判別するのに便利。
・特定の範囲(例:A B C)を部分的(例:A' B C')に変更することが出来る。

今回の場合、変換元の文字列は変数ですが、置き換える文字は固定で少数なので、strtr()使ってやっていきます。
参考サイトはココ公式



ん~...正規表現使えた方がカッコいいな。
ちょっと本を参考に頑張ってみる。

色々試せる素敵サイト見つけた。

試したところ、「;」と「&」を同時に置換指定して「☆」に置き換えるとすると、下記のように変わりました。
上記から、htmlspecialcharsが自動的にかかるような挙動になると思われる。

また、
1. 上記状態で置換指定文字に「"」「<」「>」を追加しても置換結果変わらず。
2. 「"」「<」「>」の3つだけで置換指定しても置換されず。
3. 「'」だけを置換指定すると変な挙動になった。



20:00

夕飯食って、燻製も仕込んできた。(ついでに)変換も出来た。
            
php
function h($s) {
    $s = htmlspecialchars($s, ENT_QUOTES);
    $s = preg_replace('![|;&`()$"<>*{}]!','☆', $s);
    return $s;
}
            
        



21:00

謎のエラーが続出するなぁと思っていたら、別ファイル内の関数であっても、関数名が重なっているとエラーを吐くようです。
この日誌で言うと、「header.php」「forDiary.php」「footer.php」の3ファイルを呼び出しているので、どこか1つのファイル内で「function h($s) 」を宣言すると、他の所にも反映される(グローバル化される?)ので、他のファイル内での再宣言は不要、てことですね。
「header.php」「footer.php」のどちらか片方と、完全に独立している「contact.php」で宣言しておけばOKです。

3.phpファイルをfunctionでまとめる。

現在ほぼすべてのphpファイルがベタ打ち状態なので、function でまとめていきます。
何が問題かと言うと、どこからでもグローバル変数を呼び出せる状態になっており、何かの拍子に変数書き換えたりすると予期せぬエラーが起こる可能性がある。のと、なんとなく攻撃されやすい気がする。

数が多いので省略しますが、全体的に下記のようにします。
            
--- 変更前 ---
betauchi = genzai;

--- 変更後(変数無し) ---
function kansu(){ //関数宣言
    betauchi = genzai;
}
kansu(); //コレで呼び出し

--- 変更後(変数有り) ---
function kansu($hensu){ //変数が入る
    betauchi = genzai;
}
kansu($hensu);
            
        

21:30

完了。

今日はこれで終了して、明日phpのエラー表示の再調整。
それが終わったらSEOを再検討して終了かな!

1冊本読んだら寝るぞー。




作成日:2021/01/18 - 更新日:2021/01/26

≪ 36日目≪ 一覧に戻る ≫38日目 ≫

HOME > 日誌一覧 > 37日目:布団の中で覚醒。