libis-format 1.2.9 → 1.3.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +4 -0
  3. data/bin/{pdf_copy → pdf_tool} +3 -2
  4. data/data/types.yml +1 -1
  5. data/lib/libis/format/command_line.rb +2 -3
  6. data/lib/libis/format/config.rb +17 -20
  7. data/lib/libis/format/converter/base.rb +9 -16
  8. data/lib/libis/format/converter/chain.rb +36 -28
  9. data/lib/libis/format/converter/email_converter.rb +5 -8
  10. data/lib/libis/format/converter/fop_pdf_converter.rb +4 -6
  11. data/lib/libis/format/converter/image_converter.rb +51 -58
  12. data/lib/libis/format/converter/jp2_converter.rb +33 -35
  13. data/lib/libis/format/converter/office_converter.rb +19 -23
  14. data/lib/libis/format/converter/pdf_converter.rb +133 -52
  15. data/lib/libis/format/converter/repository.rb +7 -13
  16. data/lib/libis/format/converter/spreadsheet_converter.rb +7 -11
  17. data/lib/libis/format/converter/video_converter.rb +41 -55
  18. data/lib/libis/format/converter/xslt_converter.rb +14 -13
  19. data/lib/libis/format/converter.rb +1 -1
  20. data/lib/libis/format/identifier.rb +41 -43
  21. data/lib/libis/format/tool/droid.rb +29 -30
  22. data/lib/libis/format/tool/ff_mpeg.rb +11 -13
  23. data/lib/libis/format/tool/fido.rb +1 -1
  24. data/lib/libis/format/tool/pdf_optimizer.rb +21 -27
  25. data/lib/libis/format/tool/pdf_to_pdfa.rb +2 -6
  26. data/lib/libis/format/tool/pdf_tool.rb +52 -0
  27. data/lib/libis/format/tool/pdfa_validator.rb +2 -3
  28. data/lib/libis/format/tool/spreadsheet_to_ods.rb +23 -20
  29. data/lib/libis/format/tool.rb +2 -2
  30. data/lib/libis/format/type_database.rb +51 -28
  31. data/lib/libis/format/type_database_impl.rb +57 -24
  32. data/lib/libis/format/version.rb +1 -1
  33. data/lib/libis/format.rb +3 -2
  34. data/lib/libis-format.rb +2 -0
  35. data/tools/PdfTool.jar +0 -0
  36. data/tools/pdfbox/pdfbox-app-3.0.3.jar +0 -0
  37. data/tools/pdfbox/{preflight-app-2.0.13.jar → preflight-app-3.0.3.jar} +0 -0
  38. metadata +8 -10
  39. data/lib/libis/format/tool/pdf_copy.rb +0 -57
  40. data/lib/libis/format/tool/pdf_merge.rb +0 -58
  41. data/lib/libis/format/tool/pdf_split.rb +0 -56
  42. data/tools/pdfbox/pdfbox-app-2.0.13.jar +0 -0
@@ -1,4 +1,6 @@
1
- require_relative "base"
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
- return [] unless input_types.include?(format)
14
- end
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 "No xsl_file supplied"
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 == "java"
38
- require "saxon-xslt"
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 "nokogiri"
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, "r")
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, "w")
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? or fp.closed?
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
- # code utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Libis
4
4
  module Format
@@ -1,4 +1,4 @@
1
- # encoding: utf-8
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[:droid] = true unless options.keys.include?(:droid) or (options[:tool] and options[:tool] != :droid)
46
- options[:fido] = true unless options.keys.include?(:fido) or (options[:tool] and options[:tool] != :fido)
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] =~ /^(text|application)\/xml$/
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', format_version: '', }
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].keys.each do |file|
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
- mimetype: 'application/octet-stream',
160
- puid: 'fmt/unknown',
161
- score: 0,
162
- tool: nil
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
- when 0
171
- # No this really cannot happen. If there are no hits, there will be at least a format [nil,nil]
172
- when 1
173
- # only one match, that's easy. The first of the highest score will be used
174
- file_result.merge!(get_best_result(output))
175
- else
176
- process_multiple_formats(file_result, format_matches, output)
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.keys.each do |mime, puid|
184
+ format_matches.each_key do |mime, puid|
188
185
  next if file_result[:mimetype] == mime && puid.nil?
