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

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

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

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

Q&A

3回答

284閲覧

文字の重複(?)について

fbygqw

総合スコア37

PHP

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

0グッド

1クリップ

投稿2017/09/29 07:57

編集2017/09/29 09:30
1<>なお<>test1<>2017年09月28日 11:01:57<>pass1 2<>まき<>test2<>2017年09月28日 11:02:05<>pass2

こんなデータがtext.txtに保存されていたとして、それをphpで読み込んでexplode<>で分割して表示するというものを度々見かけます。
ここで、もしも"なお"という部分に<>が入力されたら、explodeの分割がおかしいことになってしまうと考えました。
調べたところ、非常に情報が少なかったですがwikipediaの記事がヒットしました。しかし、文章が難しくて、なかなか理解することができません。
どなたか分かりやすくご教授していただけないでしょうか?

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

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

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

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

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

guest

回答3

0

データを<>で区切る方法は、CGIやPHPでかなり昔から使われていた方法です。私は2chのdatフォーマットで知りました。いつ頃からあって、どこの誰がオリジナルかまではわかりませんが、当時(2000年前後)は掲示板等でデータを保存する方式としてよく使われていました。私も、同じ方式で掲示板を自作したこともあります。この方式は何だったのか、掲示板等のデータとして保存するときになぜこれが良かったのかを説明します。

###生データとして表れない文字列

通常、掲示板においては、ユーザーはあらゆる文字を入力でき、それを投稿できます。その中にはいわゆるHTMLタグの表記をそのまま書いている物もあります。しかし、HTMLタグをそのまま受け付け、掲示板に表示したすることは大変危険です。たとえば、<script>...</script>のようにJavaScriptを埋め込んで、任意のJavaScriptを実行させることができてしまうからです。

そこで、HTMLタグを許さないような掲示板では、サニタイジングと言う処理でタグの開始や終了である<>&lt;&gt;に変換するようになっていました。つまり、投稿されたデータをサニタイジングしたあとのデータには絶対に<>は含まれなくなると言うことです。

###含まれない文字を使って区切るという発想

もう、おわかりですね。ユーザーから投稿されたデータはサニタイジングによって<>も絶対に無い状態になりました。そこで<>を区切り文字に使うと、データの中に<>が含まれることは絶対に無いため、再度分割するときに間違うことが無いと言うことです。

具体的に、もし"なお"というデータではなく"な<>お"というデータが保存された場合はどうなるかというと、

1<>な&lt;&gt;お<>test1<>2017年09月28日 11:01:57<>pass1

となって、<>の分割がおかしくなることはありません。

###サニタイジング済みのデータを保存すると言うこと

そもそも、なぜサニタイジング済みのデータを保存するのでしょうか?

この形式の掲示板では、ファイルから読み込んだデータはすでにサニタイジング済みになっていますので、再度サニタイジングする処理も不要ですので、表示するだけで済みます。その分、処理が軽くなると言うことです。

(本来の意味での)世紀末であった当時、最新のサーバーであっても、その性能は現在のスマホ以下です。そんなしょぼしょぼなサーバーで動かしていましたので、ちょっとした処理の重さの違いはCGI/PHPの表示速度に目に見えるほどの影響を与えるものでした。そういったこともあって、この方式になったと__当時の__私は思っていました。

詳しいことは長くなるので省略しますが、サニタイジングしたデータを保存し、それを信頼するという方法は、今にして思うと良くなかったと思っています。

###なぜ2文字なのか?

さて、<>を使うのはわかったところで、なぜ、<だけ>だけにしないのでしょうか?1文字だけの方がファイルサイズも小さくなりますし、処理も速くなるはずです。

実際にこのデータ方式で作ってみるとわかるのですが、生データの見やすさが異なると言うことです。

1<>なお<>test1<>2017年09月28日 11:01:57<>pass1 1<なお<test1<2017年09月28日 11:01:57<pass1 1>なお>test1>2017年09月28日 11:01:57>pass1

1行目に比べて、2行目3行目はぱっと見えてきません。当時はユニットテストだデバッグでステップ実行だなんてものは__私は__知らなかった(今でもそんなにしてないような気もするけど)ので、開発中は生データの確認を何度も行うというローテクな方法でやっていました。となると、区切りが想定通りされているかすぐに確認できるかどうかは重要なことです。

つまり、人間の目からも見やすかったと言うことです。時には、データを直接修正というのも必要だったりしますし、そのときも扱いやすいというのもありました。

###現代においてこれは利用すべきなのか?

2chのような古くからあって互換性のために残しているというのであればいざ知らず、新規に作成する物にこの方法を使うのは、私は既に古くさい方法であると考えています。

まず、もしできるのであればデータベースを利用すべきです。当時はデータベース自体が高級であり、使用できる環境が非常に限られていました。しかし、現在のWebサーバー環境ではデータベースを利用できるところが多くなっていると思います。また、MariaDBやPostgreSQLのようなサーバー型データーベースが利用できなくても、SQliteのようなファイル型データベースという選択肢もあります。

