雑談掲示板を作成しているのですが、入力画面と表示画面の2ファイル構成だと作成できたのですが、確認画面を追加する場合のアップロード画像の扱い方が分かりません。

goo質問のように名前、メッセージ、スタンプ、アップロード画像の入力ページで入力したものを確認ページで表示させて、修正する送信するボタンの2つから送信ボタンを押したときにのみデータベースに名前、メッセージをレンタルサーバーに画像動画をレンタルサーバーのディレクトリに保存するようにしたいです。

参考サイトを見ると、入力画面でアップロードされたものを保持して、確認画面の送信で保存する作りになっているのですが、アップロードファイルが安全かどうか確認する必要もあるため訳が分からない状態です。  
どのような作りになるのかアドバイスお願い致します。

※参考サイト  
※確認画面で画像を保存  
<https://qiita.com/ryouya3948/items/66294cb445663f2a9d95>

<https://nw.myds.me/wprdpress-ad/contact_us/>

※switch(true){}について  
<https://okwave.jp/qa/q3902353.html>

※雑談掲示板のファイル構成  
core.php (index.phpの役割 ファイルの統括)  
enter-information.php (入力フォーム)  
identify.php (確認画面)  
finish.php (送信完了)  
rerification.php (文字列チェック)  
channel-chat.php (データ削除)

**enter information.php**

