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

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

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

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

解決済

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

erp
erp

総合スコア45

PHP

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

1回答

0評価

1クリップ

671閲覧

投稿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

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

error

Failed getting comment. ```となってしまいます。 ### 該当のソースコード index.php ```php <?php session_start(); include('../../assets/php/comments.php'); ?> <!DOCTYPE HTML> <html lang="ja" dir="ltr" prefix="og: http://ogp.me/ns#"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <!-- responsive --> <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"> </head> <body> <center><a class="btn btn-2" href="javascript:history.back()">Back</a></center> <aside id="show_comments" class="m_4r"> <form class="m_b_4r" method="post" action="/assets/php/xhr_comment_send.php"> <span class="ts tm">コメント</span> <div class="fields" style="display: block;"> <div class="field half"> <div class="align-left"><label for="comment_name">Name</label></div> <input type="text" name="name" id="comment_name" placeholder="Handle name" required> <input type="hidden" name="id" value="<?php echo substr(base_convert(md5(session_id()), 16, 36), 0, 6); ?>"> </div> <div class="field half"> <div class="align-left"><label for="comment_text">Comment</label></div> <textarea id="comment_text" name="message" placeholder="お気軽にコメントください" rows="4" required></textarea> </div> </div> <ul class="actions"> <li><input id="comment_button" type="submit" value="Send Message" class="primary message_b" /></li> <li><input id="reset_b" type="reset" value="Reset" /></li> </ul> </form> <div class="align-left"> <small>※短時間で連続してのコメントはできません。</small><br> <small>※いたずら防止のためにIP アドレスを記録しています。ご了承願います。</small> </div> <?php if(isset($comments)) { // コメント部のHTMLを出力する関数 ?> <ul> <?php foreach($comments as $msg) { ?> <li> <div> <span><?php echo $msg['name']; ?> <?php if(preg_match('/(管理人)/i', $msg['name'])){ } else { echo 'さん'; } ?> </span> <span>(ID:<?php echo $msg['id']; ?>)</span> <span>date:<?php echo $msg['time']; ?></span> </div> <p> <?php echo $msg['message']; ?> </p> <?php } ?> </li> <?php } ?> </ul> </aside> </div> </body> </html>

comments.php

php

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

xhr_comment_send.php

php

