collecting an HTTP quoted string

引用文字列 (電子メール、HTTP)

[91] 電子メールおよび派生プロトコルの構文要素 quoted-string は、" で括られた文字列です。

quoted-string の仕様

RFC 724 (電子メイル)

[26] quoted-string を規定した最初のメイル規格です。 基本的には現在の電子メイル仕様と同じなのですが、 quoted-pair が無い代わりに <""><"> を表現しました。

この規格は廃止されて既に随分経っていて、この形式のメッセージはみたことがありません。 (但し RFC 724 の quoted-string の形式と Micro$oftVisualBasic文字列型の表記法は同じです。 おそらく偶然だとは思いますが。)

[16]

 <quoted-string>   ::=   <double quote mark ("), decimal 34>
                         <a sequence of one or more TELNET
                          ASCII characters, where two
                          adjacent quotes are treated as a
                          single quote and part of the
                          string> <">

>>16ABNF で書き直すと、こうです。

  • [19] quoted-string = <"> qcontent <">
  • [20] qcontent = qtext / quotes
  • [21] qtext = 1*(%x00-09 / %x0B-0C / %x0E-21 / %x23-7F)
  • [22] quotes = <"">

[23] >>16 では <"> の出現が禁じられていませんが、常識的に考えてそんなもんは出てきてはいかんでしょう。 (>>21)

[25] >>16 では ASCII なんでもありのように読めるけど、 >>24 を読むと CRLF が認められていないことがわかる。 (>>21) (単独の LF は認められているんだろうか?)

[24] II.B.1.C.3) Quoted strings

Where permitted (i.e., in structured fields) quoted strings are treated as a single symbol (i.e. equivalent to an <atom> syntactically). However, if quoted strings are to be "folded" onto multiple lines, then the syntax for folding must be adhered to (See items II.B.1.a.1, above, and II.B.1.c.6, below.) Note that the official semantics do not encounter <crlf>s in quoted strings, although particular parsing programs may wish to note their presence.

認められているところ (つまり構造化欄の中) では引用符で囲まれた文字列を単一の記号 (つまり構文的に <atom> と等しいもの) として取り扱います。しかし、引用符で囲まれた文字列が複数行に「折畳まれ」ている時は、折畳みの構文に従わなければいけません。なお、公式な意味では引用符で囲まれた文字列中に <crlf> は現れません。解析プログラムでこの出現に注意したいと思うのがあるかもしれませんが。

  • [18] BS が最初に来てはいけません。 (>>12 と同じ)

RFC 733 (電子メイル)

[13] RFC 733 の規定はほぼそのまま RFC 822 に受け継がれました。詳しくは RFC 822 の節 (>>14) と RFC 733 urn:ietf:rfc:733 をご覧下さい。

 quoted-string = <"> *(qtext/quoted-pair) <">; Any number of qtext
                                             ;   chars or any
                                             ;   quoted char.
 qtext       =  <any CHAR excepting <">      ; => may be folded
                 and CR, and including
                 linear-white-space>
 quoted-pair =  "\" CHAR

[15] qtext"\" が除外されていないので、これでは quoted-pair の構文解析が出来なくなってしまいますが、 RFC 822 で修正されています (>>14) し、単なる不具合と考えて良いでしょう。

[17] RFC 724 の方法 (>>16) とは互換性がありません。

RFC 822 (電子メイル)

[14]

 quoted-string = <"> *(qtext/quoted-pair) <">; Regular qtext or
                                             ;   quoted chars.
                 ; 普通の qtext か引用符で囲んだ文字
 qtext       =  <any CHAR excepting <">,     ; => may be folded
                 "\" & CR, and including
                 linear-white-space>
                 <任意の CHAR。但し <">, "\", CR を除き、
                  linear-white-space を含む>
                 ; ⇒折畳んでも良い。
 CHAR        =  <any ASCII character>        ; (  0-177,  0.-127.)
 quoted-pair =  "\" CHAR                     ; may quote any char
                 ; 任意の文字を quote 可能

[3] phrase 中では、前後に隣接する word との間に SPACE が1つあると仮定します。 (実際の LWSP-char の数によらず 1SPACE とします。)

複数の LWSP-char を入れたいときは <"> の内側に入れます。 (3.4.4)