```

    <?php
    /*
    雑談掲示板 入力画面
    Template Name: enter-informtion
    */
    //セッションを開始して、setToken() でトークンを生成
    session_start();
    
    // スタンプ
    $stamps = [];
    $stamps[0] = 'http://www.irasuto.cfbx.jp/wp-content/uploads/2022/10/FIGURE-146070.jpg';
    $stamps[1] = 'http://www.irasuto.cfbx.jp/wp-content/uploads/2022/10/FIGURE-146281.jpg';
    $stamps[2] = 'http://www.irasuto.cfbx.jp/wp-content/uploads/2022/10/FIGURE-146282.jpg';
    $stamps[3] = 'http://www.irasuto.cfbx.jp/wp-content/uploads/2022/10/9416845000734.jpg';
    $stamps[4] = 'http://www.irasuto.cfbx.jp/wp-content/uploads/2022/10/bd3713656360f94acb07764cbb2b05a90006a26d160f9f9241f14fff7417fc51_01.jpg';
    $stamps[5] = 'http://www.irasuto.cfbx.jp/wp-content/uploads/2022/09/FIGURE-145522.jpg';
    
    // エラーメッセージと不正アクセスフラグ
    $error_mes = '';
    $noindexaccess = true;
    if (!empty($_POST)) {
        require_once 'rerification.php';
        if (empty($error_mes)) {
            require_once 'finish.php';
            exit;
        }
    }
    // トークン生成
    setToken();
    
    // 他のサイトでインラインフレーム表示を禁止する（クリックジャッキング対策）
    header('X-FRAME-OPTIONS: SAMEORIGIN');  
    
    // 不正アクセスチェック
    if(!$noindexaccess || isBot()){
        header('HTTP/1.0 404 Not Found');
        exit;
    }
    
    get_header();
    
    echo '<div style="color:red;">';
    // エラーメッセージがあったら表示する
    echo ($error_mes) ? '
    ---------------------<br />
    　入力エラーです<br />
    ---------------------<br />'.$error_mes : '';
    echo '</div>';
    ?>
      <script>
      //2重送信防止スクリプト
      var flg_Submit = false;
    
      function Fnk_DoubleSubmit() {
        if (flg_Submit) {
          alert("処理中です。");
          return false;
        } else {
          flg_Submit = true;
          return true;
             }
          }
      <script>
    <style>
      .selected {
        border: 3px solid red;
         }
    </style>
    
    <?php
    $namae_value = isset($namae) ? htmlspecialchars($namae, ENT_QUOTES) : '';
    $message_value = isset($message) ? htmlspecialchars($message, ENT_QUOTES) : '';
    
    // 送信時のデータ形式を指定する
    echo '<form name="toiawase" method="post" enctype="multipart/form-data" action="'.esc_url(home_url('/informtion/')).'">';
    // accept属性、受け付けるファイルの拡張子や種類を指定
    echo '<div>';
    echo '<label>';
    // <!-- ▽見せる部分 -->
    echo '<span class="filelabel" title="ファイルを選択">';
    echo '<img src="camera-orange-rev.png" width="32" height="26" alt="＋画像">';
    echo '<img src="camera-orange-rev.png" width="32" height="26" alt="＋画像">';
    echo '</span>';
    // <!-- ▽本来の選択フォームは隠す -->
    echo '<input type="hidden" name="MAX_FILE_SIZE" value="15725640">';
    echo '<input type="hidden" name="token" value="'.getToken().'">';
    echo '<input type="file" name="attachment_file_1" id="my_image" accept=".png, .jpg, .jpeg, .pdf, .doc">';
    echo '<input type="file" name="attachment_file_2" id="my_image" accept=".png, .jpg, .jpeg, .pdf, .doc">';
    echo '</label>';
    echo '</div>';
    
    echo '<div>';
    echo '<label>お名前</label><span>※</span><br />';
    echo '<input type="text" name="namae" size="40" maxlength="60" value="'.$namae_value.'" required />';
    echo '<label>お問い合わせ内容</label><span>※</span><br />';
    echo '<textarea name="message" cols="40" rows="10" required>'.$message_value.'</textarea>';
    echo '</div>';
    foreach ($stamps as $stamp_path) {
        echo '<img class="selimg" src="'.$stamp_path.'">';
    }
    echo '<div class="g-recaptcha" data-sitekey="6LfCq78kAAAAAGi9QvXn9UnYFxTZqCE3_nxeZV41" data-callback="myAlert">';
    echo '</div>';
    echo '<div>';
    echo '<input type="submit" value="送信する" id="send" disabled>';
    echo '</div>';
    echo '<input type="hidden" name="stamp" id="select" value="enter information">';
    echo '</form>';
    ?>
    <script>
      //jQuery版
      const sizeLimit = 1024 * 1024 * 1; // 制限サイズ
      const fileInput = document.getElementById('my_image'); //  id プロパティが一致するElement オブジェクトを返す
      // changeイベントで呼び出す関数
      const handleFileSelect = () => {
        const files = fileInput.files;
        for (let i = 0; i < files.length; i++) {
          if (files[i].size > sizeLimit) {
            // ファイルサイズが制限以上
            alert('ファイルサイズは1MB以下にしてください'); // エラーメッセージを表示
            fileInput.value = ''; // inputの中身をリセット
            return; // この時点で処理を終了する
                  }
       }
      }
      // フィールドの値が変更された時（≒ファイル選択時）に、handleFileSelectを発火
      fileInput.addEventListener('change', handleFileSelect);
    <script>
    <script>
      const select = document.querySelector('#select');
      const selimg = document.querySelectorAll('.selimg');
      selimg[select.value].classList.toggle('selected');
      for (let i = 0; i < selimg.length; i++) {
        selimg[i].addEventListener('click', function() {
          // 選択状態を移動
          selimg[select.value].classList.toggle('selected');
          select.value = i;
          selimg[select.value].classList.toggle('selected');
          });
      }
    <script>
    <script>
      //.g-recaptcha タグの data-callback 属性で指定したコールバック関数の定義
      var myAlert = function(response) {
        alert("チェックボックスがチェックされました！");
        document.getElementById("send").disabled = false;
      };
    <script>
    <script src="https://www.google.com/recaptcha/api.js" async defer><script>
    <!-- API の読み込み -->
    
```

**rerification.php**

