• ベストアンサー

WordPressの質問(q10093310)の続

スタンプ画像を送信する機能をデータベースに格納したいのですが、格納した数字と画像URLを結び付ける方法が分かりません。 アドバイスお願い致します。 ※最新のコード https://wandbox.org/permlink/A4VLYzAR2h4uYYRh

質問者が選んだベストアンサー

  • ベストアンサー
  • dell_OK
  • ベストアンサー率13% (766/5720)
回答No.33

・3点目は表示についてになります。前述のとおりtokenの使い方が難しく参考サイトを見ても文字と画像どちらに対する防御コードか理解できておりません。 tokenについては先の回答で大丈夫ですね ・表示コードは下記のようになるのではないかと書いているのですが、スタンプ画像のほかに名前とメッセージにもisset関数で変数がセットされているか確認する必要があるのか分からなかったため、 それっぽい処理はすでにされていますよ。 ただ、メール送信から部分的にコピーしてきただけのようなのでこれだけではだめです。 ---- $namae_value = isset($namae) ? htmlspecialchars($namae, ENT_QUOTES) : ''; $message_value = isset($message) ? htmlspecialchars($message, ENT_QUOTES) : ''; ---- あと、必須のチェックはHTML任せになっているので、PHP側でもチェックするようにした方がいいのかも知れません。 いただいた質問にだけ簡単に回答していたので、コードをよく見ていませんでした。 細かく見てみると、いろいろと直した方がよさそうです。 メール送信から拝借したためなのもあるので、あれとはまったく別物と思ってください。 その1。 最初の方にある不正アクセスはコードに無駄があります。 ---- $noindexaccess = true; ~(省略:インラインフレーム禁止) // 不正アクセスチェック if (!$noindexaccess) { header('HTTP/1.0 404 Not Found'); exit; } // 不正アクセスチェック if (!$noindexaccess || isBot()) { header('HTTP/1.0 404 Not Found'); exit; } ---- これだけでいいです。 ---- // 不正アクセスチェック if (isBot()) { header('HTTP/1.0 404 Not Found'); exit; } ---- その2。 エラー表示がありますが、チェック処理がありません。 ---- echo '<div style="color:red;">'; // エラーメッセージがあったら表示する echo ($error_mes) ? ' ---------------------<br />  入力エラーです<br /> ---------------------<br />'.$error_mes : ''; echo '</div>'; ---- これより前にチェック処理をしてください。 こんな流れになります。 ---- // エラーメッセージ $error_mes = ''; ~チェック処理 echo '<div style="color:red;">'; // エラーメッセージがあったら表示する echo ($error_mes) ? ' ---------------------<br />  入力エラーです<br /> ---------------------<br />'.$error_mes : ''; echo '</div>'; ---- 他にもありますが、今日はここまでにしておきます。

php_learn
質問者

補足

Q.tokenについては先の回答で大丈夫ですね それっぽい処理はすでにされていますよ。 ただ、メール送信から部分的にコピーしてきただけのようなのでこれだけではだめです。 ---- $namae_value = isset($namae) ? htmlspecialchars($namae, ENT_QUOTES) : ''; $message_value = isset($message) ? htmlspecialchars($message, ENT_QUOTES) : ''; ---- A.アドバイスありがとうございます。tokenは送信する際に生成するものだと理解できました。 確かに中の文字列チェックは行われていますがHTMLですね。 Q.その1。 最初の方にある不正アクセスはコードに無駄があります。 ---- $noindexaccess = true; ~(省略:インラインフレーム禁止) // 不正アクセスチェック if (!$noindexaccess) { header('HTTP/1.0 404 Not Found'); exit; } // 不正アクセスチェック if (!$noindexaccess || isBot()) { header('HTTP/1.0 404 Not Found'); exit; } ---- A.こちらのコードは保存と表示のファイルを分けるという想定をしていたので残しておりました。今のところ削除と保存のコードファイルは分けることに決めているのですが、表示は同じファイルで実装できそうでしょうか? Q.その2。 エラー表示がありますが、チェック処理がありません。 ---- echo '<div style="color:red;">'; // エラーメッセージがあったら表示する echo ($error_mes) ? ' ---------------------<br />  入力エラーです<br /> ---------------------<br />'.$error_mes : ''; echo '</div>'; ---- A.こちらはお問合せフォーム用のファイルを見ると文字列チェックなどのコードを別ファイルに書いていてそちらを外部から読み込んでいるようです。 rerification.phpに文字列チェック用コードを書いたのですが、こちらは外部から読み込ませたほうが良いでしょうか?そのままecho '<div style="color:red;">';の上に追加するべきでしょうか? ※最新コード https://wandbox.org/permlink/4aLeppvHjfrIycUx