<?php // 任意のディレクトリに置く // 上記JavascriptからこのファイルにPOST送信する $referer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : null; $referer = preg_replace('/[?#][\s\S]*\z/', '', $referer); /* if(!preg_match('/http?://[\w/:%#$&?()~.=+\-]+/', $referer)){ // 他ドメインからのアクセスは拒否する exit("Bad Request!!"); } */ // POSTメソッドじゃなかったら終了 if($_SERVER['REQUEST_METHOD'] !== 'POST'){ exit('Failed getting POST data.'); } // TOPページのURL // "index.html"などのファイル名は書かない $top_url = 'http://xxx.jp/'; // このファイルからTOPページがあるディレクトリまでの相対パス $top_path = '../../'; // 書き出しファイルを呼び出し元から取得する // 出力先は表示ページと同じディレクトリの同じ名前で拡張子が".dat" $buff = explode('/', (__DIR__. '/')); $m = count(explode('../', $top_path)); array_splice($buff, (0 - $m)); $input = implode('/', $buff). '/'. str_replace($top_url, '', $referer); $output = preg_replace('/.php\z/', '.dat', $input); // 現状のデータを読み込む if(file_exists($output)){ $data = @json_decode(@file_get_contents($output), true); } else { $data = array(); } /* if(!is_array($data)){ exit('Failed loading current data.'); } */ // POSTデータを取得する $p_data = array(); foreach($_POST as $k => $v){ switch($k){ case 'name': case 'message': // タグを全て削除 $p_data[$k] = preg_replace('/<[^>]*>/', '', $v); // 改行を全て<BR>に置き換える $p_data[$k] = preg_replace('/\n/', '<BR>', $p_data[$k]); break; case 'id': // IDが英数字6文字であることを確認する if(!preg_match('/\A[a-z0-9]{6}\z/', $v)){ exit('Failed getting ID code.'); } $p_data[$k] = $v; } } // サニタイズ //$p_data['name'] = htmlspecialchars( $msg['name'], ENT_QUOTES); //$p_data['message'] = htmlspecialchars( $msg['message'], ENT_QUOTES); // 名前に"管理"や"admin","root"といった文字が含まれた場合は名前を削除する $p_data['name'] = mb_convert_kana($p_data['name'], 'a'); if(preg_match('/(管理|admin|root)/i', $p_data['name'])){ $p_data['name'] = ''; } // コメント内容が空でないことを確認する if(empty(preg_replace('/(\s|\n|\r|<BR>)/', '', $p_data['message']))){ exit('Failed getting comment.'); } if(empty(preg_replace('/(\s|\n|\r|<BR>)/', '', $p_data['name']))){ exit('Failed getting name'); } // 同じIDが短時間でアクセスしていないか確認する if(isset($data)) { if(strtotime('now') - strtotime($data[0]['time']) < 60){ exit('Failed sending comment.'); } } // コメントを配列に追加する array_unshift($data, array_merge($p_data, array('time' => date('Y-m-d H:i:s'), 'ip' => $_SERVER['REMOTE_ADDR']))); // ファイルに出力する $result = file_put_contents($output, json_encode($data), LOCK_EX); // 結果を返す if($result === false){ exit('Failed writing file.'); } else{ // 管理者にメールを送信する send__mail('xxx', 'xxx@jp', '', '', 'xxx@icloud.com', '', 'ブログにコメントされました', str_replace('<BR>', "\n", $data[0]['message']). "\n\n{$referer}#show_comments"); // HTMLをJavascriptに返す echo comment_html($data[0]); // ここ! exit; } ////////// /* 関数 */ ////////// // メール送信の処理関数 // 戻り値は送信受付可否(true/false) function send__mail($to_name, $to_address, $cc, $bcc, $from, $reply, $title, $body){ // 文字コード変換 // 文字コードは"ISO-2022-JP"(S-JIS)に変換する $to = mb_convert_encoding($to_address, 'ISO-2022-JP', 'ASCII,JIS,UTF-8,EUC-JP,SJIS-WIN'); $cc = mb_convert_encoding($cc, 'ISO-2022-JP', 'ASCII,JIS,UTF-8,EUC-JP,SJIS-WIN'); $bcc = mb_convert_encoding($bcc, 'ISO-2022-JP', 'ASCII,JIS,UTF-8,EUC-JP,SJIS-WIN'); $from = mb_convert_encoding($from, 'ISO-2022-JP', 'ASCII,JIS,UTF-8,EUC-JP,SJIS-WIN'); $title = mb_convert_encoding($title, 'ISO-2022-JP', 'ASCII,JIS,UTF-8,EUC-JP,SJIS-WIN'); $body = mb_convert_encoding($body, 'ISO-2022-JP', 'ASCII,JIS,UTF-8,EUC-JP,SJIS-WIN'); // 件名に日本語が使えるようにエンコードする // (mb_send_mailを使わずにmailを使う為) $title = '=?iso-2022-jp?B?'. base64_encode($title). '?='; // 送信情報の成形 $send_to = mb_encode_mimeheader($to_name, 'ISO-2022-JP'). "<$to>"; $headers = array(); $headers[] = 'From: '. $from; $headers[] = 'Cc: '. $cc; $headers[] = 'Bcc: '. $bcc; $headers[] = 'Reply-To: '. $reply; $headers[] = 'Return-Path: '. $reply; $headers[] = 'Content-Type: text/plain; charset=ISO-2022-JP'; // $headers[] = 'Message-Id: <'. md5(uniqid(microtime())). '@web.analogstd.com>'; $headers[] = 'X-Mailer: PHP/'. phpversion(); $pfrom = '-f $from'; $smresult = mail($send_to, $title, $body, implode("\n", $headers), $pfrom); return $smresult; } function comment_html($msg){ ob_start(); // 標準出力のバッファ開始 // <li>~</li>の中身を出力する ?> <div> <span><?php echo $msg['name']; ?> <?php if(preg_match('/(管理人)/i', $msg['name'])){ } else { echo 'さん'; } ?> </span> <span>(ID:<?php echo $msg['id']; ?>)</span> <span>date:<?php echo $msg['time']; ?></span> </div> <p> <?php echo $msg['message']; ?> </p> <?php $html = ob_get_contents(); ob_end_clean(); // バッファここまで // 出力するHTMLを返す return $html; } ?>

試したこと

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

php

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

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

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

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

良い質問の評価を上げる

以下のような質問は評価を上げましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

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

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

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

teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

  • プログラミングに関係のない質問
  • やってほしいことだけを記載した丸投げの質問
  • 問題・課題が含まれていない質問
  • 意図的に内容が抹消された質問
  • 過去に投稿した質問と同じ内容の質問
  • 広告と受け取られるような投稿

評価を下げると、トップページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

m.ts10806

2020/11/03 13:29

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

まだ回答がついていません

会員登録して回答してみよう

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

ただいまの回答率
87.20%

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

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

質問する

関連した質問

同じタグがついた質問を見る

PHP

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