```

    <?php
    /*
    雑談掲示板 文字列チェック
    */
    
    // 他のサイトでインラインフレーム表示を禁止する（クリックジャッキング対策）
    header('X-FRAME-OPTIONS: SAMEORIGIN');
    
    // 不正アクセスチェック
    if (!$noindexaccess) {
        header('HTTP/1.0 404 Not Found');
        exit;
    }
    
    // トークン確認
    $token = getToken();
    if ($_POST['token'] !== $token) {
        header('HTTP/1.0 404 Not Found');
        exit;
    }
    
    /* 危険文字列置換ファンクション */
    function Chk_StrMode($str)
    {
    
        // タグを除去
        $str = strip_tags($str);
        // 空白を除去
        $str = mb_ereg_replace('^(　){0,}', '', $str);
        $str = mb_ereg_replace('(　){0,}$', '', $str);
        $str = trim($str);
        // 特殊文字を HTML エンティティに変換する
        $str = htmlspecialchars($str);
    
        return $str;
    }
    /* 未入力チェックファンクション */
    function Chk_InputMode($str, $mes)
    {
        $errmes = '';
        if ('' == $str) {
            $errmes .= "{$mes}<br>\n";
        }
        return $errmes;
    }
    
    // ----------------------------------------------------------------------------------
    // データの受け取りと危険文字列置換  ※Chk_StrMode(文字列);
    // ----------------------------------------------------------------------------------
    $param = [];
    
    // 引数を元に文字列処理及び変換処理を行う
    foreach ($_POST as $k => $e) {
        $params[$k] = Chk_StrMode($e);
    }
    
    // 変数に入れる
    extract($params);
    $error_mes .= Chk_InputMode($namae, "・お名前をご記入ください。<br />\n");
    $error_mes .= Chk_InputMode($message, "・お問い合わせ内容をご記入ください。<br />\n");
    if (!isset($stamps[$stamp])) {
        $error_mes .= "・スタンプを選択してください。<br />\n<br>\n";
    }
    ?>
    
```

**functions.php**

```

    <?php
    function isBot() {
    $bot_list = array (
    'Googlebot',
    'Yahoo! Slurp',
    'Mediapartners-Google',
    'msnbot',
    'bingbot',
    'MJ12bot',
    'Ezooms',
    'pirst; MSIE 8.0;',
    'Google Web Preview',
    'ia_archiver',
    'Sogou web spider',
    'Googlebot-Mobile',
    'AhrefsBot',
    'YandexBot',
    'Purebot',
    'Baiduspider',
    'UnwindFetchor',
    'TweetmemeBot',
    'MetaURI',
    'PaperLiBot',
    'Showyoubot',
    'JS-Kit',
    'PostRank',
    'Crowsnest',
    'PycURL',
    'bitlybot',
    'Hatena',
    'facebookexternalhit',
    'NINJA bot',
    'YahooCacheSystem',
    'NHN Corp.',
    'Steeler',
    'DoCoMo',
    );
    $is_bot = false;
    foreach ($bot_list as $bot) {
    if (stripos($_SERVER['HTTP_USER_AGENT'], $bot) !== false) {
    $is_bot = true;
    break;
    }
    }
    return $is_bot;
    }
    
    function setToken()
    {
        global $_SESSION;
        if (!isset($_SESSION['csrf_token'])) {
            // bin2hexはphp7.0,openssl_random_pseudo_bytesはphp5.3
            $_SESSION['csrf_token'] = bin2hex(random_bytes(16));
        }
        // スクリプト自体の実行を終了
        return;
    }
    function getToken()
    {
        global $_SESSION;
        $token = null;
        if (isset($_SESSION['csrf_token'])) {
            $token = $_SESSION['csrf_token'];
        }
    
        return $token;
    }
    
```

**channel-chat.php**

