discourse/lib/ical_encoder.rb
Régis HANOL cfd5b466b9
FIX: Prevent HTML-encoding of special characters in ICS feeds (#39152)
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 `&amp;` 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
2026-04-08 16:43:41 +02:00

20 lines
563 B
Ruby

# frozen_string_literal: true
module IcalEncoder
SANITIZER = Rails::Html::FullSanitizer.new
# Encodes a string for use in iCalendar text fields (SUMMARY, DESCRIPTION, LOCATION).
# Strips HTML tags, decodes HTML entities, and escapes special characters per RFC 5545.
def self.encode(text)
return "" if text.blank?
text = SANITIZER.sanitize(text)
text = CGI.unescapeHTML(text)
text
.gsub("\\", "\\\\\\\\")
.gsub(",", "\\,")
.gsub(";", "\\;")
.gsub("\r\n", "\\n")
.gsub("\n", "\\n")
.html_safe
end
end