origami 1.2.7 → 2.0.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/CHANGELOG.md +66 -0
- data/README.md +112 -0
- data/bin/config/pdfcop.conf.yml +232 -233
- data/bin/gui/about.rb +27 -37
- data/bin/gui/config.rb +108 -117
- data/bin/gui/file.rb +416 -365
- data/bin/gui/gtkhex.rb +1138 -1153
- data/bin/gui/hexview.rb +55 -57
- data/bin/gui/imgview.rb +48 -51
- data/bin/gui/menu.rb +388 -386
- data/bin/gui/properties.rb +114 -130
- data/bin/gui/signing.rb +571 -617
- data/bin/gui/textview.rb +77 -95
- data/bin/gui/treeview.rb +382 -387
- data/bin/gui/walker.rb +227 -232
- data/bin/gui/xrefs.rb +56 -60
- data/bin/pdf2pdfa +53 -57
- data/bin/pdf2ruby +212 -228
- data/bin/pdfcop +338 -348
- data/bin/pdfdecompress +58 -65
- data/bin/pdfdecrypt +56 -60
- data/bin/pdfencrypt +75 -80
- data/bin/pdfexplode +185 -182
- data/bin/pdfextract +201 -218
- data/bin/pdfmetadata +83 -82
- data/bin/pdfsh +4 -5
- data/bin/pdfwalker +1 -2
- data/bin/shell/.irbrc +45 -82
- data/bin/shell/console.rb +105 -130
- data/bin/shell/hexdump.rb +40 -64
- data/examples/README.md +34 -0
- data/examples/attachments/attachment.rb +38 -0
- data/examples/attachments/nested_document.rb +51 -0
- data/examples/encryption/encryption.rb +28 -0
- data/{samples/actions/triggerevents/trigger.rb → examples/events/events.rb} +13 -16
- data/examples/flash/flash.rb +37 -0
- data/{samples → examples}/flash/helloworld.swf +0 -0
- data/examples/forms/javascript.rb +54 -0
- data/examples/forms/xfa.rb +115 -0
- data/examples/javascript/hello_world.rb +22 -0
- data/examples/javascript/js_emulation.rb +54 -0
- data/examples/loop/goto.rb +32 -0
- data/examples/loop/named.rb +33 -0
- data/examples/signature/signature.rb +65 -0
- data/examples/uri/javascript.rb +56 -0
- data/examples/uri/open-uri.rb +21 -0
- data/examples/uri/submitform.rb +47 -0
- data/lib/origami.rb +29 -42
- data/lib/origami/3d.rb +350 -225
- data/lib/origami/acroform.rb +262 -288
- data/lib/origami/actions.rb +268 -288
- data/lib/origami/annotations.rb +697 -722
- data/lib/origami/array.rb +258 -184
- data/lib/origami/boolean.rb +74 -84
- data/lib/origami/catalog.rb +397 -434
- data/lib/origami/collections.rb +144 -0
- data/lib/origami/destinations.rb +233 -194
- data/lib/origami/dictionary.rb +253 -232
- data/lib/origami/encryption.rb +1274 -1243
- data/lib/origami/export.rb +232 -268
- data/lib/origami/extensions/fdf.rb +307 -220
- data/lib/origami/extensions/ppklite.rb +368 -435
- data/lib/origami/filespec.rb +197 -0
- data/lib/origami/filters.rb +301 -295
- data/lib/origami/filters/ascii.rb +177 -180
- data/lib/origami/filters/ccitt.rb +528 -535
- data/lib/origami/filters/crypt.rb +26 -35
- data/lib/origami/filters/dct.rb +46 -52
- data/lib/origami/filters/flate.rb +95 -94
- data/lib/origami/filters/jbig2.rb +49 -55
- data/lib/origami/filters/jpx.rb +38 -44
- data/lib/origami/filters/lzw.rb +189 -183
- data/lib/origami/filters/predictors.rb +221 -235
- data/lib/origami/filters/runlength.rb +103 -104
- data/lib/origami/font.rb +173 -186
- data/lib/origami/functions.rb +67 -81
- data/lib/origami/graphics.rb +25 -21
- data/lib/origami/graphics/colors.rb +178 -187
- data/lib/origami/graphics/instruction.rb +79 -85
- data/lib/origami/graphics/path.rb +142 -148
- data/lib/origami/graphics/patterns.rb +160 -167
- data/lib/origami/graphics/render.rb +43 -50
- data/lib/origami/graphics/state.rb +138 -153
- data/lib/origami/graphics/text.rb +188 -205
- data/lib/origami/graphics/xobject.rb +819 -815
- data/lib/origami/header.rb +63 -78
- data/lib/origami/javascript.rb +596 -597
- data/lib/origami/linearization.rb +285 -290
- data/lib/origami/metadata.rb +139 -148
- data/lib/origami/name.rb +112 -148
- data/lib/origami/null.rb +53 -62
- data/lib/origami/numeric.rb +162 -175
- data/lib/origami/obfuscation.rb +186 -174
- data/lib/origami/object.rb +593 -573
- data/lib/origami/outline.rb +42 -47
- data/lib/origami/outputintents.rb +73 -82
- data/lib/origami/page.rb +703 -592
- data/lib/origami/parser.rb +238 -290
- data/lib/origami/parsers/fdf.rb +41 -33
- data/lib/origami/parsers/pdf.rb +75 -95
- data/lib/origami/parsers/pdf/lazy.rb +137 -0
- data/lib/origami/parsers/pdf/linear.rb +64 -66
- data/lib/origami/parsers/ppklite.rb +34 -70
- data/lib/origami/pdf.rb +1030 -1005
- data/lib/origami/reference.rb +102 -102
- data/lib/origami/signature.rb +591 -609
- data/lib/origami/stream.rb +668 -551
- data/lib/origami/string.rb +397 -373
- data/lib/origami/template/patterns.rb +56 -0
- data/lib/origami/template/widgets.rb +151 -0
- data/lib/origami/trailer.rb +144 -158
- data/lib/origami/tree.rb +62 -0
- data/lib/origami/version.rb +23 -0
- data/lib/origami/webcapture.rb +88 -79
- data/lib/origami/xfa.rb +2863 -2882
- data/lib/origami/xreftable.rb +472 -384
- data/test/dataset/calc.pdf +85 -0
- data/test/dataset/crypto.pdf +82 -0
- data/test/dataset/empty.pdf +49 -0
- data/test/test_actions.rb +27 -0
- data/test/test_annotations.rb +90 -0
- data/test/test_pages.rb +31 -0
- data/test/test_pdf.rb +16 -0
- data/test/test_pdf_attachment.rb +34 -0
- data/test/test_pdf_create.rb +24 -0
- data/test/test_pdf_encrypt.rb +95 -0
- data/test/test_pdf_parse.rb +96 -0
- data/test/test_pdf_sign.rb +58 -0
- data/test/test_streams.rb +182 -0
- data/test/test_xrefs.rb +67 -0
- metadata +88 -58
- data/README +0 -67
- data/bin/pdf2graph +0 -121
- data/bin/pdfcocoon +0 -104
- data/lib/origami/file.rb +0 -233
- data/samples/README.txt +0 -45
- data/samples/actions/launch/calc.rb +0 -87
- data/samples/actions/launch/winparams.rb +0 -22
- data/samples/actions/loop/loopgoto.rb +0 -24
- data/samples/actions/loop/loopnamed.rb +0 -21
- data/samples/actions/named/named.rb +0 -31
- data/samples/actions/samba/smbrelay.rb +0 -26
- data/samples/actions/webbug/submitform.js +0 -26
- data/samples/actions/webbug/webbug-browser.rb +0 -68
- data/samples/actions/webbug/webbug-js.rb +0 -67
- data/samples/actions/webbug/webbug-reader.rb +0 -90
- data/samples/attachments/attach.rb +0 -40
- data/samples/attachments/attached.txt +0 -1
- data/samples/crypto/crypto.rb +0 -28
- data/samples/digsig/signed.rb +0 -46
- data/samples/exploits/cve-2008-2992-utilprintf.rb +0 -87
- data/samples/exploits/cve-2009-0927-geticon.rb +0 -65
- data/samples/exploits/exploit_customdictopen.rb +0 -55
- data/samples/exploits/getannots.rb +0 -69
- data/samples/flash/flash.rb +0 -31
- data/samples/javascript/attached.txt +0 -1
- data/samples/javascript/js.rb +0 -52
- data/templates/patterns.rb +0 -66
- data/templates/widgets.rb +0 -173
- data/templates/xdp.rb +0 -92
- data/test/ts_pdf.rb +0 -50
|
@@ -1,333 +1,328 @@
|
|
|
1
1
|
=begin
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
19
|
-
GNU Lesser General Public License for more details.
|
|
20
|
-
|
|
21
|
-
You should have received a copy of the GNU Lesser General Public License
|
|
22
|
-
along with Origami. If not, see <http://www.gnu.org/licenses/>.
|
|
3
|
+
This file is part of Origami, PDF manipulation framework for Ruby
|
|
4
|
+
Copyright (C) 2016 Guillaume Delugré.
|
|
5
|
+
|
|
6
|
+
Origami is free software: you can redistribute it and/or modify
|
|
7
|
+
it under the terms of the GNU Lesser General Public License as published by
|
|
8
|
+
the Free Software Foundation, either version 3 of the License, or
|
|
9
|
+
(at your option) any later version.
|
|
10
|
+
|
|
11
|
+
Origami is distributed in the hope that it will be useful,
|
|
12
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14
|
+
GNU Lesser General Public License for more details.
|
|
15
|
+
|
|
16
|
+
You should have received a copy of the GNU Lesser General Public License
|
|
17
|
+
along with Origami. If not, see <http://www.gnu.org/licenses/>.
|
|
23
18
|
|
|
24
19
|
=end
|
|
25
20
|
|
|
26
21
|
module Origami
|
|
27
22
|
|
|
28
|
-
|
|
23
|
+
class PDF
|
|
29
24
|
|
|
30
|
-
|
|
31
|
-
|
|
25
|
+
class LinearizationError < Error #:nodoc:
|
|
26
|
+
end
|
|
32
27
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
28
|
+
#
|
|
29
|
+
# Returns whether the current document is linearized.
|
|
30
|
+
#
|
|
31
|
+
def linearized?
|
|
32
|
+
begin
|
|
33
|
+
first_obj = @revisions.first.objects.min_by{|obj| obj.file_offset}
|
|
34
|
+
rescue
|
|
35
|
+
return false
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
@revisions.size > 1 and first_obj.is_a?(Dictionary) and first_obj.has_key? :Linearized
|
|
39
|
+
end
|
|
42
40
|
|
|
43
|
-
|
|
44
|
-
|
|
41
|
+
#
|
|
42
|
+
# Tries to delinearize the document if it has been linearized.
|
|
43
|
+
# This operation is xrefs destructive, should be fixed in the future to merge tables.
|
|
44
|
+
#
|
|
45
|
+
def delinearize!
|
|
46
|
+
raise LinearizationError, 'Not a linearized document' unless self.linearized?
|
|
47
|
+
|
|
48
|
+
#
|
|
49
|
+
# Saves the first trailer.
|
|
50
|
+
#
|
|
51
|
+
prev_trailer = @revisions.first.trailer
|
|
52
|
+
|
|
53
|
+
lin_dict = @revisions.first.objects.min_by{|obj| obj.file_offset}
|
|
54
|
+
hints = lin_dict[:H]
|
|
55
|
+
|
|
56
|
+
#
|
|
57
|
+
# Removes hint streams used by linearization.
|
|
58
|
+
#
|
|
59
|
+
if hints.is_a?(::Array)
|
|
60
|
+
if hints.length > 0 and hints[0].is_a?(Integer)
|
|
61
|
+
hint_stream = get_object_by_offset(hints[0])
|
|
62
|
+
delete_object(hint_stream.reference) if hint_stream.is_a?(Stream)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
if hints.length > 2 and hints[2].is_a?(Integer)
|
|
66
|
+
overflow_stream = get_object_by_offset(hints[2])
|
|
67
|
+
delete_object(overflow_stream.reference) if overflow_stream.is_a?(Stream)
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
#
|
|
72
|
+
# Update the trailer.
|
|
73
|
+
#
|
|
74
|
+
last_trailer = (@revisions.last.trailer ||= Trailer.new)
|
|
75
|
+
|
|
76
|
+
last_trailer.dictionary ||= Dictionary.new
|
|
77
|
+
|
|
78
|
+
if prev_trailer.has_dictionary?
|
|
79
|
+
last_trailer.dictionary =
|
|
80
|
+
last_trailer.dictionary.merge(prev_trailer.dictionary)
|
|
81
|
+
else
|
|
82
|
+
xrefstm = @revisions.last.xrefstm
|
|
83
|
+
raise LinearizationError,
|
|
84
|
+
'Cannot find trailer info while delinearizing document' unless xrefstm.is_a?(XRefStream)
|
|
85
|
+
|
|
86
|
+
last_trailer.dictionary[:Root] = xrefstm[:Root]
|
|
87
|
+
last_trailer.dictionary[:Encrypt] = xrefstm[:Encrypt]
|
|
88
|
+
last_trailer.dictionary[:Info] = xrefstm[:Info]
|
|
89
|
+
last_trailer.dictionary[:ID] = xrefstm[:ID]
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
#
|
|
93
|
+
# Remove all xrefs.
|
|
94
|
+
# Fix: Should be merged instead.
|
|
95
|
+
#
|
|
96
|
+
remove_xrefs
|
|
97
|
+
|
|
98
|
+
#
|
|
99
|
+
# Remove the linearization revision.
|
|
100
|
+
#
|
|
101
|
+
@revisions.first.body.delete(lin_dict.reference)
|
|
102
|
+
@revisions.last.body.merge! @revisions.first.body
|
|
103
|
+
|
|
104
|
+
remove_revision(0)
|
|
105
|
+
|
|
106
|
+
self
|
|
107
|
+
end
|
|
108
|
+
end
|
|
45
109
|
|
|
46
110
|
#
|
|
47
|
-
#
|
|
48
|
-
# This operation is xrefs destructive, should be fixed in the future to merge tables.
|
|
111
|
+
# Class representing a linearization dictionary.
|
|
49
112
|
#
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
hint_stream = get_object_by_offset(hints[0])
|
|
67
|
-
delete_object(hint_stream.reference) if hint_stream.is_a?(Stream)
|
|
113
|
+
class Linearization < Dictionary
|
|
114
|
+
include StandardObject
|
|
115
|
+
|
|
116
|
+
field :Linearized, :Type => Real, :Default => 1.0, :Required => true
|
|
117
|
+
field :L, :Type => Integer, :Required => true
|
|
118
|
+
field :H, :Type => Array.of(Integer), :Required => true
|
|
119
|
+
field :O, :Type => Integer, :Required => true
|
|
120
|
+
field :E, :Type => Integer, :Required => true
|
|
121
|
+
field :N, :Type => Integer, :Required => true
|
|
122
|
+
field :T, :Type => Integer, :Required => true
|
|
123
|
+
field :P, :Type => Integer, :Default => 0
|
|
124
|
+
|
|
125
|
+
def initialize(hash = {}, parser = nil)
|
|
126
|
+
super(hash, parser)
|
|
127
|
+
|
|
128
|
+
set_indirect(true)
|
|
68
129
|
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
class InvalidHintTableError < Error #:nodoc:
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
module HintTable
|
|
136
|
+
module ClassMethods
|
|
137
|
+
def header_item_size(number, size)
|
|
138
|
+
@header_items_size[number] = size
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def get_header_item_size(number)
|
|
142
|
+
@header_items_size[number]
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def entry_item_size(number, size)
|
|
146
|
+
@entry_items_size[number] = size
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def get_entry_item_size(number)
|
|
150
|
+
@entry_items_size[number]
|
|
151
|
+
end
|
|
69
152
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
153
|
+
def nb_header_items
|
|
154
|
+
@header_items_size.size
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def nb_entry_items
|
|
158
|
+
@entry_items_size.size
|
|
159
|
+
end
|
|
73
160
|
end
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
#
|
|
77
|
-
# Update the trailer.
|
|
78
|
-
#
|
|
79
|
-
last_trailer = (@revisions.last.trailer ||= Trailer.new)
|
|
80
|
-
|
|
81
|
-
last_trailer.dictionary ||= Dictionary.new
|
|
82
|
-
|
|
83
|
-
if prev_trailer.has_dictionary?
|
|
84
|
-
last_trailer.dictionary =
|
|
85
|
-
last_trailer.dictionary.merge(prev_trailer.dictionary)
|
|
86
|
-
else
|
|
87
|
-
xrefstm = get_object_by_offset(last_trailer.startxref)
|
|
88
|
-
raise LinearizationError,
|
|
89
|
-
'Cannot find trailer info while delinearizing document' unless xrefstm.is_a?(XRefStream)
|
|
90
|
-
|
|
91
|
-
last_trailer.dictionary[:Root] = xrefstm[:Root]
|
|
92
|
-
last_trailer.dictionary[:Encrypt] = xrefstm[:Encrypt]
|
|
93
|
-
last_trailer.dictionary[:Info] = xrefstm[:Info]
|
|
94
|
-
last_trailer.dictionary[:ID] = xrefstm[:ID]
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
#
|
|
98
|
-
# Remove all xrefs.
|
|
99
|
-
# Fix: Should be merged instead.
|
|
100
|
-
#
|
|
101
|
-
remove_xrefs
|
|
102
|
-
|
|
103
|
-
#
|
|
104
|
-
# Remove the linearization revision.
|
|
105
|
-
#
|
|
106
|
-
remove_revision(0)
|
|
107
|
-
|
|
108
|
-
self
|
|
109
|
-
end
|
|
110
161
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
class Linearization < Dictionary
|
|
117
|
-
include StandardObject
|
|
118
|
-
|
|
119
|
-
field :Linearized, :Type => Real, :Default => 1.0, :Required => true
|
|
120
|
-
field :L, :Type => Integer, :Required => true
|
|
121
|
-
field :H, :Type => Array, :Required => true
|
|
122
|
-
field :O, :Type => Integer, :Required => true
|
|
123
|
-
field :E, :Type => Integer, :Required => true
|
|
124
|
-
field :N, :Type => Integer, :Required => true
|
|
125
|
-
field :T, :Type => Integer, :Required => true
|
|
126
|
-
field :P, :Type => Integer, :Default => 0
|
|
127
|
-
|
|
128
|
-
def initialize(hash = {})
|
|
129
|
-
super(hash, true)
|
|
130
|
-
end
|
|
162
|
+
def self.included(receiver)
|
|
163
|
+
receiver.instance_variable_set(:@header_items_size, {})
|
|
164
|
+
receiver.instance_variable_set(:@entry_items_size, {})
|
|
165
|
+
receiver.extend(ClassMethods)
|
|
166
|
+
end
|
|
131
167
|
|
|
132
|
-
|
|
168
|
+
attr_accessor :header_items
|
|
169
|
+
attr_accessor :entries
|
|
133
170
|
|
|
134
|
-
|
|
135
|
-
|
|
171
|
+
def initialize
|
|
172
|
+
@header_items = {}
|
|
173
|
+
@entries = []
|
|
174
|
+
end
|
|
136
175
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
def header_item_size(number, size)
|
|
140
|
-
@header_items_size[number] = size
|
|
141
|
-
end
|
|
176
|
+
def to_s
|
|
177
|
+
data = ""
|
|
142
178
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
179
|
+
nitems = self.class.nb_header_items
|
|
180
|
+
for no in (1..nitems)
|
|
181
|
+
unless @header_items.include?(no)
|
|
182
|
+
raise InvalidHintTableError, "Missing item #{no} in header section of #{self.class}"
|
|
183
|
+
end
|
|
146
184
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
end
|
|
185
|
+
value = @header_items[no]
|
|
186
|
+
item_size = self.class.get_header_item_size(no)
|
|
150
187
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
188
|
+
item_size = ((item_size + 7) >> 3) << 3
|
|
189
|
+
item_data = value.to_s(2)
|
|
190
|
+
item_data = "0" * (item_size - item_data.size) + item_data
|
|
154
191
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
end
|
|
192
|
+
data << [ item_data ].pack("B*")
|
|
193
|
+
end
|
|
158
194
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
195
|
+
i = 0
|
|
196
|
+
nitems = self.class.nb_entry_items
|
|
197
|
+
@entries.each do |entry|
|
|
198
|
+
for no in (1..items)
|
|
199
|
+
unless entry.include?(no)
|
|
200
|
+
raise InvalidHintTableError, "Missing item #{no} in entry #{i} of #{self.class}"
|
|
201
|
+
end
|
|
163
202
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
receiver.instance_variable_set(:@entry_items_size, {})
|
|
167
|
-
receiver.extend(ClassMethods)
|
|
168
|
-
end
|
|
203
|
+
value = entry[no]
|
|
204
|
+
item_size = self.class.get_entry_item_size(no)
|
|
169
205
|
|
|
170
|
-
|
|
171
|
-
|
|
206
|
+
item_size = ((item_size + 7) >> 3) << 3
|
|
207
|
+
item_data = value.to_s(2)
|
|
208
|
+
item_data = "0" * (item_size - item_data.size) + item_data
|
|
172
209
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
@entries = []
|
|
176
|
-
end
|
|
210
|
+
data << [ item_data ].pack("B*")
|
|
211
|
+
end
|
|
177
212
|
|
|
178
|
-
|
|
179
|
-
|
|
213
|
+
i = i + 1
|
|
214
|
+
end
|
|
180
215
|
|
|
181
|
-
|
|
182
|
-
for no in (1..nitems)
|
|
183
|
-
unless @header_items.include?(no)
|
|
184
|
-
raise InvalidHintTableError, "Missing item #{no} in header section of #{self.class}"
|
|
216
|
+
data
|
|
185
217
|
end
|
|
186
218
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
data << [ item_data ].pack("B*")
|
|
219
|
+
class PageOffsetTable
|
|
220
|
+
include HintTable
|
|
221
|
+
|
|
222
|
+
header_item_size 1, 32
|
|
223
|
+
header_item_size 2, 32
|
|
224
|
+
header_item_size 3, 16
|
|
225
|
+
header_item_size 4, 32
|
|
226
|
+
header_item_size 5, 16
|
|
227
|
+
header_item_size 6, 32
|
|
228
|
+
header_item_size 7, 16
|
|
229
|
+
header_item_size 8, 32
|
|
230
|
+
header_item_size 9, 16
|
|
231
|
+
header_item_size 10, 16
|
|
232
|
+
header_item_size 11, 16
|
|
233
|
+
header_item_size 12, 16
|
|
234
|
+
header_item_size 13, 16
|
|
235
|
+
|
|
236
|
+
entry_item_size 1, 16
|
|
237
|
+
entry_item_size 2, 16
|
|
238
|
+
entry_item_size 3, 16
|
|
239
|
+
entry_item_size 4, 16
|
|
240
|
+
entry_item_size 5, 16
|
|
241
|
+
entry_item_size 6, 16
|
|
242
|
+
entry_item_size 7, 16
|
|
213
243
|
end
|
|
214
244
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
header_item_size 8, 32
|
|
232
|
-
header_item_size 9, 16
|
|
233
|
-
header_item_size 10, 16
|
|
234
|
-
header_item_size 11, 16
|
|
235
|
-
header_item_size 12, 16
|
|
236
|
-
header_item_size 13, 16
|
|
237
|
-
|
|
238
|
-
entry_item_size 1, 16
|
|
239
|
-
entry_item_size 2, 16
|
|
240
|
-
entry_item_size 3, 16
|
|
241
|
-
entry_item_size 4, 16
|
|
242
|
-
entry_item_size 5, 16
|
|
243
|
-
entry_item_size 6, 16
|
|
244
|
-
entry_item_size 7, 16
|
|
245
|
+
class SharedObjectTable
|
|
246
|
+
include HintTable
|
|
247
|
+
|
|
248
|
+
header_item_size 1, 32
|
|
249
|
+
header_item_size 2, 32
|
|
250
|
+
header_item_size 3, 32
|
|
251
|
+
header_item_size 4, 32
|
|
252
|
+
header_item_size 5, 16
|
|
253
|
+
header_item_size 6, 32
|
|
254
|
+
header_item_size 7, 16
|
|
255
|
+
|
|
256
|
+
entry_item_size 1, 16
|
|
257
|
+
entry_item_size 2, 1
|
|
258
|
+
entry_item_size 3, 128
|
|
259
|
+
entry_item_size 4, 16
|
|
260
|
+
end
|
|
245
261
|
end
|
|
246
262
|
|
|
247
|
-
class
|
|
248
|
-
include HintTable
|
|
249
|
-
|
|
250
|
-
header_item_size 1, 32
|
|
251
|
-
header_item_size 2, 32
|
|
252
|
-
header_item_size 3, 32
|
|
253
|
-
header_item_size 4, 32
|
|
254
|
-
header_item_size 5, 16
|
|
255
|
-
header_item_size 6, 32
|
|
256
|
-
header_item_size 7, 16
|
|
257
|
-
|
|
258
|
-
entry_item_size 1, 16
|
|
259
|
-
entry_item_size 2, 1
|
|
260
|
-
entry_item_size 3, 128
|
|
261
|
-
entry_item_size 4, 16
|
|
263
|
+
class InvalidHintStreamObjectError < InvalidStreamObjectError #:nodoc:
|
|
262
264
|
end
|
|
263
265
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
save_table(@page_labels_table, :L)
|
|
316
|
-
save_table(@renditions_table, :R)
|
|
317
|
-
save_table(@embedded_files_table, :B)
|
|
318
|
-
|
|
319
|
-
super
|
|
320
|
-
end
|
|
266
|
+
class HintStream < Stream
|
|
267
|
+
attr_accessor :page_offset_table
|
|
268
|
+
attr_accessor :shared_objects_table
|
|
269
|
+
attr_accessor :thumbnails_table
|
|
270
|
+
attr_accessor :outlines_table
|
|
271
|
+
attr_accessor :threads_table
|
|
272
|
+
attr_accessor :named_destinations_table
|
|
273
|
+
attr_accessor :interactive_forms_table
|
|
274
|
+
attr_accessor :information_dictionary_table
|
|
275
|
+
attr_accessor :logical_structure_table
|
|
276
|
+
attr_accessor :page_labels_table
|
|
277
|
+
attr_accessor :renditions_table
|
|
278
|
+
attr_accessor :embedded_files_table
|
|
279
|
+
|
|
280
|
+
field :S, :Type => Integer, :Required => true # Shared objects
|
|
281
|
+
field :T, :Type => Integer # Thumbnails
|
|
282
|
+
field :O, :Type => Integer # Outlines
|
|
283
|
+
field :A, :Type => Integer # Threads
|
|
284
|
+
field :E, :Type => Integer # Named destinations
|
|
285
|
+
field :V, :Type => Integer # Interactive forms
|
|
286
|
+
field :I, :Type => Integer # Information dictionary
|
|
287
|
+
field :C, :Type => Integer # Logical structure
|
|
288
|
+
field :L, :Type => Integer # Page labels
|
|
289
|
+
field :R, :Type => Integer # Renditions
|
|
290
|
+
field :B, :Type => Integer # Embedded files
|
|
291
|
+
|
|
292
|
+
def pre_build
|
|
293
|
+
if @page_offset_table.nil?
|
|
294
|
+
raise InvalidHintStreamObjectError, "No page offset hint table"
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
if @shared_objects_table.nil?
|
|
298
|
+
raise InvalidHintStreamObjectError, "No shared objects hint table"
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
@data = ""
|
|
302
|
+
save_table(@page_offset_table)
|
|
303
|
+
save_table(@shared_objects_table, :S)
|
|
304
|
+
save_table(@thumbnails_table, :T)
|
|
305
|
+
save_table(@outlines_table, :O)
|
|
306
|
+
save_table(@threads_table, :A)
|
|
307
|
+
save_table(@named_destinations_table, :E)
|
|
308
|
+
save_table(@interactive_forms_table, :V)
|
|
309
|
+
save_table(@information_dictionary_table, :I)
|
|
310
|
+
save_table(@logical_structure_table, :C)
|
|
311
|
+
save_table(@page_labels_table, :L)
|
|
312
|
+
save_table(@renditions_table, :R)
|
|
313
|
+
save_table(@embedded_files_table, :B)
|
|
314
|
+
|
|
315
|
+
super
|
|
316
|
+
end
|
|
321
317
|
|
|
322
|
-
|
|
318
|
+
private
|
|
323
319
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
320
|
+
def save_table(table, name = nil)
|
|
321
|
+
unless table.nil?
|
|
322
|
+
self[name] = @data.size if name
|
|
323
|
+
@data << table.to_s
|
|
324
|
+
end
|
|
325
|
+
end
|
|
329
326
|
end
|
|
330
327
|
|
|
331
|
-
end
|
|
332
|
-
|
|
333
328
|
end
|