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

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

ただいまの
回答率

90.47%

  • PHP

    20839questions

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

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

受付中

回答 3

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 411

fbygqw

score 29

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


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

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

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

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

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

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

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

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

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

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

+4

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

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

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

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

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

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

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

1<>&lt;&gt;お<>test1<>2017092811: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/30 06:45

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

    なんかよく分からないんですけど、だーからteratailは以前、トップに羅列された質問のプレビューにおいて&lt;とか&gt;とか寝ぼけた表記を平気でしていたのですか?

    キャンセル

  • 2017/09/30 06:50

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

    頭おかしい人、結構たくさん居るんですよ、世の中には。

    キャンセル

+2

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

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

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

 制御文字

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

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

 エスケープ

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

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

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

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

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


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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

-7

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

うん、分かり易い♪

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 90.47%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

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

  • PHP

    20839questions

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