その他の回答 (32)

  • dell_OK
  • ベストアンサー率13% (766/5720)
回答No.32

・2点目は動画のアップロードサイズになります。15mbで制限を設けたいのですが、dell_okさんではなく別の方からアドバイスいただいたものだとMAX_FILE_SIZEを使うのですが、tokenもCSRF対策のため設置したいためinput typeだけで複数重なってしまい自分でもよくわからない状態です。 MAX_FILE_SIZEとtokenはひとつあればいいですよ。 アップロードファイルはふたつありますが、どちらも同じサイズで制限するので、MAX_FILE_SIZEは共通で使います。 tokenは送信単位で行なう生成とチェックなのでファイルごとにするわけではありません。

php_learn
質問者

補足

A.回答ありがとうございます。それぞれ1つずつ追加いたしました。 ※最新コード(63行目に追加) https://wandbox.org/permlink/hTVVFMGLRHGmEsmQ

  • dell_OK
  • ベストアンサー率13% (766/5720)
回答No.31

・1点目は320×320のリサイズ処理をコードに追加する場合原寸サイズのコードは削除してもいいのでしょうか?縮小の際にコピー元の画像サイズが必要なためむやみに消せないのではないかと思い残しました。 削除してかまいません。 いただいたコードで、 以下の部分がコメントにもされていないので、 これらも削除してください。 $image_path = $upload_dir['basedir'].'/'.$sub_dir.'/'.$image_filename; $image_url = $upload_dir['baseurl'].'/'.$sub_dir.'/'.$image_filename; echo '<img src="'.$image_url.'">'; あと、オーバレイ用の保存ファイル名と保存ファイルパスの処理を追加してください。

php_learn
質問者

補足

アドバイスありがとうございます。削除いたしました。オーバーレイ用の保存ファイル名は追加したのですが、保存ファイルパスの処理というのはどこに追加すればよいでしょうか? // オーバーレイ保存ファイル名は203行目に追加しました。 ※最新コード https://wandbox.org/permlink/L4N401XhPDsbLdtQ

  • dell_OK
  • ベストアンサー率13% (766/5720)
回答No.30

・自分なりに考えてみたのですが、ID番号の表示方法と選択スタンプ画像の表示についてわかりませんでした。 IDとスタンプの表示はこれだけです。 ---- echo "ID:{$wpdb->insert_id}"; echo '<img class="selimg" src="'.$stamps[$stamp].'">'; ---- これだけにするための準備が必要だったのですが、 以前説明したコードが導入されていないのでそれを付加したものをアップロードしました。 以下の差分を確認して、現在のコードに反映してみてください。 https://github.com/dell-GH/sample_theme/commit/fc290bbacefc153bcd3f84afd5614e85297349ac 差分の見方について。 行番号とコードの間に「-」があるものは、 その行が削除されていることを示し、背景色が赤系です。 行番号とコードの間に「+」があるものは、 その行が追加されていることを示し、背景色が緑系です。

php_learn
質問者

お礼

https://okwave.jp/qa/q10113307.html 質問の期限が明日で切れてしまうため新たに質問いたしました。引き続きアドバイスお願い致します。

php_learn
質問者

補足

