mirror of
https://github.com/meineerde/redmine.git
synced 2026-03-09 18:53:05 +00:00
Ensure unique attachment filenames (#35539).
Patch by Jens Krämer. git-svn-id: http://svn.redmine.org/redmine/trunk@21071 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
parent
8f0d358533
commit
8e4d71adc9
@ -138,14 +138,10 @@ class Attachment < ActiveRecord::Base
|
|||||||
def files_to_final_location
|
def files_to_final_location
|
||||||
if @temp_file
|
if @temp_file
|
||||||
self.disk_directory = target_directory
|
self.disk_directory = target_directory
|
||||||
self.disk_filename = Attachment.disk_filename(filename, disk_directory)
|
|
||||||
logger.info("Saving attachment '#{self.diskfile}' (#{@temp_file.size} bytes)") if logger
|
|
||||||
path = File.dirname(diskfile)
|
|
||||||
unless File.directory?(path)
|
|
||||||
FileUtils.mkdir_p(path)
|
|
||||||
end
|
|
||||||
sha = Digest::SHA256.new
|
sha = Digest::SHA256.new
|
||||||
File.open(diskfile, "wb") do |f|
|
Attachment.create_diskfile(filename, disk_directory) do |f|
|
||||||
|
self.disk_filename = File.basename f.path
|
||||||
|
logger.info("Saving attachment '#{self.diskfile}' (#{@temp_file.size} bytes)") if logger
|
||||||
if @temp_file.respond_to?(:read)
|
if @temp_file.respond_to?(:read)
|
||||||
buffer = ""
|
buffer = ""
|
||||||
while (buffer = @temp_file.read(8192))
|
while (buffer = @temp_file.read(8192))
|
||||||
@ -557,9 +553,8 @@ class Attachment < ActiveRecord::Base
|
|||||||
|
|
||||||
# Singleton class method is public
|
# Singleton class method is public
|
||||||
class << self
|
class << self
|
||||||
# Returns an ASCII or hashed filename that do not
|
# Claims a unique ASCII or hashed filename, yields the open file handle
|
||||||
# exists yet in the given subdirectory
|
def create_diskfile(filename, directory=nil, &block)
|
||||||
def disk_filename(filename, directory=nil)
|
|
||||||
timestamp = DateTime.now.strftime("%y%m%d%H%M%S")
|
timestamp = DateTime.now.strftime("%y%m%d%H%M%S")
|
||||||
ascii = ''
|
ascii = ''
|
||||||
if %r{^[a-zA-Z0-9_\.\-]*$}.match?(filename) && filename.length <= 50
|
if %r{^[a-zA-Z0-9_\.\-]*$}.match?(filename) && filename.length <= 50
|
||||||
@ -569,11 +564,21 @@ class Attachment < ActiveRecord::Base
|
|||||||
# keep the extension if any
|
# keep the extension if any
|
||||||
ascii << $1 if filename =~ %r{(\.[a-zA-Z0-9]+)$}
|
ascii << $1 if filename =~ %r{(\.[a-zA-Z0-9]+)$}
|
||||||
end
|
end
|
||||||
while File.exist?(File.join(storage_path, directory.to_s,
|
|
||||||
"#{timestamp}_#{ascii}"))
|
path = File.join storage_path, directory.to_s
|
||||||
|
FileUtils.mkdir_p(path) unless File.directory?(path)
|
||||||
|
begin
|
||||||
|
name = "#{timestamp}_#{ascii}"
|
||||||
|
File.open(
|
||||||
|
File.join(path, name),
|
||||||
|
flags: File::CREAT | File::EXCL | File::BINARY | File::WRONLY,
|
||||||
|
binmode: true,
|
||||||
|
&block
|
||||||
|
)
|
||||||
|
rescue Errno::EEXIST
|
||||||
timestamp.succ!
|
timestamp.succ!
|
||||||
|
retry
|
||||||
end
|
end
|
||||||
"#{timestamp}_#{ascii}"
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -275,12 +275,28 @@ class AttachmentTest < ActiveSupport::TestCase
|
|||||||
assert_equal 'valid_[] invalid_chars', a.filename
|
assert_equal 'valid_[] invalid_chars', a.filename
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_diskfilename
|
def test_create_diskfile
|
||||||
assert Attachment.disk_filename("test_file.txt") =~ /^\d{12}_test_file.txt$/
|
Attachment.create_diskfile("test_file.txt") do |f|
|
||||||
assert_equal 'test_file.txt', Attachment.disk_filename("test_file.txt")[13..-1]
|
path = f.path
|
||||||
assert_equal '770c509475505f37c2b8fb6030434d6b.txt', Attachment.disk_filename("test_accentué.txt")[13..-1]
|
assert_match(/^\d{12}_test_file.txt$/, File.basename(path))
|
||||||
assert_equal 'f8139524ebb8f32e51976982cd20a85d', Attachment.disk_filename("test_accentué")[13..-1]
|
assert_equal 'test_file.txt', File.basename(path)[13..-1]
|
||||||
assert_equal 'cbb5b0f30978ba03731d61f9f6d10011', Attachment.disk_filename("test_accentué.ça")[13..-1]
|
File.unlink f.path
|
||||||
|
end
|
||||||
|
|
||||||
|
Attachment.create_diskfile("test_accentué.txt") do |f|
|
||||||
|
assert_equal '770c509475505f37c2b8fb6030434d6b.txt', File.basename(f.path)[13..-1]
|
||||||
|
File.unlink f.path
|
||||||
|
end
|
||||||
|
|
||||||
|
Attachment.create_diskfile("test_accentué") do |f|
|
||||||
|
assert_equal 'f8139524ebb8f32e51976982cd20a85d', File.basename(f.path)[13..-1]
|
||||||
|
File.unlink f.path
|
||||||
|
end
|
||||||
|
|
||||||
|
Attachment.create_diskfile("test_accentué.ça") do |f|
|
||||||
|
assert_equal 'cbb5b0f30978ba03731d61f9f6d10011', File.basename(f.path)[13..-1]
|
||||||
|
File.unlink f.path
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_title
|
def test_title
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user