Skip to content

Commit

Permalink
Zip attachments and raw data extension
Browse files Browse the repository at this point in the history
  • Loading branch information
picman committed Oct 3, 2024
1 parent 4a72aaa commit 5e81d5e
Show file tree
Hide file tree
Showing 5 changed files with 161 additions and 31 deletions.
14 changes: 7 additions & 7 deletions app/controllers/dmsf_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,7 @@ def email_entries(selected_folders, selected_files)
raise RedmineDmsf::Errors::DmsfEmailMaxFileSizeError
end

zip.files.each do |f|
zip.dmsf_files.each do |f|
# Action
audit = DmsfFileRevisionAccess.new
audit.user = User.current
Expand All @@ -517,7 +517,7 @@ def email_entries(selected_folders, selected_files)

# Notification
begin
DmsfMailer.deliver_files_downloaded(@project, zip.files, request.remote_ip)
DmsfMailer.deliver_files_downloaded @project, zip.dmsf_files, request.remote_ip
rescue StandardError => e
Rails.logger.error "Could not send email notifications: #{e.message}"
end
Expand All @@ -540,7 +540,7 @@ def email_entries(selected_folders, selected_files)
def download_entries(selected_folders, selected_files)
zip = Zip.new
zip_entries(zip, selected_folders, selected_files)
zip.files.each do |f|
zip.dmsf_files.each do |f|
# Action
audit = DmsfFileRevisionAccess.new
audit.user = User.current
Expand All @@ -550,7 +550,7 @@ def download_entries(selected_folders, selected_files)
end
# Notifications
begin
DmsfMailer.deliver_files_downloaded(@project, zip.files, request.remote_ip)
DmsfMailer.deliver_files_downloaded @project, zip.dmsf_files, request.remote_ip
rescue StandardError => e
Rails.logger.error "Could not send email notifications: #{e.message}"
end
Expand All @@ -570,7 +570,7 @@ def zip_entries(zip, selected_folders, selected_files)
folder = DmsfFolder.visible.find_by(id: selected_folder_id)
raise RedmineDmsf::Errors::DmsfFileNotFoundError unless folder

zip.add_folder folder, member, folder&.dmsf_folder&.dmsf_path_str
zip.add_dmsf_folder folder, member, folder&.dmsf_folder&.dmsf_path_str
end
selected_files.each do |selected_file_id|
file = DmsfFile.visible.find_by(id: selected_file_id)
Expand All @@ -581,10 +581,10 @@ def zip_entries(zip, selected_folders, selected_files)
raise RedmineDmsf::Errors::DmsfAccessError
end

zip.add_file file, member, file.dmsf_folder&.dmsf_path_str
zip.add_dmsf_file file, member, file.dmsf_folder&.dmsf_path_str
end
max_files = Setting.plugin_redmine_dmsf['dmsf_max_file_download'].to_i
raise RedmineDmsf::Errors::DmsfZipMaxFilesError if max_files.positive? && zip.files.length > max_files
raise RedmineDmsf::Errors::DmsfZipMaxFilesError if max_files.positive? && zip.dmsf_files.length > max_files

zip
end
Expand Down
77 changes: 57 additions & 20 deletions lib/redmine_dmsf/dmsf_zip.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,20 @@ module RedmineDmsf
module DmsfZip
# ZIP
class Zip
attr_reader :files
attr_reader :dmsf_files

def initialize
@temp_file = Tempfile.new(%w[dmsf_zip_ .zip], Rails.root.join('tmp'))
@zip_file = ::Zip::OutputStream.open(@temp_file)
@files = []
@dmsf_files = []
@folders = []
end

def read
File.read @temp_file
end

def finish
@zip_file.close
@temp_file.path
Expand All @@ -42,37 +47,69 @@ def close
@zip_file.close
end

def add_file(file, member, root_path = nil)
return if @files.include?(file)
unless file&.last_revision && File.exist?(file.last_revision&.disk_file)
def add_dmsf_file(dmsf_file, member = nil, root_path = nil, path = nil)
unless dmsf_file&.last_revision && File.exist?(dmsf_file.last_revision.disk_file)
raise RedmineDmsf::Errors::DmsfFileNotFoundError
end

string_path = file.dmsf_folder.nil? ? '' : (file.dmsf_folder.dmsf_path_str + File::SEPARATOR)
string_path = string_path[(root_path.length + 1)..string_path.length] if root_path
string_path += file.formatted_name(member)
if path
string_path = path
else
string_path = dmsf_file.dmsf_folder.nil? ? '' : (dmsf_file.dmsf_folder.dmsf_path_str + File::SEPARATOR)
string_path = string_path[(root_path.length + 1)..string_path.length] if root_path
end
string_path += dmsf_file.formatted_name(member)

return if @files.include?(string_path)

zip_entry = ::Zip::Entry.new(@zip_file, string_path, nil, nil, nil, nil, nil, nil,
::Zip::DOSTime.at(file.last_revision.updated_at))
@zip_file.put_next_entry(zip_entry)
File.open(file.last_revision.disk_file, 'rb') do |f|
::Zip::DOSTime.at(dmsf_file.last_revision.updated_at))
@zip_file.put_next_entry zip_entry
File.open(dmsf_file.last_revision.disk_file, 'rb') do |f|
while (buffer = f.read(8192))
@zip_file.write buffer
end
end
@files << string_path
@dmsf_files << dmsf_file
end

def add_attachment(attachment, path)
return if @files.include?(path)

raise RedmineDmsf::Errors::DmsfFileNotFoundError unless File.exist?(attachment.diskfile)

