require "application_system_test_case" require "socket" class UnfurlingLinksTest < ApplicationSystemTestCase setup do @website = Website.new @website.start RestrictedHTTP::PrivateNetworkGuard.stubs(:resolve).returns("127.0.0.1") sign_in "jz@37signals.com" join_room rooms(:designers) end teardown do @website.stop end test "a quote in the opengraph image URL cannot add attributes to the preview" do paste_in_composer @website.page_url assert_selector "#composer lexxy-editor .og-embed__title", text: "A normal looking link" assert_equal @website.image_url, preview_image_attributes["src"] assert_empty preview_image_attributes.keys - %w[ src class alt ] end private def preview_image_attributes page.evaluate_script(<<~JS) Object.fromEntries(Array.from(document.querySelector("#composer lexxy-editor .og-embed__image img").attributes, attribute => [ attribute.name, attribute.value ])) JS end # Serves a page whose og:image URL carries a double quote, so an unescaped # preview closes the src attribute early and takes the rest as attributes. class Website def start @socket = TCPServer.new("127.0.0.1", 0) @thread = Thread.new { serve } end def stop @thread&.kill @socket&.close end def page_url "http://127.0.0.1:#{port}/page.html" end def image_url %(http://127.0.0.1:#{port}/image.png?from=" style="outline:9px solid red) end private def port @socket.addr[1] end def serve loop do client = @socket.accept Thread.new(client) { |connection| respond_to(connection) } end rescue IOError, Errno::EBADF nil end def respond_to(client) request_line = client.gets.to_s nil while (line = client.gets) && line != "\r\n" method, path = request_line.split(" ") if path.to_s.start_with?("/image.png") respond client, "image/png", method == "HEAD" ? "" : "not really a PNG" else respond client, "text/html", page end rescue IOError, Errno::ECONNRESET nil ensure client.close rescue nil end def respond(client, content_type, body) client.write "HTTP/1.1 200 OK\r\nContent-Type: #{content_type}\r\nContent-Length: #{body.bytesize}\r\nConnection: close\r\n\r\n#{body}" end def page <<~HTML
Hello HTML end end end