origami 1.2.3 → 1.2.4
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.
- data/README +5 -4
- data/bin/gui/COPYING +674 -0
- data/bin/gui/about.rb +9 -9
- data/bin/gui/config.rb +7 -7
- data/bin/gui/file.rb +7 -7
- data/bin/gui/gtkhex.rb +1341 -0
- data/bin/gui/hexview.rb +16 -25
- data/bin/gui/imgview.rb +7 -7
- data/bin/gui/menu.rb +8 -8
- data/bin/gui/properties.rb +27 -14
- data/bin/gui/signing.rb +7 -7
- data/bin/gui/textview.rb +14 -17
- data/bin/gui/treeview.rb +8 -8
- data/bin/gui/walker.rb +7 -7
- data/bin/gui/xrefs.rb +7 -7
- data/bin/pdf2ruby +7 -3
- data/bin/pdfencrypt +2 -2
- data/bin/pdfextract +7 -7
- data/bin/pdfwalker +1 -1
- data/bin/shell/console.rb +2 -2
- data/lib/origami/encryption.rb +7 -9
- data/lib/origami/filters.rb +10 -0
- data/lib/origami/filters/ascii.rb +12 -7
- data/lib/origami/filters/ccitt.rb +14 -5
- data/lib/origami/filters/flate.rb +2 -11
- data/lib/origami/filters/lzw.rb +10 -3
- data/lib/origami/filters/runlength.rb +1 -1
- data/lib/origami/object.rb +7 -5
- data/lib/origami/parsers/pdf/linear.rb +6 -6
- data/lib/origami/pdf.rb +2 -2
- data/lib/origami/stream.rb +10 -9
- data/lib/origami/string.rb +9 -5
- metadata +44 -46
- data/bin/gui/hexdump.rb +0 -74
- data/lib/origami/docmdp.rb +0 -96
data/bin/pdfextract
CHANGED
|
@@ -135,7 +135,7 @@ begin
|
|
|
135
135
|
|
|
136
136
|
pdf.root_objects.find_all{|obj| obj.is_a?(Stream)}.each do |stream|
|
|
137
137
|
stream_file = "#{OUTPUT_DIR}/streams/stream_#{stream.reference.refno}.dmp"
|
|
138
|
-
File.open(stream_file, "
|
|
138
|
+
File.open(stream_file, "wb") do |fd|
|
|
139
139
|
fd.write(stream.data)
|
|
140
140
|
end
|
|
141
141
|
nstreams += 1
|
|
@@ -150,7 +150,7 @@ begin
|
|
|
150
150
|
|
|
151
151
|
pdf.ls(/^JS$/).each do |script|
|
|
152
152
|
script_file = "#{OUTPUT_DIR}/scripts/script_#{script.hash}.js"
|
|
153
|
-
File.open(script_file, "
|
|
153
|
+
File.open(script_file, "wb") do |fd|
|
|
154
154
|
fd.write(
|
|
155
155
|
case script
|
|
156
156
|
when Stream then
|
|
@@ -187,7 +187,7 @@ begin
|
|
|
187
187
|
xfadoc = REXML::Document.new(xml)
|
|
188
188
|
REXML::XPath.match(xfadoc, "//script").each do |script|
|
|
189
189
|
script_file = "#{OUTPUT_DIR}/script_#{script.hash}.js"
|
|
190
|
-
File.open(script_file,
|
|
190
|
+
File.open(script_file, "wb") do |fd|
|
|
191
191
|
fd.write(script.text)
|
|
192
192
|
end
|
|
193
193
|
nscripts += 1
|
|
@@ -205,7 +205,7 @@ begin
|
|
|
205
205
|
attached_file = "#{OUTPUT_DIR}/attachments/attached_#{File.basename(name)}"
|
|
206
206
|
spec = attachment.solve
|
|
207
207
|
if spec and spec.EF and f = spec.EF.F and f.is_a?(Stream)
|
|
208
|
-
File.open(attached_file, "
|
|
208
|
+
File.open(attached_file, "wb") do |fd|
|
|
209
209
|
fd.write(f.data)
|
|
210
210
|
end
|
|
211
211
|
nattach += 1
|
|
@@ -223,7 +223,7 @@ begin
|
|
|
223
223
|
font = stream.xrefs.find{|obj| obj.is_a?(FontDescriptor)}
|
|
224
224
|
if font
|
|
225
225
|
font_file = "#{OUTPUT_DIR}/fonts/font_#{File.basename(font.FontName.value.to_s)}"
|
|
226
|
-
File.open(font_file, "
|
|
226
|
+
File.open(font_file, "wb") do |fd|
|
|
227
227
|
fd.write(stream.data)
|
|
228
228
|
end
|
|
229
229
|
nfonts += 1
|
|
@@ -239,7 +239,7 @@ begin
|
|
|
239
239
|
|
|
240
240
|
pdf.root_objects.find_all{|obj| obj.is_a?(MetadataStream)}.each do |stream|
|
|
241
241
|
metadata_file = "#{OUTPUT_DIR}/metadata/metadata_#{stream.reference.refno}.xml"
|
|
242
|
-
File.open(metadata_file, "
|
|
242
|
+
File.open(metadata_file, "wb") do |fd|
|
|
243
243
|
fd.write(stream.data)
|
|
244
244
|
end
|
|
245
245
|
nmeta += 1
|
|
@@ -261,7 +261,7 @@ begin
|
|
|
261
261
|
STDERR.puts "Warning: file '#{image_file}' is intended to be viewed in CMYK color space."
|
|
262
262
|
end
|
|
263
263
|
|
|
264
|
-
File.open(image_file, "
|
|
264
|
+
File.open(image_file, "wb") do |fd|
|
|
265
265
|
fd.write(image_data)
|
|
266
266
|
end
|
|
267
267
|
nimages += 1
|
data/bin/pdfwalker
CHANGED
data/bin/shell/console.rb
CHANGED
|
@@ -41,7 +41,7 @@ module Origami
|
|
|
41
41
|
end
|
|
42
42
|
end
|
|
43
43
|
|
|
44
|
-
unless
|
|
44
|
+
unless RUBY_VERSION < '1.9'
|
|
45
45
|
require 'tempfile'
|
|
46
46
|
|
|
47
47
|
class Stream
|
|
@@ -50,7 +50,7 @@ module Origami
|
|
|
50
50
|
tmpfile.write(self.data)
|
|
51
51
|
tmpfile.close
|
|
52
52
|
|
|
53
|
-
Process.wait Kernel.spawn "#{editor
|
|
53
|
+
Process.wait Kernel.spawn "#{editor} #{tmpfile.path}"
|
|
54
54
|
|
|
55
55
|
self.data = File.read(tmpfile.path)
|
|
56
56
|
tmpfile.unlink
|
data/lib/origami/encryption.rb
CHANGED
|
@@ -25,7 +25,6 @@
|
|
|
25
25
|
|
|
26
26
|
require 'digest/md5'
|
|
27
27
|
require 'digest/sha2'
|
|
28
|
-
require 'iconv'
|
|
29
28
|
|
|
30
29
|
module Origami
|
|
31
30
|
|
|
@@ -115,16 +114,15 @@ module Origami
|
|
|
115
114
|
doc_id = doc_id.first
|
|
116
115
|
end
|
|
117
116
|
|
|
118
|
-
if handler.
|
|
117
|
+
if handler.is_user_password?(passwd, doc_id)
|
|
118
|
+
encryption_key = handler.compute_user_encryption_key(passwd, doc_id)
|
|
119
|
+
elsif handler.is_owner_password?(passwd, doc_id)
|
|
119
120
|
if handler.V.to_i < 5
|
|
120
121
|
user_passwd = handler.retrieve_user_password(passwd)
|
|
121
122
|
encryption_key = handler.compute_user_encryption_key(user_passwd, doc_id)
|
|
122
123
|
else
|
|
123
124
|
encryption_key = handler.compute_owner_encryption_key(passwd)
|
|
124
125
|
end
|
|
125
|
-
|
|
126
|
-
elsif handler.is_user_password?(passwd, doc_id)
|
|
127
|
-
encryption_key = handler.compute_user_encryption_key(passwd, doc_id)
|
|
128
126
|
else
|
|
129
127
|
raise EncryptionInvalidPasswordError
|
|
130
128
|
end
|
|
@@ -1325,10 +1323,10 @@ module Origami
|
|
|
1325
1323
|
end
|
|
1326
1324
|
|
|
1327
1325
|
64.times do |j|
|
|
1328
|
-
x =
|
|
1329
|
-
unless
|
|
1330
|
-
|
|
1331
|
-
|
|
1326
|
+
x = ''
|
|
1327
|
+
x += aes.update(password) unless password.empty?
|
|
1328
|
+
x += aes.update(block)
|
|
1329
|
+
x += aes.update(vector) unless vector.empty?
|
|
1332
1330
|
|
|
1333
1331
|
if j == 0
|
|
1334
1332
|
block_size = 32 + (x.unpack("C16").inject(0) {|a,b| a+b} % 3) * 16
|
data/lib/origami/filters.rb
CHANGED
|
@@ -30,6 +30,16 @@ module Origami
|
|
|
30
30
|
#
|
|
31
31
|
module Filter
|
|
32
32
|
|
|
33
|
+
class InvalidFilterDataError < Exception # :nodoc:
|
|
34
|
+
attr_reader :decoded_data
|
|
35
|
+
|
|
36
|
+
def initialize(message, decoded_data = nil)
|
|
37
|
+
super(message)
|
|
38
|
+
|
|
39
|
+
@decoded_data = decoded_data
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
33
43
|
module Utils
|
|
34
44
|
|
|
35
45
|
class BitWriterError < Exception #:nodoc:
|
|
@@ -27,7 +27,7 @@ module Origami
|
|
|
27
27
|
|
|
28
28
|
module Filter
|
|
29
29
|
|
|
30
|
-
class InvalidASCIIHexStringError <
|
|
30
|
+
class InvalidASCIIHexStringError < InvalidFilterDataError #:nodoc:
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
#
|
|
@@ -64,7 +64,7 @@ module Origami
|
|
|
64
64
|
|
|
65
65
|
end
|
|
66
66
|
|
|
67
|
-
class InvalidASCII85StringError <
|
|
67
|
+
class InvalidASCII85StringError < InvalidFilterDataError #:nodoc:
|
|
68
68
|
end
|
|
69
69
|
|
|
70
70
|
#
|
|
@@ -141,7 +141,7 @@ module Origami
|
|
|
141
141
|
codelen = 5
|
|
142
142
|
|
|
143
143
|
if input.length - i < 5
|
|
144
|
-
raise InvalidASCII85StringError
|
|
144
|
+
raise InvalidASCII85StringError.new("Invalid length", result) if input.length - i == 1
|
|
145
145
|
|
|
146
146
|
addend = 5 - (input.length - i)
|
|
147
147
|
input << "u" * addend
|
|
@@ -152,15 +152,20 @@ module Origami
|
|
|
152
152
|
# Checking if this string is in base85
|
|
153
153
|
5.times do |j|
|
|
154
154
|
if input[i+j].ord > "u"[0].ord or input[i+j].ord < "!"[0].ord
|
|
155
|
-
raise InvalidASCII85StringError
|
|
155
|
+
raise InvalidASCII85StringError.new(
|
|
156
|
+
"Invalid character sequence: #{input[i,5].inspect}",
|
|
157
|
+
result
|
|
158
|
+
)
|
|
156
159
|
else
|
|
157
160
|
inblock += (input[i+j].ord - "!"[0].ord) * 85 ** (4 - j)
|
|
158
161
|
end
|
|
159
162
|
end
|
|
160
163
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
+
|
|
165
|
+
raise InvalidASCII85StringError.new(
|
|
166
|
+
"Invalid value (#{inblock}) for block #{input[i,5].inspect}",
|
|
167
|
+
result
|
|
168
|
+
) if inblock >= 2**32
|
|
164
169
|
|
|
165
170
|
end
|
|
166
171
|
|
|
@@ -27,7 +27,7 @@ module Origami
|
|
|
27
27
|
|
|
28
28
|
module Filter
|
|
29
29
|
|
|
30
|
-
class InvalidCCITTFaxDataError <
|
|
30
|
+
class InvalidCCITTFaxDataError < InvalidFilterDataError #:nodoc:
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
class CCITTFaxFilterError < Exception #:nodoc:
|
|
@@ -388,8 +388,8 @@ module Origami
|
|
|
388
388
|
bitr = Utils::BitReader.new(stream)
|
|
389
389
|
bitw = Utils::BitWriter.new
|
|
390
390
|
|
|
391
|
-
current_color = white
|
|
392
391
|
until bitr.eod? or rows == 0
|
|
392
|
+
current_color = white
|
|
393
393
|
|
|
394
394
|
# realign the read line on a 8-bit boundary if required
|
|
395
395
|
if aligned and bitr.pos % 8 != 0
|
|
@@ -404,7 +404,10 @@ module Origami
|
|
|
404
404
|
|
|
405
405
|
# checking for the presence of EOL
|
|
406
406
|
if bitr.peek(EOL[1]) != EOL[0]
|
|
407
|
-
raise
|
|
407
|
+
raise InvalidCCITTFaxDataError.new(
|
|
408
|
+
"No end-of-line pattern found (at bit pos #{bitr.pos}/#{bitr.size}})",
|
|
409
|
+
bitw.final.to_s
|
|
410
|
+
)if has_eol
|
|
408
411
|
else
|
|
409
412
|
bitr.pos += EOL[1]
|
|
410
413
|
end
|
|
@@ -417,10 +420,16 @@ module Origami
|
|
|
417
420
|
bit_length = get_black_bits(bitr)
|
|
418
421
|
end
|
|
419
422
|
|
|
420
|
-
raise
|
|
423
|
+
raise InvalidCCITTFaxDataError.new(
|
|
424
|
+
"Unfinished line (at bit pos #{bitr.pos}/#{bitr.size}})",
|
|
425
|
+
bitw.final.to_s
|
|
426
|
+
) if bit_length.nil?
|
|
421
427
|
|
|
422
428
|
line_length += bit_length
|
|
423
|
-
raise
|
|
429
|
+
raise InvalidCCITTFaxDataError.new(
|
|
430
|
+
"Line is too long (at bit pos #{bitr.pos}/#{bitr.size}})",
|
|
431
|
+
bitw.final.to_s
|
|
432
|
+
) if line_length > columns
|
|
424
433
|
|
|
425
434
|
write_bit_range(bitw, current_color, bit_length)
|
|
426
435
|
current_color ^= 1
|
|
@@ -30,16 +30,7 @@ module Origami
|
|
|
30
30
|
|
|
31
31
|
module Filter
|
|
32
32
|
|
|
33
|
-
class InvalidFlateDataError <
|
|
34
|
-
attr_reader :zlib_stream, :zlib_except
|
|
35
|
-
|
|
36
|
-
def initialize(zlib_stream, zlib_except)
|
|
37
|
-
super(zlib_except.message)
|
|
38
|
-
|
|
39
|
-
@zlib_stream = zlib_stream
|
|
40
|
-
@zlib_except = zlib_except
|
|
41
|
-
end
|
|
42
|
-
end
|
|
33
|
+
class InvalidFlateDataError < InvalidFilterDataError; end #:nodoc:
|
|
43
34
|
|
|
44
35
|
#
|
|
45
36
|
# Class representing a Filter used to encode and decode data with zlib/Flate compression algorithm.
|
|
@@ -92,7 +83,7 @@ module Origami
|
|
|
92
83
|
begin
|
|
93
84
|
uncompressed = zlib_stream.inflate(stream)
|
|
94
85
|
rescue Zlib::DataError => zlib_except
|
|
95
|
-
raise InvalidFlateDataError.new(
|
|
86
|
+
raise InvalidFlateDataError.new(zlib_except.message, zlib_stream.flush_next_out)
|
|
96
87
|
end
|
|
97
88
|
|
|
98
89
|
if @params.Predictor.is_a?(Integer)
|
data/lib/origami/filters/lzw.rb
CHANGED
|
@@ -29,7 +29,7 @@ module Origami
|
|
|
29
29
|
|
|
30
30
|
module Filter
|
|
31
31
|
|
|
32
|
-
class InvalidLZWDataError <
|
|
32
|
+
class InvalidLZWDataError < InvalidFilterDataError #:nodoc:
|
|
33
33
|
end
|
|
34
34
|
|
|
35
35
|
#
|
|
@@ -131,8 +131,10 @@ module Origami
|
|
|
131
131
|
when 4095
|
|
132
132
|
if byte != CLEARTABLE
|
|
133
133
|
then
|
|
134
|
-
raise InvalidLZWDataError
|
|
135
|
-
"LZW table is full and no clear flag was set (codeword #{byte.to_s(2).rjust(codesize,'0')} at bit #{bstring.pos - codesize}/#{bstring.size})"
|
|
134
|
+
raise InvalidLZWDataError.new(
|
|
135
|
+
"LZW table is full and no clear flag was set (codeword #{byte.to_s(2).rjust(codesize,'0')} at bit #{bstring.pos - codesize}/#{bstring.size})",
|
|
136
|
+
result
|
|
137
|
+
)
|
|
136
138
|
end
|
|
137
139
|
end
|
|
138
140
|
|
|
@@ -150,6 +152,11 @@ module Origami
|
|
|
150
152
|
result << table.key(byte)
|
|
151
153
|
redo
|
|
152
154
|
else
|
|
155
|
+
raise InvalidLZWDataError.new(
|
|
156
|
+
"No entry for codeword #{prevbyte.to_s(2).rjust(codesize,'0')}.",
|
|
157
|
+
result
|
|
158
|
+
) unless table.key(prevbyte)
|
|
159
|
+
|
|
153
160
|
if table.has_value?(byte)
|
|
154
161
|
entry = table.key(byte)
|
|
155
162
|
else
|
data/lib/origami/object.rb
CHANGED
|
@@ -490,13 +490,15 @@ module Origami
|
|
|
490
490
|
end
|
|
491
491
|
|
|
492
492
|
def skip_until_next_obj(stream) #:nodoc:
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
493
|
+
[ @@regexp_obj, /xref/, /trailer/, /startxref/ ].each do |re|
|
|
494
|
+
if stream.scan_until(re)
|
|
495
|
+
stream.pos -= stream.matched_size
|
|
496
|
+
return true
|
|
497
|
+
end
|
|
498
|
+
end
|
|
496
499
|
|
|
497
|
-
|
|
500
|
+
false
|
|
498
501
|
end
|
|
499
|
-
|
|
500
502
|
end
|
|
501
503
|
|
|
502
504
|
def pdf_version_required #:nodoc:
|
|
@@ -45,15 +45,15 @@ module Origami
|
|
|
45
45
|
begin
|
|
46
46
|
pdf.add_new_revision unless revision.zero?
|
|
47
47
|
revision = revision + 1
|
|
48
|
-
|
|
48
|
+
|
|
49
49
|
info "...Parsing revision #{pdf.revisions.size}..."
|
|
50
50
|
loop do
|
|
51
51
|
break if (object = parse_object).nil?
|
|
52
52
|
pdf.insert(object)
|
|
53
53
|
end
|
|
54
|
-
|
|
54
|
+
|
|
55
55
|
pdf.revisions.last.xreftable = parse_xreftable
|
|
56
|
-
|
|
56
|
+
|
|
57
57
|
trailer = parse_trailer
|
|
58
58
|
pdf.revisions.last.trailer = trailer
|
|
59
59
|
|
|
@@ -61,7 +61,7 @@ module Origami
|
|
|
61
61
|
(pdf.get_object_by_offset(trailer.XRefStm) if trailer.has_field? :XRefStm)
|
|
62
62
|
|
|
63
63
|
if not xrefstm.nil?
|
|
64
|
-
|
|
64
|
+
warn "Found a XRefStream for this revision at #{xrefstm.reference}"
|
|
65
65
|
pdf.revisions.last.xrefstm = xrefstm
|
|
66
66
|
end
|
|
67
67
|
|
|
@@ -70,10 +70,10 @@ module Origami
|
|
|
70
70
|
rescue Exception => e
|
|
71
71
|
error "Cannot read : " + (@data.peek(10) + "...").inspect
|
|
72
72
|
error "Stopped on exception : " + e.message
|
|
73
|
-
|
|
73
|
+
|
|
74
74
|
break
|
|
75
75
|
end
|
|
76
|
-
|
|
76
|
+
|
|
77
77
|
end
|
|
78
78
|
|
|
79
79
|
parse_finalize(pdf)
|
data/lib/origami/pdf.rb
CHANGED
data/lib/origami/stream.rb
CHANGED
|
@@ -249,11 +249,19 @@ module Origami
|
|
|
249
249
|
filters = [ filters ] unless filters.is_a?(::Array)
|
|
250
250
|
|
|
251
251
|
@data = @rawdata.dup
|
|
252
|
+
@data.freeze
|
|
253
|
+
|
|
252
254
|
filters.length.times do |layer|
|
|
253
255
|
params = dparams[layer].is_a?(Dictionary) ? dparams[layer] : {}
|
|
254
256
|
filter = filters[layer]
|
|
255
257
|
|
|
256
|
-
|
|
258
|
+
begin
|
|
259
|
+
@data = decode_data(@data, filter, params)
|
|
260
|
+
rescue Filter::InvalidFilterDataError => e
|
|
261
|
+
@data = e.decoded_data if e.decoded_data
|
|
262
|
+
raise InvalidStreamObjectError,
|
|
263
|
+
"Error while decoding stream #{self.reference}\n\t-> [#{e.class}] #{e.message}"
|
|
264
|
+
end
|
|
257
265
|
end
|
|
258
266
|
else
|
|
259
267
|
raise InvalidStreamObjectError, "Invalid Filter type parameter"
|
|
@@ -357,15 +365,8 @@ module Origami
|
|
|
357
365
|
raise InvalidStreamObjectError, "Unknown filter : #{filter}"
|
|
358
366
|
end
|
|
359
367
|
|
|
360
|
-
|
|
361
|
-
Origami::Filter.const_get(filter.value.to_s.sub(/Decode$/,"")).decode(data, params)
|
|
362
|
-
|
|
363
|
-
rescue Filter::InvalidFlateDataError => flate_e
|
|
364
|
-
return flate_e.zlib_stream.flush_next_out
|
|
368
|
+
Origami::Filter.const_get(filter.value.to_s.sub(/Decode$/,"")).decode(data, params)
|
|
365
369
|
|
|
366
|
-
rescue Exception => e
|
|
367
|
-
raise InvalidStreamObjectError, "Error while decoding stream #{self.reference}\n\t-> [#{e.class}] #{e.message}"
|
|
368
|
-
end
|
|
369
370
|
end
|
|
370
371
|
|
|
371
372
|
def encode_data(data, filter, params) #:nodoc:
|
data/lib/origami/string.rb
CHANGED
|
@@ -125,12 +125,16 @@ module Origami
|
|
|
125
125
|
# Convert String object to an UTF8 encoded Ruby string.
|
|
126
126
|
#
|
|
127
127
|
def to_utf8
|
|
128
|
-
require 'iconv'
|
|
129
|
-
|
|
130
128
|
infer_encoding
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
129
|
+
|
|
130
|
+
if RUBY_VERSION < '1.9'
|
|
131
|
+
require 'iconv'
|
|
132
|
+
i = Iconv.new("UTF-8", "UTF-16")
|
|
133
|
+
utf8str = i.iconv(self.encoding.to_utf16be(self.value))
|
|
134
|
+
i.close
|
|
135
|
+
else
|
|
136
|
+
utf8str = self.encoding.to_utf16be(self.value).encode("utf-8", "utf-16")
|
|
137
|
+
end
|
|
134
138
|
|
|
135
139
|
utf8str
|
|
136
140
|
end
|