##// END OF EJS Templates
Files upload restriction by files extensions (#20008)....
Jean-Philippe Lang -
r14410:dd1c5f8900bb
parent child
Show More
@@ -26,7 +26,7 class Attachment < ActiveRecord::Base
26 validates_length_of :filename, :maximum => 255
26 validates_length_of :filename, :maximum => 255
27 validates_length_of :disk_filename, :maximum => 255
27 validates_length_of :disk_filename, :maximum => 255
28 validates_length_of :description, :maximum => 255
28 validates_length_of :description, :maximum => 255
29 validate :validate_max_file_size
29 validate :validate_max_file_size, :validate_file_extension
30 attr_protected :id
30 attr_protected :id
31
31
32 acts_as_event :title => :filename,
32 acts_as_event :title => :filename,
@@ -69,6 +69,15 class Attachment < ActiveRecord::Base
69 end
69 end
70 end
70 end
71
71
72 def validate_file_extension
73 if @temp_file
74 extension = File.extname(filename)
75 unless self.class.valid_extension?(extension)
76 errors.add(:base, l(:error_attachment_extension_not_allowed, :extension => extension))
77 end
78 end
79 end
80
72 def file=(incoming_file)
81 def file=(incoming_file)
73 unless incoming_file.nil?
82 unless incoming_file.nil?
74 @temp_file = incoming_file
83 @temp_file = incoming_file
@@ -333,6 +342,22 class Attachment < ActiveRecord::Base
333 end
342 end
334 end
343 end
335
344
345 # Returns true if the extension is allowed, otherwise false
346 def self.valid_extension?(extension)
347 extension = extension.downcase.sub(/\A\.+/, '')
348
349 denied, allowed = [:attachment_extensions_denied, :attachment_extensions_allowed].map do |setting|
350 Setting.send(setting).to_s.split(",").map {|s| s.strip.downcase.sub(/\A\.+/, '')}.reject(&:blank?)
351 end
352 if denied.present? && denied.include?(extension)
353 return false
354 end
355 unless allowed.blank? || allowed.include?(extension)
356 return false
357 end
358 true
359 end
360
336 private
361 private
337
362
338 # Physically deletes the file from the file system
363 # Physically deletes the file from the file system
@@ -3,6 +3,12
3 <div class="box tabular settings">
3 <div class="box tabular settings">
4 <p><%= setting_text_field :attachment_max_size, :size => 6 %> <%= l(:"number.human.storage_units.units.kb") %></p>
4 <p><%= setting_text_field :attachment_max_size, :size => 6 %> <%= l(:"number.human.storage_units.units.kb") %></p>
5
5
6 <p><%= setting_text_area :attachment_extensions_allowed %>
7 <em class="info"><%= l(:text_comma_separated) %> <%= l(:label_example) %>: txt, png</em></p>
8
9 <p><%= setting_text_area :attachment_extensions_denied %>
10 <em class="info"><%= l(:text_comma_separated) %> <%= l(:label_example) %>: js, swf</em></p>
11
6 <p><%= setting_text_field :file_max_size_displayed, :size => 6 %> <%= l(:"number.human.storage_units.units.kb") %></p>
12 <p><%= setting_text_field :file_max_size_displayed, :size => 6 %> <%= l(:"number.human.storage_units.units.kb") %></p>
7
13
8 <p><%= setting_text_field :diff_max_lines_displayed, :size => 6 %></p>
14 <p><%= setting_text_field :diff_max_lines_displayed, :size => 6 %></p>
@@ -210,6 +210,7 en:
210 error_invalid_file_encoding: "The file is not a valid %{encoding} encoded file"
210 error_invalid_file_encoding: "The file is not a valid %{encoding} encoded file"
211 error_invalid_csv_file_or_settings: "The file is not a CSV file or does not match the settings below"
211 error_invalid_csv_file_or_settings: "The file is not a CSV file or does not match the settings below"
212 error_can_not_read_import_file: "An error occurred while reading the file to import"
212 error_can_not_read_import_file: "An error occurred while reading the file to import"
213 error_attachment_extension_not_allowed: "Attachment extension %{extension} is not allowed"
213
214
214 mail_subject_lost_password: "Your %{value} password"
215 mail_subject_lost_password: "Your %{value} password"
215 mail_body_lost_password: 'To change your password, click on the following link:'
216 mail_body_lost_password: 'To change your password, click on the following link:'
@@ -426,6 +427,8 en:
426 setting_link_copied_issue: Link issues on copy
427 setting_link_copied_issue: Link issues on copy
427 setting_max_additional_emails: Maximum number of additional email addresses
428 setting_max_additional_emails: Maximum number of additional email addresses
428 setting_search_results_per_page: Search results per page
429 setting_search_results_per_page: Search results per page
430 setting_attachment_extensions_allowed: Allowed extensions
431 setting_attachment_extensions_denied: Disallowed extensions
429
432
430 permission_add_project: Create project
433 permission_add_project: Create project
431 permission_add_subprojects: Create subprojects
434 permission_add_subprojects: Create subprojects
@@ -230,6 +230,7 fr:
230 error_invalid_file_encoding: "Le fichier n'est pas un fichier %{encoding} valide"
230 error_invalid_file_encoding: "Le fichier n'est pas un fichier %{encoding} valide"
231 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"
231 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"
232 error_can_not_read_import_file: "Une erreur est survenue lors de la lecture du fichier Γ  importer"
232 error_can_not_read_import_file: "Une erreur est survenue lors de la lecture du fichier Γ  importer"
233 error_attachment_extension_not_allowed: "L'extension %{extension} n'est pas autorisΓ©e"
233
234
234 mail_subject_lost_password: "Votre mot de passe %{value}"
235 mail_subject_lost_password: "Votre mot de passe %{value}"
235 mail_body_lost_password: 'Pour changer votre mot de passe, cliquez sur le lien suivant :'
236 mail_body_lost_password: 'Pour changer votre mot de passe, cliquez sur le lien suivant :'
@@ -446,6 +447,8 fr:
446 setting_link_copied_issue: Lier les demandes lors de la copie
447 setting_link_copied_issue: Lier les demandes lors de la copie
447 setting_max_additional_emails: Nombre maximal d'adresses email additionnelles
448 setting_max_additional_emails: Nombre maximal d'adresses email additionnelles
448 setting_search_results_per_page: RΓ©sultats de recherche affichΓ©s par page
449 setting_search_results_per_page: RΓ©sultats de recherche affichΓ©s par page
450 setting_attachment_extensions_allowed: Extensions autorisΓ©es
451 setting_attachment_extensions_denied: Extensions non autorisΓ©es
449
452
450 permission_add_project: CrΓ©er un projet
453 permission_add_project: CrΓ©er un projet
451 permission_add_subprojects: CrΓ©er des sous-projets
454 permission_add_subprojects: CrΓ©er des sous-projets
@@ -55,6 +55,10 session_timeout:
55 attachment_max_size:
55 attachment_max_size:
56 format: int
56 format: int
57 default: 5120
57 default: 5120
58 attachment_extensions_allowed:
59 default:
60 attachment_extensions_denied:
61 default:
58 issues_export_limit:
62 issues_export_limit:
59 format: int
63 format: int
60 default: 500
64 default: 500
@@ -122,6 +122,45 class AttachmentTest < ActiveSupport::TestCase
122 end
122 end
123 end
123 end
124
124
125 def test_extension_should_be_validated_against_allowed_extensions
126 with_settings :attachment_extensions_allowed => "txt, png" do
127 a = Attachment.new(:container => Issue.find(1),
128 :file => mock_file_with_options(:original_filename => "test.png"),
129 :author => User.find(1))
130 assert_save a
131
132 a = Attachment.new(:container => Issue.find(1),
133 :file => mock_file_with_options(:original_filename => "test.jpeg"),
134 :author => User.find(1))
135 assert !a.save
136 end
137 end
138
139 def test_extension_should_be_validated_against_denied_extensions
140 with_settings :attachment_extensions_denied => "txt, png" do
141 a = Attachment.new(:container => Issue.find(1),
142 :file => mock_file_with_options(:original_filename => "test.jpeg"),
143 :author => User.find(1))
144 assert_save a
145
146 a = Attachment.new(:container => Issue.find(1),
147 :file => mock_file_with_options(:original_filename => "test.png"),
148 :author => User.find(1))
149 assert !a.save
150 end
151 end
152
153 def test_valid_extension_should_be_case_insensitive
154 with_settings :attachment_extensions_allowed => "txt, Png" do
155 assert Attachment.valid_extension?(".pnG")
156 assert !Attachment.valid_extension?(".jpeg")
157 end
158 with_settings :attachment_extensions_denied => "txt, Png" do
159 assert !Attachment.valid_extension?(".pnG")
160 assert Attachment.valid_extension?(".jpeg")
161 end
162 end
163
125 def test_description_length_should_be_validated
164 def test_description_length_should_be_validated
126 a = Attachment.new(:description => 'a' * 300)
165 a = Attachment.new(:description => 'a' * 300)
127 assert !a.save
166 assert !a.save
General Comments 0
You need to be logged in to leave comments. Login now