189
- selection = output.select {|x| x[:mimetype] == mime && x[:puid] == puid}
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 rescue nil
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.has_key?(:droid_headers)
9
- CSV::HeaderConverters[:droid_headers] = lambda {|h|
10
- h.encode(ConverterEncoding).downcase.strip.
11
- gsub(/\W+/, "").to_sym
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
- :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]
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
- .map {|a| Hash[keys.zip(a)]}
51
- .select {|a| a[:type] == 'File'}
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
- '-e', report,
74
- '-p', profile,
75
- '-q'
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
- Libis::Format::Config[:droid_cmd], *args,
80
- timeout: timeout,
81
- kill_after: timeout * 2
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 RuntimeError, "#{self.class} report took too long (> #{timeout} seconds) to complete" if result[:timeout]
85
- raise RuntimeError, "#{self.class} report errors: #{result[:err].join("\n")}" unless result[:err].empty?
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 = (file_or_list.is_a?(Array)) ? file_or_list.map(&:escape_for_string) : [file_or_list.escape_for_string]
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
- Libis::Format::Config[:droid_cmd], *args,
100
- timeout: timeout,
101
- kill_after: timeout * 2
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 RuntimeError, "#{self.class} profile took too long (> #{timeout} seconds) to complete" if result[:timeout]
105
- raise RuntimeError, "#{self.class} profile errors: #{result[:err].join("\n")}" unless result[:err].empty?
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], "-h")
18
- result[:status] == 0
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
- self.instance.run source, target, options
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
- Libis::Format::Config[:ffmpeg_cmd], *opts,
37
- timeout: timeout,
38
- kill_after: timeout * 2
37
+ Libis::Format::Config[:ffmpeg_cmd], *opts,
38
+ timeout:,
39
+ kill_after: timeout * 2
39
40
  )
40
41
 
41
- raise RuntimeError, "#{self.class} took too long (> #{timeout} seconds) to complete" if result[:timeout]
42
- raise RuntimeError, "#{self.class} errors: #{result[:err].join("\n")}" unless result[:status] == 0
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: [ target ]
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]).zero? && result[:err].empty?
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,46 +11,38 @@ require 'libis/format/config'
9
11
  module Libis
10
12
  module Format
11
13
  module Tool
12
-
13
14
  class PdfOptimizer
14
15
  include ::Libis::Tools::Logger
15
16
 
16
17
  def self.installed?
17
- result = Libis::Tools::Command.run(Libis::Format::Config[:ghostscript_cmd], "--version")
18
- result[:status] == 0
18
+ result = Libis::Tools::Command.run(Libis::Format::Config[:ghostscript_cmd], '--version')
19
+ (result[:status]).zero?
19
20
  end
20
21
 
21
22
  def self.run(source, target, quality)
22
- self.new.run source, target, quality
23
+ new.run source, target, quality
23
24
  end
24
25
 
25
26
  def run(source, target, quality)
26
-
27
27
  timeout = Libis::Format::Config[:timeouts][:pdf_optimizer]
28
- result = Libis::Tools::Command.run(
29
- Libis::Format::Config[:ghostscript_cmd],
30
- '-sDEVICE=pdfwrite',
31
- '-dCompatibilityLevel=1.4',
32
- "-dPDFSETTINGS=/#{quality}",
33
- '-dNOPAUSE',
34
- '-dBATCH',
35
- "-sOutputFile=#{target}",
36
- "#{source}",
37
- timeout: timeout,
38
- kill_after: timeout * 2
39
- )
40
-
41
- raise RuntimeError, "#{self.class} took too long (> #{timeout} seconds) to complete" if result[:timeout]
42
- raise RuntimeError, "#{self.class} errors: #{result[:err].join("\n")}" unless result[:status] == 0
43
-
44
- {
45
- command: result,
46
- files: [ target ]
47
- }
48
-
28
+ args = [
29
+ Libis::Format::Config[:ghostscript_cmd],
30
+ '-sDEVICE=pdfwrite',
31
+ '-dCompatibilityLevel=1.4',
32
+ "-dPDFSETTINGS=/#{quality}",
33
+ '-dNOPAUSE',
34
+ '-dBATCH',
35
+ "-sOutputFile=#{target}",
36
+ source.to_s
37
+ ]
38
+
39
+ result = Libis::Tools::Command.run(*args, timeout:, kill_after: timeout * 2)
40
+
41
+ result[:err] << "#{self.class} took too long (> #{timeout} seconds) to complete" if result[:timeout]
42
+
43
+ result
49
44
  end