修正ありがとうございます。スタンプ画像に関して真偽を確認する必要があるとのことですが、まだ自分で意図を理解しきれていないかもしれません。参考サイトを確認したところ変数の確認は行われているため必要な気はしています。 恐らく名前とメッセージも空かどうか念のため確認すべきだと思うのですが、そうなるとアップロード画像も表示する際に確認が必要になりフォームで送る際は表示の時に中の変数をすべてチェックすることになりそうです… ※参考サイト https://www.webdesignleaves.com/pr/php/php_filters.php ※アドバイス引用 取得した $select の値が「正しい値か」はチェックすべきです。想定したform要素からだけ POSTされると決めつけてはいけません。チェックせずに(配列などから)スタンプの画像を使おうとすれば undefined index になってしまう可能性があります(通常は起こり得ませんが、可能性を排除してはいけない)。 また別件になるのですがtokenも実装したい場合、ファイル送信フォームを2つ用意しているためどちらにも適応させる方法が分かりませんでした。 ファイルサイズ制限のコードも2つのファイル送信フォームにどのように適応させればよいのか分からず1つだけで考えております。 雑談掲示板の送信フォーム側で動画ファイルサイズ(15mb)の制限とtokenの実装、表示ファイル(finish.php)で ID名前メッセージスタンプ画像アップロード画像の表示コード、別ファイルに特定の荒らしIDの書き込み制限を実装予定です。 <input type="hidden" name="MAX_FILE_SIZE" value="15725640"> <input type="file" name="attachment_file_1"…以下略>; <input type="file" name="attachment_file_2"…以下略>;

  • dell_OK
  • ベストアンサー率13% (766/5720)
回答No.29

・通常は150×150で表示して拡大時(オーバーレイ)の際は320×320で想定しております。 それでしたら原寸のところを、320×320のリサイズ処理に変更してみてください。

php_learn
質問者

補足

回答ありがとうございます。色々お聞きしたいことがあるのですが、 1点目は320×320のリサイズ処理をコードに追加する場合原寸サイズのコードは削除してもいいのでしょうか?縮小の際にコピー元の画像サイズが必要なためむやみに消せないのではないかと思い残しました。 ※223行目からオーバーレイ用の拡大画像用コードを書いております。 ※現在のコード https://wandbox.org/permlink/rnlDqXMzNIOqimxW // 縮小(サムネイル) imagecopyresized($thumb_image, $base_image, 0, 0, 0, 0, $thumb_width, $thumb_height, $base_width, $base_height); 2点目は動画のアップロードサイズになります。15mbで制限を設けたいのですが、dell_okさんではなく別の方からアドバイスいただいたものだとMAX_FILE_SIZEを使うのですが、tokenもCSRF対策のため設置したいためinput typeだけで複数重なってしまい自分でもよくわからない状態です。 上手くまとめる方法はないでしょうか?$_FILES['userfile']['size']でも制限できるようですが、検索しても使用例がないためどのようにコードを書くのかわかりませんでした… ※参考サイト https://369code.tokyo/304/ ※MAX_FILE_SIZEとtokenについてのコード //トークンを生成 setToken(); 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="file" name="attachment_file_1" id="my_image" accept=".png, .jpg, .jpeg, .pdf, .doc">'; echo '<input type="hidden" name="MAX_FILE_SIZE" value="15725640">; echo '<input type="file" name="attachment_file_2" id="my_image" accept=".png, .jpg, .jpeg, .pdf, .doc">'; echo '<input type="hidden" name="token" value="<?php echo getToken(); ?>">; echo '<input type="hidden" name="token" value="<?php echo getToken(); ?>">; echo '</label>'; 3点目は表示についてになります。前述のとおりtokenの使い方が難しく参考サイトを見ても文字と画像どちらに対する防御コードか理解できておりません。 表示コードは下記のようになるのではないかと書いているのですが、スタンプ画像のほかに名前とメッセージにもisset関数で変数がセットされているか確認する必要があるのか分からなかったため、dell_okさんにお聞きしてからアップロード画像の表示処理を書こうと思っております。画像に関しましては真偽のチェックは必ず行うように教えていただいたので、コードを書いております。 ※アドバイス 取得した $select の値が「正しい値か」はチェックすべきです。想定したform要素からだけ POSTされると決めつけてはいけません。 <?php $token = getToken(); $namae = $_POST['namae']; $message = $_POST['message']; //特殊文字を無効化 string htmlspecialchars( $string ,$flags ,$encoding ) //h() 関数の定義 function h($str) { return htmlspecialchars($str, ENT_QUOTES, 'UTF-8'); } echo h(@$_POST['namae']); echo h(@$_POST['message']); //スタンプ画像 $select = intval(filter_input(INPUT_POST, 'select')); $img_arr = ['sample1.png', 'sample2.png', 'sample3.png']; // issetでtrueだった場合の処理 if (isset($img_arr[$select])) foreach ($img_arr as $tmp){ printf('<img class="selimg" src="%s">', $tmp); } else { echo "値が入力されていません。"; } … … … ?>

  • dell_OK
  • ベストアンサー率13% (766/5720)
