discourse/lib/validators/upload_validator.rb

147 lines
3.9 KiB
Ruby
Raw Normal View History

# frozen_string_literal: true
2014-04-14 16:55:57 -04:00
require_dependency "file_helper"
module Validators; end
class UploadValidator < ActiveModel::Validator
2014-04-14 16:55:57 -04:00
def validate(upload)
# staff can upload any file in PM
2018-11-14 02:03:02 -05:00
if (upload.for_private_message && SiteSetting.allow_staff_to_upload_any_file_in_pm)
return true if upload.user&.staff?
end
# check the attachment blacklist
if upload.for_group_message && SiteSetting.allow_all_attachments_for_group_messages
return upload.original_filename =~ SiteSetting.attachment_filename_blacklist_regex
end
extension = File.extname(upload.original_filename)[1..-1] || ""
2014-04-14 16:55:57 -04:00
2018-11-14 02:03:02 -05:00
if upload.for_site_setting &&
upload.user&.staff? &&
FileHelper.is_supported_image?(upload.original_filename)
return true
end
if upload.for_gravatar &&
FileHelper.supported_gravatar_extensions.include?(extension)
maximum_image_file_size(upload)
return true
end
2014-04-14 16:55:57 -04:00
if is_authorized?(upload, extension)
if FileHelper.is_supported_image?(upload.original_filename)
2014-04-14 16:55:57 -04:00
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)
extension_authorized?(upload, extension, authorized_extensions(upload))
2014-04-14 16:55:57 -04:00
end
def authorized_image_extension(upload, extension)
extension_authorized?(upload, extension, authorized_images(upload))
2014-04-14 16:55:57 -04:00
end
def maximum_image_file_size(upload)
maximum_file_size(upload, "image")
end
def authorized_attachment_extension(upload, extension)
extension_authorized?(upload, extension, authorized_attachments(upload))
2014-04-14 16:55:57 -04:00
end
def maximum_attachment_file_size(upload)
maximum_file_size(upload, "attachment")
end
private
def extensions_to_set(exts)
extensions = Set.new
2014-04-14 16:55:57 -04:00
exts
.gsub(/[\s\.]+/, "")
.downcase
2014-04-14 16:55:57 -04:00
.split("|")
.each { |extension| extensions << extension unless extension.include?("*") }
extensions
end
2014-04-14 16:55:57 -04:00
def authorized_extensions(upload)
extensions = if upload.for_theme
SiteSetting.theme_authorized_extensions
elsif upload.for_export
SiteSetting.export_authorized_extensions
else
SiteSetting.authorized_extensions
end
extensions_to_set(extensions)
2014-04-14 16:55:57 -04:00
end
def authorized_images(upload)
authorized_extensions(upload) & FileHelper.supported_images
2014-04-14 16:55:57 -04:00
end
def authorized_attachments(upload)
authorized_extensions(upload) - FileHelper.supported_images
end
def authorizes_all_extensions?(upload)
if upload.user&.staff?
return true if SiteSetting.authorized_extensions_for_staff.include?("*")
end
extensions = if upload.for_theme
SiteSetting.theme_authorized_extensions
elsif upload.for_export
SiteSetting.export_authorized_extensions
else
SiteSetting.authorized_extensions
end
extensions.include?("*")
2014-04-14 16:55:57 -04:00
end
def extension_authorized?(upload, extension, extensions)
return true if authorizes_all_extensions?(upload)
staff_extensions = Set.new
if upload.user&.staff?
staff_extensions = extensions_to_set(SiteSetting.authorized_extensions_for_staff)
return true if staff_extensions.include?(extension.downcase)
end
unless authorized = extensions.include?(extension.downcase)
message = I18n.t("upload.unauthorized", authorized_extensions: (extensions | staff_extensions).to_a.join(", "))
2014-04-14 16:55:57 -04:00
upload.errors.add(:original_filename, message)
end
2014-04-14 16:55:57 -04:00
authorized
end
def maximum_file_size(upload, type)
max_size_kb = if upload.for_export
SiteSetting.max_export_file_size_kb
else
SiteSetting.get("max_#{type}_size_kb")
end
2019-05-06 21:27:05 -04:00
2015-05-03 13:26:54 -04:00
max_size_bytes = max_size_kb.kilobytes
2015-05-03 13:26:54 -04:00
if upload.filesize > max_size_bytes
2014-04-14 16:55:57 -04:00
message = I18n.t("upload.#{type}s.too_large", max_size_kb: max_size_kb)
upload.errors.add(:filesize, message)
end
end
end