例えば、 atom1 (SP) "quoted-string" (SP) (TAB) atom2atom1 (SP) quoted-string (SP) atom2 と解釈され、 atom1 (SP) " (TAB) quoted-string" (TAB) (TAB) atom2atom1 (SP) (TAB) quoted-string (SP) atom2 と解釈されます。

[4]

3.4.5. QUOTED-STRINGS 引用符で囲まれた文字列

Where permitted (i.e., in words in structured fields) quoted-strings are treated as a single symbol. That is, a quoted-string is equivalent to an atom, syntactically. If a quoted-string is to be "folded" onto multiple lines, then the syntax for folding must be adhered to. (See the "Lexical Analysis of Messages" section on "Folding Long Header Fields" above, and the section on "Case Independence" below.) Therefore, the official semantics do not "see" any bare CRLFs that are in quoted-strings; however particular parsing programs may wish to note their presence. For such programs, it would be reasonable to interpret a "CRLF LWSP-char" as being a CRLF which is part of the quoted-string; i.e., the CRLF is kept and the LWSP-char is discarded. Quoted CRLFs (i.e., a backslash followed by a CR followed by a LF) are also subject to rules of folding, but the presence of the quoting character (backslash) explicitly indicates that the CRLF is data to the quoted string. Stripping off the first following LWSP-char is also appropriate when parsing quoted CRLFs.

認められているところ (例えば構造化欄の word 中) では quoted-string は単一の記号として扱われます。 つまり、構文的には 1つの quoted-string は 1つの atom に相当します。 quoted-string が複数行に「折畳まれ」る場合、折畳みの構文を守らないといけません。 (上の「メッセージの字句解析」節の「長い頭欄の折畳み」と下の 「大文字・小文字不区別性」を参照。) 従って、公式な意味では生の CRLFquoted-string 中で見ることはありません。 しかし解析プログラムにはこの出現に注意したいと願うのもあるかもしれません。 そうしたプログラムでは、「CRLF LWSP-char」 を quoted-string の一部である CRLF と解釈するのが良いでしょう。従って CRLF は残して LWSP-char は捨てます。 Quote された CRLF (つまり逆斜線に CR と LF が続くもの。) も折畳みの規則の対象ですが、 quote 文字 (逆斜線) の存在が CRLFquoted-string のデータの一部であることを明示しています。 Quote された CRLF を解析する時には最初に続く LWSP-char を読み飛ばすのも適切でしょう。

  • [5] >>4 の後半部分の解釈:
  • [6] (a) 「qtext CRLF LWSP-char qtext」は「qtext LWSP-char qtext」と解釈する。
  • [7] (b) 「qtext CRLF LWSP-char qtext」は「qtext CRLF qtext」と解釈しても良い。
  • [8] (A) 「qtext "\" CRLF LWSP-char qtext」は「qtext CRLF LWSP-char qtext」と解釈する。
  • [9] (B) 「qtext "\" CRLF LWSP-char qtext」は「qtext CRLF qtext」と解釈しても良い。
  • [10] >>6-9 であってますかね? しかしこうだとすると、(欄の定義を見ずに) CRLF LWSP-char ⇒ LWSP-char という風に unfolding を実装することが出来なくなってしまいます...

HTTP メッセージ

RFC 1945 HTTP/1.0 によると、

  1. quoted-string = ( <"> *(qdtext) <"> )
  2. qdtext = <any CHAR except <"> and CTLs, but including LWS>

[55] RFC 2068 (HTTP/1.1) によると:

  • [56] quoted-string = ( <"> *(qdtext) <"> )
  • [57] qdtext = <any TEXT except <">>
  • [58] quoted-pair = "\" CHAR

[59] RFC 2616 HTTP/1.1 によると、

  1. quoted-string = ( <"> *(qdtext | quoted-pair ) <"> )
  2. qdtext = <any TEXT except <">>
  3. quoted-pair = "\" CHAR

[60] HTTP/1.0 では quoted-pair が使えなかったと。それで HTTP/1.1 でも使えるけど使えないみたいな玉虫色。 See メッセージ頭のcomment の HTTP のとこ。 (さすがに RFC 733 の bug (>>15) を引きずってるのではないでしょう。)

  1. http1.0.quoted-string = <"> http1.0.qcontent <">
  2. http1.0.qcontent = *http1.0.qtext
  3. http1.0.qtext = %x20-21 / %x23-%x7E / FWS
  1. http1.1.quoted-string = <"> http1.1.qcontent <">
  2. http1.1.qcontent = *( http1.1.qtext / http.quoted-pair )
  3. http1.1.qtext = %x00-21 / %x23-5B / %x5D-FF
  4. http.quoted-string = "\" %x00-7F