回答No.28

・ウイルスに対する確認がバイナリーデータの確認になるようです。 それならひとまず先日のコードでよさそうですね。 ・PNGやJPEGもバイナリー判定する方法をお聞きしたところ、画像ファイルはgetimagesize関数で識別するようです。 識別方法がわかりませんが、もしかしたら、defaultを追加してエラー処理を入ればいいのかも知れないですね。 ---- // 元画像の読込 switch ($info[2]) { case IMAGETYPE_PNG: $base_image = imagecreatefrompng($tmp_name); break; case IMAGETYPE_JPEG: $base_image = imagecreatefromjpeg($tmp_name); break; default: // エラー処理 break; } ----

php_learn
質問者

補足

<?php $namae = $_POST['namae']; $message = $_POST['message']; $select = $_POST['select']; //特殊文字を無効化 string htmlspecialchars( $string ,$flags ,$encoding ) //h() 関数の定義 function h($str) { return htmlspecialchars($str, ENT_QUOTES, 'UTF-8'); } echo h(@$_POST['namae']); echo h(@$_POST['message']); echo (@$_POST['select']); ?> 自分なりに考えてみたのですが、ID番号の表示方法と選択スタンプ画像の表示についてわかりませんでした。 参考サイトを見ながらセキュリティに注意してコードを書いてみました。 メール送信の際に下記のコードが使われているためそちらをみて応用できるのではないかと思い$post[]で囲っております。 $subject = $_POST['subject']; $namae = $_POST['namae']; $email = $_POST['email']; $message = $_POST['message']; $action = $_POST['action']; ※参考サイト https://www.webdesignleaves.com/pr/php/php_basic_06.php スタンプ画像を選択する場合html部分は下記のようになっているため名前とメッセージの形態に沿って書いてみたのですが、セキュリティ上問題がありそうな気もしています。 参考サイトのように1度クッションを挟む方がよいでしょうか? <form method="post"> <!-- 初期状態で最初の画像を選択状態とする --> <input type="hidden" name="select" id="select" value="0"> <button>send</button> </form> ※参考サイト https://thinkit.co.jp/story/2015/06/11/6118

  • dell_OK
  • ベストアンサー率13% (766/5720)
回答No.27

・拡大して表示する際の大きさで保存しておいた方が良いのではないかと考えたのですがそちらはcssで拡大表示させるという認識で良いでしょうか? そうですね。 私はそのつもりでした。 拡大になるか縮小になるかは原寸と表示領域の大小でかわってくるとは思います。 拡大表示する際の大きさで保存してもかまいません。 ブラウザ上で見るだけならそれでいいと思います。 私はてっきり原寸のものをダウンロードして画像編集でもするのかと思っていたので、そうでなければ、拡大表示寸法で保存した方がファイルサイズが小さくなるかも知れないのでいいかも知れません。 ・知識不足な面もありこの2つについてdell_okさんの見解をお聞きしたいです。 質問者さまよりも私の方が知識不足です。 そのうえで私が思うには、これらの解説からすると、ブラウザで画像を見るだけならスクリプトは実行されないのではないかと思います。 メールを開いたり、メールに添付されているファイルを開いたりすると実行される、と言うのは、ローカルマシンがそのスクリプトやEXE(実行ファイル)を実行可能であるからです。 ブラウザ内に表示したものを実行するのは、主にJavaScriptだと思います。 画像にスクリプトを入れることができるのかどうか私にはわかりませんが、それはスクリプトとして実行されないような気がします。 参考サイトにはダウンロードした場合は危ないようなことが書かれていますが、つまりブラウザで見るだけなら問題ないということだと思います。

php_learn
質問者

補足

Q.拡大表示する際の大きさで保存してもかまいません。 ブラウザ上で見るだけならそれでいいと思います。 私はてっきり原寸のものをダウンロードして画像編集でもするのかと思っていたので、そうでなければ、拡大表示寸法で保存した方がファイルサイズが小さくなるかも知れないのでいいかも知れません。 A.アドバイスありがとうございます。通常は150×150で表示して拡大時(オーバーレイ)の際は320×320で想定しております。 ・知識不足な面もありこの2つについてdell_okさんの見解をお聞きしたいです。 Q.参考サイトにはダウンロードした場合は危ないようなことが書かれていますが、つまりブラウザで見るだけなら問題ないということだと思います。 A.なるほど画像をダウンロードしてただ開くだけであれば問題という事ですね。メールなどのローカルマシンが発動している状態でないとウイルスに感染することもなさそうですね。

  • dell_OK
  • ベストアンサー率13% (766/5720)
