PHPでテキストファイルを読み込み、タグをエスケープする方法について

このQ&Aのポイント
  • PHPで作成したスクリプトでテキストファイルを読み込み、HTMLタグが含まれている場合にタグをエスケープする方法について説明します。
  • 現在のスクリプトでは、テキストデータをそのまま出力するため、HTMLタグが有効になっています。
  • しかし、テキストデータにHTMLタグが含まれている場合は、ブラウザがタグとして認識し、表示されない問題があります。タグをエスケープする方法として、htmlspecialchars関数を使用することができます。
回答を見る
  • ベストアンサー

エスケープしたくない、けど、したいのもある

とあるテキストデータ(.txt)を読み込み、それを表示するスクリプトをPHPで作りました。 その際、もしテキストデータにHTMLタグが入っている場合、そのまま出力させて、タグが有効になるようにしています。 (というかテキストを何も処理せずそのまま出力するだけ) (セキュリティ的には、テキストデータは信頼できる自サイトの同一ディレクトリに置いてあるものからしか読み込ませないようになっています) しかし、今度は逆に、もしそのテキストデータに「<hoge>」などの文字がふくまれていた場合、ブラウザはそれをタグと認識し、見えない表示になります。 本当は見えるようにそこは「&lt;hoge&gt;」と出力してほしいわけです。 かと言って、 echo htmlspecialchars($txt, ENT_QUOTES|ENT_HTML5, "UTF-8"); などエスケープして出力すると、今度はHTMLタグとして出力させたい「<br>」なども「&lt;br&gt;」として出力されてしまい都合が悪いです.. ようは、 「こんにちは<hoge><br>ほげ」 という文字列のテキストを、 「こんにちは&lt;hoge&gt;<br>ほげ」 と出力してほしい.. もちろんテキストは「hoge」であるとは限りません。 何かよい解決方法はないでしょうか? ご教示頂けましたら幸いです。

  • cnkozo
  • お礼率39% (158/402)
  • PHP
  • 回答数2
  • ありがとう数2

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

  • ベストアンサー
回答No.2