[46] たぶん HTTP/1.1 でも qdtext に LWS が使えると解釈したほーがいいんだろうけど、 HTTP だと単独の CR が使えるから BNF がちょいとばかり複雑になるなあ。

[54] HTTP でも CHAR = %x00-7F ですから、 quoted-pair で8ビットの値を使用することは出来ません。

     quoted-string  = DQUOTE *( qdtext / quoted-pair ) DQUOTE
     qdtext         = HTAB / SP /%x21 / %x23-5B / %x5D-7E / obs-text
     obs-text       = %x80-FF
     quoted-pair    = "\" ( HTAB / SP / VCHAR / obs-text )
  1. "
  2. *
    1. |
      1. qdtext
      2. =
        1. \
        2. |
          1. "
          2. \
  3. "

[93] RFC 7616unq() 構文により、引用文字列から " を除去したもの >>92 を表しています。 quoted-pair の扱いは不明瞭です。

RTSP メッセージ

[48] HTTP/1.1 (RFC2068) 派生プロトコルの1つ、 RTSP/1.0 (RFC2326) は次のように定義しています。

  • [49] quoted-string = ( <"> *(qdtext) <"> )
  • [50] qdtext = <any TEXT except <">> ;; %x20-21 / %x23-7E / %x80-FF
  • [51] quoted-pair = "\" CHAR ;; "\" %x00-7F

[52] RTSP において8ビットの値は UTF-8 と解釈されます。 >>51 にあるように8ビットの時は quoted-pair が使えません。単に HTTP からのコピペで済ませたから使えないままなのか、 UTF-8 の2オクテット目以降を quote するのかの問題が生じるのが嫌だから敢えて使えないままにしたのかはわかりません。

[53] >>49-50 quoted-pair をどこに使うのかわからないのは HTTP 譲りでしょうか(藁)。

SIP メッセージ

[27] HTTP を元にしてる SIP だけど、びみょーに違う。いやらしーのは HTTP/1.1 と同じ。(たぶん何も考えずに写したんだ。)

  1. quoted-string = ( <"> *(qdtext | quoted-pair ) <"> )
  2. qdtext = <any TEXT-UTF8 except <">>
  3. quoted-pair = " \ " CHAR

[47] " \ " はたぶん "\" の間違いだ。そー信じたい。

  1. sip.quoted-string = <"> sip.quoted-string <">
  2. sip.qcontent = *( sip.qtext / http.quoted-pair )
  3. sip.qtext = %x20-21 / %x23-5B / %x5D-7E / utf8-xtra-char / FWS

CGI

[87]

      quoted-string = <"> *qdtext <">
      qdtext        = <any CHAR except <"> and CTLs but including LWSP>

[89] これは実質的に RFC 1945 の定義と一致しています。

仕様書

RFC 2822 (電子メイル)

3.2.2. Quoted characters

Some characters are reserved for special interpretation, such as delimiting lexical tokens. To permit use of these characters as uninterpreted data, a quoting mechanism is provided.

