Преглед на файлове

Files upload restriction by files extensions (#20008).

git-svn-id: http://svn.redmine.org/redmine/trunk@14792 e93f8b46-1217-0410-a6f0-8f06a7374b81
tags/3.2.0
Jean-Philippe Lang преди 8 години
родител
ревизия
dd1c5f8900
променени са 6 файла, в които са добавени 81 реда и са изтрити 1 реда
  1. 26
    1
      app/models/attachment.rb
  2. 6
    0
      app/views/settings/_attachments.html.erb
  3. 3
    0
      config/locales/en.yml
  4. 3
    0
      config/locales/fr.yml
  5. 4
    0
      config/settings.yml
  6. 39
    0
      test/unit/attachment_test.rb

+ 26
- 1
app/models/attachment.rb Целия файл

@@ -26,7 +26,7 @@ class Attachment < ActiveRecord::Base
validates_length_of :filename, :maximum => 255
validates_length_of :disk_filename, :maximum => 255
validates_length_of :description, :maximum => 255
validate :validate_max_file_size
validate :validate_max_file_size, :validate_file_extension
attr_protected :id

acts_as_event :title => :filename,
@@ -69,6 +69,15 @@ class Attachment < ActiveRecord::Base
end
end

def validate_file_extension
if @temp_file
extension = File.extname(filename)
unless self.class.valid_extension?(extension)
errors.add(:base, l(:error_attachment_extension_not_allowed, :extension => extension))
end
end
end

def file=(incoming_file)
unless incoming_file.nil?
@temp_file = incoming_file
@@ -333,6 +342,22 @@ class Attachment < ActiveRecord::Base
end
end

# Returns true if the extension is allowed, otherwise false
def self.valid_extension?(extension)
extension = extension.downcase.sub(/\A\.+/, '')

denied, allowed = [:attachment_extensions_denied, :attachment_extensions_allowed].map do |setting|
Setting.send(setting).to_s.split(",").map {|s| s.strip.downcase.sub(/\A\.+/, '')}.reject(&:blank?)
end
if denied.present? && denied.include?(extension)
return false
end
unless allowed.blank? || allowed.include?(extension)
return false
end
true
end

private

# Physically deletes the file from the file system

+ 6
- 0
app/views/settings/_attachments.html.erb Целия файл

@@ -3,6 +3,12 @@
<div class="box tabular settings">
<p><%= setting_text_field :attachment_max_size, :size => 6 %> <%= l(:"number.human.storage_units.units.kb") %></p>

<p><%= setting_text_area :attachment_extensions_allowed %>
<em class="info"><%= l(:text_comma_separated) %> <%= l(:label_example) %>: txt, png</em></p>

<p><%= setting_text_area :attachment_extensions_denied %>
<em class="info"><%= l(:text_comma_separated) %> <%= l(:label_example) %>: js, swf</em></p>

<p><%= setting_text_field :file_max_size_displayed, :size => 6 %> <%= l(:"number.human.storage_units.units.kb") %></p>

<p><%= setting_text_field :diff_max_lines_displayed, :size => 6 %></p>

+ 3
- 0
config/locales/en.yml Целия файл

@@ -210,6 +210,7 @@ en:
error_invalid_file_encoding: "The file is not a valid %{encoding} encoded file"
error_invalid_csv_file_or_settings: "The file is not a CSV file or does not match the settings below"
error_can_not_read_import_file: "An error occurred while reading the file to import"
error_attachment_extension_not_allowed: "Attachment extension %{extension} is not allowed"

mail_subject_lost_password: "Your %{value} password"
mail_body_lost_password: 'To change your password, click on the following link:'
@@ -426,6 +427,8 @@ en:
setting_link_copied_issue: Link issues on copy
setting_max_additional_emails: Maximum number of additional email addresses
setting_search_results_per_page: Search results per page
setting_attachment_extensions_allowed: Allowed extensions
setting_attachment_extensions_denied: Disallowed extensions

permission_add_project: Create project
permission_add_subprojects: Create subprojects

+ 3
- 0
config/locales/fr.yml Целия файл

@@ -230,6 +230,7 @@ fr:
error_invalid_file_encoding: "Le fichier n'est pas un fichier %{encoding} valide"
error_invalid_csv_file_or_settings: "Le fichier n'est pas un fichier CSV ou n'est pas conforme aux paramètres sélectionnés"
error_can_not_read_import_file: "Une erreur est survenue lors de la lecture du fichier à importer"
error_attachment_extension_not_allowed: "L'extension %{extension} n'est pas autorisée"

mail_subject_lost_password: "Votre mot de passe %{value}"
mail_body_lost_password: 'Pour changer votre mot de passe, cliquez sur le lien suivant :'
@@ -446,6 +447,8 @@ fr:
setting_link_copied_issue: Lier les demandes lors de la copie
setting_max_additional_emails: Nombre maximal d'adresses email additionnelles
setting_search_results_per_page: Résultats de recherche affichés par page
setting_attachment_extensions_allowed: Extensions autorisées
setting_attachment_extensions_denied: Extensions non autorisées

permission_add_project: Créer un projet
permission_add_subprojects: Créer des sous-projets

+ 4
- 0
config/settings.yml Целия файл

@@ -55,6 +55,10 @@ session_timeout:
attachment_max_size:
format: int
default: 5120
attachment_extensions_allowed:
default:
attachment_extensions_denied:
default:
issues_export_limit:
format: int
default: 500

+ 39
- 0
test/unit/attachment_test.rb Целия файл

@@ -122,6 +122,45 @@ class AttachmentTest < ActiveSupport::TestCase
end
end

def test_extension_should_be_validated_against_allowed_extensions
with_settings :attachment_extensions_allowed => "txt, png" do
a = Attachment.new(:container => Issue.find(1),
:file => mock_file_with_options(:original_filename => "test.png"),
:author => User.find(1))
assert_save a

a = Attachment.new(:container => Issue.find(1),
:file => mock_file_with_options(:original_filename => "test.jpeg"),
:author => User.find(1))
assert !a.save
end
end

def test_extension_should_be_validated_against_denied_extensions
with_settings :attachment_extensions_denied => "txt, png" do
a = Attachment.new(:container => Issue.find(1),
:file => mock_file_with_options(:original_filename => "test.jpeg"),
:author => User.find(1))
assert_save a

a = Attachment.new(:container => Issue.find(1),
:file => mock_file_with_options(:original_filename => "test.png"),
:author => User.find(1))
assert !a.save
end
end

def test_valid_extension_should_be_case_insensitive
with_settings :attachment_extensions_allowed => "txt, Png" do
assert Attachment.valid_extension?(".pnG")
assert !Attachment.valid_extension?(".jpeg")
end
with_settings :attachment_extensions_denied => "txt, Png" do
assert !Attachment.valid_extension?(".pnG")
assert Attachment.valid_extension?(".jpeg")
end
end

def test_description_length_should_be_validated
a = Attachment.new(:description => 'a' * 300)
assert !a.save

Loading…
Отказ
Запис