discourse/lib/validators/upload_validator.rb

97 lines
2.6 KiB
Ruby

require_dependency "file_helper"
module Validators; end
class Validators::UploadValidator < ActiveModel::Validator
def validate(upload)
# allow all attachments except S/MIME signatures
# cf. https://meta.discourse.org/t/strip-s-mime-signatures/46371
if upload.is_attachment_for_group_message && SiteSetting.allow_all_attachments_for_group_messages
return upload.original_filename != "smime.p7s".freeze
end
extension = File.extname(upload.original_filename)[1..-1] || ""
if is_authorized?(upload, extension)
if FileHelper.is_image?(upload.original_filename)
authorized_image_extension(upload, extension)
maximum_image_file_size(upload)
else
authorized_attachment_extension(upload, extension)
maximum_attachment_file_size(upload)
end
end
end
def is_authorized?(upload, extension)
authorized_extensions(upload, extension, authorized_uploads)
end
def authorized_image_extension(upload, extension)
authorized_extensions(upload, extension, authorized_images)
end
def maximum_image_file_size(upload)
maximum_file_size(upload, "image")
end
def authorized_attachment_extension(upload, extension)
authorized_extensions(upload, extension, authorized_attachments)
end
def maximum_attachment_file_size(upload)
maximum_file_size(upload, "attachment")
end
private
def authorized_uploads
authorized_uploads = Set.new
SiteSetting.authorized_extensions
.tr(" ", "")
.split("|")
.each do |extension|
next if extension.include?("*")
authorized_uploads << (extension.start_with?(".") ? extension[1..-1] : extension).downcase
end
authorized_uploads
end
def authorized_images
authorized_uploads & FileHelper.images
end
def authorized_attachments
authorized_uploads - FileHelper.images
end
def authorizes_all_extensions?
SiteSetting.authorized_extensions.include?("*")
end
def authorized_extensions(upload, extension, extensions)
return true if authorizes_all_extensions?
unless authorized = extensions.include?(extension.downcase)
message = I18n.t("upload.unauthorized", authorized_extensions: extensions.to_a.join(", "))
upload.errors.add(:original_filename, message)
end
authorized
end
def maximum_file_size(upload, type)
max_size_kb = SiteSetting.send("max_#{type}_size_kb")
max_size_bytes = max_size_kb.kilobytes
if upload.filesize > max_size_bytes
message = I18n.t("upload.#{type}s.too_large", max_size_kb: max_size_kb)
upload.errors.add(:filesize, message)
end
end
end