```

    <?php
    /*
    雑談掲示板 データ削除
    Template Name: channel-chat
    */
    get_header();
    // アップロードディレクトリ
    $upload_dir = wp_upload_dir();
    $sub_dir = 'informtion-form';
    $dir = $upload_dir['basedir'].'/'.$sub_dir.'/';
    // 削除対象日付
    $delete_date = date('Y-m-d H:i:s', strtotime('-6 days'));
    // 古い雑談掲示板の取得
    $sql = 'SELECT ID FROM sortable WHERE TS < %s';
    $query = $wpdb->prepare($sql, $delete_date);
    $delete_items = $wpdb->get_results($query);
    foreach ($delete_items as $delete_item) {
        // アップロードファイル一覧取得
        $files = glob($dir.$delete_item->ID.'_*');
        // アップロードファイル削除
        foreach ($files as $file) {
            unlink($file);
        }
        // 古い雑談掲示板の削除
        $sql = 'DELETE FROM sortable WHERE ID = %s';
        $query = $wpdb->prepare($sql, $delete_item->ID);
        $wpdb->query($query);
    }
    ?>
    
```

**finish.php**

```

    <?php
    
    // ファイルの拡張子
    const FILE_EXT_PNG = '.png';
    const FILE_EXT_JPEG = '.jpeg';
    const FILE_EXT_PDF = '.pdf';
    const FILE_EXT_MP4 = '.mp4';
    
    // アップロードファイル保存関数
    // 第一引数：ＩＤ
    // 第二引数：連番
    function save_upload_file($id, $i)
    {
        // アップロードファイルコントロール名生成
        $attachment_file = "attachment_file_{$i}";
        // アップロードファイルが指定されているか
        // アップロードに成功しているか
        if (isset($_FILES[$attachment_file]) && is_array($_FILES[$attachment_file]) && UPLOAD_ERR_OK === $_FILES[$attachment_file]['error']) {
            // WordPressアップロードディレクトリ取得
            $upload_dir = wp_upload_dir();
            // サブディレクトリ
            $sub_dir = 'informtion-form';
            // アップロードファイル拡張子
            $ext = strtolower(substr($_FILES[$attachment_file]['name'], strrpos($_FILES[$attachment_file]['name'], '.')));
            // アップロードテンポラリーファイルパス
            $tmp_name = $_FILES[$attachment_file]['tmp_name'];
            // 拡張子とファイルの種類を判定して拡張子を再取得
            $ext = get_file_ext($ext, $tmp_name);
            // アップロードファイルが画像か判定
            switch ($ext) {
                case FILE_EXT_PNG:
                case FILE_EXT_JPEG:
                    // アップロードファイルが画像の場合は原寸とサムネイルを保存
                   // 保存ファイル名（サムネイル）
                    $thumb_filename = "{$id}_{$i}_thumb.png";
                    // 保存ファイル名（オーバレイ）
                    $overlay_filename = "{$id}_{$i}_overlay.png";
                    // 保存ファイルパス（サムネイル）
                    $thumb_path = $upload_dir['basedir'].'/'.$sub_dir.'/'.$thumb_filename;
                    // 保存ファイルパス（オーバレイ）
                    $overlay_path = $upload_dir['basedir'].'/'.$sub_dir.'/'.$overlay_filename;
                    // 元画像の情報を取得
                    $info = getimagesize($tmp_name);
                    // 元画像の読込
                    switch ($info[2]) {
                        case IMAGETYPE_PNG:
                            $base_image = imagecreatefrompng($tmp_name);
                            break;
                        case IMAGETYPE_JPEG:
                            $base_image = imagecreatefromjpeg($tmp_name);
                            break;
                    }
                    // 元画像のサイズ
                    $base_width = $info[0];
                    $base_height = $info[1];
                    // サムネイルサイズ
                    $thumb_width = 200;
                    $thumb_height = 200;
                    // オーバーレイサイズ
                    $overlay_width = 320;
                    $overlay_height = 320;
                    // サムネイル画像を準備
                    $thumb_image = imagecreatetruecolor($thumb_width, $thumb_height);
                    // オーバーレイ画像を準備
                    $overlay_image = imagecreatetruecolor($overlay_width, $overlay_height);
                    // 縮小（サムネイル）
                    imagecopyresized($thumb_image, $base_image, 0, 0, 0, 0, $thumb_width, $thumb_height, $base_width, $base_height);
                    // 縮小（オーバーレイ）
                    imagecopyresized($overlay_image, $base_image, 0, 0, 0, 0, $overlay_width, $overlay_height, $base_width, $base_height);
                    // PNG形式で保存（サムネイル）
                    imagepng($thumb_image, $thumb_path);
                    // PNG形式で保存（オーバレイ）
                    imagepng($overlay_image, $overlay_path);
                    // 元画像を削除
                    unlink($tmp_name);
                    // 保存ファイル参照パス
                    $thumb_url = $upload_dir['baseurl'].'/'.$sub_dir.'/'.$thumb_filename;
                    $overlay_url = $upload_dir['baseurl'].'/'.$sub_dir.'/'.$overlay_filename;
                    // 画像表示
                    echo '<img src="'.$thumb_url.'">';
                    // 画像表示(オーバーレイ)
                    echo '<img src="'.$overlay_url.'">';
                    break;
                case FILE_EXT_PDF:
                case FILE_EXT_MP4:
                    // アップロードファイルが画像以外（PDF,MP4）の場合はそのまま保存
                    // 保存ファイル名
                    $save_filename = "{$id}_{$i}{$ext}";
                    // 保存ファイルパス
                    $save_path = $upload_dir['basedir'].'/'.$sub_dir.'/'.$save_filename;
                    // アップロードファイル（テンポラリー）を保存ファイルパスへ移動
                    if (move_uploaded_file($tmp_name, $save_path)) {
                        // 保存ファイル参照パス
                        $url = $upload_dir['baseurl'].'/'.$sub_dir.'/'.$save_filename;
                        // アップロードファイル表示
                        switch ($ext) {
                            case FILE_EXT_PDF:
                                echo '<iframe src="'.$url.'" width="200"></iframe>';
                                break;
                            case FILE_EXT_MP4:
                                echo '<video controls src="'.$url.'" width="200">';
                                break;
                        }
                    }
                    break;
                default:
                    echo 'エラー';
                    break;
            }
        }
    }
    // 拡張子とファイルの種類を判定して拡張子を再取得
    // 第一引数：拡張子
    // 第二引数：ファイルパス
    function get_file_ext($ext, $path)
    {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $mime_type = finfo_file($finfo, $path);
        if (FILE_EXT_PNG == $ext && 'image/png' == $mime_type) {
        } elseif (in_array($ext, [FILE_EXT_JPEG, '.jpg']) && 'image/jpeg' == $mime_type) {
            $ext = FILE_EXT_JPEG;
        } else {
            // バイナリー文字列確認
            $contents = file_get_contents($path);
            if (FILE_EXT_PDF == $ext && 'application/pdf' == $mime_type && '%PDF-' == substr($contents, 0, 5)) {
            } elseif (FILE_EXT_MP4 == $ext && 'video/mp4' == $mime_type && 'ftyp' == substr($contents, 4, 4)) {
            } else {
                $ext = null;
            }
        }
        return $ext;
    }
    
    // h() 関数の定義
    function h($str)
    {
        return htmlspecialchars($str, ENT_QUOTES, 'UTF-8');
    }
    
    $sql = 'INSERT INTO sortable(message,namae,stamp)   VALUES(%s,%s,%d)';
    $wpdb->query($wpdb->prepare($sql, $message, $namae, $stamp));
    // ループカウンタ$iが1から2までのループ
    for ($i = 1; $i <= 2; ++$i) {
        // アップロードファイル保存関数を呼ぶ
        // 第一引数：保存されたメッセージのＩＤ
        // 第二引数：ループカウンタ
        save_upload_file($wpdb->insert_id, $i);
    }
    // ここから表示(ID)
    echo "ID:{$wpdb->insert_id}";
    // 名前
    echo h($namae);
    // スタンプ
    foreach ($stamps as $stamp_path) {
        echo '<img class="selimg" src="'.$stamp_path.'">';
    }
    // メッセージ
    echo h($message);
    // ループカウンタ$iが1から2までのループ
    for ($i = 1; $i <= 2; ++$i) {
        // アップロードファイル保存関数を呼ぶ
        // 第一引数：保存されたメッセージのＩＤ
        // 第二引数：ループカウンタ
        save_upload_file($wpdb->insert_id, $i);
    }
    
    // 画像表示
    echo '<img src="'.$thumb_url.'">';
    // 画像表示(オーバーレイ)
    echo '<img src="'.$overlay_url.'">';
    ?>
    
```

