CGI :: unescape无法处理unescaping" wymiana + teflon%F3w"?

时间:2014-03-25 21:54:14

标签: ruby-on-rails ruby unicode ruby-on-rails-4 escaping

我正在研究从遗留数据库导入到sqlite进行开发的数据,遗留数据库有很多带有波兰字符的url编码字符串。我可以使用

来获取大多数这些字符串
CGI::unescape_html( CGI::unescape "string" )

除了一个案例(我注意到,可能还有更多,因为我还没有进行任何测试),字母“ó”。例如,在字符串“wymiana + teflon%F3w”上使用unescapeHTML会引发invalid byte sequence异常。

现在问题是我的字符串被正确转义,因为其他波兰字符正在使用“& #nnn;”的序列比如“b%26%23322%3Bad + zapisu +%2D + powinno + by%26%23263%3B + brak”,这似乎遵循numeric character referencing的标准。顺便说一下,这个字符串被正确转义为

  

“bładzapisu - powinnobyćbabk”

但是,另一方面,也存在具有相似字符编码的字符串,例如,由CGI::unescapeHTML正确处理的“odpowietrzanie + weza%5C”。但是,%5C表示backslash而不是代码点低于U + 0256的字母。这可能是原因吗?我试图对此进行研究,但没有找到任何解释。我还将我的Ruby更新为2.1.0,因为CGI :: Util在新版本中已经改变,但仍然没有运气。

2 个答案:

答案 0 :(得分:3)

ó在ISO-8859-2(和ISO-8859-1)中是0xF3,但'\xF3' 是有效的UTF-8字符串,{{1如果您期望UTF-8,则URL中应为ó。有人可能会使用已弃用的escape JavaScript function来编码字符串而不是现代encodeURIComponent;您可以在浏览器的JavaScript控制台中看到与简单测试的不同之处:

%C3%B3

您看到的是> escape('ó') "%F3" > encodeURIComponent('ó') "%C3%B3" ,您希望看到%F3。应该做的一件事是手动修复编码:

%C3%B3

这假设您知道应该是什么ISO-8859-1以及什么应该是UTF-8。您可能在数据中混合使用ISO-8859-2(或-1,-3,...,Windows CP-1258,...);不幸的是,由于编码重叠而没有可靠的方法来区分这些差异,并且没有办法确定哪些结果没有引人注目并且知道所涉及的各种语言。

你可以做的最好的事情可能是:

  1. 通过irb> CGI::unescape('wymiana+teflon%F3w').force_encoding('ISO-8859-2').encode('UTF-8') => "wymiana teflonów" 转换器发送所有内容。
  2. 在异常处理程序中包装它以捕获不可避免的问题。
  3. 将问题字符串存放到某处。
  4. 尝试从(3)对字符串进行ISO-8859-2到UTF-8的转换,然后用眼球看它们是否有意义。
  5. 重复其他常见编码,直到您无需关心。
  6. 请注意,我使用的是ISO-8859-2而不是更常见的ISO-8859-1,因为Latin-2适用于东欧语言(例如波兰语),而Latin-1适用于西欧语言。它们在CGI::unescape_html(CGI::unescape(...))上重叠,但在Latin-1中没有ó。对于这样的任务,你通常会尝试先编码的编码,然后再回到其他常见的编码上,然后再回到你能想到的任何其他编码,然后再回到烈酒上。

    祝你好运,遗留数据的现代化并不是世界上最有趣的工作。

答案 1 :(得分:0)

我选择了另一种方法来解决我的问题,只需用'%F3'代替所有'%26%23xF3%3B'代替unescaping。顺便说一下,大写字母Ó也需要类似的替代。我使用的实际代码:

  def unescape_ó(s)
   s = s.gsub(/%D3|%F3/, {'%D3' =>'%26%23xD3%3B', '%F3' => '%26%23xF3%3B'})
  end

使用这种方法,我不必处理invalid byte sequence异常,因为在CGI::unescapeHTML中使用了正确的转义字符串