origami-docspring 2.2.0 → 2.3.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 +18 -0
- data/examples/attachments/attachment.rb +7 -8
- data/examples/attachments/nested_document.rb +6 -5
- data/examples/encryption/encryption.rb +5 -4
- data/examples/events/events.rb +7 -6
- data/examples/flash/flash.rb +10 -9
- data/examples/forms/javascript.rb +14 -13
- data/examples/forms/xfa.rb +67 -66
- data/examples/javascript/hello_world.rb +6 -5
- data/examples/javascript/js_emulation.rb +26 -26
- data/examples/loop/goto.rb +12 -11
- data/examples/loop/named.rb +17 -16
- data/examples/signature/signature.rb +11 -11
- data/examples/uri/javascript.rb +25 -24
- data/examples/uri/open-uri.rb +5 -4
- data/examples/uri/submitform.rb +11 -10
- data/lib/origami/3d.rb +330 -334
- data/lib/origami/acroform.rb +267 -268
- data/lib/origami/actions.rb +266 -278
- data/lib/origami/annotations.rb +659 -670
- data/lib/origami/array.rb +192 -196
- data/lib/origami/boolean.rb +66 -70
- data/lib/origami/catalog.rb +360 -363
- data/lib/origami/collections.rb +132 -133
- data/lib/origami/compound.rb +125 -129
- data/lib/origami/destinations.rb +226 -237
- data/lib/origami/dictionary.rb +155 -154
- data/lib/origami/encryption.rb +967 -923
- data/lib/origami/extensions/fdf.rb +270 -275
- data/lib/origami/extensions/ppklite.rb +323 -328
- data/lib/origami/filespec.rb +170 -173
- data/lib/origami/filters/ascii.rb +162 -167
- data/lib/origami/filters/ccitt/tables.rb +248 -252
- data/lib/origami/filters/ccitt.rb +309 -312
- data/lib/origami/filters/crypt.rb +31 -34
- data/lib/origami/filters/dct.rb +47 -50
- data/lib/origami/filters/flate.rb +57 -60
- data/lib/origami/filters/jbig2.rb +50 -53
- data/lib/origami/filters/jpx.rb +40 -43
- data/lib/origami/filters/lzw.rb +151 -155
- data/lib/origami/filters/predictors.rb +250 -255
- data/lib/origami/filters/runlength.rb +111 -115
- data/lib/origami/filters.rb +319 -325
- data/lib/origami/font.rb +173 -177
- data/lib/origami/functions.rb +62 -66
- data/lib/origami/graphics/colors.rb +203 -208
- data/lib/origami/graphics/instruction.rb +79 -81
- data/lib/origami/graphics/path.rb +141 -144
- data/lib/origami/graphics/patterns.rb +156 -160
- data/lib/origami/graphics/render.rb +51 -47
- data/lib/origami/graphics/state.rb +144 -142
- data/lib/origami/graphics/text.rb +185 -188
- data/lib/origami/graphics/xobject.rb +818 -804
- data/lib/origami/graphics.rb +25 -26
- data/lib/origami/header.rb +63 -65
- data/lib/origami/javascript.rb +718 -651
- data/lib/origami/linearization.rb +284 -285
- data/lib/origami/metadata.rb +156 -135
- data/lib/origami/name.rb +98 -100
- data/lib/origami/null.rb +49 -51
- data/lib/origami/numeric.rb +133 -135
- data/lib/origami/obfuscation.rb +180 -182
- data/lib/origami/object.rb +634 -631
- data/lib/origami/optionalcontent.rb +147 -149
- data/lib/origami/outline.rb +46 -48
- data/lib/origami/outputintents.rb +76 -77
- data/lib/origami/page.rb +637 -596
- data/lib/origami/parser.rb +214 -221
- data/lib/origami/parsers/fdf.rb +44 -45
- data/lib/origami/parsers/pdf/lazy.rb +147 -154
- data/lib/origami/parsers/pdf/linear.rb +104 -109
- data/lib/origami/parsers/pdf.rb +109 -107
- data/lib/origami/parsers/ppklite.rb +44 -46
- data/lib/origami/pdf.rb +886 -896
- data/lib/origami/reference.rb +116 -120
- data/lib/origami/signature.rb +617 -625
- data/lib/origami/stream.rb +560 -558
- data/lib/origami/string.rb +366 -368
- data/lib/origami/template/patterns.rb +50 -52
- data/lib/origami/template/widgets.rb +111 -114
- data/lib/origami/trailer.rb +153 -157
- data/lib/origami/tree.rb +55 -57
- data/lib/origami/version.rb +19 -19
- data/lib/origami/webcapture.rb +87 -90
- data/lib/origami/xfa/config.rb +409 -414
- data/lib/origami/xfa/connectionset.rb +113 -117
- data/lib/origami/xfa/datasets.rb +38 -42
- data/lib/origami/xfa/localeset.rb +33 -37
- data/lib/origami/xfa/package.rb +49 -52
- data/lib/origami/xfa/pdf.rb +54 -59
- data/lib/origami/xfa/signature.rb +33 -37
- data/lib/origami/xfa/sourceset.rb +34 -38
- data/lib/origami/xfa/stylesheet.rb +35 -39
- data/lib/origami/xfa/template.rb +1630 -1634
- data/lib/origami/xfa/xdc.rb +33 -37
- data/lib/origami/xfa/xfa.rb +132 -123
- data/lib/origami/xfa/xfdf.rb +34 -38
- data/lib/origami/xfa/xmpmeta.rb +34 -38
- data/lib/origami/xfa.rb +50 -53
- data/lib/origami/xreftable.rb +462 -462
- data/lib/origami.rb +37 -38
- data/test/test_actions.rb +22 -20
- data/test/test_annotations.rb +54 -52
- data/test/test_forms.rb +23 -21
- data/test/test_native_types.rb +82 -78
- data/test/test_object_tree.rb +25 -24
- data/test/test_pages.rb +43 -41
- data/test/test_pdf.rb +2 -0
- data/test/test_pdf_attachment.rb +23 -21
- data/test/test_pdf_create.rb +16 -15
- data/test/test_pdf_encrypt.rb +69 -66
- data/test/test_pdf_parse.rb +131 -129
- data/test/test_pdf_parse_lazy.rb +53 -53
- data/test/test_pdf_sign.rb +67 -67
- data/test/test_streams.rb +145 -143
- data/test/test_xrefs.rb +46 -45
- metadata +64 -8
@@ -1,22 +1,22 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# This file is part of Origami, PDF manipulation framework for Ruby
|
5
|
+
# Copyright (C) 2016 Guillaume Delugré.
|
6
|
+
#
|
7
|
+
# Origami is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU Lesser General Public License as published by
|
9
|
+
# the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# Origami is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU Lesser General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU Lesser General Public License
|
18
|
+
# along with Origami. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
#
|
20
20
|
|
21
21
|
require 'origami/object'
|
22
22
|
require 'origami/name'
|
@@ -34,389 +34,384 @@ require 'origami/parsers/ppklite'
|
|
34
34
|
require 'openssl'
|
35
35
|
|
36
36
|
module Origami
|
37
|
+
#
|
38
|
+
# Class representing an Adobe Reader certificate store.
|
39
|
+
#
|
40
|
+
class PPKLite
|
41
|
+
class Error < Origami::Error; end
|
42
|
+
|
43
|
+
def self.read(path, options = {})
|
44
|
+
path = File.expand_path(path) if path.is_a?(::String)
|
45
|
+
|
46
|
+
PPKLite::Parser.new(options).parse(path)
|
47
|
+
end
|
37
48
|
|
38
49
|
#
|
39
|
-
# Class representing
|
50
|
+
# Class representing a certificate store header.
|
40
51
|
#
|
41
|
-
class
|
52
|
+
class Header
|
53
|
+
MAGIC = /%PPKLITE-(?<major>\d)\.(?<minor>\d)/
|
54
|
+
|
55
|
+
attr_accessor :major_version, :minor_version
|
56
|
+
|
57
|
+
#
|
58
|
+
# Creates a file header, with the given major and minor versions.
|
59
|
+
# _major_version_:: Major version.
|
60
|
+
# _minor_version_:: Minor version.
|
61
|
+
#
|
62
|
+
def initialize(major_version = 2, minor_version = 1)
|
63
|
+
@major_version, @minor_version = major_version, minor_version
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.parse(stream) # :nodoc:
|
67
|
+
scanner = Parser.init_scanner(stream)
|
68
|
+
|
69
|
+
if !scanner.scan(MAGIC).nil?
|
70
|
+
maj = scanner['major'].to_i
|
71
|
+
min = scanner['minor'].to_i
|
72
|
+
else
|
73
|
+
raise InvalidHeader, "Invalid header format"
|
74
|
+
end
|
42
75
|
|
43
|
-
|
76
|
+
scanner.skip(REGEXP_WHITESPACES)
|
44
77
|
|
45
|
-
|
46
|
-
|
78
|
+
PPKLite::Header.new(maj, min)
|
79
|
+
end
|
47
80
|
|
48
|
-
|
49
|
-
|
81
|
+
#
|
82
|
+
# Outputs self into PDF code.
|
83
|
+
#
|
84
|
+
def to_s(eol: $/)
|
85
|
+
"%PPKLITE-#{@major_version}.#{@minor_version}".b + eol
|
86
|
+
end
|
50
87
|
|
51
|
-
|
52
|
-
#
|
53
|
-
|
54
|
-
class Header
|
55
|
-
MAGIC = /%PPKLITE-(?<major>\d)\.(?<minor>\d)/
|
56
|
-
|
57
|
-
attr_accessor :major_version, :minor_version
|
58
|
-
|
59
|
-
#
|
60
|
-
# Creates a file header, with the given major and minor versions.
|
61
|
-
# _major_version_:: Major version.
|
62
|
-
# _minor_version_:: Minor version.
|
63
|
-
#
|
64
|
-
def initialize(major_version = 2, minor_version = 1)
|
65
|
-
@major_version, @minor_version = major_version, minor_version
|
66
|
-
end
|
67
|
-
|
68
|
-
def self.parse(stream) #:nodoc:
|
69
|
-
scanner = Parser.init_scanner(stream)
|
70
|
-
|
71
|
-
if not scanner.scan(MAGIC).nil?
|
72
|
-
maj = scanner['major'].to_i
|
73
|
-
min = scanner['minor'].to_i
|
74
|
-
else
|
75
|
-
raise InvalidHeader, "Invalid header format"
|
76
|
-
end
|
77
|
-
|
78
|
-
scanner.skip(REGEXP_WHITESPACES)
|
79
|
-
|
80
|
-
PPKLite::Header.new(maj, min)
|
81
|
-
end
|
82
|
-
|
83
|
-
#
|
84
|
-
# Outputs self into PDF code.
|
85
|
-
#
|
86
|
-
def to_s(eol: $/)
|
87
|
-
"%PPKLITE-#{@major_version}.#{@minor_version}".b + eol
|
88
|
-
end
|
89
|
-
|
90
|
-
def to_sym #:nodoc:
|
91
|
-
"#{@major_version}.#{@minor_version}".to_sym
|
92
|
-
end
|
93
|
-
|
94
|
-
def to_f #:nodoc:
|
95
|
-
to_sym.to_s.to_f
|
96
|
-
end
|
97
|
-
end
|
88
|
+
def to_sym # :nodoc:
|
89
|
+
:"#{@major_version}.#{@minor_version}"
|
90
|
+
end
|
98
91
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
def initialize(adbk)
|
105
|
-
@document = adbk
|
106
|
-
@body = {}
|
107
|
-
@xreftable = nil
|
108
|
-
@trailer = nil
|
109
|
-
end
|
110
|
-
|
111
|
-
def trailer=(trl)
|
112
|
-
trl.document = @document
|
113
|
-
@trailer = trl
|
114
|
-
end
|
115
|
-
|
116
|
-
def each_object(&b)
|
117
|
-
@body.each_value(&b)
|
118
|
-
end
|
119
|
-
|
120
|
-
def objects
|
121
|
-
@body.values
|
122
|
-
end
|
123
|
-
end
|
92
|
+
def to_f # :nodoc:
|
93
|
+
to_sym.to_s.to_f
|
94
|
+
end
|
95
|
+
end
|
124
96
|
|
125
|
-
|
126
|
-
|
127
|
-
|
97
|
+
class Revision # :nodoc;
|
98
|
+
attr_accessor :document
|
99
|
+
attr_accessor :body, :xreftable
|
100
|
+
attr_reader :trailer
|
101
|
+
|
102
|
+
def initialize(adbk)
|
103
|
+
@document = adbk
|
104
|
+
@body = {}
|
105
|
+
@xreftable = nil
|
106
|
+
@trailer = nil
|
107
|
+
end
|
108
|
+
|
109
|
+
def trailer=(trl)
|
110
|
+
trl.document = @document
|
111
|
+
@trailer = trl
|
112
|
+
end
|
113
|
+
|
114
|
+
def each_object(&b)
|
115
|
+
@body.each_value(&b)
|
116
|
+
end
|
117
|
+
|
118
|
+
def objects
|
119
|
+
@body.values
|
120
|
+
end
|
121
|
+
end
|
128
122
|
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
end
|
133
|
-
end
|
123
|
+
module Descriptor
|
124
|
+
CERTIFICATE = 1
|
125
|
+
USER = 2
|
134
126
|
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
module Flags
|
142
|
-
CAN_CERTIFY = 1 << 1
|
143
|
-
ALLOW_DYNAMIC_CONTENT = 1 << 2
|
144
|
-
UNKNOWN_1 = 1 << 3
|
145
|
-
ALLOW_HIGH_PRIV_JS = 1 << 4
|
146
|
-
UNKNOWN_2 = 1 << 5
|
147
|
-
IS_ROOT_CA = 1 << 6
|
148
|
-
|
149
|
-
#FULL_TRUST = 1 << 1 | 1 << 2 | 1 << 3 | 1 << 4 | 1 << 5 | 1 << 6
|
150
|
-
FULL_TRUST = 8190
|
151
|
-
end
|
152
|
-
|
153
|
-
field :ABEType, :Type => Integer, :Default => Descriptor::CERTIFICATE, :Required => true
|
154
|
-
field :Usage, :Type => Integer, :Default => 1, :Required => true
|
155
|
-
field :Viewable, :Type => Boolean, :Default => true
|
156
|
-
field :Editable, :Type => Boolean, :Default => true
|
157
|
-
field :Cert, :Type => String, :Required => true
|
158
|
-
field :Trust, :Type => Integer, :Default => Flags::UNKNOWN_2, :Required => true
|
159
|
-
end
|
127
|
+
def self.included(receiver) # :nodoc:
|
128
|
+
receiver.field :ID, Type: Integer, Required: true
|
129
|
+
receiver.field :ABEType, Type: Integer, Default: Descriptor::CERTIFICATE, Required: true
|
130
|
+
end
|
131
|
+
end
|
160
132
|
|
161
|
-
|
162
|
-
|
163
|
-
|
133
|
+
class Certificate < Dictionary
|
134
|
+
include StandardObject
|
135
|
+
include Descriptor
|
136
|
+
|
137
|
+
add_type_signature ABEType: Descriptor::CERTIFICATE
|
138
|
+
|
139
|
+
module Flags
|
140
|
+
CAN_CERTIFY = 1 << 1
|
141
|
+
ALLOW_DYNAMIC_CONTENT = 1 << 2
|
142
|
+
UNKNOWN_1 = 1 << 3
|
143
|
+
ALLOW_HIGH_PRIV_JS = 1 << 4
|
144
|
+
UNKNOWN_2 = 1 << 5
|
145
|
+
IS_ROOT_CA = 1 << 6
|
146
|
+
|
147
|
+
# FULL_TRUST = 1 << 1 | 1 << 2 | 1 << 3 | 1 << 4 | 1 << 5 | 1 << 6
|
148
|
+
FULL_TRUST = 8190
|
149
|
+
end
|
150
|
+
|
151
|
+
field :ABEType, Type: Integer, Default: Descriptor::CERTIFICATE, Required: true
|
152
|
+
field :Usage, Type: Integer, Default: 1, Required: true
|
153
|
+
field :Viewable, Type: Boolean, Default: true
|
154
|
+
field :Editable, Type: Boolean, Default: true
|
155
|
+
field :Cert, Type: String, Required: true
|
156
|
+
field :Trust, Type: Integer, Default: Flags::UNKNOWN_2, Required: true
|
157
|
+
end
|
164
158
|
|
165
|
-
|
159
|
+
class User < Dictionary
|
160
|
+
include StandardObject
|
161
|
+
include Descriptor
|
166
162
|
|
167
|
-
|
168
|
-
field :Name, :Type => String, :Required => true
|
169
|
-
field :Encrypt, :Type => Integer
|
170
|
-
field :Certs, :Type => Array.of(Certificate), :Default => [], :Required => true
|
171
|
-
end
|
163
|
+
add_type_signature ABEType: Descriptor::USER
|
172
164
|
|
173
|
-
|
174
|
-
|
165
|
+
field :ABEType, Type: Integer, Default: Descriptor::USER, Required: true
|
166
|
+
field :Name, Type: String, Required: true
|
167
|
+
field :Encrypt, Type: Integer
|
168
|
+
field :Certs, Type: Array.of(Certificate), Default: [], Required: true
|
169
|
+
end
|
175
170
|
|
176
|
-
|
177
|
-
|
178
|
-
field :Entries, :Type => Array.of(Descriptor), :Default => [], :Required => true
|
179
|
-
end
|
171
|
+
class AddressList < Dictionary
|
172
|
+
include StandardObject
|
180
173
|
|
181
|
-
|
182
|
-
|
174
|
+
field :Type, Type: Name, Default: :AddressBook, Required: true
|
175
|
+
field :NextID, Type: Integer
|
176
|
+
field :Entries, Type: Array.of(Descriptor), Default: [], Required: true
|
177
|
+
end
|
183
178
|
|
184
|
-
|
185
|
-
|
179
|
+
class UserList < Dictionary
|
180
|
+
include StandardObject
|
186
181
|
|
187
|
-
|
188
|
-
|
182
|
+
field :Type, Type: Name, Default: :User, Required: true
|
183
|
+
end
|
189
184
|
|
190
|
-
|
191
|
-
|
192
|
-
field :AddressBook, :Type => AddressList, :Required => true
|
193
|
-
field :V, :Type => Integer, :Default => 0x10001, :Required => true
|
194
|
-
end
|
185
|
+
class PPK < Dictionary
|
186
|
+
include StandardObject
|
195
187
|
|
196
|
-
|
197
|
-
|
188
|
+
field :Type, Type: Name, Default: :PPK, Required: true
|
189
|
+
field :User, Type: UserList, Required: true
|
190
|
+
field :AddressBook, Type: AddressList, Required: true
|
191
|
+
field :V, Type: Integer, Default: 0x10001, Required: true
|
192
|
+
end
|
198
193
|
|
199
|
-
|
200
|
-
|
201
|
-
end
|
194
|
+
class Catalog < Dictionary
|
195
|
+
include StandardObject
|
202
196
|
|
203
|
-
|
197
|
+
field :Type, Type: Name, Default: :Catalog, Required: true
|
198
|
+
field :PPK, Type: PPK, Required: true
|
199
|
+
end
|
204
200
|
|
205
|
-
|
206
|
-
@header = PPKLite::Header.new
|
207
|
-
@revisions = [ Revision.new(self) ]
|
208
|
-
@revisions.first.trailer = Trailer.new
|
209
|
-
@parser = parser
|
201
|
+
attr_accessor :header, :revisions
|
210
202
|
|
211
|
-
|
212
|
-
|
203
|
+
def initialize(parser = nil) # :nodoc:
|
204
|
+
@header = PPKLite::Header.new
|
205
|
+
@revisions = [Revision.new(self)]
|
206
|
+
@revisions.first.trailer = Trailer.new
|
207
|
+
@parser = parser
|
213
208
|
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
nil
|
227
|
-
end
|
228
|
-
end
|
229
|
-
end
|
209
|
+
init if parser.nil?
|
210
|
+
end
|
211
|
+
|
212
|
+
def indirect_objects
|
213
|
+
@revisions.inject([]) do |set, rev| set.concat(rev.objects) end
|
214
|
+
end
|
215
|
+
alias_method :root_objects, :indirect_objects
|
216
|
+
|
217
|
+
def cast_object(reference, type) # :nodoc:
|
218
|
+
@revisions.each do |rev|
|
219
|
+
if rev.body.include?(reference) && (type < rev.body[reference].class)
|
220
|
+
rev.body[reference] = rev.body[reference].cast_to(type, @parser)
|
230
221
|
|
231
|
-
|
232
|
-
case no
|
233
|
-
when Reference
|
234
|
-
target = no
|
235
|
-
when ::Integer
|
236
|
-
target = Reference.new(no, generation)
|
237
|
-
when Origami::Object
|
238
|
-
return no
|
239
|
-
end
|
240
|
-
|
241
|
-
@revisions.first.body[target]
|
222
|
+
rev.body[reference]
|
242
223
|
end
|
224
|
+
end
|
225
|
+
end
|
243
226
|
|
244
|
-
|
245
|
-
|
246
|
-
|
227
|
+
def get_object(no, generation = 0) # :nodoc:
|
228
|
+
case no
|
229
|
+
when Reference
|
230
|
+
target = no
|
231
|
+
when ::Integer
|
232
|
+
target = Reference.new(no, generation)
|
233
|
+
when Origami::Object
|
234
|
+
return no
|
235
|
+
end
|
236
|
+
|
237
|
+
@revisions.first.body[target]
|
238
|
+
end
|
247
239
|
|
248
|
-
|
249
|
-
|
250
|
-
|
240
|
+
def <<(object)
|
241
|
+
object.set_indirect(true)
|
242
|
+
object.set_document(self)
|
251
243
|
|
252
|
-
|
253
|
-
|
254
|
-
|
244
|
+
if object.no.zero?
|
245
|
+
maxno = 1
|
246
|
+
maxno = maxno.succ while get_object(maxno)
|
255
247
|
|
256
|
-
|
248
|
+
object.generation = 0
|
249
|
+
object.no = maxno
|
250
|
+
end
|
257
251
|
|
258
|
-
|
259
|
-
end
|
260
|
-
alias insert <<
|
252
|
+
@revisions.first.body[object.reference] = object
|
261
253
|
|
262
|
-
|
263
|
-
|
264
|
-
|
254
|
+
object.reference
|
255
|
+
end
|
256
|
+
alias_method :insert, :<<
|
265
257
|
|
266
|
-
|
267
|
-
|
268
|
-
|
258
|
+
def Catalog
|
259
|
+
get_object(@revisions.first.trailer.Root)
|
260
|
+
end
|
269
261
|
|
270
|
-
|
262
|
+
def save(path)
|
263
|
+
bin = "".b
|
264
|
+
bin << @header.to_s
|
271
265
|
|
272
|
-
|
273
|
-
xrefsection = XRef::Section.new
|
266
|
+
lastno, brange = 0, 0
|
274
267
|
|
275
|
-
|
276
|
-
|
277
|
-
xrefsection << XRef::Subsection.new(brange, xrefs)
|
278
|
-
brange = obj.no
|
279
|
-
xrefs.clear
|
280
|
-
end
|
268
|
+
xrefs = [XRef.new(0, XRef::FIRSTFREE, XRef::FREE)]
|
269
|
+
xrefsection = XRef::Section.new
|
281
270
|
|
282
|
-
|
283
|
-
|
271
|
+
@revisions.first.body.values.sort.each { |obj|
|
272
|
+
if (obj.no - lastno).abs > 1
|
273
|
+
xrefsection << XRef::Subsection.new(brange, xrefs)
|
274
|
+
brange = obj.no
|
275
|
+
xrefs.clear
|
276
|
+
end
|
284
277
|
|
285
|
-
|
278
|
+
xrefs << XRef.new(bin.size, obj.generation, XRef::USED)
|
279
|
+
lastno = obj.no
|
286
280
|
|
287
|
-
|
281
|
+
obj.pre_build
|
288
282
|
|
289
|
-
|
290
|
-
}
|
283
|
+
bin << obj.to_s
|
291
284
|
|
292
|
-
|
285
|
+
obj.post_build
|
286
|
+
}
|
293
287
|
|
294
|
-
|
295
|
-
@trailer ||= Trailer.new
|
296
|
-
@trailer.Size = @revisions.first.body.size + 1
|
297
|
-
@trailer.startxref = bin.size
|
288
|
+
xrefsection << XRef::Subsection.new(brange, xrefs)
|
298
289
|
|
299
|
-
|
300
|
-
|
290
|
+
@xreftable = xrefsection
|
291
|
+
@trailer ||= Trailer.new
|
292
|
+
@trailer.Size = @revisions.first.body.size + 1
|
293
|
+
@trailer.startxref = bin.size
|
301
294
|
|
302
|
-
|
303
|
-
|
304
|
-
else
|
305
|
-
path = File.expand_path(path)
|
306
|
-
io = File.open(path, "wb", encoding: 'binary')
|
307
|
-
close = true
|
308
|
-
end
|
295
|
+
bin << @xreftable.to_s
|
296
|
+
bin << @trailer.to_s
|
309
297
|
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
298
|
+
if path.respond_to?(:write)
|
299
|
+
io = path
|
300
|
+
else
|
301
|
+
path = File.expand_path(path)
|
302
|
+
io = File.open(path, "wb", encoding: 'binary')
|
303
|
+
close = true
|
304
|
+
end
|
315
305
|
|
316
|
-
|
317
|
-
|
306
|
+
begin
|
307
|
+
io.write(bin)
|
308
|
+
ensure
|
309
|
+
io.close if close
|
310
|
+
end
|
318
311
|
|
319
|
-
|
320
|
-
|
321
|
-
end
|
312
|
+
self
|
313
|
+
end
|
322
314
|
|
323
|
-
|
324
|
-
|
325
|
-
|
315
|
+
def each_user(&b)
|
316
|
+
each_entry(Descriptor::USER, &b)
|
317
|
+
end
|
326
318
|
|
327
|
-
|
328
|
-
|
329
|
-
|
319
|
+
def get_user(id)
|
320
|
+
each_user.find { |user| user.ID == id }
|
321
|
+
end
|
330
322
|
|
331
|
-
|
332
|
-
|
333
|
-
|
323
|
+
def users
|
324
|
+
each_user.to_a
|
325
|
+
end
|
334
326
|
|
335
|
-
|
336
|
-
|
337
|
-
|
327
|
+
def each_certificate(&b)
|
328
|
+
each_entry(Descriptor::CERTIFICATE, &b)
|
329
|
+
end
|
338
330
|
|
339
|
-
|
340
|
-
|
341
|
-
|
331
|
+
def get_certificate(id)
|
332
|
+
each_certificate.find { |cert| cert.ID == id }
|
333
|
+
end
|
342
334
|
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
def add_certificate(certfile, attributes, viewable: false, editable: false)
|
347
|
-
if certfile.is_a?(OpenSSL::X509::Certificate)
|
348
|
-
x509 = certfile
|
349
|
-
else
|
350
|
-
x509 = OpenSSL::X509::Certificate.new(certfile)
|
351
|
-
end
|
335
|
+
def certificates
|
336
|
+
each_certificate.to_a
|
337
|
+
end
|
352
338
|
|
353
|
-
|
339
|
+
#
|
340
|
+
# Add a certificate into the address book
|
341
|
+
#
|
342
|
+
def add_certificate(certfile, attributes, viewable: false, editable: false)
|
343
|
+
x509 = if certfile.is_a?(OpenSSL::X509::Certificate)
|
344
|
+
certfile
|
345
|
+
else
|
346
|
+
OpenSSL::X509::Certificate.new(certfile)
|
347
|
+
end
|
354
348
|
|
355
|
-
|
356
|
-
cert.Cert = x509.to_der
|
357
|
-
cert.ID = address_book.NextID
|
358
|
-
address_book.NextID += 1
|
349
|
+
address_book = get_address_book
|
359
350
|
|
360
|
-
|
361
|
-
|
362
|
-
|
351
|
+
cert = Certificate.new
|
352
|
+
cert.Cert = x509.to_der
|
353
|
+
cert.ID = address_book.NextID
|
354
|
+
address_book.NextID += 1
|
363
355
|
|
364
|
-
|
365
|
-
|
356
|
+
cert.Trust = attributes
|
357
|
+
cert.Viewable = viewable
|
358
|
+
cert.Editable = editable
|
366
359
|
|
367
|
-
|
360
|
+
address_book.Entries.push(self << cert)
|
361
|
+
end
|
368
362
|
|
369
|
-
|
370
|
-
catalog = Catalog.new(
|
371
|
-
PPK: PPK.new(
|
372
|
-
User: UserList.new,
|
373
|
-
AddressBook: AddressList.new(
|
374
|
-
Entries: [],
|
375
|
-
NextID: 1
|
376
|
-
)
|
377
|
-
)
|
378
|
-
)
|
363
|
+
private
|
379
364
|
|
380
|
-
|
381
|
-
|
365
|
+
def init
|
366
|
+
catalog = Catalog.new(
|
367
|
+
PPK: PPK.new(
|
368
|
+
User: UserList.new,
|
369
|
+
AddressBook: AddressList.new(
|
370
|
+
Entries: [],
|
371
|
+
NextID: 1
|
372
|
+
)
|
373
|
+
)
|
374
|
+
)
|
382
375
|
|
383
|
-
|
384
|
-
|
376
|
+
@revisions.first.trailer.Root = insert(catalog)
|
377
|
+
end
|
385
378
|
|
386
|
-
|
379
|
+
def each_entry(type)
|
380
|
+
return enum_for(__method__, type) unless block_given?
|
387
381
|
|
388
|
-
|
389
|
-
entry = entry.solve
|
382
|
+
address_book = get_address_book
|
390
383
|
|
391
|
-
|
392
|
-
|
393
|
-
end
|
384
|
+
address_book.Entries.each do |entry|
|
385
|
+
entry = entry.solve
|
394
386
|
|
395
|
-
|
396
|
-
|
387
|
+
yield(entry) if entry.is_a?(Dictionary) && (entry.ABEType == type)
|
388
|
+
end
|
389
|
+
end
|
397
390
|
|
398
|
-
|
399
|
-
|
391
|
+
def get_address_book
|
392
|
+
raise Error, "Broken catalog" unless self.Catalog.is_a?(Dictionary) && self.Catalog.PPK.is_a?(Dictionary)
|
400
393
|
|
401
|
-
|
402
|
-
|
394
|
+
ppk = self.Catalog.PPK
|
395
|
+
raise Error, "Broken PPK" unless ppk.AddressBook.is_a?(Dictionary)
|
403
396
|
|
404
|
-
|
405
|
-
|
397
|
+
address_book = ppk.AddressBook
|
398
|
+
raise Error, "Broken address book" unless address_book.Entries.is_a?(Array)
|
406
399
|
|
407
|
-
|
408
|
-
|
409
|
-
objectoffset = bodyoffset
|
400
|
+
address_book
|
401
|
+
end
|
410
402
|
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
objectoffset += object.to_s.size
|
415
|
-
end
|
416
|
-
}
|
403
|
+
def get_object_offset(no, generation) # :nodoc:
|
404
|
+
bodyoffset = @header.to_s.size
|
405
|
+
objectoffset = bodyoffset
|
417
406
|
|
418
|
-
|
407
|
+
@revisions.first.body.values.each { |object|
|
408
|
+
if (object.no == no) && (object.generation == generation) then return objectoffset
|
409
|
+
else
|
410
|
+
objectoffset += object.to_s.size
|
419
411
|
end
|
412
|
+
}
|
420
413
|
|
414
|
+
nil
|
421
415
|
end
|
416
|
+
end
|
422
417
|
end
|