50
45
  end
51
-
52
46
  end
53
47
  end
54
48
  end
@@ -64,15 +64,11 @@ module Libis
64
64
  kill_after: timeout * 2
65
65
  )
66
66
 
67
- raise "#{self.class} took too long (> #{timeout} seconds) to complete" if result[:timeout]
68
- raise "#{self.class} failed with error #{result[:status]}: \n#{(result[:out] + result[:err]).join("\n")}" if result[:status] != 0
67
+ result[:err] << "#{self.class} took too long (> #{timeout} seconds) to complete" if result[:timeout]
69
68
 
70
69
  FileUtils.rm [icc_file, def_filename].compact, force: true
71
70
 
72
- {
73
- command: result,
74
- files: [target]
75
- }
71
+ result
76
72
  end
77
73
 
78
74
  private
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'os'
4
+
5
+ require 'libis/tools/extend/string'
6
+ require 'libis/tools/logger'
7
+ require 'libis/tools/command'
8
+
9
+ require 'libis/format/config'
10
+
11
+ module Libis
12
+ module Format
13
+ module Tool
14
+ class PdfTool
15
+ include ::Libis::Tools::Logger
16
+
17
+ def self.installed?
18
+ result = Libis::Tools::Command.run(Libis::Format::Config[:java_cmd], '-version')
19
+ return false unless (result[:status]).zero?
20
+
21
+ File.exist?(Libis::Format::Config[:pdf_tool])
22
+ end
23
+
24
+ def self.run(command, source, target, *options)
25
+ new.run command, source, target, *options
26
+ end
27
+
28
+ def run(command, source, target, *options)
29
+ if OS.java?
30
+ # TODO: import library and execute in current VM. For now do exactly as in MRI.
31
+ end
32
+
33
+ timeout = Libis::Format::Config[:timeouts][:pdf_tool]
34
+ args = [
35
+ Libis::Format::Config[:java_cmd],
36
+ '-jar', Libis::Format::Config[:pdf_tool],
37
+ [command],
38
+ '-i', source,
39
+ '-o', target,
40
+ options,
41
+ ].flatten
42
+
43
+ result = Libis::Tools::Command.run(*args, timeout: , kill_after: timeout * 2)
44
+
45
+ result[:err] << "#{self.class} took too long (> #{timeout} seconds) to complete" if result[:timeout]
46
+
47
+ result
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -38,8 +38,7 @@ module Libis
38
38
  kill_after: timeout * 2
39
39
  )
40
40
 
41
- raise "#{self.class} took too long (> #{timeout} seconds) to complete" if result[:timeout]
42
- raise "#{self.class} errors: #{result[:err].join("\n")}" unless (result[:status]).zero? && result[:err].empty?
41
+ result[:err] << "#{self.class} took too long (> #{timeout} seconds) to complete" if result[:timeout]
43
42
 
44
43
  Dir.chdir(previous_wd)
45
44
 
@@ -57,7 +56,7 @@ module Libis
57
56
  kill_after: timeout * 2
58
57
  )
59
58
 
60
- raise "#{self.class} took too long (> #{timeout} seconds) to complete" if result[:timeout]
59
+ result[:err] << "#{self.class} took too long (> #{timeout} seconds) to complete" if result[:timeout]
61
60
 
62
61
  end
63
62
  result