origami 1.0.2
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/COPYING.LESSER +165 -0
- data/README +77 -0
- data/VERSION +1 -0
- data/bin/config/pdfcop.conf.yml +237 -0
- data/bin/gui/about.rb +46 -0
- data/bin/gui/config.rb +132 -0
- data/bin/gui/file.rb +385 -0
- data/bin/gui/hexdump.rb +74 -0
- data/bin/gui/hexview.rb +91 -0
- data/bin/gui/imgview.rb +72 -0
- data/bin/gui/menu.rb +392 -0
- data/bin/gui/properties.rb +132 -0
- data/bin/gui/signing.rb +635 -0
- data/bin/gui/textview.rb +107 -0
- data/bin/gui/treeview.rb +409 -0
- data/bin/gui/walker.rb +282 -0
- data/bin/gui/xrefs.rb +79 -0
- data/bin/pdf2graph +121 -0
- data/bin/pdf2ruby +353 -0
- data/bin/pdfcocoon +104 -0
- data/bin/pdfcop +455 -0
- data/bin/pdfdecompress +104 -0
- data/bin/pdfdecrypt +95 -0
- data/bin/pdfencrypt +112 -0
- data/bin/pdfextract +221 -0
- data/bin/pdfmetadata +123 -0
- data/bin/pdfsh +13 -0
- data/bin/pdfwalker +7 -0
- data/bin/shell/.irbrc +104 -0
- data/bin/shell/console.rb +136 -0
- data/bin/shell/hexdump.rb +83 -0
- data/origami.rb +36 -0
- data/origami/3d.rb +239 -0
- data/origami/acroform.rb +321 -0
- data/origami/actions.rb +299 -0
- data/origami/adobe/fdf.rb +259 -0
- data/origami/adobe/ppklite.rb +489 -0
- data/origami/annotations.rb +775 -0
- data/origami/array.rb +187 -0
- data/origami/boolean.rb +101 -0
- data/origami/catalog.rb +486 -0
- data/origami/destinations.rb +213 -0
- data/origami/dictionary.rb +188 -0
- data/origami/docmdp.rb +96 -0
- data/origami/encryption.rb +1293 -0
- data/origami/export.rb +283 -0
- data/origami/file.rb +222 -0
- data/origami/filters.rb +250 -0
- data/origami/filters/ascii.rb +189 -0
- data/origami/filters/ccitt.rb +515 -0
- data/origami/filters/crypt.rb +47 -0
- data/origami/filters/dct.rb +61 -0
- data/origami/filters/flate.rb +112 -0
- data/origami/filters/jbig2.rb +63 -0
- data/origami/filters/jpx.rb +53 -0
- data/origami/filters/lzw.rb +195 -0
- data/origami/filters/predictors.rb +276 -0
- data/origami/filters/runlength.rb +117 -0
- data/origami/font.rb +209 -0
- data/origami/functions.rb +93 -0
- data/origami/graphics.rb +33 -0
- data/origami/graphics/colors.rb +191 -0
- data/origami/graphics/instruction.rb +126 -0
- data/origami/graphics/path.rb +154 -0
- data/origami/graphics/patterns.rb +180 -0
- data/origami/graphics/state.rb +164 -0
- data/origami/graphics/text.rb +224 -0
- data/origami/graphics/xobject.rb +493 -0
- data/origami/header.rb +90 -0
- data/origami/linearization.rb +318 -0
- data/origami/metadata.rb +114 -0
- data/origami/name.rb +170 -0
- data/origami/null.rb +75 -0
- data/origami/numeric.rb +188 -0
- data/origami/obfuscation.rb +233 -0
- data/origami/object.rb +527 -0
- data/origami/outline.rb +59 -0
- data/origami/page.rb +559 -0
- data/origami/parser.rb +268 -0
- data/origami/parsers/fdf.rb +45 -0
- data/origami/parsers/pdf.rb +27 -0
- data/origami/parsers/pdf/linear.rb +113 -0
- data/origami/parsers/ppklite.rb +86 -0
- data/origami/pdf.rb +1144 -0
- data/origami/reference.rb +113 -0
- data/origami/signature.rb +474 -0
- data/origami/stream.rb +575 -0
- data/origami/string.rb +416 -0
- data/origami/trailer.rb +173 -0
- data/origami/webcapture.rb +87 -0
- data/origami/xfa.rb +3027 -0
- data/origami/xreftable.rb +447 -0
- data/templates/patterns.rb +66 -0
- data/templates/widgets.rb +173 -0
- data/templates/xdp.rb +92 -0
- data/tests/dataset/test.dummycrt +28 -0
- data/tests/dataset/test.dummykey +27 -0
- data/tests/tc_actions.rb +32 -0
- data/tests/tc_annotations.rb +85 -0
- data/tests/tc_pages.rb +37 -0
- data/tests/tc_pdfattach.rb +24 -0
- data/tests/tc_pdfencrypt.rb +110 -0
- data/tests/tc_pdfnew.rb +32 -0
- data/tests/tc_pdfparse.rb +98 -0
- data/tests/tc_pdfsig.rb +37 -0
- data/tests/tc_streams.rb +129 -0
- data/tests/ts_pdf.rb +45 -0
- metadata +193 -0
data/origami/header.rb
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
=begin
|
2
|
+
|
3
|
+
= File
|
4
|
+
header.rb
|
5
|
+
|
6
|
+
= Info
|
7
|
+
This file is part of Origami, PDF manipulation framework for Ruby
|
8
|
+
Copyright (C) 2010 Guillaume Delugr� <guillaume@security-labs.org>
|
9
|
+
All right reserved.
|
10
|
+
|
11
|
+
Origami is free software: you can redistribute it and/or modify
|
12
|
+
it under the terms of the GNU Lesser General Public License as published by
|
13
|
+
the Free Software Foundation, either version 3 of the License, or
|
14
|
+
(at your option) any later version.
|
15
|
+
|
16
|
+
Origami is distributed in the hope that it will be useful,
|
17
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
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/>.
|
23
|
+
|
24
|
+
=end
|
25
|
+
|
26
|
+
module Origami
|
27
|
+
|
28
|
+
class PDF
|
29
|
+
|
30
|
+
class InvalidHeaderError < Exception #:nodoc:
|
31
|
+
end
|
32
|
+
|
33
|
+
#
|
34
|
+
# Class representing a PDF Header.
|
35
|
+
#
|
36
|
+
class Header
|
37
|
+
|
38
|
+
MINVERSION = 0
|
39
|
+
MAXVERSION = 7
|
40
|
+
|
41
|
+
MAGIC = /%PDF-(\d+)\.(\d+)/
|
42
|
+
|
43
|
+
attr_accessor :majorversion, :minorversion
|
44
|
+
|
45
|
+
#
|
46
|
+
# Creates a file header, with the given major and minor versions.
|
47
|
+
# _majorversion_:: Major PDF version, must be 1.
|
48
|
+
# _minorversion_:: Minor PDF version, must be between 0 and 7.
|
49
|
+
#
|
50
|
+
def initialize(majorversion = 1, minorversion = 4)
|
51
|
+
|
52
|
+
#if majorversion.to_i != 1 || ! ((MINVERSION..MAXVERSION) === minorversion.to_i)
|
53
|
+
# colorprint("[info ] Warning: Invalid file version : #{majorversion}.#{minorversion}\n", Colors::YELLOW, false, STDERR)
|
54
|
+
#end
|
55
|
+
|
56
|
+
@majorversion, @minorversion = majorversion, minorversion
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.parse(stream) #:nodoc:
|
60
|
+
|
61
|
+
if not stream.scan(MAGIC).nil?
|
62
|
+
maj = stream[1].to_i
|
63
|
+
min = stream[2].to_i
|
64
|
+
else
|
65
|
+
raise InvalidHeaderError, "Invalid header format : #{stream.peek(15).inspect}"
|
66
|
+
end
|
67
|
+
|
68
|
+
PDF::Header.new(maj,min)
|
69
|
+
end
|
70
|
+
|
71
|
+
#
|
72
|
+
# Outputs self into PDF code.
|
73
|
+
#
|
74
|
+
def to_s
|
75
|
+
"%PDF-#{@majorversion}.#{@minorversion}" + EOL
|
76
|
+
end
|
77
|
+
|
78
|
+
def to_sym #:nodoc:
|
79
|
+
"#{@majorversion}.#{@minorversion}".to_sym
|
80
|
+
end
|
81
|
+
|
82
|
+
def to_f #:nodoc:
|
83
|
+
to_sym.to_s.to_f
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
@@ -0,0 +1,318 @@
|
|
1
|
+
=begin
|
2
|
+
|
3
|
+
= File
|
4
|
+
linearization.rb
|
5
|
+
|
6
|
+
= Info
|
7
|
+
This file is part of Origami, PDF manipulation framework for Ruby
|
8
|
+
Copyright (C) 2010 Guillaume Delugr� <guillaume@security-labs.org>
|
9
|
+
All right reserved.
|
10
|
+
|
11
|
+
Origami is free software: you can redistribute it and/or modify
|
12
|
+
it under the terms of the GNU Lesser General Public License as published by
|
13
|
+
the Free Software Foundation, either version 3 of the License, or
|
14
|
+
(at your option) any later version.
|
15
|
+
|
16
|
+
Origami is distributed in the hope that it will be useful,
|
17
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
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/>.
|
23
|
+
|
24
|
+
=end
|
25
|
+
|
26
|
+
module Origami
|
27
|
+
|
28
|
+
class PDF
|
29
|
+
|
30
|
+
#
|
31
|
+
# Returns whether the current document is linearized.
|
32
|
+
#
|
33
|
+
def is_linearized?
|
34
|
+
begin
|
35
|
+
obj = @revisions.first.objects.sort_by{|obj| obj.file_offset}.first
|
36
|
+
rescue
|
37
|
+
return false
|
38
|
+
end
|
39
|
+
|
40
|
+
obj.is_a?(Dictionary) and obj.has_key? :Linearized
|
41
|
+
end
|
42
|
+
|
43
|
+
#
|
44
|
+
# Tries to delinearize the document if it has been linearized.
|
45
|
+
# This operation is xrefs destructive, should be fixed in the future to merge tables.
|
46
|
+
#
|
47
|
+
def delinearize!
|
48
|
+
raise RuntimeError, 'Not a linearized document' unless is_linearized?
|
49
|
+
|
50
|
+
#
|
51
|
+
# Saves the first trailer.
|
52
|
+
#
|
53
|
+
prev_trailer = @revisions.first.trailer
|
54
|
+
|
55
|
+
lin_dict = @revisions.first.objects.first
|
56
|
+
hints = lin_dict[:H]
|
57
|
+
|
58
|
+
#
|
59
|
+
# Removes hint streams used by linearization.
|
60
|
+
#
|
61
|
+
if hints.is_a?(::Array)
|
62
|
+
if hints.length > 0 and hints[0].is_a?(Integer)
|
63
|
+
hint_stream = get_object_by_offset(hints[0])
|
64
|
+
delete_object(hint_stream.reference) if hint_stream.is_a?(Stream)
|
65
|
+
end
|
66
|
+
|
67
|
+
if hints.length > 2 and hints[2].is_a?(Integer)
|
68
|
+
overflow_stream = get_object_by_offset(hints[2])
|
69
|
+
delete_object(overflow_stream.reference) if overflow_stream.is_a?(Stream)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
#
|
74
|
+
# Remove all xrefs.
|
75
|
+
# Fix: Should be merged instead.
|
76
|
+
#
|
77
|
+
remove_xrefs
|
78
|
+
|
79
|
+
#
|
80
|
+
# Remove the linearization revision.
|
81
|
+
#
|
82
|
+
remove_revision(0)
|
83
|
+
|
84
|
+
#
|
85
|
+
# Update the trailer.
|
86
|
+
#
|
87
|
+
last_trailer = (@revisions.last.trailer ||= Trailer.new)
|
88
|
+
|
89
|
+
last_trailer.dictionary ||= Dictionary.new
|
90
|
+
last_trailer.dictionary =
|
91
|
+
last_trailer.dictionary.merge(prev_trailer.dictionary)
|
92
|
+
|
93
|
+
self
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
|
98
|
+
#
|
99
|
+
# Class representing a linearization dictionary.
|
100
|
+
#
|
101
|
+
class Linearization < Dictionary
|
102
|
+
include StandardObject
|
103
|
+
|
104
|
+
field :Linearized, :Type => Real, :Default => 1.0, :Required => true
|
105
|
+
field :L, :Type => Integer, :Required => true
|
106
|
+
field :H, :Type => Array, :Required => true
|
107
|
+
field :O, :Type => Integer, :Required => true
|
108
|
+
field :E, :Type => Integer, :Required => true
|
109
|
+
field :N, :Type => Integer, :Required => true
|
110
|
+
field :T, :Type => Integer, :Required => true
|
111
|
+
field :P, :Type => Integer, :Default => 0
|
112
|
+
|
113
|
+
def initialize(hash = {})
|
114
|
+
super(hash, true)
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
|
119
|
+
class InvalidHintTableError < Exception #:nodoc:
|
120
|
+
end
|
121
|
+
|
122
|
+
module HintTable
|
123
|
+
module ClassMethods
|
124
|
+
def header_item_size(number, size)
|
125
|
+
@header_items_size[number] = size
|
126
|
+
end
|
127
|
+
|
128
|
+
def get_header_item_size(number)
|
129
|
+
@header_items_size[number]
|
130
|
+
end
|
131
|
+
|
132
|
+
def entry_item_size(number, size)
|
133
|
+
@entry_items_size[number] = size
|
134
|
+
end
|
135
|
+
|
136
|
+
def get_entry_item_size(number)
|
137
|
+
@entry_items_size[number]
|
138
|
+
end
|
139
|
+
|
140
|
+
def nb_header_items
|
141
|
+
@header_items_size.size
|
142
|
+
end
|
143
|
+
|
144
|
+
def nb_entry_items
|
145
|
+
@entry_items_size.size
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def self.included(receiver)
|
150
|
+
receiver.instance_variable_set(:@header_items_size, {})
|
151
|
+
receiver.instance_variable_set(:@entry_items_size, {})
|
152
|
+
receiver.extend(ClassMethods)
|
153
|
+
end
|
154
|
+
|
155
|
+
attr_accessor :header_items
|
156
|
+
attr_accessor :entries
|
157
|
+
|
158
|
+
def initialize
|
159
|
+
@header_items = {}
|
160
|
+
@entries = []
|
161
|
+
end
|
162
|
+
|
163
|
+
def to_s
|
164
|
+
data = ""
|
165
|
+
|
166
|
+
nitems = self.class.nb_header_items
|
167
|
+
for no in (1..nitems)
|
168
|
+
unless @header_items.include?(no)
|
169
|
+
raise InvalidHintTableError, "Missing item #{no} in header section of #{self.class}"
|
170
|
+
end
|
171
|
+
|
172
|
+
value = @header_items[no]
|
173
|
+
item_size = self.class.get_header_item_size(no)
|
174
|
+
|
175
|
+
item_size = ((item_size + 7) >> 3) << 3
|
176
|
+
item_data = value.to_s(2)
|
177
|
+
item_data = "0" * (item_size - item_data.size) + item_data
|
178
|
+
|
179
|
+
data << [ item_data ].pack("B*")
|
180
|
+
end
|
181
|
+
|
182
|
+
i = 0
|
183
|
+
nitems = self.class.nb_entry_items
|
184
|
+
@entries.each do |entry|
|
185
|
+
for no in (1..items)
|
186
|
+
unless entry.include?(no)
|
187
|
+
raise InvalidHintTableError, "Missing item #{no} in entry #{i} of #{self.class}"
|
188
|
+
end
|
189
|
+
|
190
|
+
value = entry[no]
|
191
|
+
item_size = self.class.get_entry_item_size(no)
|
192
|
+
|
193
|
+
item_size = ((item_size + 7) >> 3) << 3
|
194
|
+
item_data = value.to_s(2)
|
195
|
+
item_data = "0" * (item_size - item_data.size) + item_data
|
196
|
+
|
197
|
+
data << [ item_data ].pack("B*")
|
198
|
+
end
|
199
|
+
|
200
|
+
i = i + 1
|
201
|
+
end
|
202
|
+
|
203
|
+
data
|
204
|
+
end
|
205
|
+
|
206
|
+
class PageOffsetTable
|
207
|
+
include HintTable
|
208
|
+
|
209
|
+
header_item_size 1, 32
|
210
|
+
header_item_size 2, 32
|
211
|
+
header_item_size 3, 16
|
212
|
+
header_item_size 4, 32
|
213
|
+
header_item_size 5, 16
|
214
|
+
header_item_size 6, 32
|
215
|
+
header_item_size 7, 16
|
216
|
+
header_item_size 8, 32
|
217
|
+
header_item_size 9, 16
|
218
|
+
header_item_size 10, 16
|
219
|
+
header_item_size 11, 16
|
220
|
+
header_item_size 12, 16
|
221
|
+
header_item_size 13, 16
|
222
|
+
|
223
|
+
entry_item_size 1, 16
|
224
|
+
entry_item_size 2, 16
|
225
|
+
entry_item_size 3, 16
|
226
|
+
entry_item_size 4, 16
|
227
|
+
entry_item_size 5, 16
|
228
|
+
entry_item_size 6, 16
|
229
|
+
entry_item_size 7, 16
|
230
|
+
end
|
231
|
+
|
232
|
+
class SharedObjectTable
|
233
|
+
include HintTable
|
234
|
+
|
235
|
+
header_item_size 1, 32
|
236
|
+
header_item_size 2, 32
|
237
|
+
header_item_size 3, 32
|
238
|
+
header_item_size 4, 32
|
239
|
+
header_item_size 5, 16
|
240
|
+
header_item_size 6, 32
|
241
|
+
header_item_size 7, 16
|
242
|
+
|
243
|
+
entry_item_size 1, 16
|
244
|
+
entry_item_size 2, 1
|
245
|
+
entry_item_size 3, 128
|
246
|
+
entry_item_size 4, 16
|
247
|
+
end
|
248
|
+
|
249
|
+
end
|
250
|
+
|
251
|
+
class InvalidHintStreamObjectError < InvalidStreamObjectError #:nodoc:
|
252
|
+
end
|
253
|
+
|
254
|
+
class HintStream < Stream
|
255
|
+
|
256
|
+
attr_accessor :page_offset_table
|
257
|
+
attr_accessor :shared_objects_table
|
258
|
+
attr_accessor :thumbnails_table
|
259
|
+
attr_accessor :outlines_table
|
260
|
+
attr_accessor :threads_table
|
261
|
+
attr_accessor :named_destinations_table
|
262
|
+
attr_accessor :interactive_forms_table
|
263
|
+
attr_accessor :information_dictionary_table
|
264
|
+
attr_accessor :logical_structure_table
|
265
|
+
attr_accessor :page_labels_table
|
266
|
+
attr_accessor :renditions_table
|
267
|
+
attr_accessor :embedded_files_table
|
268
|
+
|
269
|
+
field :S, :Type => Integer, :Required => true # SHared objects
|
270
|
+
field :T, :Type => Integer # Thumbnails
|
271
|
+
field :O, :Type => Integer # Outlines
|
272
|
+
field :A, :Type => Integer # Threads
|
273
|
+
field :E, :Type => Integer # Named destinations
|
274
|
+
field :V, :Type => Integer # Interactive forms
|
275
|
+
field :I, :Type => Integer # Information dictionary
|
276
|
+
field :C, :Type => Integer # Logical structure
|
277
|
+
field :L, :Type => Integer # Page labels
|
278
|
+
field :R, :Type => Integer # Renditions
|
279
|
+
field :B, :Type => Integer # Embedded files
|
280
|
+
|
281
|
+
def pre_build
|
282
|
+
if @page_offset_table.nil?
|
283
|
+
raise InvalidHintStreamObjectError, "No page offset hint table"
|
284
|
+
end
|
285
|
+
|
286
|
+
if @shared_objects_table.nil?
|
287
|
+
raise InvalidHintStreamObjectError, "No shared objects hint table"
|
288
|
+
end
|
289
|
+
|
290
|
+
@data = ""
|
291
|
+
save_table(@page_offset_table)
|
292
|
+
save_table(@shared_objects_table, :S)
|
293
|
+
save_table(@thumbnails_table, :T)
|
294
|
+
save_table(@outlines_table, :O)
|
295
|
+
save_table(@threads_table, :A)
|
296
|
+
save_table(@named_destinations_table, :E)
|
297
|
+
save_table(@interactive_forms_table, :V)
|
298
|
+
save_table(@information_dictionary_table, :I)
|
299
|
+
save_table(@logical_structure_table, :C)
|
300
|
+
save_table(@page_labels_table, :L)
|
301
|
+
save_table(@renditions_table, :R)
|
302
|
+
save_table(@embedded_files_table, :B)
|
303
|
+
|
304
|
+
super
|
305
|
+
end
|
306
|
+
|
307
|
+
private
|
308
|
+
|
309
|
+
def save_table(table, name = nil)
|
310
|
+
unless table.nil?
|
311
|
+
self[name] = @data.size if name
|
312
|
+
@data << table.to_s
|
313
|
+
end
|
314
|
+
end
|
315
|
+
|
316
|
+
end
|
317
|
+
|
318
|
+
end
|
data/origami/metadata.rb
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
=begin
|
2
|
+
|
3
|
+
= File
|
4
|
+
metadata.rb
|
5
|
+
|
6
|
+
= Info
|
7
|
+
This file is part of Origami, PDF manipulation framework for Ruby
|
8
|
+
Copyright (C) 2010 Guillaume Delugré <guillaume@security-labs.org>
|
9
|
+
All right reserved.
|
10
|
+
|
11
|
+
Origami is free software: you can redistribute it and/or modify
|
12
|
+
it under the terms of the GNU Lesser General Public License as published by
|
13
|
+
the Free Software Foundation, either version 3 of the License, or
|
14
|
+
(at your option) any later version.
|
15
|
+
|
16
|
+
Origami is distributed in the hope that it will be useful,
|
17
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
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/>.
|
23
|
+
|
24
|
+
=end
|
25
|
+
|
26
|
+
require 'rexml/document'
|
27
|
+
|
28
|
+
module Origami
|
29
|
+
|
30
|
+
class PDF
|
31
|
+
|
32
|
+
#
|
33
|
+
# Returns true if the document has a document information dictionary.
|
34
|
+
#
|
35
|
+
def has_document_info?
|
36
|
+
has_attr? :Info
|
37
|
+
end
|
38
|
+
|
39
|
+
#
|
40
|
+
# Returns true if the document has a catalog metadata stream.
|
41
|
+
#
|
42
|
+
def has_metadata?
|
43
|
+
self.Catalog.has_key? :Metadata
|
44
|
+
end
|
45
|
+
|
46
|
+
#
|
47
|
+
# Returns the document information dictionary if present.
|
48
|
+
#
|
49
|
+
def get_document_info
|
50
|
+
get_doc_attr :Info
|
51
|
+
end
|
52
|
+
|
53
|
+
#
|
54
|
+
# Returns a Hash of the information found in the metadata stream
|
55
|
+
#
|
56
|
+
def get_metadata
|
57
|
+
metadata_stm = self.Catalog.Metadata
|
58
|
+
|
59
|
+
if metadata_stm.is_a?(Stream)
|
60
|
+
doc = REXML::Document.new(metadata_stm.data)
|
61
|
+
|
62
|
+
info = {}
|
63
|
+
|
64
|
+
doc.elements.each('*/*/rdf:Description') do |description|
|
65
|
+
|
66
|
+
description.attributes.each_attribute do |attr|
|
67
|
+
case attr.prefix
|
68
|
+
when 'pdf','xap','pdf'
|
69
|
+
info[attr.name] = attr.value
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
description.elements.each('*') do |element|
|
74
|
+
value = (element.elements['.//rdf:li'] || element).text
|
75
|
+
info[element.name] = value.to_s
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
return info
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
#
|
87
|
+
# Class representing an information Dictionary, containing title, author, date of creation and the like.
|
88
|
+
#
|
89
|
+
class Metadata < Dictionary
|
90
|
+
include StandardObject
|
91
|
+
|
92
|
+
field :Title, :Type => String, :Version => "1.1"
|
93
|
+
field :Author, :Type => String
|
94
|
+
field :Subject, :Type => String, :Version => "1.1"
|
95
|
+
field :Keywords, :Type => String, :Version => "1.1"
|
96
|
+
field :Creator, :Type => String
|
97
|
+
field :Producer, :Type => String
|
98
|
+
field :CreationDate, :Type => ByteString
|
99
|
+
field :ModDate, :Type => ByteString, :Version => "1.1"
|
100
|
+
field :Trapped, :Type => Name, :Default => :Unknown, :Version => "1.3"
|
101
|
+
end
|
102
|
+
|
103
|
+
#
|
104
|
+
# Class representing a metadata Stream.
|
105
|
+
# This stream can contain the same information as the Metadata dictionary, but is storing in XML data.
|
106
|
+
#
|
107
|
+
class MetadataStream < Stream
|
108
|
+
include StandardObject
|
109
|
+
|
110
|
+
field :Type, :Type => Name, :Default => :Metadata, :Required => true
|
111
|
+
field :Subtype, :Type => Name, :Default =>:XML, :Required => true
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|