diff --git a/lib/rails_ext/actiontext_opengraph_embeds.rb b/lib/rails_ext/actiontext_opengraph_embeds.rb index 712844d..d0748cd 100644 --- a/lib/rails_ext/actiontext_opengraph_embeds.rb +++ b/lib/rails_ext/actiontext_opengraph_embeds.rb @@ -48,11 +48,17 @@ class ActionText::Attachment::OpengraphEmbed end # A preview names a page on the public internet, so its host is a domain - # name: it has a dot and a letter in it, and no escapes. A bare address is - # not one, and a browser rewrites the many spellings of an address into a + # name, written plainly. A bare address is not one, and a browser rewrites + # the many spellings of an address ("2130706433", "0x7f.0.0.1") into a # single one before it fetches, which is a race a comparison here loses. def named_host?(host) - host.present? && host.exclude?("%") && host.include?(".") && host.match?(/[a-z]/i) + host.present? && host.exclude?("%") && host.include?(".") && domain_ending?(host.split(".").last) + end + + # What keeps a name from reading as an address is its last label, which is + # a word: never a number, and never the hexadecimal spelling of one. + def domain_ending?(label) + label.match?(/[a-z]/i) && !label.match?(/\A0x/i) end def canonical_host(host) diff --git a/test/lib/rails_ext/actiontext_opengraph_embeds_test.rb b/test/lib/rails_ext/actiontext_opengraph_embeds_test.rb index a93360b..6949f79 100644 --- a/test/lib/rails_ext/actiontext_opengraph_embeds_test.rb +++ b/test/lib/rails_ext/actiontext_opengraph_embeds_test.rb @@ -38,7 +38,8 @@ class ActionText::Attachment::OpengraphEmbedTest < ActiveSupport::TestCase test "drops a link and an image on a bare address rather than a domain name" do [ "http://127.0.0.1/rooms/1", "http://2130706433/rooms/1", "http://0177.0.0.1/rooms/1", - "http://[::1]/rooms/1", "http://localhost/rooms/1", "https://203.0.113.10/image.png" ].each do |value| + "http://0x7f.0.0.1/rooms/1", "http://1.2.3.0xff/rooms/1", "http://[::1]/rooms/1", + "http://localhost/rooms/1", "https://203.0.113.10/image.png" ].each do |value| embed = embed_from href: value, url: value assert_nil embed.href, "expected #{value.inspect} to be dropped as a link" @@ -46,6 +47,13 @@ class ActionText::Attachment::OpengraphEmbedTest < ActiveSupport::TestCase end end + test "keeps an internationalized domain written in punycode" do + embed = embed_from href: "https://xn--80aswg.xn--p1ai/page", url: "https://xn--80aswg.xn--p1ai/image.png" + + assert_equal "https://xn--80aswg.xn--p1ai/page", embed.href + assert_equal "https://xn--80aswg.xn--p1ai/image.png", embed.url + end + test "renders the image and the link when both are web URLs" do html = render_embed href: "https://example.com/page", url: "https://example.com/image.png"