質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

解決済

1回答

1047閲覧

コメント機能でページ遷移してしまう、サニタイズできない

erp

総合スコア46

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

0グッド

1クリップ

投稿2020/11/03 12:18

編集2020/11/04 06:22

前提・実現したいこと

PHPでデータベースを使わないコメント機能を作っています。

// 追記
ページ遷移の問題解決しました。あとはサニタイズの問題だけです。

https://web.analogstd.com/tips/posts/php/how-to-mount-comment-func-without-sql.php こちらのページを参考にしたのですが、コメントをするとそのページにとどまらずにPost先のphpファイルに移動してしまって困っています。エラーは特に出ていなく、メッセージも呼び出し元ページをリロードすればちゃんと書き込まれています。

あとサニタイズができなくて困っています。

何が問題なのかわかる方はご教授ください。

発生している問題・エラーメッセージ

ページ遷移せずに出力したいです。

あと、サニタイズのxhr_comment_send.phpでコメントアウトを外すと

php

1// サニタイズ 2$p_data['name'] = htmlspecialchars( $msg['name'], ENT_QUOTES); 3$p_data['message'] = htmlspecialchars( $msg['message'], ENT_QUOTES);

error

1Failed getting comment. 2```となってしまいます。 3 4### 該当のソースコード 5index.php 6```php 7<?php 8session_start(); 9include('../../assets/php/comments.php'); 10?> 11<!DOCTYPE HTML> 12<html lang="ja" dir="ltr" prefix="og: http://ogp.me/ns#"> 13 14<head> 15 <meta charset="utf-8"> 16 <meta http-equiv="X-UA-Compatible" content="IE=edge"> 17 <!-- responsive --> 18 <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"> 19</head> 20<body> 21<center><a class="btn btn-2" href="javascript:history.back()">Back</a></center> 22 23 <aside id="show_comments" class="m_4r"> 24 <form class="m_b_4r" method="post" action="/assets/php/xhr_comment_send.php"> 25 <span class="ts tm">コメント</span> 26 <div class="fields" style="display: block;"> 27 <div class="field half"> 28 <div class="align-left"><label for="comment_name">Name</label></div> 29 <input type="text" name="name" id="comment_name" placeholder="Handle name" required> 30 <input type="hidden" name="id" value="<?php echo substr(base_convert(md5(session_id()), 16, 36), 0, 6); ?>"> 31 </div> 32 <div class="field half"> 33 <div class="align-left"><label for="comment_text">Comment</label></div> 34 <textarea id="comment_text" name="message" placeholder="お気軽にコメントください" rows="4" required></textarea> 35 </div> 36 </div> 37 <ul class="actions"> 38 <li><input id="comment_button" type="submit" value="Send Message" class="primary message_b" /></li> 39 <li><input id="reset_b" type="reset" value="Reset" /></li> 40 </ul> 41 </form> 42 <div class="align-left"> 43 <small>※短時間で連続してのコメントはできません。</small><br> 44 <small>※いたずら防止のためにIP アドレスを記録しています。ご了承願います。</small> 45 </div> 46 <?php 47 if(isset($comments)) { 48 // コメント部のHTMLを出力する関数 49 ?> 50 <ul> 51 <?php 52 foreach($comments as $msg) { 53 ?> 54 <li> 55 <div> 56 <span><?php echo $msg['name']; ?> 57 <?php 58 if(preg_match('/(管理人)/i', $msg['name'])){ 59 } else { 60 echo 'さん'; 61 } 62 ?> 63 </span> 64 <span>(ID:<?php echo $msg['id']; ?>)</span> 65 <span>date:<?php echo $msg['time']; ?></span> 66 </div> 67 <p> 68 <?php echo $msg['message']; ?> 69 </p> 70 <?php } 71 ?> 72 </li> 73 <?php 74 } 75 ?> 76 </ul> 77 </aside> 78 </div> 79</body> 80</html>

comments.php

php

1<?php 2// HTMLを出力する前にsession_start();しておいて下さい 3// ID生成にsession_id()を使います 4// 以下をPHPファイルに直接埋め込むか別ファイルに記述しておきrequire()やinclude()で呼び出して下さい 5 6// このPHPファイルをrequireした呼び出し元のディレクトリとファイル名を取得する 7// 直接埋め込む場合は"$r_buff[0]['file']"を"__FILE__"に置き換えて下さい 8$r_buff = @debug_backtrace(); 9if(isset($r_buff[0])){ 10 $r_name = preg_replace('/.php\z/', '.dat', $r_buff[0]['file']); 11} else{ 12 $r_name = false; 13} 14// コメントを取得する 15if($r_name){ 16 if(file_exists($r_name)){ 17 $comments = json_decode(file_get_contents($r_name), true); 18 } else{ 19 $comments = array(); 20 } 21} 22// 最後の10件だけ表示する 23// $comments = array_slice($comments , 0, 10); 24?>

