diff --git a/app/models/file_yard.rb b/app/models/file_yard.rb index ef18b2ce..79e8f04d 100644 --- a/app/models/file_yard.rb +++ b/app/models/file_yard.rb @@ -16,9 +16,12 @@ class FileYard sanitize_file_name(name) if io.kind_of?(Tempfile) io.close + check_upload_size(io.size) FileUtils.mv(io.path, file_path(name)) else - File.open(file_path(name), 'wb') { |f| f.write(io.read) } + content = io.read + check_upload_size(content.length) + File.open(file_path(name), 'wb') { |f| f.write(content) } end # just in case, restrict read access and prohibit write access to the uploaded file FileUtils.chmod(0440, file_path(name)) @@ -44,5 +47,12 @@ class FileYard "Only latin characters, digits, dots, underscores and dashes are accepted.") end end + + def check_upload_size(actual_upload_size) + if actual_upload_size > @max_upload_size.kilobytes + raise Instiki::ValidationError.new("Uploaded file size (#{actual_upload_size / 1024} " + + "kbytes) exceeds the maximum (#{@max_upload_size} kbytes) set for this wiki") + end + end end diff --git a/test/unit/file_yard_test.rb b/test/unit/file_yard_test.rb index 6598caa1..ece421ff 100755 --- a/test/unit/file_yard_test.rb +++ b/test/unit/file_yard_test.rb @@ -13,6 +13,11 @@ class FileYardTest < Test::Unit::TestCase @yard = FileYard.new(file_path, 100) end + def test_check_upload_size + assert_nothing_raised { @yard.check_upload_size(100.kilobytes) } + assert_raises(Instiki::ValidationError) { @yard.check_upload_size(100.kilobytes + 1) } + end + def test_files assert_equal [], @yard.files @@ -28,6 +33,32 @@ class FileYardTest < Test::Unit::TestCase assert_equal "#{file_path}/abcd", @yard.file_path('abcd') end + def test_size_limit + @yard = FileYard.new(file_path, 1) + one_kylobyte_string = "a" * 1024 + + # as StringIO + assert_nothing_raised { + @yard.upload_file('acceptable_file', StringIO.new(one_kylobyte_string)) + } + assert_raises(Instiki::ValidationError) { + @yard.upload_file('one_byte_too_long', StringIO.new(one_kylobyte_string + 'a')) + } + + # as Tempfile + require 'tempfile' + Tempfile.open('acceptable_file') { |f| f.write(one_kylobyte_string) } + assert_nothing_raised { + @yard.upload_file('acceptable_file', f) + } + } + Tempfile.open('one_byte_too_long') { |f| f.write(one_kylobyte_string + 'a') + assert_nothing_raised { + @yard.upload_file('one_byte_too_long_2', f) + } + } + end + def file_path "#{RAILS_ROOT}/storage/test/instiki" end