discourse/lib/validators/upload_setting_validator.rb
Kris 72a51e8943
DEV: clean up splash SVG on upload, not when rendering (#37681)
This moves the splash screen SVG processing (SMIL and script stripping)
to upload rather than render for the `splash_screen_image` setting.

While testing I also found a case where SVG dimensions could make splash
images very tiny, so I strip out the dimensions (as long as a viewbox is
present) so the SVG can scale to fit the wrapper better.

---------

Co-authored-by: Régis Hanol <regis@hanol.fr>
Co-authored-by: Martin Brennan <martin@discourse.org>
2026-02-16 13:14:35 +10:00

47 lines
1.1 KiB
Ruby

# frozen_string_literal: true
class UploadSettingValidator
def initialize(opts = {})
@opts = opts
end
def valid_value?(val)
return true if val.blank?
upload = Upload.find_by(id: val)
upload.present? && additional_validation_passed(upload)
end
def error_message
return I18n.t("site_settings.errors.invalid_svg") if @opts[:name] == :splash_screen_image
I18n.t("site_settings.errors.invalid_upload")
end
def additional_validation_passed(upload)
if @opts[:name] == :splash_screen_image
validate_svg(upload)
else
true
end
end
# We also clean svgs in UploadCreator#clean_svg!,
# but this is a good extra fallback.
def validate_svg(upload)
content =
begin
upload.content
rescue StandardError
nil
end
return false if content.blank?
svg = Nokogiri.XML(content).at_css("svg")
return false if svg.blank?
has_scripts = svg.xpath("//*[local-name()='script']").present?
has_event_handlers = svg.xpath("//@*[starts-with(local-name(), 'on')]").present?
!has_scripts && !has_event_handlers
end
end