zip_entry = ::Zip::Entry.new(@zip_file, path, nil, nil, nil, nil, nil, nil,
::Zip::DOSTime.at(attachment.created_on))
@zip_file.put_next_entry zip_entry
File.open(attachment.diskfile, 'rb') do |f|
while (buffer = f.read(8192))
@zip_file.write(buffer)
@zip_file.write buffer
end
end
@files << file
@files << path
end

def add_folder(folder, member, root_path = nil)
return if @folders.include?(folder)
def add_raw_file(filename, data)
return if @files.include?(filename)

zip_entry = ::Zip::Entry.new(@zip_file, filename, nil, nil, nil, nil, nil, nil, ::Zip::DOSTime.now)
@zip_file.put_next_entry zip_entry
@zip_file.write data
@files << filename
end

string_path = folder.dmsf_path_str + File::SEPARATOR
def add_dmsf_folder(dmsf_folder, member, root_path = nil)
string_path = dmsf_folder.dmsf_path_str + File::SEPARATOR
string_path = string_path[(root_path.length + 1)..string_path.length] if root_path
zip_entry = ::Zip::Entry.new(@zip_file, string_path, nil, nil, nil, nil, nil, nil,
::Zip::DOSTime.at(folder.modified))
@zip_file.put_next_entry(zip_entry)
@folders << folder
folder.dmsf_folders.visible.each { |subfolder| add_folder(subfolder, member, root_path) }
folder.dmsf_files.visible.each { |file| add_file(file, member, root_path) }
::Zip::DOSTime.at(dmsf_folder.modified))
return if @folders.include?(string_path)

@zip_file.put_next_entry zip_entry
@folders << string_path
dmsf_folder.dmsf_folders.visible.each { |folder| add_dmsf_folder(folder, member, root_path) }
dmsf_folder.dmsf_files.visible.each { |file| add_dmsf_file(file, member, root_path) }
end
end
end
Expand Down
3 changes: 1 addition & 2 deletions test/helper_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,9 @@ def setup
[@project1, @project2].each do |prj|
prj.enable_module! :dmsf
end
Setting.plugin_redmine_dmsf['dmsf_storage_directory'] = File.join('files', ['dmsf'])
Setting.plugin_redmine_dmsf['dmsf_storage_directory'] = File.join('files', 'dmsf')
Setting.plugin_redmine_dmsf['dmsf_webdav_use_project_names'] = nil
Setting.plugin_redmine_dmsf['dmsf_projects_as_subfolders'] = nil
Setting.plugin_redmine_dmsf['dmsf_storage_directory'] = File.join('files', ['dmsf'])
FileUtils.cp_r File.join(File.expand_path('../fixtures/files', __FILE__), '.'), DmsfFile.storage_path
end

Expand Down
3 changes: 1 addition & 2 deletions test/unit/lib/redmine_dmsf/dmsf_macros_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,7 @@ class DmsfMacrosTest < RedmineDmsf::Test::HelperTest
include Rails.application.routes.url_helpers
include ActionView::Helpers::UrlHelper

fixtures :dmsf_folders, :dmsf_files, :dmsf_file_revisions, :dmsf_folders, :dmsf_files,
:dmsf_file_revisions
fixtures :dmsf_folders, :dmsf_files, :dmsf_file_revisions

def setup
super
Expand Down
95 changes: 95 additions & 0 deletions test/unit/lib/redmine_dmsf/dmsf_zip_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# frozen_string_literal: true

# Redmine plugin for Document Management System "Features"
#
# Karel Pičman <[email protected]>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

require File.expand_path('../../../../test_helper', __FILE__)

# Plugin tests
class DmsfZipTest < RedmineDmsf::Test::HelperTest
fixtures :dmsf_folders, :dmsf_files, :dmsf_file_revisions, :attachments
def setup
@zip = RedmineDmsf::DmsfZip::Zip.new

Setting.plugin_redmine_dmsf['dmsf_storage_directory'] = File.join('files', 'dmsf')
FileUtils.cp_r File.join(File.expand_path('../../../../fixtures/files', __FILE__), '.'), DmsfFile.storage_path
@dmsf_file1 = DmsfFile.find(1)
@dmsf_folder2 = DmsfFolder.find(2)
set_fixtures_attachments_directory
@attachment4 = Attachment.find(4)
end

def teardown
# Delete our tmp folder
FileUtils.rm_rf DmsfFile.storage_path
rescue StandardError => e
Rails.logger.error e.message
end

def test_add_dmsf_file
@zip.add_dmsf_file @dmsf_file1
assert_equal 1, @zip.dmsf_files.size
zip_file = @zip.finish
Zip::File.open(zip_file) do |file|
file.each do |entry|
assert_equal @dmsf_file1.last_revision.name, entry.name
end
end
end

def test_add_attachment
@zip.add_attachment @attachment4, @attachment4.filename
assert_equal 0, @zip.dmsf_files.size
zip_file = @zip.finish
Zip::File.open(zip_file) do |file|
file.each do |entry|
assert_equal @attachment4.filename, entry.name
end
end
end

def test_add_raw_file
filename = 'data.txt'
content = '1,2,3'
@zip.add_raw_file filename, content
assert_equal 0, @zip.dmsf_files.size
zip_file = @zip.finish
Zip::File.open(zip_file) do |file|
file.each do |entry|
assert_equal filename, entry.name
assert_equal content, entry.get_input_stream.read
end
end
end

def test_read
@zip.add_dmsf_file @dmsf_file1
assert_not_empty @zip.read
end

def test_finish
@zip.add_dmsf_file @dmsf_file1
zip_file = @zip.finish
assert File.exist?(zip_file)
end

def test_close
@zip.add_dmsf_file @dmsf_file1
assert @zip.close
end
end

0 comments on commit 5e81d5e

Please sign in to comment.