回答No.26

・保存ファイル名の$idと$iというのはswitch ($file_type){}内の処理の最後から求めているのでしょうか? 関数の引数で受け取っています。 function save_upload_file($id, $i) ここから渡しています。 save_upload_file($wpdb->insert_id, $i); ・ファイル送信の際の画像の大きさをそのまま保存する場合オーバーレイで拡大させるようにしたい場合問題ないでしょうか? 問題ないと思います。 どのような問題があると思われましたか。 ・下記コードの保存ファイル参照パスは保存した画像を削除するために開くためのものでしょうか? 表示するためのパスです。 削除では使いません。 数日たってコメントと共に削除する際のことでしたら、ここのパスを使います。 // 保存ファイル名 $image_filename = "{$id}_{$i}.png"; $thumb_filename = "{$id}_{$i}_thumb.png"; // 保存ファイルパス $image_path = $upload_dir['basedir'].'/'.$sub_dir.'/'.$image_filename; $thumb_path = $upload_dir['basedir'].'/'.$sub_dir.'/'.$thumb_filename; ・jpg,png,mp4,pdfという拡張子自体にウイルスが混ざっていた場合に対処は可能でしょうか? 拡張子自体にウイルスが混ざると言うのが理解できません。 アップロードファイルの拡張子は信用できないので最初から使っていません。 なので対処する必要もないと思います。 ファイルそのものにウィルスが吹き込まれているかどうかの対応は私にはわかりません。 心配なら、この質問とは無関係のものとして、ウィルス感染確認方法を質問されてみてはどうでしょうか。 その方法を取り込めばいいような気がします。 ・MIME_TYPEについての理解ができていないのですが、拡張子の文字列を調べるものでしょうか? 違います。 finfo_file()がどのような仕組みでファイルの種類を判定しているか私にはわかりません。 拡張子が違っていても、あるいは、拡張子がなくても、それなりのMIME_TYPEを返してくれます。 私が勘違いしていたために、まどわせてしまっていたらすみません。 私のコードに大問題がありましたので訂正します。 アップロードファイルの拡張子が信用できないのでそれは使わず、 ファイルの内容からファイルの種類だけを判定するようにしていました。 これだと、拡張子が違っていても直してくれるので便利だと思っていたのですが、 そのせいで、許可しない方がいいファイルまで許可されてしまっていました。 いただいていたコードの判定処理をさらに取り込んでみました。 拡張子でも判定して、なるべく許可しない方法にしました。 今のところfinfo_file()のMIME_TYPEも併用していますが、 PNGやJPEGもバイナリー判定する方法を見つけていただければ、 MIME_TYPEをやめることもできると思います。 https://github.com/dell-GH/sample_theme/blob/main/entry-confirmationform.php

php_learn
質問者

お礼

A.ウイルスに対する確認がバイナリーデータの確認になるようです。 PNGやJPEGもバイナリー判定する方法をお聞きしたところ、画像ファイルはgetimagesize関数で識別するようです。

php_learn
質問者

補足

