mirror of
https://gh.wpcy.net/https://github.com/discourse/discourse.git
synced 2026-05-04 18:48:01 +08:00
ERB's `<%= %>` calls `ERB::Util.html_escape` on all non-`html_safe` strings, even in non-HTML templates like `.ics.erb`. This caused ampersands (and potentially other special characters) to be double-encoded as `&` in calendar subscription feeds, which external calendar apps like Google Calendar displayed verbatim. Mark `IcalEncoder.encode` output as `html_safe` since it already performs all necessary ICS encoding (HTML sanitization, entity decoding, RFC 5545 escaping). Also route the URL fields in both ICS templates through `IcalEncoder.encode` for consistency. https://meta.discourse.org/t/400166
64 lines
2.2 KiB
Ruby
64 lines
2.2 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
RSpec.describe IcalEncoder do
|
|
describe ".encode" do
|
|
it "returns empty string for nil" do
|
|
expect(described_class.encode(nil)).to eq("")
|
|
end
|
|
|
|
it "returns empty string for blank string" do
|
|
expect(described_class.encode("")).to eq("")
|
|
end
|
|
|
|
it "passes through plain text" do
|
|
expect(described_class.encode("Hello World")).to eq("Hello World")
|
|
end
|
|
|
|
it "strips HTML tags" do
|
|
expect(described_class.encode("<b>Bold</b> and <i>italic</i>")).to eq("Bold and italic")
|
|
end
|
|
|
|
it "decodes HTML entities" do
|
|
expect(described_class.encode("Tom & Jerry")).to eq("Tom & Jerry")
|
|
expect(described_class.encode("1 < 2 > 0")).to eq("1 < 2 > 0")
|
|
expect(described_class.encode(""quoted"")).to eq('"quoted"')
|
|
end
|
|
|
|
it "strips HTML tags then decodes entities" do
|
|
expect(
|
|
described_class.encode("<a href="https://example.com">link</a>"),
|
|
).to eq('<a href="https://example.com">link</a>')
|
|
end
|
|
|
|
it "escapes commas" do
|
|
expect(described_class.encode("New York, NY")).to eq("New York\\, NY")
|
|
end
|
|
|
|
it "escapes semicolons" do
|
|
expect(described_class.encode("one; two")).to eq("one\\; two")
|
|
end
|
|
|
|
it "escapes backslashes" do
|
|
expect(described_class.encode("path\\to\\file")).to eq("path\\\\to\\\\file")
|
|
end
|
|
|
|
it "escapes newlines" do
|
|
expect(described_class.encode("line one\nline two")).to eq("line one\\nline two")
|
|
expect(described_class.encode("line one\r\nline two")).to eq("line one\\nline two")
|
|
end
|
|
|
|
it "returns html_safe strings to prevent double-escaping in ERB templates" do
|
|
expect(described_class.encode("Tom & Jerry")).to be_html_safe
|
|
end
|
|
|
|
it "handles complex HTML content from Discourse posts" do
|
|
html =
|
|
'<a class="lightbox" href="https://example.com/image.jpg">[Image]</a> \nSome text with & special chars'
|
|
result = described_class.encode(html)
|
|
expect(result).not_to include("<")
|
|
expect(result).not_to include("&")
|
|
expect(result).not_to include(""")
|
|
expect(result).to include("& special chars")
|
|
end
|
|
end
|
|
end
|