次に、データベースが使えないとしても、データの保存形式は、独自ではない規格化されたフォーマットを使うべきと考えます。XMLやJSONなどです。なぜなら、これらは優れたパーサーがライブラリとして提供されているため、下手に独自形式を実装するよりも高速かつ安全に利用できる場合が多いからです。

初めの方を読んでいただければわかるとおり、この方法は<>をサニタイジングすることが前提であり、実質Webでしか使えません。その意味でも汎用性に欠けていると言えます。昔はそんなこともしていたなー程度で捉えた方が良いのでは無いかと思います。

投稿2017/09/29 14:32

raccy

総合スコア21735

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

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

退会済みユーザー

退会済みユーザー

2017/09/29 21:45

-------------------------------------------------------- そこで、HTMLタグを許さないような掲示板では、サニタイジングと言う処理でタグの開始や終了である<と>を&lt;と&gt;に変換するようになっていました。つまり、投稿されたデータをサニタイジングしたあとのデータには絶対に<と>は含まれなくなると言うことです。 -------------------------------------------------------- なんかよく分からないんですけど、だーからteratailは以前、トップに羅列された質問のプレビューにおいて&lt;とか&gt;とか寝ぼけた表記を平気でしていたのですか?
退会済みユーザー

退会済みユーザー

2017/09/29 21:50

あと、実話としては、普通の企業のシステムの認証系で、大して意味もわかってない感じで"ID<>customer_category<>timestamp"みたいなのをmd5した値をCookieに持たせて認証している謎システムも見たことありまぁーす。 頭おかしい人、結構たくさん居るんですよ、世の中には。
guest

0

Raccyさんのご回答に補足します。

サニタイズを前提とすれば、<>を使って「含まれない文字を使って区切る」を実現できました[1]。一方、現在の多くのアプリケーションがそうであるように、データ格納時にサニタイズをしない (出力時に文字参照に変換する) のであれば、ほとんどの文字をデータに含めることができてしまいます。ですから、通常の文字を区切り文字に選ぶことができません。

これに対する対策として、ウィキペディアの解説では、次のような方式を挙げています (一部のみとりあげます)。

制御文字

制御文字 (たとえば、タブ文字) は普通のテキストには現れませんから、これを区切り文字にする。

ただし、データに制御文字が含まれないよう、サニタイズが必要です。また、制御文字は通常の文字のようにはっきり表示されるとは限らないので、生データをテキストエディタなどで編集する (そういうことをする必要があるのなら) ときに制御文字を削除してしまうなど、データ破損を起こすリスクも高まります。

エスケープ

文字の前や後に特別な文字を置いた場合は通常の文字と違う意味 (この場合はデータの区切り) を持つと見なす。たとえば多くのプログラミング言語で、文字列中で\が前についた文字は特別な意味を持ちます。制御文字のような表示に問題のある文字を使わないので、生データの編集も安全にできます。

ただし、処理が複雑になります。「前や後に特別な文字が置かれた文字」を検出するには、テキストを最初 (または最後) から1文字ずつ順番に見ていく必要があります (どうしてそうなるのかについては、自分で考えてみてください)。つまり、explode()などで簡単に分割することはできません。

また、特別な文字と決めた文字自身も、エスケープが必要になります。先の例で言うと、\自身を表すには「特別な文字ではない」という「特別な意味」を持たせなければいけなくなってしまいます。そこで、「\が前についた文字」にして、\などと表すことになります。

HTMLなどで用いられる文字参照も、エスケープの一種であると言えます。&で始まるある決まった文字の並びが、特定の文字を表すことに決まっています (&自身を表すのにも文字参照を使います)。また、区切り文字の重複 (データ中に区切り文字と衝突する文字が現れた場合、文字を重複させることで区切り文字でないことを示す) という方法も、エスケープの一種であると言えます。これらもやはり、区切り文字を検出するにはテキストを最初から1文字ずつ順番に見ていく必要があります。

とはいえ、Raccyさんもおっしゃるように、現在ではこのようなデータの処理を一から自分で書くことは少なくなってきていると思います。しかるべきパーサライブラリを使って、特別な文字を意識することなく本来のデータを読み書きできる場合が多いでしょう。


[1] 余談ですが、<>が使われたのは、万一これが出力されるHTMLに含まれてしまっても、多くのブラウザで無意味なタグとして無視される、という利点もあったのではないかと推察します。<>だけを区切りにしていた場合、万一出力にまじってしまうとその前後のテキストまで表示されなくなる可能性があります。

とはいえ現在の視点では、そのようなことが起こり得るようなプログラミング手法自体に問題があると言えます。やはり、現在では奨められる方式ではありません。

投稿2017/10/03 04:28

ikedas

総合スコア4317

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

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

0

それが分かっていてどうしてもそうしたいなら、エスケープの仕様を追加するんすよ。

うん、分かり易い♪

投稿2017/09/29 08:05

編集2017/09/29 08:07
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

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

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問