xhr_comment_send.php

php

1<?php 2// 任意のディレクトリに置く 3// 上記JavascriptからこのファイルにPOST送信する 4$referer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : null; 5$referer = preg_replace('/[?#][\s\S]*\z/', '', $referer); 6/* if(!preg_match('/http?://[\w/:%#$&?()~.=+\-]+/', $referer)){ 7// 他ドメインからのアクセスは拒否する 8exit("Bad Request!!"); 9} */ 10// POSTメソッドじゃなかったら終了 11if($_SERVER['REQUEST_METHOD'] !== 'POST'){ 12exit('Failed getting POST data.'); 13} 14// TOPページのURL 15// "index.html"などのファイル名は書かない 16$top_url = 'http://xxx.jp/'; 17// このファイルからTOPページがあるディレクトリまでの相対パス 18$top_path = '../../'; 19// 書き出しファイルを呼び出し元から取得する 20// 出力先は表示ページと同じディレクトリの同じ名前で拡張子が".dat" 21$buff = explode('/', (__DIR__. '/')); 22$m = count(explode('../', $top_path)); 23array_splice($buff, (0 - $m)); 24$input = implode('/', $buff). '/'. str_replace($top_url, '', $referer); 25$output = preg_replace('/.php\z/', '.dat', $input); 26// 現状のデータを読み込む 27if(file_exists($output)){ 28 $data = @json_decode(@file_get_contents($output), true); 29} else { 30 $data = array(); 31} 32/* 33if(!is_array($data)){ 34exit('Failed loading current data.'); 35} 36*/ 37// POSTデータを取得する 38$p_data = array(); 39foreach($_POST as $k => $v){ 40switch($k){ 41case 'name': 42case 'message': 43 // タグを全て削除 44 $p_data[$k] = preg_replace('/<[^>]*>/', '', $v); 45 // 改行を全て<BR>に置き換える 46 $p_data[$k] = preg_replace('/\n/', '<BR>', $p_data[$k]); 47break; 48case 'id': 49// IDが英数字6文字であることを確認する 50if(!preg_match('/\A[a-z0-9]{6}\z/', $v)){ 51 exit('Failed getting ID code.'); 52} 53 $p_data[$k] = $v; 54} 55} 56// サニタイズ 57//$p_data['name'] = htmlspecialchars( $msg['name'], ENT_QUOTES); 58//$p_data['message'] = htmlspecialchars( $msg['message'], ENT_QUOTES); 59// 名前に"管理"や"admin","root"といった文字が含まれた場合は名前を削除する 60$p_data['name'] = mb_convert_kana($p_data['name'], 'a'); 61if(preg_match('/(管理|admin|root)/i', $p_data['name'])){ 62 $p_data['name'] = ''; 63} 64// コメント内容が空でないことを確認する 65if(empty(preg_replace('/(\s|\n|\r|<BR>)/', '', $p_data['message']))){ 66exit('Failed getting comment.'); 67} 68if(empty(preg_replace('/(\s|\n|\r|<BR>)/', '', $p_data['name']))){ 69 exit('Failed getting name'); 70} 71 72// 同じIDが短時間でアクセスしていないか確認する 73if(isset($data)) { 74 if(strtotime('now') - strtotime($data[0]['time']) < 60){ 75 exit('Failed sending comment.'); 76 } 77} 78// コメントを配列に追加する 79array_unshift($data, array_merge($p_data, array('time' => date('Y-m-d H:i:s'), 'ip' => $_SERVER['REMOTE_ADDR']))); 80// ファイルに出力する 81$result = file_put_contents($output, json_encode($data), LOCK_EX); 82// 結果を返す 83if($result === false){ 84exit('Failed writing file.'); 85} else{ 86// 管理者にメールを送信する 87send__mail('xxx', 'xxx@jp', '', '', 'xxx@icloud.com', '', 'ブログにコメントされました', str_replace('<BR>', "\n", $data[0]['message']). "\n\n{$referer}#show_comments"); 88// HTMLをJavascriptに返す 89echo comment_html($data[0]); 90// ここ! 91 exit; 92} 93////////// 94/* 関数 */ 95////////// 96// メール送信の処理関数 97// 戻り値は送信受付可否(true/false) 98function send__mail($to_name, $to_address, $cc, $bcc, $from, $reply, $title, $body){ 99// 文字コード変換 100// 文字コードは"ISO-2022-JP"(S-JIS)に変換する 101$to = mb_convert_encoding($to_address, 'ISO-2022-JP', 'ASCII,JIS,UTF-8,EUC-JP,SJIS-WIN'); 102$cc = mb_convert_encoding($cc, 'ISO-2022-JP', 'ASCII,JIS,UTF-8,EUC-JP,SJIS-WIN'); 103$bcc = mb_convert_encoding($bcc, 'ISO-2022-JP', 'ASCII,JIS,UTF-8,EUC-JP,SJIS-WIN'); 104$from = mb_convert_encoding($from, 'ISO-2022-JP', 'ASCII,JIS,UTF-8,EUC-JP,SJIS-WIN'); 105$title = mb_convert_encoding($title, 'ISO-2022-JP', 'ASCII,JIS,UTF-8,EUC-JP,SJIS-WIN'); 106$body = mb_convert_encoding($body, 'ISO-2022-JP', 'ASCII,JIS,UTF-8,EUC-JP,SJIS-WIN'); 107// 件名に日本語が使えるようにエンコードする 108// (mb_send_mailを使わずにmailを使う為) 109$title = '=?iso-2022-jp?B?'. base64_encode($title). '?='; 110// 送信情報の成形 111$send_to = mb_encode_mimeheader($to_name, 'ISO-2022-JP'). "<$to>"; 112$headers = array(); 113$headers[] = 'From: '. $from; 114$headers[] = 'Cc: '. $cc; 115$headers[] = 'Bcc: '. $bcc; 116$headers[] = 'Reply-To: '. $reply; 117$headers[] = 'Return-Path: '. $reply; 118$headers[] = 'Content-Type: text/plain; charset=ISO-2022-JP'; 119// $headers[] = 'Message-Id: <'. md5(uniqid(microtime())). '@web.analogstd.com>'; 120$headers[] = 'X-Mailer: PHP/'. phpversion(); 121$pfrom = '-f $from'; 122$smresult = mail($send_to, $title, $body, implode("\n", $headers), $pfrom); 123return $smresult; 124} 125function comment_html($msg){ 126 ob_start(); // 標準出力のバッファ開始 127 // <li>~</li>の中身を出力する 128?> 129<div> 130 <span><?php echo $msg['name']; ?> 131 <?php 132 if(preg_match('/(管理人)/i', $msg['name'])){ 133 } else { 134 echo 'さん'; 135 } 136?> 137 </span> 138 <span>(ID:<?php echo $msg['id']; ?>)</span> 139 <span>date:<?php echo $msg['time']; ?></span> 140</div> 141<p> 142 <?php echo $msg['message']; ?> 143</p> 144<?php 145 $html = ob_get_contents(); 146 ob_end_clean(); // バッファここまで 147 // 出力するHTMLを返す 148 return $html; 149} 150?>

試したこと

// ここ!と記述のある所に

php

1$r_buff = @debug_backtrace(); 2$r_name = preg_replace('/.php\z/', '.php', $r_buff[0]['file']); 3header("Location: $r_name");

と書いたら遷移しませんでした。
サニタイズをするにはどうすればいいですか。助けてくださいお願いします。

補足情報(FW/ツールのバージョンなど)

firefox最新版、safari604.1
ここにより詳細な情報を記載してください。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

m.ts10806

2020/11/03 13:29

インデントぐちゃっとしてみるに堪えないというか、全体が見えにくいというか。コードフォーマット機能のついたエディタ(できればIDE)使ってください。
guest

回答1

0

自己解決

全体を $_POST で囲って

php

1if( !empty($_POST['comment_button']) ) { 2 foreach($_POST as $k => $v){ 3 $p_data['name'] = htmlspecialchars( $_POST['name'], ENT_QUOTES); 4 $p_data['message'] = htmlspecialchars( $_POST['message'], ENT_QUOTES); 5 } 6}

としたらサニタイズできました。自己解決できました。

投稿2020/11/04 07:22

erp

総合スコア46

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問