Q.保存ファイル名の$idと$iというのはswitch ($file_type){}内の処理の最後から求めているのでしょうか? A.回答ありがとうございます。理解することができました。 Q.ファイル送信の際の画像の大きさをそのまま保存する場合オーバーレイで拡大させるようにしたい場合問題ないでしょうか? A.拡大して表示する際の大きさで保存しておいた方が良いのではないかと考えたのですがそちらはcssで拡大表示させるという認識で良いでしょうか? Q.下記コードの保存ファイル参照パスは保存した画像を削除するために開くためのものでしょうか? 表示するためのパスです。 削除では使いません。 A.回答ありがとうございます。理解することができました。 Q.拡張子自体にウイルスが混ざると言うのが理解できません。 アップロードファイルの拡張子は信用できないので最初から使っていません。 なので対処する必要もないと思います。 ファイルそのものにウィルスが吹き込まれているかどうかの対応は私にはわかりません。 心配なら、この質問とは無関係のものとして、ウィルス感染確認方法を質問されてみてはどうでしょうか。 その方法を取り込めばいいような気がします。 アップロードファイルの拡張子が信用できないのでそれは使わず、 ファイルの内容からファイルの種類だけを判定するようにしていました。 今のところfinfo_file()のMIME_TYPEも併用していますが、 PNGやJPEGもバイナリー判定する方法を見つけていただければ、 MIME_TYPEをやめることもできると思います。 https://github.com/dell-GH/sample_theme/blob/main/entry-confirmationform.php A.修正ありがとうございます。解釈として間違えているかもしれないですが、本来の拡張子がjpgやpngでないものを意図的に画像ファイルとして変更してそこにウイルスを入れていた場合表示の際にマルウェアのスクリプトが実行されるなどの例が挙げられていました。 下記画像のように別の拡張子に見せかけるためにRLOが悪用されていることもあるようです。 知識不足な面もありこの2つについてdell_okさんの見解をお聞きしたいです。 https://imgur.com/7CRSQEt.jpg ※RLOについて https://officenomadoguchi.com/column/20191024-24471/ ※マルウェアのスクリプトについて https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q10180392655 ファイルそのものにウイルスが吹き込まれている場合の対処法については別途質問してみます。 ファイルの拡張子を判定していると考えていたのですが、中身から判定しているのであれば問題ない気もしています… PNGやJPEGもバイナリー判定する方法につきましても質問してみます。

  • dell_OK
  • ベストアンサー率13% (766/5720)
回答No.25

組み合わせることは可能ですが、そのままというわけにはいきません。 バイナリー判定を追加してみましたが、組み合わせると言うほど元のコードは利用していません。 バイナリー文字列の取得方法とその対応文字列程度です。 finfo_file()によるMIME_TYPEを優先しています。 この時点でPDFかmp4だと判明すればバイナリー判定はしません。 finfo_file()が予期せぬ値を返した場合にバイナリー判定しています。 コードが長くて投稿できないため、githubにアップロードしました。 https://github.com/dell-GH/sample_theme/blob/main/entry-confirmationform.php

php_learn
質問者

補足

A.修正ありがとうございます。いくつかお聞きしたいことと不安な事があります。 1点目になるのですが、保存ファイル名の$idと$iというのはswitch ($file_type){}内の処理の最後から求めているのでしょうか? // 保存ファイル名 $image_filename = "{$id}_{$i}.png"; $thumb_filename = "{$id}_{$i}_thumb.png"; 2点目になるのですが、ファイル送信の際の画像の大きさをそのまま保存する場合オーバーレイで拡大させるようにしたい場合問題ないでしょうか? // PNG形式で保存(原寸) imagepng($base_image, $image_path, 0); 3点目になるのですが、下記コードの保存ファイル参照パスは保存した画像を削除するために開くためのものでしょうか? // 元画像を削除 unlink($tmp_name); // 保存ファイル参照パス $image_url = $upload_dir['baseurl'].'/'.$sub_dir.'/'.$image_filename; $thumb_url = $upload_dir['baseurl'].'/'.$sub_dir.'/'.$thumb_filename; // 画像表示 echo '<img src="'.$image_url.'">'; echo '<img src="'.$thumb_url.'">'; 不安な点になるのですが、MIME_TYPEで画像の識別を行っている点になります。 以前他の方からアドバイス頂いたのでそちらから引用させていただきますが、jpg,png,mp4,pdfという拡張子自体にウイルスが混ざっていた場合に対処は可能でしょうか? atom構造の.mp4のファイル構造をバイナリデータから見た場合、中身の確認はできていると思うのですが、拡張子に偽装工作がされていた場合文字列が一致していてもウイルスが吹き込まれている気がします… MIME_TYPEについての理解ができていないのですが、拡張子の文字列を調べるものでしょうか? 拡張子が意図的に作られたものである場合そちらに対しての防御などが別途必要になる気がしています。 ※引用文 あと「拡張子から判断」するのは危険です(その拡張子のファイルに関連付けられたアプリのバグを利用して悪さする内容が仕込まれている可能性を排除できません)。 #過去にそういう例がjpegか何かでありましたよねぇ・・・ #他のファイルで起こらない保証はありません。 ※参考画像 https://imgur.com/cj5aCq7.jpg ※気になる拡張子について https://xtech.nikkei.com/it/free/ITPro/NEWS/20041008/151027/ https://officenomadoguchi.com/column/20191024-24471/ https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q10180392655

  • dell_OK
  • ベストアンサー率13% (766/5720)
