libis-format 1.2.9 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile +2 -0
- data/data/types.yml +1 -1
- data/lib/libis/format/command_line.rb +2 -3
- data/lib/libis/format/config.rb +18 -19
- data/lib/libis/format/converter/base.rb +9 -16
- data/lib/libis/format/converter/chain.rb +36 -28
- data/lib/libis/format/converter/email_converter.rb +5 -8
- data/lib/libis/format/converter/fop_pdf_converter.rb +4 -6
- data/lib/libis/format/converter/image_converter.rb +51 -58
- data/lib/libis/format/converter/jp2_converter.rb +33 -35
- data/lib/libis/format/converter/office_converter.rb +19 -23
- data/lib/libis/format/converter/pdf_converter.rb +22 -28
- data/lib/libis/format/converter/repository.rb +7 -13
- data/lib/libis/format/converter/spreadsheet_converter.rb +7 -11
- data/lib/libis/format/converter/video_converter.rb +41 -55
- data/lib/libis/format/converter/xslt_converter.rb +14 -13
- data/lib/libis/format/converter.rb +1 -1
- data/lib/libis/format/identifier.rb +41 -43
- data/lib/libis/format/tool/droid.rb +29 -30
- data/lib/libis/format/tool/ff_mpeg.rb +11 -13
- data/lib/libis/format/tool/fido.rb +1 -1
- data/lib/libis/format/tool/pdf_copy.rb +17 -18
- data/lib/libis/format/tool/pdf_merge.rb +17 -17
- data/lib/libis/format/tool/pdf_optimizer.rb +18 -20
- data/lib/libis/format/tool/spreadsheet_to_ods.rb +23 -20
- data/lib/libis/format/tool.rb +2 -2
- data/lib/libis/format/type_database.rb +51 -28
- data/lib/libis/format/type_database_impl.rb +57 -24
- data/lib/libis/format/version.rb +1 -1
- data/lib/libis/format.rb +3 -2
- data/lib/libis-format.rb +2 -0
- metadata +3 -3
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'base'
|
2
4
|
|
3
5
|
module Libis
|
4
6
|
module Format
|
@@ -9,10 +11,9 @@ module Libis
|
|
9
11
|
end
|
10
12
|
|
11
13
|
def self.output_types(format = nil)
|
12
|
-
if format
|
13
|
-
|
14
|
-
|
15
|
-
[:XML, :HTML, :TXT]
|
14
|
+
return [] if format && !input_types.include?(format)
|
15
|
+
|
16
|
+
%i[XML HTML TXT]
|
16
17
|
end
|
17
18
|
|
18
19
|
def xsl_file(file_path)
|
@@ -28,20 +29,20 @@ module Libis
|
|
28
29
|
end
|
29
30
|
|
30
31
|
unless @options[:xsl_file]
|
31
|
-
error
|
32
|
+
error 'No xsl_file supplied'
|
32
33
|
return nil
|
33
34
|
end
|
34
35
|
|
35
36
|
FileUtils.mkpath(File.dirname(target))
|
36
37
|
|
37
|
-
if RUBY_PLATFORM ==
|
38
|
-
require
|
38
|
+
if RUBY_PLATFORM == 'java'
|
39
|
+
require 'saxon-xslt'
|
39
40
|
xsl = Saxon.XSLT(File.open(@options[:xsl_file]))
|
40
41
|
xml = Saxon.XML(File.open(source))
|
41
42
|
result = xsl.transform(xml)
|
42
43
|
File.write(target, result.to_s)
|
43
44
|
else
|
44
|
-
require
|
45
|
+
require 'nokogiri'
|
45
46
|
|
46
47
|
doc = nil
|
47
48
|
begin
|
@@ -65,7 +66,7 @@ module Libis
|
|
65
66
|
xsl = nil
|
66
67
|
|
67
68
|
begin
|
68
|
-
fp = File.open(file,
|
69
|
+
fp = File.open(file, 'r')
|
69
70
|
xsl = Nokogiri::XSLT(fp) do |config|
|
70
71
|
config.options = Nokogiri::XML::ParseOptions::STRICT | Nokogiri::XML::ParseOptions::NOBLANKS
|
71
72
|
end
|
@@ -80,17 +81,17 @@ module Libis
|
|
80
81
|
|
81
82
|
begin
|
82
83
|
target_xml = xsl.transform(doc)
|
83
|
-
fp = File.open(target,
|
84
|
+
fp = File.open(target, 'w')
|
84
85
|
fp.write(target_xml)
|
85
86
|
rescue Exception => e
|
86
87
|
error "Error transforming '#{source}' with '#{file}': #{e.message} @ #{e.backtrace[0]}"
|
87
88
|
return nil
|
88
89
|
ensure
|
89
|
-
fp.close unless fp.nil?
|
90
|
+
fp.close unless fp.nil? || fp.closed?
|
90
91
|
end
|
91
92
|
|
92
93
|
{
|
93
|
-
command: {status: 0},
|
94
|
+
command: { status: 0 },
|
94
95
|
files: [target]
|
95
96
|
}
|
96
97
|
|
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'singleton'
|
4
4
|
require 'pathname'
|
@@ -7,7 +7,6 @@ require 'libis-tools'
|
|
7
7
|
require 'libis/tools/extend/hash'
|
8
8
|
require 'libis/tools/extend/string'
|
9
9
|
require 'libis/tools/extend/empty'
|
10
|
-
require 'nori/core_ext/object'
|
11
10
|
|
12
11
|
require 'libis/format/type_database'
|
13
12
|
|
@@ -19,13 +18,10 @@ require_relative 'tool/extension_identification'
|
|
19
18
|
|
20
19
|
module Libis
|
21
20
|
module Format
|
22
|
-
|
23
21
|
class Identifier
|
24
22
|
include ::Libis::Tools::Logger
|
25
23
|
include Singleton
|
26
24
|
|
27
|
-
public
|
28
|
-
|
29
25
|
def self.add_xml_validation(mimetype, xsd_file)
|
30
26
|
instance.xml_validations[mimetype] = xsd_file
|
31
27
|
end
|
@@ -41,29 +37,28 @@ module Libis
|
|
41
37
|
attr_reader :xml_validations
|
42
38
|
|
43
39
|
def get(file, options = {})
|
44
|
-
|
45
|
-
options[:
|
46
|
-
options[:
|
47
|
-
options[:file] = true unless options.keys.include?(:file) or (options[:tool] and options[:tool] != :file)
|
40
|
+
options[:droid] = true unless options.keys.include?(:droid) || (options[:tool] && (options[:tool] != :droid))
|
41
|
+
options[:fido] = true unless options.keys.include?(:fido) || (options[:tool] && (options[:tool] != :fido))
|
42
|
+
options[:file] = true unless options.keys.include?(:file) || (options[:tool] && (options[:tool] != :file))
|
48
43
|
options[:xml_validation] = true if options[:xml_validation].nil?
|
49
44
|
|
50
|
-
result = {messages: [], output: {}, formats: {}}
|
45
|
+
result = { messages: [], output: {}, formats: {} }
|
51
46
|
|
52
47
|
begin
|
53
48
|
get_droid_identification(file, result, options) if options[:droid]
|
54
|
-
rescue => e
|
49
|
+
rescue StandardError => e
|
55
50
|
log_msg(result, :error, "Error running Droid: #{e.message} @ #{e.backtrace.first}")
|
56
51
|
end
|
57
52
|
|
58
53
|
begin
|
59
54
|
get_fido_identification(file, result, options) if options[:fido]
|
60
|
-
rescue => e
|
55
|
+
rescue StandardError => e
|
61
56
|
log_msg(result, :error, "Error running Fido: #{e.message} @ #{e.backtrace.first}")
|
62
57
|
end
|
63
58
|
|
64
59
|
begin
|
65
60
|
get_file_identification(file, result, options) if options[:file]
|
66
|
-
rescue => e
|
61
|
+
rescue StandardError => e
|
67
62
|
log_msg(result, :error, "Error running File: #{e.message} @ #{e.backtrace.first}")
|
68
63
|
end
|
69
64
|
|
@@ -74,14 +69,13 @@ module Libis
|
|
74
69
|
# Libis::Tools::Format::Identifier.add_xml_validation('my_type', '/path/to/my_type.xsd')
|
75
70
|
begin
|
76
71
|
validate_against_xml_schema(result, options[:base_dir]) if options[:xml_validation]
|
77
|
-
rescue => e
|
72
|
+
rescue StandardError => e
|
78
73
|
log_msg(result, :error, "Error validating XML files: #{e.message} @ #{e.backtrace.first}")
|
79
74
|
end
|
80
75
|
|
81
76
|
process_results(result, !options[:keep_output])
|
82
77
|
|
83
78
|
result
|
84
|
-
|
85
79
|
end
|
86
80
|
|
87
81
|
protected
|
@@ -123,18 +117,21 @@ module Libis
|
|
123
117
|
end
|
124
118
|
|
125
119
|
def xml_validate(file, file_result, result, base_dir)
|
126
|
-
return unless file_result[:mimetype] =~
|
120
|
+
return unless file_result[:mimetype] =~ %r{^(text|application)/xml$}
|
121
|
+
|
127
122
|
filepath = base_dir ? File.join(base_dir, file) : file
|
128
123
|
doc = ::Libis::Tools::XmlDocument.open filepath
|
129
124
|
xml_validations.each do |mime, xsd_file|
|
130
125
|
next unless xsd_file
|
126
|
+
|
131
127
|
begin
|
132
128
|
if doc.validates_against?(xsd_file)
|
133
129
|
log_msg result, :debug, "XML file validated against XML Schema: #{xsd_file}"
|
134
|
-
info = {mimetype: mime, tool_raw: file_result[:tool], tool: :xsd_validation, match_type: 'xsd_validation',
|
130
|
+
info = { mimetype: mime, tool_raw: file_result[:tool], tool: :xsd_validation, match_type: 'xsd_validation',
|
131
|
+
format_version: '' }
|
135
132
|
file_result.merge! Libis::Format::TypeDatabase.enrich(info, PUID: :puid, MIME: :mimetype, NAME: :format_name)
|
136
133
|
end
|
137
|
-
rescue => e
|
134
|
+
rescue StandardError => e
|
138
135
|
# Do nothing - probably Nokogiri chrashed during validation. Could have many causes
|
139
136
|
# (remote schema (firewall, network, link rot, ...), schema syntax error, corrupt XML,...)
|
140
137
|
# so we log and continue.
|
@@ -142,7 +139,7 @@ module Libis
|
|
142
139
|
"Error during XML validation of file #{file} against #{File.basename(xsd_file)}: #{e.message}")
|
143
140
|
end
|
144
141
|
end
|
145
|
-
rescue => e
|
142
|
+
rescue StandardError => e
|
146
143
|
# Not much we can do. probably Nokogiri chrashed opening the XML file. What caused this?
|
147
144
|
# (XML not parsable, false XML identification, ???)
|
148
145
|
# so we log and continue.
|
@@ -150,30 +147,30 @@ module Libis
|
|
150
147
|
end
|
151
148
|
|
152
149
|
def process_results(result, delete_output = true)
|
153
|
-
result[:output].
|
150
|
+
result[:output].each_key do |file|
|
154
151
|
output = result[:output][file]
|
155
152
|
file_result = result[:formats][file] = {}
|
156
153
|
if output.empty?
|
157
154
|
log_msg(result, :warn, "Could not identify format of '#{file}'.")
|
158
|
-
file_result
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
155
|
+
file_result.merge!(
|
156
|
+
mimetype: 'application/octet-stream',
|
157
|
+
puid: 'fmt/unknown',
|
158
|
+
score: 0,
|
159
|
+
tool: nil
|
160
|
+
)
|
164
161
|
else
|
165
|
-
format_matches = output.group_by {|x| [x[:mimetype], x[:puid]]}
|
162
|
+
format_matches = output.group_by { |x| [x[:mimetype], x[:puid]] }
|
166
163
|
format_matches.each do |match, group|
|
167
|
-
format_matches[match] = group.group_by {|x| x[:score]}.sort.reverse.to_h
|
164
|
+
format_matches[match] = group.group_by { |x| x[:score] }.sort.reverse.to_h
|
168
165
|
end
|
169
166
|
case format_matches.count
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
167
|
+
when 0
|
168
|
+
# No this really cannot happen. If there are no hits, there will be at least a format [nil,nil]
|
169
|
+
when 1
|
170
|
+
# only one match, that's easy. The first of the highest score will be used
|
171
|
+
file_result.merge!(get_best_result(output))
|
172
|
+
else
|
173
|
+
process_multiple_formats(file_result, format_matches, output)
|
177
174
|
end
|
178
175
|
end
|
179
176
|
end
|
@@ -184,12 +181,13 @@ module Libis
|
|
184
181
|
# multiple matches. Let's select the highest score matches
|
185
182
|
file_result.merge!(get_best_result(output))
|
186
183
|
file_result[:alternatives] = []
|
187
|
-
format_matches.
|
184
|
+
format_matches.each_key do |mime, puid|
|
188
185
|
next if file_result[:mimetype] == mime && puid.nil?
|
189
|
-
|
186
|
+
|
187
|
+
selection = output.select { |x| x[:mimetype] == mime && x[:puid] == puid }
|
190
188
|
file_result[:alternatives] << get_best_result(selection)
|
191
189
|
end
|
192
|
-
file_result[:alternatives] = file_result[:alternatives].sort_by {|x| x[:score]}.reverse
|
190
|
+
file_result[:alternatives] = file_result[:alternatives].sort_by { |x| x[:score] }.reverse
|
193
191
|
file_result.delete(:alternatives) if file_result[:alternatives].size <= 1
|
194
192
|
end
|
195
193
|
|
@@ -208,15 +206,15 @@ module Libis
|
|
208
206
|
end
|
209
207
|
|
210
208
|
def get_mimetype(puid)
|
211
|
-
::Libis::Format::TypeDatabase.puid_typeinfo(puid)[:MIME].first
|
209
|
+
::Libis::Format::TypeDatabase.puid_typeinfo(puid)[:MIME].first
|
210
|
+
rescue StandardError
|
211
|
+
nil
|
212
212
|
end
|
213
213
|
|
214
214
|
def get_best_result(results)
|
215
|
-
score = results.map {|x| x[:score]}.max
|
216
|
-
results.select {|x| x[:score] == score}.reduce(:apply_defaults)
|
215
|
+
score = results.map { |x| x[:score] }.max
|
216
|
+
results.select { |x| x[:score] == score }.reduce(:apply_defaults)
|
217
217
|
end
|
218
|
-
|
219
218
|
end
|
220
|
-
|
221
219
|
end
|
222
220
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'singleton'
|
2
4
|
|
3
5
|
require 'tempfile'
|
@@ -5,10 +7,10 @@ require 'csv'
|
|
5
7
|
|
6
8
|
require 'libis/format/config'
|
7
9
|
|
8
|
-
unless CSV::HeaderConverters.
|
9
|
-
CSV::HeaderConverters[:droid_headers] = lambda {|h|
|
10
|
-
h.encode(ConverterEncoding).downcase.strip
|
11
|
-
|
10
|
+
unless CSV::HeaderConverters.key?(:droid_headers)
|
11
|
+
CSV::HeaderConverters[:droid_headers] = lambda { |h|
|
12
|
+
h.encode(ConverterEncoding).downcase.strip
|
13
|
+
.gsub(/\W+/, '').to_sym
|
12
14
|
}
|
13
15
|
end
|
14
16
|
|
@@ -17,9 +19,7 @@ require_relative 'identification_tool'
|
|
17
19
|
module Libis
|
18
20
|
module Format
|
19
21
|
module Tool
|
20
|
-
|
21
22
|
class Droid < Libis::Format::Tool::IdentificationTool
|
22
|
-
|
23
23
|
def run_list(filelist, _options = {})
|
24
24
|
runner(filelist)
|
25
25
|
end
|
@@ -43,12 +43,13 @@ module Libis
|
|
43
43
|
end
|
44
44
|
|
45
45
|
def parse_report(report)
|
46
|
-
keys = [
|
47
|
-
|
48
|
-
|
46
|
+
keys = %i[
|
47
|
+
id parent_id uri filepath filename matchtype status filesize type extension
|
48
|
+
mod_time ext_mismatch hash format_count puid mimetype format_name format_version
|
49
|
+
]
|
49
50
|
result = CSV.parse(File.readlines(report).join)
|
50
|
-
|
51
|
-
|
51
|
+
.map { |a| Hash[keys.zip(a)] }
|
52
|
+
.select { |a| a[:type] == 'File' }
|
52
53
|
# File.delete report
|
53
54
|
result.each do |r|
|
54
55
|
r.delete(:id)
|
@@ -70,39 +71,39 @@ module Libis
|
|
70
71
|
|
71
72
|
def create_report(profile, report)
|
72
73
|
args = [
|
73
|
-
|
74
|
-
|
75
|
-
|
74
|
+
'-e', report,
|
75
|
+
'-p', profile,
|
76
|
+
'-q'
|
76
77
|
]
|
77
78
|
timeout = Libis::Format::Config[:timeouts][:droid]
|
78
79
|
result = Libis::Tools::Command.run(
|
79
|
-
|
80
|
-
|
81
|
-
|
80
|
+
Libis::Format::Config[:droid_cmd], *args,
|
81
|
+
timeout:,
|
82
|
+
kill_after: timeout * 2
|
82
83
|
)
|
83
|
-
result[:err].select! {|x| x =~ /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2},\d{3} ERROR /}
|
84
|
-
raise
|
85
|
-
raise
|
84
|
+
result[:err].select! { |x| x =~ /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2},\d{3} ERROR / }
|
85
|
+
raise "#{self.class} report took too long (> #{timeout} seconds) to complete" if result[:timeout]
|
86
|
+
raise "#{self.class} report errors: #{result[:err].join("\n")}" unless result[:err].empty?
|
86
87
|
|
87
88
|
File.delete profile
|
88
89
|
end
|
89
90
|
|
90
91
|
def create_profile(file_or_list, profile, recursive = false)
|
91
92
|
args = []
|
92
|
-
files =
|
93
|
-
files.each {|file| args << '-a' << file}
|
93
|
+
files = file_or_list.is_a?(Array) ? file_or_list.map(&:escape_for_string) : [file_or_list.escape_for_string]
|
94
|
+
files.each { |file| args << '-a' << file }
|
94
95
|
args << '-q'
|
95
96
|
args << '-p' << profile
|
96
97
|
args << '-R' if recursive
|
97
98
|
timeout = Libis::Format::Config[:timeouts][:droid]
|
98
99
|
result = Libis::Tools::Command.run(
|
99
|
-
|
100
|
-
|
101
|
-
|
100
|
+
Libis::Format::Config[:droid_cmd], *args,
|
101
|
+
timeout:,
|
102
|
+
kill_after: timeout * 2
|
102
103
|
)
|
103
|
-
result[:err].select! {|x| x =~ /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2},\d{3} ERROR /}
|
104
|
-
raise
|
105
|
-
raise
|
104
|
+
result[:err].select! { |x| x =~ /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2},\d{3} ERROR / }
|
105
|
+
raise "#{self.class} profile took too long (> #{timeout} seconds) to complete" if result[:timeout]
|
106
|
+
raise "#{self.class} profile errors: #{result[:err].join("\n")}" unless result[:err].empty?
|
106
107
|
end
|
107
108
|
|
108
109
|
def profile_file_name
|
@@ -112,9 +113,7 @@ module Libis
|
|
112
113
|
def result_file_name
|
113
114
|
Tools::TempFile.name('droid', '.csv')
|
114
115
|
end
|
115
|
-
|
116
116
|
end
|
117
|
-
|
118
117
|
end
|
119
118
|
end
|
120
119
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'libis/tools/extend/string'
|
2
4
|
require 'libis/tools/extend/empty'
|
3
5
|
require 'libis/tools/command'
|
@@ -8,18 +10,17 @@ require 'libis/format/config'
|
|
8
10
|
module Libis
|
9
11
|
module Format
|
10
12
|
module Tool
|
11
|
-
|
12
13
|
class FFMpeg
|
13
14
|
include Singleton
|
14
15
|
include ::Libis::Tools::Logger
|
15
16
|
|
16
17
|
def self.installed?
|
17
|
-
result = Libis::Tools::Command.run(Libis::Format::Config[:ffmpeg_cmd],
|
18
|
-
result[:status]
|
18
|
+
result = Libis::Tools::Command.run(Libis::Format::Config[:ffmpeg_cmd], '-h')
|
19
|
+
(result[:status]).zero?
|
19
20
|
end
|
20
21
|
|
21
22
|
def self.run(source, target, options = {})
|
22
|
-
|
23
|
+
instance.run source, target, options
|
23
24
|
end
|
24
25
|
|
25
26
|
def run(source, target, options = {})
|
@@ -33,25 +34,22 @@ module Libis
|
|
33
34
|
|
34
35
|
timeout = Libis::Format::Config[:timeouts][:ffmpeg]
|
35
36
|
result = Libis::Tools::Command.run(
|
36
|
-
|
37
|
-
|
38
|
-
|
37
|
+
Libis::Format::Config[:ffmpeg_cmd], *opts,
|
38
|
+
timeout:,
|
39
|
+
kill_after: timeout * 2
|
39
40
|
)
|
40
41
|
|
41
|
-
raise
|
42
|
-
raise
|
42
|
+
raise "#{self.class} took too long (> #{timeout} seconds) to complete" if result[:timeout]
|
43
|
+
raise "#{self.class} errors: #{result[:err].join("\n")}" unless (result[:status]).zero?
|
43
44
|
|
44
45
|
warn "FFMpeg warnings: #{(result[:err] + result[:out]).join("\n")}" unless result[:err].empty?
|
45
46
|
|
46
47
|
{
|
47
48
|
command: result,
|
48
|
-
files: [
|
49
|
+
files: [target]
|
49
50
|
}
|
50
|
-
|
51
51
|
end
|
52
|
-
|
53
52
|
end
|
54
|
-
|
55
53
|
end
|
56
54
|
end
|
57
55
|
end
|
@@ -80,7 +80,7 @@ module Libis
|
|
80
80
|
|
81
81
|
# Log warning if needed
|
82
82
|
raise "#{self.class} took too long (> #{timeout} seconds) to complete" if result[:timeout]
|
83
|
-
raise "#{self.class} errors: #{result[:err].join("\n")}" unless (result[:status])
|
83
|
+
raise "#{self.class} errors: #{result[:err].join("\n")}" unless (result[:status])&.zero? && result[:err].empty?
|
84
84
|
|
85
85
|
# Parse output (CSV) text into array and return result
|
86
86
|
keys = %i[status time puid format_name format_version filesize filepath mimetype matchtype]
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'os'
|
2
4
|
|
3
5
|
require 'libis/tools/extend/string'
|
@@ -9,49 +11,46 @@ require 'libis/format/config'
|
|
9
11
|
module Libis
|
10
12
|
module Format
|
11
13
|
module Tool
|
12
|
-
|
13
14
|
class PdfCopy
|
14
15
|
include ::Libis::Tools::Logger
|
15
16
|
|
16
17
|
def self.installed?
|
17
|
-
result = Libis::Tools::Command.run(Libis::Format::Config[:java_cmd],
|
18
|
-
return false unless result[:status]
|
18
|
+
result = Libis::Tools::Command.run(Libis::Format::Config[:java_cmd], '-version')
|
19
|
+
return false unless (result[:status]).zero?
|
20
|
+
|
19
21
|
File.exist?(Libis::Format::Config[:pdf_tool])
|
20
22
|
end
|
21
23
|
|
22
24
|
def self.run(source, target, options = [])
|
23
|
-
|
25
|
+
new.run source, target, options
|
24
26
|
end
|
25
27
|
|
26
28
|
def run(source, target, options = [])
|
27
|
-
|
28
29
|
if OS.java?
|
29
30
|
# TODO: import library and execute in current VM. For now do exactly as in MRI.
|
30
31
|
end
|
31
32
|
|
32
33
|
timeout = Libis::Format::Config[:timeouts][:pdf_copy]
|
33
34
|
result = Libis::Tools::Command.run(
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
35
|
+
Libis::Format::Config[:java_cmd],
|
36
|
+
'-cp', Libis::Format::Config[:pdf_tool],
|
37
|
+
'CopyPdf',
|
38
|
+
'--file_input', source,
|
39
|
+
'--file_output', target,
|
40
|
+
*options,
|
41
|
+
timeout:,
|
42
|
+
kill_after: timeout * 2
|
42
43
|
)
|
43
44
|
|
44
|
-
raise
|
45
|
-
raise
|
45
|
+
raise "#{self.class} took too long (> #{timeout} seconds) to complete" if result[:timeout]
|
46
|
+
raise "#{self.class} errors: #{result[:err].join("\n")}" unless (result[:status]).zero? && result[:err].empty?
|
46
47
|
|
47
48
|
{
|
48
49
|
command: result,
|
49
|
-
files: [
|
50
|
+
files: [target]
|
50
51
|
}
|
51
|
-
|
52
52
|
end
|
53
53
|
end
|
54
|
-
|
55
54
|
end
|
56
55
|
end
|
57
56
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'os'
|
2
4
|
|
3
5
|
require 'libis/tools/extend/string'
|
@@ -9,18 +11,18 @@ require 'libis/format/config'
|
|
9
11
|
module Libis
|
10
12
|
module Format
|
11
13
|
module Tool
|
12
|
-
|
13
14
|
class PdfMerge
|
14
15
|
include ::Libis::Tools::Logger
|
15
16
|
|
16
17
|
def self.installed?
|
17
|
-
result = Libis::Tools::Command.run(Libis::Format::Config[:java_cmd],
|
18
|
-
return false unless result[:status]
|
18
|
+
result = Libis::Tools::Command.run(Libis::Format::Config[:java_cmd], '-version')
|
19
|
+
return false unless (result[:status]).zero?
|
20
|
+
|
19
21
|
File.exist?(Libis::Format::Config[:pdf_tool])
|
20
22
|
end
|
21
23
|
|
22
24
|
def self.run(source, target, options = [])
|
23
|
-
|
25
|
+
new.run source, target, options
|
24
26
|
end
|
25
27
|
|
26
28
|
def run(source, target, options = [])
|
@@ -32,27 +34,25 @@ module Libis
|
|
32
34
|
|
33
35
|
timeout = Libis::Format::Config[:timeouts][:pdf_merge]
|
34
36
|
result = Libis::Tools::Command.run(
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
37
|
+
Libis::Format::Config[:java_cmd],
|
38
|
+
'-cp', Libis::Format::Config[:pdf_tool],
|
39
|
+
'MergePdf',
|
40
|
+
'--file_output', target,
|
41
|
+
*options,
|
42
|
+
*source,
|
43
|
+
timeout:,
|
44
|
+
kill_after: timeout * 2
|
43
45
|
)
|
44
46
|
|
45
|
-
raise
|
46
|
-
raise
|
47
|
+
raise "#{self.class} took too long (> #{timeout} seconds) to complete" if result[:timeout]
|
48
|
+
raise "#{self.class} errors: #{result[:err].join("\n")}" unless (result[:status]).zero? && result[:err].empty?
|
47
49
|
|
48
50
|
{
|
49
51
|
command: result,
|
50
|
-
files: [
|
52
|
+
files: [target]
|
51
53
|
}
|
52
|
-
|
53
54
|
end
|
54
55
|
end
|
55
|
-
|
56
56
|
end
|
57
57
|
end
|
58
58
|
end
|