“CGI.unescapeHTML”的不完整性

时间:2014-04-07 11:35:05

标签: html ruby escaping cgi

CGI.unescapeHTML似乎无法用HTML格式表达字符,例如"<",它以HTML格式转义为"&lt;"

require "cgi"
CGI.unescapeHTML("&lt;") # => "<"

但是,当谈到可以用字面表达或不表达的字符时,它似乎并没有超越它。例如,"§"可以用HTML表示为"&sect;",而后者不会被此方法转义:

CGI.unescape("&sect;") # => "&sect;"
  1. 这是一个功能吗?有没有办法完全取消包含这些字符的HTML字符串?
  2. 我可以在Ruby 1.9.3的RDoc中找到有关CGI.escapeHTMLCGI.unescapeHTML的说明,但我找不到最新的Ruby。什么事发生在他们身上?他们被诽谤了,或者这些方法有没有变化?

2 个答案:

答案 0 :(得分:2)

您可以在CGI::Util中找到有关较新Ruby版本的文档。 CGI::Util还定义了一个带有特殊字符及其转义值的常量。那个清单很短:

> CGI::Util::TABLE_FOR_ESCAPE_HTML__
{
    "'"  => "&#39;",
    "&"  => "&amp;",
    "\"" => "&quot;",
    "<"  => "&lt;",
    ">"  => "&gt;"
}

查看unescapeHTML的实现,您会发现一些替换项,具体取决于字符串的字符集:

# File lib/cgi/util.rb, line 43
def unescapeHTML(string)
  return string unless string.include? '&'
  enc = string.encoding
  if enc != Encoding::UTF_8 && [Encoding::UTF_16BE, Encoding::UTF_16LE, Encoding::UTF_32BE, Encoding::UTF_32LE].include?(enc)
    return string.gsub(Regexp.new('&(apos|amp|quot|gt|lt|#[0-9]+|#x[0-9A-Fa-f]+);'.encode(enc))) do
      case $1.encode(Encoding::US_ASCII)
      when 'apos'                then "'".encode(enc)
      when 'amp'                 then '&'.encode(enc)
      when 'quot'                then '"'.encode(enc)
      when 'gt'                  then '>'.encode(enc)
      when 'lt'                  then '<'.encode(enc)
      when /\A#0*(\d+)\z/        then $1.to_i.chr(enc)
      when /\A#x([0-9a-f]+)\z/i  then $1.hex.chr(enc)
      end
    end
  end
  asciicompat = Encoding.compatible?(string, "a")
  string.gsub(/&(apos|amp|quot|gt|lt|\#[0-9]+|\#[xX][0-9A-Fa-f]+);/) do
    match = $1.dup
    case match
    when 'apos'                then "'"
    when 'amp'                 then '&'
    when 'quot'                then '"'
    when 'gt'                  then '>'
    when 'lt'                  then '<'
    when /\A#0*(\d+)\z/
      n = $1.to_i
      if enc == Encoding::UTF_8 or
        enc == Encoding::ISO_8859_1 && n < 256 or
        asciicompat && n < 128
        n.chr(enc)
      else
        "&##{$1};"
      end
    when /\A#x([0-9a-f]+)\z/i
      n = $1.hex
      if enc == Encoding::UTF_8 or
        enc == Encoding::ISO_8859_1 && n < 256 or
        asciicompat && n < 128
        n.chr(enc)
      else
        "&#x#{$1};"
      end
    else
      "&#{match};"
    end
  end
end

所以:是的,它只是一个子集。

答案 1 :(得分:0)

我发现这个问题几乎与this one重复,它有一个很好的答案,指的是htmlentities gem。