**identify.php**

```

    <?php
    /*
     雑談掲示板 確認画面
    */
    
    // 他のサイトでインラインフレーム表示を禁止する（クリックジャッキング対策）
    header('X-FRAME-OPTIONS: SAMEORIGIN');  
    
    // 不正アクセスチェック
    if(!$noindexaccess){
        header("HTTP/1.0 404 Not Found");exit();
    }
    ?>
    
    <script>
      //2重送信防止スクリプト
      var flg_Submit = false;
    
      function Fnk_DoubleSubmit() {
        if (flg_Submit) {
          alert("処理中です。");
          return false;
        } else {
          flg_Submit = true;
          return true;
             }
          }
      <script>
    
    <?php
    $namae_value = isset($namae) ? htmlspecialchars($namae, ENT_QUOTES) : '';
    $message_value = isset($message) ? htmlspecialchars($message, ENT_QUOTES) : '';
    
    //フォームデータのsubmitを中断する
    echo '<form name="toiawase2" method="post" enctype="multipart/form-data" action="<?php echo esc_url( home_url( '/contact/' ) ); ?>" onsubmit="return Fnk_DoubleSubmit();">';
    echo '<div>';
    echo '<label>お名前</label><span>※</span><br />';
    //名前表示
    echo '<?php echo $namae_value; ?><input type="hidden" name="namae" size="40" maxlength="60" value="'.$namae_value.'" required />';
    echo '<label>お問い合わせ内容</label><span>※</span><br />';
    //メッセージ表示
    echo '<?php echo nl2br($message_value); ?><textarea name="message" cols="40" rows="10" required>'.$message_value.'</textarea>';
    echo '</div>';
    //スタンプ表示
    foreach ($stamps as $stamp_path) {
        echo '<img class="selimg" src="'.$stamp_path.'">';
    }
    echo '<div>';
    echo '<input type=button value="修正する" onClick="javascript:history.back();">' ;
    echo '<input type="submit" value="送信する" id="send" disabled>';
    echo '</div>';
    echo '<input type="hidden" name="stamp" id="select" value="identify">';
    echo '</form>';
    ?>
    
```

**core.php**

```

    <?php
    /*
     雑談掲示板 全体をコントロール
    */
    require_once 'rerification.php';
    
    // エラーメッセージと不正アクセスフラグ
    $error_mes = '';
    $noindexaccess = true;
     
    switch(true){
    
        case(isset($_POST['toiawase']) and $_POST['toiawase'] == "enter information" ):
        
        require_once 'identify.php';
    
        break;
        
        case(isset($_POST['toiawase2']) and $_POST['toiawase2'] == "identify"  ):
        
        require_once 'finish.php';
    
        break;
        
    }
    ?>
    
```
CC BY-SA 4.0
2023-04-10T17:23:56.480
94482
2023-04-10T17:23:56.480
50979
question
javascript php sql
雑談掲示板の画像動画アップロード機能について