origami 1.2.3 → 1.2.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|