1

埋め込まれた soundcloud-track URL を iframe に変更するメソッドをテストする場合。結果をエスケープするときにバグが発生しました。

CASE 2 で +token+ をエスケープすると壊れる理由を誰か説明できますか? 結果をそのまま使用して追加も問題ありません。

2 つのケースを以下に詳しく示します。

#ruby --version
# => ruby 1.9.3p194 (2012-04-20 revision 35410) [x86_64-darwin12.2.1]

ケース1

require 'cgi'

class String
  def embedda
    compiled = self
    compiled = soundcloud_replace(compiled)

    return compiled
  end

 private
  def soundcloud_replace(compiled)
    r = /(https?:\/\/(?:www.)?soundcloud.com\/[A-Za-z0-9]+(?:[-_][A-Za-z0-9]+)*(?!\/sets(?:\/|$))(?:\/[A-Za-z0-9]+(?:[-_][A-Za-z0-9]+)*){1,2}\/?)/i
    compiled.gsub!(r) { |match| soundcloud_player(match) }

    return compiled
  end

  def soundcloud_player(token)
    # return token # => +matched soundcloud url+ in pry
    # puts token   # => +matched soundcloud url+ in pry

    url_encoded_string = CGI::escape(token)

    # puts url_encoded_string # => +escaped matched soundcloud url+

    # "<iframe width=\"100%\" height=\"166\" scrolling=\"no\" frameborder=\"no\" src=\"https://w.soundcloud.com/player/?url=#{token}\"></iframe>"
    # => Correct interpolated string with non-encoded url

    "<iframe width=\"100%\" height=\"166\" scrolling=\"no\" frameborder=\"no\" src=\"https://w.soundcloud.com/player/?url=#{url_encoded_string}\"></iframe>"
    # => Correct interpolated string with encoded url
  end
end

ケース 2

require 'cgi'

class String
  def embedda
    compiled = self
    compiled = soundcloud_replace(compiled)

    return compiled
  end

 private
  def soundcloud_replace(compiled)
    compiled.gsub!(/(https?:\/\/(?:www.)?soundcloud.com\/[A-Za-z0-9]+(?:[-_][A-Za-z0-9]+)*(?!\/sets(?:\/|$))(?:\/[A-Za-z0-9]+(?:[-_][A-Za-z0-9]+)*){1,2}\/?)/i, soundcloud_player("\\1"))

    return compiled
  end

  def soundcloud_player(token)
    # return token # => +matched soundcloud url+  in pry
    # puts token   # => /1                        in pry

    url_encoded_string = CGI::escape(token)

    # puts url_encoded_string = CGI::escape(token) # => %5C1  in pry

    # "<iframe width=\"100%\" height=\"166\" scrolling=\"no\" frameborder=\"no\" src=\"https://w.soundcloud.com/player/?url=#{token}\"></iframe>"
    # => Correct interpolated string with non-encoded url

    "<iframe width=\"100%\" height=\"166\" scrolling=\"no\" frameborder=\"no\" src=\"https://w.soundcloud.com/player/?url=#{url_encoded_string}\"></iframe>"
    # => Interpolated string with ...?url=%5C1
  end
end
4

2 に答える 2

1

2 番目のケースでは、gsub に渡す前に「\1」をエスケープしています。「url_encoded_string」をエスケープした後、「%5C1」が含まれます。「\1」が存在しないため、何も挿入されません。代わりに、コンテンツは「url_encoded_string」のコンテンツに置き換えられます。

以下を試して、ケース 2 の違いを確認してください。

url_encoded_string = token

それ以外の:

url_encoded_string = CGI::escape(token)
于 2013-04-10T08:59:37.600 に答える