[35] 幾つかの文字は単語字句を区切るためなどの特別な解釈に予約されています。 こうした文字を解釈しないデータとして使うことを可能にするため、 quote 機構を提供します。

  • [36] quoted-pair = ("\" text) / obs-qp

Where any quoted-pair appears, it is to be interpreted as the text character alone. That is to say, the "\" character that appears as part of a quoted-pair is semantically "invisible".

[37] quoted-pair が出現したら、これは text 文字だけであると解釈されます。言い換えれば、 quoted-pair の一部として出現する "\" 文字は意味的には「不可視」です。

Note: The "\" character may appear in a message where it is not part of a quoted-pair. A "\" character that does not appear in a quoted-pair is not semantically invisible. The only places in this standard where quoted-pair currently appears are ccontent, qcontent, dcontent, no-fold-quote, and no-fold-literal.

[38] 注意: "\" 文字はメッセージ中で quoted-pair の一部でない場所で出現するかもしれません。 quoted-pair 中でない "\" は意味的に不可視ではありません。 この規格中で現在 quoted-pair が出現するのは ccontent, qcontent, dcontent, no-fold-quote, no-fold-literal だけです。

3.2.5. Quoted strings

Strings of characters that include characters other than those allowed in atoms may be represented in a quoted string format, where the characters are surrounded by quote (DQUOTE, ASCII value 34) characters.

[28] atom 中で認められている以外の文字を含む文字列は引用符で囲まれた文字列形式, すなわち引用符 (DQUOTE, ASCII34) 文字で囲まれた文字を使って表現しても構いません。

[29]

 qtext          =       NO-WS-CTL /     ; Non white space controls
                                        ; 非空白間隔制御文字
                        %d33 /          ; The rest of the US-ASCII
                        %d35-91 /       ;  characters not including "\"
                        %d93-126        ;  or the quote character
                                        ; "\" や引用符文字を除いた US-ASCII 文字

  • [30] qcontent = qtext / quoted-pair
  • [31] quoted-string = [CFWS] DQUOTE *([FWS] qcontent) [FWS] DQUOTE [CFWS]

A quoted-string is treated as a unit. That is, quoted-string is identical to atom, semantically. Since a quoted-string is allowed to contain FWS, folding is permitted. Also note that since quoted-pair is allowed in a quoted-string, the quote and backslash characters may appear in a quoted-string so long as they appear as a quoted-pair.

[32] quoted-string は1単位として扱います。 つまり、 quoted-string は意味的には atom と同一です。 quoted-stringFWS を含むことを認めていますから、折り畳みが認められます。 quoted-string 中で quoted-pair が認められているので、引用符文字及び逆斜線文字は quoted-pair としてなら quoted-string 中に出現しても構わないことにも注意して下さい。

Semantically, neither the optional CFWS outside of the quote characters nor the quote characters themselves are part of the quoted-string; the quoted-string is what is contained between the two quote characters. As stated earlier, the "\" in any quoted-pair and the CRLF in any FWS/CFWS that appears within the quoted-string are semantically "invisible" and therefore not part of the quoted-string either.

[33] 意味的には、引用符文字の外側の省略可能な CFWS も引用符文字自体も quoted-string の一部ではありません。 quoted-string は2つの引用符文字の間に含まれるものです。 上述の通り、 quoted-string 中に出現する quoted-pair 中の "\" 及び FWS/CFWS 中の CRLF は意味的には「不可視」であって従ってこれもまた quoted-string の一部ではありません。

メモ

[42]

 text           =       %d1-9 /         ; Characters excluding CR and LF
                        %d11 /          ; CR, LF を除く文字
                        %d12 /          ;; RFC 2822 3.2.1
                        %d14-127 /
                        obs-text
[45]
 obs-char       =       %d0-9 / %d11 /          ; %d0-127 except CR and
                        %d12 / %d14-127         ;  LF
-[43] obs-text        =       *LF *CR *(obs-char *LF *CR) ;; RFC 2822 4.1
-[44] obs-qp          =       "\" (%d0-127) ;; RFC 2822 4.1
-[40] no-fold-quote   =       DQUOTE *(qtext / quoted-pair) DQUOTE ;; RFC 2822 3.6.4 (Message-ID)

USEFOR (電子ニュース)

[61] usefor-article (08) は次のような構文を定義しています。

  • [64] quoted-string = [CFWS] DQUOTE *( [FWS] qcontent ) [FWS] DQUOTE [CFWS]
  • [62] quoted-pair = "\" text
  • [63] qcontent = qtext / quoted-pair [65]
          text            = %d1-9 /            ; all UTF-8 characters except
                            %d11-12 /          ; US-ASCII NUL, CR and LF
                            %d14-127 /
                            UTF8-xtra-char

  • [67] strict-quoted-string = [CFWS] DQUOTE *( [FWS] strict-qcontent ) [FWS] DQUOTE [CFWS]
  • [68] strict-quoted-pair = "\" strict-text
  • [69] strict-qcontent = strict-qtext / strict-quoted-pair

[66]

      strict-qtext    = NO-WS-CTL /        ; qtext restricted to
                        %d33 /             ; US-ASCII
                        %d35-91 /
                        %d93-126
[71]
      no-fold-quote      = DQUOTE
                              *( strict-qtext / "\\" / "\" DQUOTE )
                              qspecial
                              *( strict-qtext / "\\" / "\" DQUOTE )
                              DQUOTE
[72]
      qspecial           = "(" / ")" /        ; same as specials except
                           "<" / ">" /        ; "\" and DQUOTE quoted
                           "[" / "]" /
                           ":" / ";" /
                           "@" / "\\" /
                           "," / "." /
                           "\" DQUOTE

[70] RFC 2822 の定義 (>>31) から非推奨構文を除き UTF-8 の文字を加えたものが quoted-string (>>64) 及び quoted-pair (>>62) です。また、電子メイル・アドレスの local-part などで使われる strict-quoted-string (>>67) は、 RFC 2822 の quoted-string (>>31) から非推奨構文を除いたものです。

[73] Message-ID で使う RFC 2822 の no-fold-quote (>>40) も更に厳格化されています。これはニュースに於いてメイル以上に重要な意味を持つ Message-ID の比較などを簡単に行えるようにするためです。 Usefor の no-fold-quote は、 RFC 2822 同様に UTF-8 の文字が使えない上に、 quoted-pair が使えるのは "\\" 及び <\"> の2種類のみです。 又、 specials に該当する文字が含まれていない場合は使うことが出来ません。 [74] (これでもまだ dot-atom-text が quote あり/なし2種類で表せるなあ。)

encoded-word と quoted-string

[75] MIMEencoded-word は、 RFC2047 (やその以前の RFC) によれば quoted-string の内側 (qcontent) で使うことは出来ません。ですから、 "=?us-ascii?q?foo?="encoded-word を含む quoted-string のように見えますが、単なる =?us-ascii?q?foo?= という文字列であって、 fooencoded-word ではありません

[76] >>75 なのですが、 M$OE のようなふざけた利用者エージェントが長く間違った利用を続けていたこともあって、バグ互換性のためにこの方法を使う UA は多いです。

[85] RFC 5255IMAP国際化に関する仕様ですが、 関係する情報源としていくつかの文書を挙げています。 その中で、ファイル名のための二重引用符の内側 (Content-Disposition: 欄の filename 引数のことと見られます。) で非標準ながら encoded-word が使われていることに言及されています。

だからどうしろとは特に述べていません。

パラメーター値である quoted-string

[77] MIMEContent-Type:欄などで導入した prameter では、値の部分 (ABNF でいう value) を token 又は quoted-string としています。 つまり、特殊文字が値に使われる場合には quoted-string が使われ (るか、後に導入された RFC2231MIMEのparameter値拡張が使われ) ます。 この方法は HTTP の一部の欄や usefor-article などの MIME に倣った幾つかの仕様でも採用されています。

[78] RFC 2231 による拡張の導入は MIME 本体より遅れ、未だにその存在を知らない人もいるくらいで、 >>75 のような encoded-word を使った例や、 シフトJIS などを (規格に反して) 直書きする実装が多く存在しています。 特に Content-Disposition:欄filename パラメーターで問題となっています。

[79] >>78 また、 RFC 2231 の方法の標準化以前に制定された規格ではこの方法を規定してしまったものもあります。 (MIMEのparameter値拡張 (>>3))

[86] multipart/form-data の項の引数の値としての quoted-string に関する説明も参照してください。

歴史

[11] RFC 7232 では、 RFC 2616 まで引用文字列だった実体タグを独自構文に変更しています。

メモ

[83] RFC 5335 により、 message/global においては quoted-string 中で UTF-8 の使用が認められるようになりました (RFC 5335 4.3)。

(名無しさん)

[84] (正確には utf8-quoted-string) (名無しさん)

[94] Feedback from @reschke. (@reschke著, ) https://github.com/w3c/webappsec-clear-site-data/commit/9f20dcc7580e241636c4787b6cf852a7e6258d63

[96] Define the Content-Type header parser (annevk著, ) https://github.com/whatwg/fetch/commit/0b2bc05b2550dcbefe1321ea3e8026702514a798

[97] Use collect an HTTP quoted string from Fetch (annevk著, ) https://github.com/whatwg/mimesniff/commit/8e9a7dd90717c595a4e4d982cd216e4411d33736

[98] Use collect an HTTP quoted string by annevk · Pull Request #92 · whatwg/mimesniff () https://github.com/whatwg/mimesniff/pull/92