回答No.24

・疑問なのですがinput要素のaccept属性に、mp4形式のファイルの拡張子を追加するだけでは難しいのでしょうか? それでかまいませんので追加しておいてください。 私がファイルの種類を正確に知りたかったか理由は、 画像ファイルであればリサイズして保存する、 そうでなければ元のファイルのまま保存する、 と言う分岐のためです。 バイナリーで確認すると言う情報もありましたが、 面倒そうなので今回はしていません。 finfo_file()の正確性は私にはわかりませんが、 コード的にはこんな感じになります。 バイナリーで確認しなければ正確ではないと言うことになってくれば、 「ファイルの種類を取得」関数のところにそれを組み込めばいいと思います。 ---- 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']) { // アップロードテンポラリーファイルパス $tmp_name = $_FILES[$attachment_file]['tmp_name']; // WordPressアップロードディレクトリ取得 $upload_dir = wp_upload_dir(); // サブディレクトリ $sub_dir = 'informtion-form'; // ファイルの種類を取得 $file_type = get_file_type($tmp_name); // アップロードファイルが画像か判定 if (in_array($file_type, ['image/png', 'image/jpeg'])) { // アップロードファイルが画像の場合 // 保存ファイル名 $image_filename = "{$id}_{$i}.png"; $thumb_filename = "{$id}_{$i}_thumb.png"; // 保存ファイルパス $image_path = $upload_dir['basedir'].'/'.$sub_dir.'/'.$image_filename; $thumb_path = $upload_dir['basedir'].'/'.$sub_dir.'/'.$thumb_filename; // 元画像の情報を取得 $info = getimagesize($tmp_name); // 元画像の読込 switch ($info[2]) { case IMAGETYPE_JPEG: $base_image = imagecreatefromjpeg($tmp_name); break; case IMAGETYPE_PNG: $base_image = imagecreatefrompng($tmp_name); break; } // 元画像のサイズ $base_width = $info[0]; $base_height = $info[1]; // サムネイルサイズ $thumb_width = 200; $thumb_height = 200; // サムネイル画像を準備 $thumb_image = imagecreatetruecolor($thumb_width, $thumb_height); // 縮小(サムネイル) imagecopyresized($thumb_image, $base_image, 0, 0, 0, 0, $thumb_width, $thumb_height, $base_width, $base_height); // PNG形式で保存(サムネイル) imagepng($thumb_image, $thumb_path); // PNG形式で保存(原寸) imagepng($base_image, $image_path, 0); // 元画像を削除 unlink($tmp_name); // 保存ファイル参照パス $image_url = $upload_dir['baseurl'].'/'.$sub_dir.'/'.$image_filename; $thumb_url = $upload_dir['baseurl'].'/'.$sub_dir.'/'.$thumb_filename; // 画像表示 echo '<img src="'.$image_url.'">'; echo '<img src="'.$thumb_url.'">'; } else { // アップロードファイルが画像以外の場合 // 拡張子を生成 switch ($file_type) { case 'application/pdf': $ext = 'pdf'; break; case 'video/mp4': $ext = 'mp4'; break; } // 保存ファイル名 $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 ($file_type) { case 'application/pdf': echo '<iframe src="'.$url.'" width="200"></iframe>'; break; case 'video/mp4': echo '<video controls src="'.$url.'" width="200">'; break; } } } } } // ファイルの種類を取得 // 第一引数:ファイルパス function get_file_type($path) { $finfo = finfo_open(FILEINFO_MIME_TYPE); return finfo_file($finfo, $path); } ----

php_learn
質問者

補足