先ほどのReplace関数用に、 変換するもののリストがあれば、よさそうには思えます。 どちらにしても、全部自動ってのは、不可能なので。 どっちをとるかは、判断が必要ですが。 1>「リスト」にあれば、そのままなのか? 2>「リスト」になければ、そのままなのか? の2択ですね。 少なくとも、変換候補を自動で判断できない以上そこは 仕方がないかもしれません。 strposなどで、"<"を見つけたら、続く">"をスキャンしてみて、 範囲をリストから抽出など。。 $pos_start=strpos($text,"<"); if ($pos_start!==false) { $pos_end=strpos($text,">",$pos_start); // これをしないとそれよりも「前」がヒットするため } あとは、substrなどで、切り出してみれば比較用文字列が取り出せるので、 それをリスト比較ですかね。。 なお、この方法を使うとき、 クオート分解がやや、めんどくさいですけどね。 <tag param="<hoge>"> と、シングルクオートまたはダブルクオート内で<>が使われる可能性があるので。そこをフィルタしつつですかね。

cnkozo
質問者

お礼

ありがとうございました。地道にエスケープします..

その他の回答 (1)

回答No.1

ならば・・・ echo htmlspecialchars($txt, ENT_QUOTES|ENT_HTML5, "UTF-8"); これを、一度変数に押し込みます。 $temp=htmlspecialchars($txt, ENT_QUOTES|ENT_HTML5, "UTF-8"); echo str_replace("&lt;br&gt;", "<br>", $temp); と、質問者さんが変換してほしくなかった場合のみのケースを、 元に戻してあげる!という手はいかがですか?

cnkozo
質問者

お礼

ご回答ありがとうございます。 ただ、テキストも決まった文字列でないのと同時に、HTMLタグも固定ではありません.. また、単なるタグでなく、<script ..ってのもありえます。 全部を置き換え指定するのも非現実的ですよね.. 半角<>を全角<>にするのも何だかな~と。テキスト上では全角にしておいて.. $txt = str_replace("<", "&lt;", $txt); $txt = str_replace(">", "&gt;", $txt); こんな感じでしょうか..

cnkozo
質問者

補足

ご回答ありがとうございます。 ただ、テキストも決まった文字列でないのと同時に、HTMLタグも固定ではありません.. また、単なるタグでなく、<script ..ってのもありえます。 全部を置き換え指定するのも非現実的ですよね.. 半角<>を全角<>にするのも何だかな~と。テキスト上では全角にしておいて.. $txt = str_replace("<", "&lt;", $txt); $txt = str_replace(">", "&gt;", $txt); こんな感じでしょうか..

関連するQ&A

  • 保存データの¥nを<br />に変換

    http://okwave.jp/qa/q7387963.html 以前こちらの質問をさせていただきまして、 htmlspecialcharsはHTMLとしてクライアントに返すときに使用することがわかりました。 しかし、ここで問題が起こりました。 フォームから入力されたデータをdata.txtに一行一データとして保存していくプログラムなのですが、 以前のやり方は、 保存時にhtmlspecialchars変換してしまう方法で以下のようにやっていました。 $honbun=htmlspecialchars($_POST["honbun"],ENT_QUOTES); $honbun=str_replace("\n","<br />",$honbun); $file=fopen("data.txt",a"); fputs($file,$honbun."\n"); //行末に\nをつけて保存 fclose($line); こうすることで、data.txtには --------------------------------------------- こんにちは、山田です。<br />元気ですか?\n こんばんは、鈴木です。<br />元気です。\n --------------------------------------------- このように行の最後以外は改行を<br />にできていました。 しかし、最初に書いた通り、 htmlspecialcharsは保存時ではなく、出力時に使う。 ということでしたのでこのやり方は正しくないのでこんな感じに書き直してみました。 $honbun=$_POST["honbun"]; //まだこの時点ではhtmlspecialcharsしない $honbun=str_replace("\n","<br />",$honbun);; $file=fopen("data.txt",a"); fputs($file,$honbun."\n"); //行末に\nをつけて保存 fclose($line); そして、htmlとして出力時に $f=file("data.txt"); foreach($f as $key=>$value){ print(htmlspecialchars($value)); //ここでhtmlspecialcharsするよう変更 print("<br />");   } こうやってみました。 が、しかし、ここで問題が発生。 html出力結果が、 こんにちは、山田です。&lt;br /&gt;元気ですか? こんばんは、鈴木です。&lt;br /&gt;元気です。 このように、<br />で改行して表示したいにもかかわらず、 <br />を文字列として表示してしまいました。 いったいどうやったら解決できるでしょうか? やはり、以前のやりかたに戻すべきでしょうか? わかる方、ご回答よろしくお願い致します。

    • ベストアンサー
    • PHP
  • HTMLタグのエスケープ文字をタグに戻す方法

    JavaのBufferedReaderクラスを使用して HTMLファイルを1行ずつ読み込んでまた、別のファイルに出力したところ HTMLファイル内では <br /> と表示されているところが出力ファイルでは &lt;br /&gt; というようにエスケープ文字で出力されてしまいました。 タグをそのまま出力したいのですがエスケープ文字で出力されないようにするためには どのようにすればよろしいでしょうか。

    • ベストアンサー
    • Java
  • DBから出力の際preg_replace等が効かぬ

    データベースを使ったウェブサイト。 POSTを使ったformタグより、textareaにてテキストをsql文にて、 MySqlにinsertし、(このときにmysql_real_escape_string) 読み出すときにhtmlspecialcharsしてprint。 これが一般的な流れなのですが、 上記のまま行うと、改行(\r\n)がウェブ上に見えてしまいます。 ですので、 1:print preg_replace("/\r\n/","<br />", htmlspecialchars($ans['Pt_txt1'], ENT_QUOTES, 'UTF-8')); 2:print nl2br(htmlspecialchars($ans['Pt_txt1'], ENT_QUOTES, 'UTF-8')); などをやって消そうとしているのですが消えません。 ためしに、 $aaa ="適当な文字"; 1:print preg_replace("/\r\n/","<br />", htmlspecialchars($aaa, ENT_QUOTES, 'UTF-8')); 2:print nl2br(htmlspecialchars($aaa, ENT_QUOTES, 'UTF-8')); のように、MySqlを介さずに直接出力した場合、 ちゃんと改行コードは<br />に変更してくれましたので ソースの記述ミスではないと思うのです。 原因はなににあるでしょうか。 なお、現状phpmyadminで覗くと、 「フィールドA」(mysql_real_escape_stringを通してinsert) ----- あいうえお\r\nかきくけこ ----- 「フィールドB」(mysql_real_escape_stringを通さずにinsert) ----- さしすせそ たちつてと ----- となっているフィールドがありますが、 それらがhtmlで出力されたもののソースを見ると、 ----- A:あいうえお\r\nかきくけこ B:さしすせそ<br />たちつてと となぜかBのほうが希望通りの動きをします。 cを通さずにDBに入れてしまったほうが希望通りに動きます。 さっぱり困りました。

    • ベストアンサー
    • MySQL
  • 特殊文字のエスケープについて

    今PHPを勉強しています。全くの初心者なので、本を頼りにやっているのですが、エスケープの所がうまく行きません。分かる方がいたら教えて下さい。お願い致します。 <?php //データを受け取る $text1 = @$_POST["text1"]; //特殊文字をエスケープする $text2 = htmlspecialchars($text1); //エスケープ後の値を表示する echo "<p>エスケープ後:".$text2; //「ENT_QUOTES」を指定したとき echo "<p>ENT_QUOTES:".htmlspecialchars($text1, ENT_QUOTES); //「ENT_NOQUOTES」を指定したとき echo "<p>ENT_NOQUOTES:".htmlspecialchars($text1, ENT_NOQUOTES); ?> <form method="POST" action="<?php echo $_SERVER["PHP_SELF"]?>"> <table> <tr> <td><input type="text" name="text1" value="<?php echo $text2?>"></td> <td><input type="submit" value="送信" name="sub1"></td> </tr> </table> </form> を実行して、<b>"太字"</b>を送信すると「"」の前に「\」が入ってしまいます。本では、<b>"太字"</b>のまま表示されるようなんです。。 文字コードはEUCで保存しています。

    • 締切済み
    • PHP
  • データベースのテキストデータの改行方法について

    別サイトで質問して nl2br関数を使えば改行が反映されるとわかったのですが、 <?php $str = nl2br(htmlspecialchars($str, ENT_QUOTES, 'UTF-8'), false); や <?php function h($str) { return htmlspecialchars($str, ENT_QUOTES, 'UTF-8'); } など、 上記のを試してみたのですが、データベース上のテキストデータの改行がサイトに反映されず困っております。 http://uploda.cc/img/img52b55ee23c01f.png このようにDBに記入したデータをどのようにすれば改行されますでしょうか? 初心者で非常に申し訳ございませんが宜しくお願いします。

    • 締切済み
    • PHP
  • HTMLタグを機能させて出力する際のエスケープ処理

    「HTMLタグを機能させて出力する」際のエスケープ処理は、どうすれば良いでしょうか? <例> ビューファイルの<head>タグ内に、下記のような文字列を渡して、実際に、タグとして機能させたい場合 <link rel="stylesheet" href="hoge.css"> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script> この場合、やり方としては、通常の文字列を渡すときのように、htmlspecialcharsで一旦「HTML エンティティに変換」した後、何らかの方法(htmlspecialchars_decode?)で元に戻すのでしょうか? それとも、「HTML エンティティに変換」した後、再変換してタグとして使うことが明白な場合は、わざわざ「HTML エンティティに変換」する必要はないのでしょうか? つまり、「HTMLタグを機能させて出力する」際のエスケープ処理は必要ない。やることと言えば、せいぜい、セッターで一旦、privateプロパティへ格納後、ゲッターで取り出すぐらい、なのでしょうか?

    • ベストアンサー
    • PHP
  • PHPの入力フォームの確認画面の構文エラー

    <?php session_start(); require_once "define.php"; echo "<b>質問内容</b><br>"; echo "タイトル : ".htmlspecialchars($_SESSION[TITLE], ENT_QUOTES)."<br>"; echo "URL : ".htmlspecialchars($_SESSION[URL], ENT_QUOTES)."<br>"; echo "メール : ".htmlspecialchars($_SESSION[MAIL], ENT_QUOTES)."<br>"; echo "<br>質問ありがとうございました。<br><br>"; echo "<a href=\"./index.php\">入力フォームに戻る</a>"; ?> こういう感じのPHPの構文を書いたんですがなぜか echoで表示してあるタイトル、URL、メールのところが ちゃんと表示されません define.phpは間違いなくちゃんとファイルとして書いてあります どこか間違っているところがあるのでしょうか? 原因がわかりません、一日中悩んだけど 答えがわかりません、どなたかよろしくお願いします。

    • 締切済み
    • PHP
  • POSTされたデータをそのまま変数名にするような・・・

    お世話になります。 タイトルのとおりなのですが、POSTされたデータをそのまま変数名にするような便利な方法はないでしょうか。 $name=htmlspecialchars($_POST["name"], ENT_QUOTES, $code); $email=htmlspecialchars($_POST["email"], ENT_QUOTES, $code); ・ ・ ・ をたくさんあるので簡単にできないかなーと思ったんですが、何か良い方法がありましたら教えてください。 よろしくお願いいたします。

    • ベストアンサー
    • PHP
  • ▲▲HTMLで特殊記号を入力する際にへんになる??▲▲

    こんばんは☆ HTMLで特殊記号を表示させる場合、例えば☆ < →&lt; 又は < > →&gt; 又は > とあるのはわかっているのですが、もしこのようなタグの中に組み込む場合どのように記入すればよいでしょうか?? -----例----- &title02=<font color="#000000">基本タグ</font>& &data02=例HTML& ------------ ↑これはフラッシュを設定するtxtに書かれているものです。すでに&が入っているためか・・・。 ↓のように入力すると -----例----- &title02=<font color="#000000">基本タグ</font>& &data02=例&lt;HTML&gt;& ------------ 基本タグ 例 ------------ ↑このように表示されてしまいます・・・。 本当は↓ ------------ 基本タグ 例<HTML> ------------ ↑このように表示させたいのです。。。。 わかる方、教えてください♪ よろしくお願いします♪

    • ベストアンサー
    • HTML
  • htmlspecialcharsとその逆

    こんにちは。PHP(&mySQL)初心者です。 基本的な事かもしれませんが、自分で調べてもよくわからないので、どなたかご教示いただけないでしょうか。 下記のような2つのファンクションが定義されているとします。 <?php function h($value) { return htmlspecialchars($value, ENT_QUOTES, 'UTF-8'); } ?> <?php function dec($hd_value) { return htmlspecialchars_decode($hd_value); } ?> フォームから受け取った文字列を「h()」で処理した上で、DB(mySQL)に格納し、ブラウザで表示するときは、DBから受け取った文字列を「dec()」で元に戻しています。 通常は、これで問題ないのですが、文字列に「<br/>」のようなHTMLタグと「<jpSampleTag=lnum1>」のような独自のタグ(のようなもの)が混在してた場合、ブラウザでの表示時に「<jpSampleTag=lnum1>」が無視されて表示されません。 一応、「dec(h($value))」のように、入れ子にすると「<jpSampleTag=lnum1>」の部分も表示されることがわかったのですが、今度はhtmlのタグのヤマ括弧まで「&lt;」のようなhtmlエンティティに変換されてしまい、改行などができずに困っています。 htmlタグだけを復元する方法はないものでしょうか? あるいは、DBに文字列を格納する段階で、なにか別の処理をした方がいいのでしょうか。 どなたか良い方法をご存知の方がいらっしゃいましたら、ご教示いただけないでしょうか。 よろしくお願いします。

    • ベストアンサー
    • PHP

専門家に質問してみよう