Q.私がファイルの種類を正確に知りたかったか理由は、 画像ファイルであればリサイズして保存する、 そうでなければ元のファイルのまま保存する、 と言う分岐のためです。 A.回答ありがとうございます。ファイルを判定する方法で拡張子から判断する方法もあるようですが、アプリのバグを利用して悪さする内容が仕込まれている可能性があるようです。getID3()のようなタグ読み系の関数もあるようですがこれも動画に関してはリスクがあるかもしれないということでした。 安全なバイナリヘッダの文字列が一致するか確認して拡張子のみを利用することがセキュリティ上安全ですが、 ただこれも妥当性をチェックしてからでないと信用してはいけないようです。 アップロードを画像や動画やpdfのすべてに対応させる場合はname="MAX_FILE_SIZE" value="15725640"は必要ない気がします。 pdfと動画は拡張子の判定のためにバイナリヘッダやマジックナンバーを使う予定なのですが、下記のコードをそのままdell_okさんのコードと組み合わせることは可能でしょうか? ※バイナリー参考サイト https://kyoyobanana.blogspot.com/2022/01/mp4.html https://unoh.github.io/2007/09/12/mp43gpp3gpp2.html //15728640 = 15 x 1024 x 1024 (15MB) <input type="hidden" name="MAX_FILE_SIZE" value="15725640"> <input type="file" name="userfile" accept=".png, .jpg, .jpeg, .pdf, .doc"> $ext = strtolower(substr($_FILES['userfile']['name'], strrpos($_FILES['userfile']['name'], '.'))); //バイナリー文字列確認(ftypmmp4 とか ftypmp42など) if ($ext === '.mp4' && substr(file_get_contents($_FILES['userfile']['tmp_name']), 4, 4) !== 'ftyp') $err[] = 'file is not mp4'; //妥当性をチェック $savedpath = 'savedir/' . md5_file($_FILES['userfile']['tmp_name']) . $ext; ー------------------------------------------ ※pdfの拡張子を切り出し $ext = strtolower(substr($_FILES['upfile']['name'], strrpos($_FILES['upfile']['name'], '.'))); if (!in_array($ext, $allow_ext)) $err[] = 'file type not allowed'; if ($ext === '.pdf' && substr(file_get_contents($_FILES['upfile']['tmp_name']), 0, 5) !== '%PDF-') $err[] = 'file is not pdf'; $allow_ext = ['.pdf', '.txt', '.csv']; if (!in_array($ext, $allow_ext)) $err[] = 'file type not allowed';

  • dell_OK
  • ベストアンサー率13% (766/5720)
回答No.23

・もう一つ挑戦してみたいことがあるのですが、pdfと別にmp4の保存は可能でしょうか? 可能だと思います。 アップロードされたファイルの種類を正確に判定する方法があればいいのですが、ご存じですか。

php_learn
質問者

お礼

疑問なのですがinput要素のaccept属性に、mp4形式のファイルの拡張子を追加するだけでは難しいのでしょうか? ※該当コード 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">'; 送信フォームからのPOSTデータを$_FILESで受け取って、拡張子のチェックを行い、該当していればバイナリヘッダを読み込むという方法が動画にも使えるそうです。 バイナリヘッダを読み込むというのが理解できていません。 ※参考サイト https://unoh.github.io/2007/09/12/mp43gpp3gpp2.html //mp4形式の拡張子のどれかに該当するかをチェック $ext = strtolower(substr($_FILES['userfile']['name'], strrpos($_FILES['userfile']['name'], '.'))); ↓ バイナリヘッダを読み込んで「mp4形式として妥当か」チェック ↓ 拡張子を保存 ※動画も画像と同じくバイナリ形式に変換してデータベースに保存することが可能 https://web.syu-u.com/blog/?p=957 name="MAX_FILE_SIZE"と$_FILES['userfile']['size']でアップロードサイズの制限ができるようですが、こちらに関しては別の有効な方法でも可能ではないかと思います。 ※アップロードサイズの上限に関して https://www.flyenginer.com/low/low_php/phpでファイルをアップロードする.html

php_learn
質問者

補足

回答ありがとうございます。画像と動画一度に識別することはphpでは不可能なようです。 画像または動画どちらになるのかif文でそれぞれ判定するのか、拡張子を取得してあてはまる場合の処理をそれぞれ書く方法のどちらかになりそうです。 ※参考サイト https://fromatom.hatenablog.com/entry/2022/08/09/010206 https://magazine.techacademy.jp/magazine/22174 https://teratail.com/questions/5950 https://hyodoblog.com/js-extension-judge/

関連するQ&A