rasn1 0.11.0 → 0.12.1
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/lib/rasn1/errors.rb +15 -3
- data/lib/rasn1/model.rb +165 -48
- data/lib/rasn1/tracer.rb +174 -0
- data/lib/rasn1/types/any.rb +38 -13
- data/lib/rasn1/types/base.rb +160 -48
- data/lib/rasn1/types/bit_string.rb +14 -9
- data/lib/rasn1/types/bmp_string.rb +30 -0
- data/lib/rasn1/types/boolean.rb +6 -0
- data/lib/rasn1/types/choice.rb +9 -1
- data/lib/rasn1/types/constrained.rb +7 -2
- data/lib/rasn1/types/constructed.rb +17 -1
- data/lib/rasn1/types/generalized_time.rb +34 -41
- data/lib/rasn1/types/ia5string.rb +2 -2
- data/lib/rasn1/types/integer.rb +17 -5
- data/lib/rasn1/types/null.rb +6 -0
- data/lib/rasn1/types/numeric_string.rb +1 -1
- data/lib/rasn1/types/octet_string.rb +2 -0
- data/lib/rasn1/types/printable_string.rb +1 -1
- data/lib/rasn1/types/sequence.rb +7 -2
- data/lib/rasn1/types/sequence_of.rb +9 -3
- data/lib/rasn1/types/utc_time.rb +9 -7
- data/lib/rasn1/types/utf8_string.rb +2 -2
- data/lib/rasn1/types.rb +32 -12
- data/lib/rasn1/version.rb +1 -1
- data/lib/rasn1/wrapper.rb +209 -0
- data/lib/rasn1.rb +22 -20
- metadata +9 -34
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 884fa6f74d0b3074ef074d061301092d55df580b663714c4a962a7b8503d777d
|
4
|
+
data.tar.gz: 77cc3c5d7bf926463464ca4d37237f0cddc358e0d7b9aa3e85c15982ab3f3fc1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fee544874a10b10618cd596b1c30edd4ad70185a783eeadbe23a86fa2439339d7d025784be5adc76904e05856ac8791817a768c0603ece0141e38d2975e588ad
|
7
|
+
data.tar.gz: 39428eb166401712d44eb60c4413bcd919d4fca380213acbe1dc29c32425c03a8852e1f0afa8934f5a04c604b376ac3c47424754b358cae96cc685029c467da7
|
data/lib/rasn1/errors.rb
CHANGED
@@ -18,10 +18,17 @@ module RASN1
|
|
18
18
|
# Enumerated error
|
19
19
|
class EnumeratedError < Error; end
|
20
20
|
|
21
|
-
# CHOICE error: #chosen not set
|
21
|
+
# CHOICE error: {Types::Choice#chosen} not set
|
22
22
|
class ChoiceError < RASN1::Error
|
23
|
+
# @param [Types::Base] object
|
24
|
+
def initialize(object)
|
25
|
+
@object = object
|
26
|
+
super()
|
27
|
+
end
|
28
|
+
|
29
|
+
# @return [String]
|
23
30
|
def message
|
24
|
-
"CHOICE #{@name}: #chosen not set"
|
31
|
+
"CHOICE #{@object.name}: #chosen not set"
|
25
32
|
end
|
26
33
|
end
|
27
34
|
|
@@ -37,7 +44,12 @@ module RASN1
|
|
37
44
|
|
38
45
|
# @return [String]
|
39
46
|
def message
|
40
|
-
"Constraint not verified on #{object.inspect}"
|
47
|
+
"Constraint not verified on #{@object.inspect}"
|
41
48
|
end
|
42
49
|
end
|
50
|
+
|
51
|
+
# Exception raised when model validation fails
|
52
|
+
# @since 0.12.0
|
53
|
+
class ModelValidationError < Error
|
54
|
+
end
|
43
55
|
end
|
data/lib/rasn1/model.rb
CHANGED
@@ -57,16 +57,47 @@ module RASN1
|
|
57
57
|
#
|
58
58
|
# == Delegation
|
59
59
|
# {Model} may delegate some methods to its root element. Thus, if root element
|
60
|
-
# is, for example, a {
|
60
|
+
# is, for example, a {Types::Choice}, model may delegate +#chosen+ and +#chosen_value+.
|
61
61
|
#
|
62
62
|
# All methods defined by root may be delegated by model, unless model also defines
|
63
63
|
# this method.
|
64
64
|
# @author Sylvain Daubert
|
65
|
-
class
|
65
|
+
# @author adfoster-r7 ModelValidationError, track source location for dynamic class methods
|
66
|
+
class Model # rubocop:disable Metrics/ClassLength
|
66
67
|
# @private
|
67
|
-
Elem = Struct.new(:name, :proc_or_class, :content)
|
68
|
+
Elem = Struct.new(:name, :proc_or_class, :content) do
|
69
|
+
# @param [String,Symbol] name
|
70
|
+
# @param [Proc,Class] proc_or_class
|
71
|
+
# @param [Hash,nil] content
|
72
|
+
def initialize(name, proc_or_class, content)
|
73
|
+
if content.is_a?(Array)
|
74
|
+
duplicate_names = find_all_duplicate_names(content.map(&:name) + [name])
|
75
|
+
raise ModelValidationError, "Duplicate name #{duplicate_names.first} found" if duplicate_names.any?
|
76
|
+
end
|
77
|
+
|
78
|
+
super
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
# @param [Array<String>] names
|
84
|
+
# @return [Array<String>] The duplicate names found in the array
|
85
|
+
def find_all_duplicate_names(names)
|
86
|
+
names.group_by { |name| name }
|
87
|
+
.select { |_name, values| values.length > 1 }
|
88
|
+
.keys
|
89
|
+
end
|
90
|
+
end
|
68
91
|
|
69
92
|
# @private
|
93
|
+
WrapElem = Struct.new(:element, :options) do
|
94
|
+
# @return [String]
|
95
|
+
def name
|
96
|
+
"#{element.name}_wrapper"
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# Define helper methods to define models
|
70
101
|
module Accel
|
71
102
|
# @return [Hash]
|
72
103
|
attr_reader :options
|
@@ -79,6 +110,15 @@ module RASN1
|
|
79
110
|
@root = Elem.new(name, model_klass, nil)
|
80
111
|
end
|
81
112
|
|
113
|
+
# Use a {Wrapper} around a {Types::Base} or a {Model} object
|
114
|
+
# @param [Types::Base,Model] element
|
115
|
+
# @param [Hash] options
|
116
|
+
# @return [WrapElem]
|
117
|
+
# @since 0.12
|
118
|
+
def wrapper(element, options={})
|
119
|
+
@root = WrapElem.new(element, options)
|
120
|
+
end
|
121
|
+
|
82
122
|
# Update options of root element.
|
83
123
|
# May be used when subclassing.
|
84
124
|
# class Model1 < RASN1::Model
|
@@ -92,8 +132,13 @@ module RASN1
|
|
92
132
|
# end
|
93
133
|
# @param [Hash] options
|
94
134
|
# @return [void]
|
135
|
+
# @since 0.12.0 may change name through +:name+
|
95
136
|
def root_options(options)
|
96
137
|
@options = options
|
138
|
+
return unless options.key?(:name)
|
139
|
+
|
140
|
+
@root = @root.dup
|
141
|
+
@root.name = options[:name]
|
97
142
|
end
|
98
143
|
|
99
144
|
# On inheritance, create +@root+ class variable
|
@@ -105,33 +150,45 @@ module RASN1
|
|
105
150
|
klass.class_eval { @root = root }
|
106
151
|
end
|
107
152
|
|
153
|
+
# @private
|
154
|
+
# @param [String,Symbol] accel_name
|
155
|
+
# @param [Class] klass
|
156
|
+
# @since 0.11.0
|
157
|
+
# @since 0.12.0 track source location on error (adfoster-r7)
|
108
158
|
def define_type_accel_base(accel_name, klass)
|
109
|
-
singleton_class.class_eval
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
159
|
+
singleton_class.class_eval <<-EVAL, __FILE__, __LINE__ + 1
|
160
|
+
def #{accel_name}(name, options={}) # def sequence(name, type, options)
|
161
|
+
options[:name] = name
|
162
|
+
proc = proc do |opts|
|
163
|
+
#{klass}.new(options.merge(opts)) # Sequence.new(options.merge(opts))
|
164
|
+
end
|
165
|
+
@root = Elem.new(name, proc, options[:content])
|
166
|
+
end
|
167
|
+
EVAL
|
118
168
|
end
|
119
169
|
|
170
|
+
# @private
|
171
|
+
# @param [String,Symbol] accel_name
|
172
|
+
# @param [Class] klass
|
173
|
+
# @since 0.11.0
|
174
|
+
# @since 0.12.0 track source location on error (adfoster-r7)
|
120
175
|
def define_type_accel_of(accel_name, klass)
|
121
|
-
singleton_class.class_eval
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
176
|
+
singleton_class.class_eval <<-EVAL, __FILE__, __LINE__ + 1
|
177
|
+
def #{accel_name}_of(name, type, options={}) # def sequence_of(name, type, options)
|
178
|
+
options[:name] = name
|
179
|
+
proc = proc do |opts|
|
180
|
+
#{klass}.new(type, options.merge(opts)) # SequenceOf.new(type, options.merge(opts))
|
181
|
+
end
|
182
|
+
@root = Elem.new(name, proc, nil)
|
183
|
+
end
|
184
|
+
EVAL
|
130
185
|
end
|
131
186
|
|
132
187
|
# Define an accelarator to access a type in a model definition
|
133
188
|
# @param [String] accel_name
|
134
|
-
# @param [Class] klass
|
189
|
+
# @param [Class] klass class to instanciate
|
190
|
+
# @since 0.11.0
|
191
|
+
# @since 0.12.0 track source location on error (adfoster-r7)
|
135
192
|
def define_type_accel(accel_name, klass)
|
136
193
|
if klass < Types::SequenceOf
|
137
194
|
define_type_accel_of(accel_name, klass)
|
@@ -184,17 +241,20 @@ module RASN1
|
|
184
241
|
|
185
242
|
extend Accel
|
186
243
|
|
187
|
-
#
|
244
|
+
# @!method sequence(name, options)
|
245
|
+
# @!scope class
|
188
246
|
# @param [Symbol,String] name name of object in model
|
189
247
|
# @param [Hash] options
|
190
248
|
# @return [Elem]
|
191
249
|
# @see Types::Sequence#initialize
|
192
|
-
#
|
250
|
+
# @!method set(name, options)
|
251
|
+
# @!scope class
|
193
252
|
# @param [Symbol,String] name name of object in model
|
194
253
|
# @param [Hash] options
|
195
254
|
# @return [Elem]
|
196
255
|
# @see Types::Set#initialize
|
197
|
-
#
|
256
|
+
# @!method choice(name, options)
|
257
|
+
# @!scope class
|
198
258
|
# @param [Symbol,String] name name of object in model
|
199
259
|
# @param [Hash] options
|
200
260
|
# @return [Elem]
|
@@ -203,13 +263,15 @@ module RASN1
|
|
203
263
|
self.define_type_accel_base(type, Types.const_get(type.capitalize))
|
204
264
|
end
|
205
265
|
|
206
|
-
#
|
266
|
+
# @!method sequence_of(name, type, options)
|
267
|
+
# @!scope class
|
207
268
|
# @param [Symbol,String] name name of object in model
|
208
269
|
# @param [Model, Types::Base] type type for SEQUENCE OF
|
209
270
|
# @param [Hash] options
|
210
271
|
# @return [Elem]
|
211
272
|
# @see Types::SequenceOf#initialize
|
212
|
-
#
|
273
|
+
# @!method set_of(name, type, options)
|
274
|
+
# @!scope class
|
213
275
|
# @param [Symbol,String] name name of object in model
|
214
276
|
# @param [Model, Types::Base] type type for SET OF
|
215
277
|
# @param [Hash] options
|
@@ -219,57 +281,68 @@ module RASN1
|
|
219
281
|
define_type_accel_of(type, Types.const_get("#{type.capitalize}Of"))
|
220
282
|
end
|
221
283
|
|
222
|
-
#
|
284
|
+
# @!method boolean(name, options)
|
285
|
+
# @!scope class
|
223
286
|
# @param [Symbol,String] name name of object in model
|
224
287
|
# @param [Hash] options
|
225
288
|
# @return [Elem]
|
226
289
|
# @see Types::Boolean#initialize
|
227
|
-
#
|
290
|
+
# @!method integer(name, options)
|
291
|
+
# @!scope class
|
228
292
|
# @param [Symbol,String] name name of object in model
|
229
293
|
# @param [Hash] options
|
230
294
|
# @return [Elem]
|
231
295
|
# @see Types::Integer#initialize
|
232
|
-
#
|
296
|
+
# @!method bit_string(name, options)
|
297
|
+
# @!scope class
|
233
298
|
# @param [Symbol,String] name name of object in model
|
234
299
|
# @param [Hash] options
|
235
300
|
# @return [Elem]
|
236
301
|
# @see Types::BitString#initialize
|
237
|
-
#
|
302
|
+
# @!method octet_string(name, options)
|
303
|
+
# @!scope class
|
238
304
|
# @param [Symbol,String] name name of object in model
|
239
305
|
# @param [Hash] options
|
240
306
|
# @return [Elem]
|
241
307
|
# @see Types::OctetString#initialize
|
242
|
-
#
|
308
|
+
# @!method null(name, options)
|
309
|
+
# @!scope class
|
243
310
|
# @param [Symbol,String] name name of object in model
|
244
311
|
# @param [Hash] options
|
245
312
|
# @return [Elem]
|
246
313
|
# @see Types::Null#initialize
|
247
|
-
#
|
314
|
+
# @!method enumerated(name, options)
|
315
|
+
# @!scope class
|
248
316
|
# @param [Symbol,String] name name of object in model
|
249
317
|
# @param [Hash] options
|
250
318
|
# @return [Elem]
|
251
319
|
# @see Types::Enumerated#initialize
|
252
|
-
#
|
320
|
+
# @!method utf8_string(name, options)
|
321
|
+
# @!scope class
|
253
322
|
# @param [Symbol,String] name name of object in model
|
254
323
|
# @param [Hash] options
|
255
324
|
# @return [Elem]
|
256
325
|
# @see Types::Utf8String#initialize
|
257
|
-
#
|
326
|
+
# @!method numeric_string(name, options)
|
327
|
+
# @!scope class
|
258
328
|
# @param [Symbol,String] name name of object in model
|
259
329
|
# @param [Hash] options
|
260
330
|
# @return [Elem]
|
261
331
|
# @see Types::NumericString#initialize
|
262
|
-
#
|
332
|
+
# @!method printable_string(name, options)
|
333
|
+
# @!scope class
|
263
334
|
# @param [Symbol,String] name name of object in model
|
264
335
|
# @param [Hash] options
|
265
336
|
# @return [Elem]
|
266
337
|
# @see Types::PrintableString#initialize
|
267
|
-
#
|
338
|
+
# @!method visible_string(name, options)
|
339
|
+
# @!scope class
|
268
340
|
# @param [Symbol,String] name name of object in model
|
269
341
|
# @param [Hash] options
|
270
342
|
# @return [Elem]
|
271
343
|
# @see Types::VisibleString#initialize
|
272
|
-
#
|
344
|
+
# @!method ia5_string(name, options)
|
345
|
+
# @!scope class
|
273
346
|
# @param [Symbol,String] name name of object in model
|
274
347
|
# @param [Hash] options
|
275
348
|
# @return [Elem]
|
@@ -285,7 +358,7 @@ module RASN1
|
|
285
358
|
# @param [Hash] args
|
286
359
|
def initialize(args={})
|
287
360
|
root = generate_root
|
288
|
-
|
361
|
+
generate_elements(root)
|
289
362
|
initialize_elements(self, args)
|
290
363
|
end
|
291
364
|
|
@@ -296,7 +369,7 @@ module RASN1
|
|
296
369
|
@elements[name]
|
297
370
|
end
|
298
371
|
|
299
|
-
# Set value of element +name+. Element should be a {Base}.
|
372
|
+
# Set value of element +name+. Element should be a {Types::Base}.
|
300
373
|
# @param [String,Symbol] name
|
301
374
|
# @param [Object] value
|
302
375
|
# @return [Object] value
|
@@ -460,14 +533,33 @@ module RASN1
|
|
460
533
|
class_element
|
461
534
|
end
|
462
535
|
|
463
|
-
def
|
536
|
+
def generate_elements(element)
|
537
|
+
if element.is_a?(WrapElem)
|
538
|
+
generate_wrapper(element)
|
539
|
+
return
|
540
|
+
end
|
464
541
|
return unless element.content.is_a? Array
|
465
542
|
|
466
543
|
@elements[name].value = element.content.map do |another_element|
|
467
|
-
|
468
|
-
|
469
|
-
|
544
|
+
add_subelement(another_element)
|
545
|
+
end
|
546
|
+
end
|
547
|
+
|
548
|
+
def generate_wrapper(wrap_elem)
|
549
|
+
inner_elem = wrap_elem.element
|
550
|
+
subel = add_subelement(inner_elem)
|
551
|
+
Wrapper.new(subel, wrap_elem.options)
|
552
|
+
end
|
553
|
+
|
554
|
+
def add_subelement(subelement)
|
555
|
+
case subelement
|
556
|
+
when Elem
|
557
|
+
subel = get_type(subelement.proc_or_class)
|
558
|
+
@elements[subelement.name] = subel
|
559
|
+
generate_elements(subelement) if composed?(subel) && subelement.content.is_a?(Array)
|
470
560
|
subel
|
561
|
+
when WrapElem
|
562
|
+
generate_wrapper(subelement)
|
471
563
|
end
|
472
564
|
end
|
473
565
|
|
@@ -477,7 +569,7 @@ module RASN1
|
|
477
569
|
|
478
570
|
case value
|
479
571
|
when Hash
|
480
|
-
raise ArgumentError, "element #{name}: may only pass a Hash for Model elements" unless obj[name].is_a?
|
572
|
+
raise ArgumentError, "element #{name}: may only pass a Hash for Model elements" unless obj[name].is_a?(Model)
|
481
573
|
|
482
574
|
initialize_elements obj[name], value
|
483
575
|
when Array
|
@@ -499,7 +591,7 @@ module RASN1
|
|
499
591
|
end
|
500
592
|
end
|
501
593
|
|
502
|
-
def private_to_h(element=nil)
|
594
|
+
def private_to_h(element=nil) # rubocop:disable Metrics/CyclomaticComplexity
|
503
595
|
my_element = element || root
|
504
596
|
my_element = my_element.root if my_element.is_a?(Model)
|
505
597
|
value = case my_element
|
@@ -507,6 +599,13 @@ module RASN1
|
|
507
599
|
sequence_of_to_h(my_element)
|
508
600
|
when Types::Sequence
|
509
601
|
sequence_to_h(my_element)
|
602
|
+
# @author adfoster-r7
|
603
|
+
when Types::Choice
|
604
|
+
raise ChoiceError.new(my_element) if my_element.chosen.nil?
|
605
|
+
|
606
|
+
private_to_h(my_element.value[my_element.chosen])
|
607
|
+
when Wrapper
|
608
|
+
wrapper_to_h(my_element)
|
510
609
|
else
|
511
610
|
my_element.value
|
512
611
|
end
|
@@ -529,11 +628,29 @@ module RASN1
|
|
529
628
|
ary = seq.value.map do |el|
|
530
629
|
next if el.optional? && el.value.nil?
|
531
630
|
|
532
|
-
|
533
|
-
|
631
|
+
case el
|
632
|
+
when Model
|
633
|
+
hsh = el.to_h
|
634
|
+
hsh = hsh[hsh.keys.first]
|
635
|
+
[@elements.key(el), hsh]
|
636
|
+
when Wrapper
|
637
|
+
[@elements.key(el.element), wrapper_to_h(el)]
|
638
|
+
else
|
639
|
+
[el.name, private_to_h(el)]
|
640
|
+
end
|
534
641
|
end
|
535
642
|
ary.compact!
|
536
643
|
ary.to_h
|
537
644
|
end
|
645
|
+
|
646
|
+
def wrapper_to_h(wrap)
|
647
|
+
case wrap.element
|
648
|
+
when Model
|
649
|
+
hsh = wrap.element.to_h
|
650
|
+
hsh[hsh.keys.first]
|
651
|
+
else
|
652
|
+
private_to_h(wrap.element)
|
653
|
+
end
|
654
|
+
end
|
538
655
|
end
|
539
656
|
end
|
data/lib/rasn1/tracer.rb
ADDED
@@ -0,0 +1,174 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RASN1
|
4
|
+
# @private
|
5
|
+
class Tracer
|
6
|
+
# @return [IO]
|
7
|
+
attr_reader :io
|
8
|
+
# @return [Integer]
|
9
|
+
attr_accessor :tracing_level
|
10
|
+
|
11
|
+
TRACED_CLASSES = [Types::Any, Types::Choice, Types::Sequence, Types::SequenceOf, Types::Base].freeze
|
12
|
+
|
13
|
+
# @param [IO] io
|
14
|
+
def initialize(io)
|
15
|
+
@io = io
|
16
|
+
@tracing_level = 0
|
17
|
+
end
|
18
|
+
|
19
|
+
# Puts +msg+ onto {#io}.
|
20
|
+
# @param [String] msg
|
21
|
+
# @return [void]
|
22
|
+
def trace(msg)
|
23
|
+
@io.puts(indent << msg)
|
24
|
+
end
|
25
|
+
|
26
|
+
# Return identation for given +level+. If +nil+, use {#tracing_level}.
|
27
|
+
# @param [Integer,nil] level
|
28
|
+
# @return [String]
|
29
|
+
def indent(level=nil)
|
30
|
+
level ||= @tracing_level
|
31
|
+
' ' * level
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Trace RASN1 parsing to +io+.
|
36
|
+
# All parsing methods called in block are traced to +io+. Each ASN.1 element is
|
37
|
+
# traced in a line showing element's id, its length and its data.
|
38
|
+
# @param [IO] io
|
39
|
+
# @example
|
40
|
+
# RASN1.trace do
|
41
|
+
# RASN1.parse("\x02\x01\x01") # puts "INTEGER id: 2 (0x02), len: 1 (0x01), data: 0x01"
|
42
|
+
# end
|
43
|
+
# RASN1.parse("\x01\x01\xff") # puts nothing onto STDOUT
|
44
|
+
# @return [void]
|
45
|
+
def self.trace(io=$stdout)
|
46
|
+
@tracer = Tracer.new(io)
|
47
|
+
Tracer::TRACED_CLASSES.each(&:start_tracing)
|
48
|
+
|
49
|
+
begin
|
50
|
+
yield @tracer
|
51
|
+
ensure
|
52
|
+
Tracer::TRACED_CLASSES.reverse.each(&:stop_tracing)
|
53
|
+
@tracer.io.flush
|
54
|
+
@tracer = nil
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# @private
|
59
|
+
def self.tracer
|
60
|
+
@tracer
|
61
|
+
end
|
62
|
+
|
63
|
+
module Types
|
64
|
+
class Base
|
65
|
+
class << self
|
66
|
+
# @private
|
67
|
+
# Patch {#do_parse} to add tracing ability
|
68
|
+
def start_tracing
|
69
|
+
alias_method :do_parse_without_tracing, :do_parse
|
70
|
+
alias_method :do_parse, :do_parse_with_tracing
|
71
|
+
alias_method :do_parse_explicit_without_tracing, :do_parse_explicit
|
72
|
+
alias_method :do_parse_explicit, :do_parse_explicit_with_tracing
|
73
|
+
end
|
74
|
+
|
75
|
+
# @private
|
76
|
+
# Unpatch {#do_parse} to remove tracing ability
|
77
|
+
def stop_tracing
|
78
|
+
alias_method :do_parse, :do_parse_without_tracing # rubocop:disable Lint/DuplicateMethods
|
79
|
+
alias_method :do_parse_explicit, :do_parse_explicit_without_tracing # rubocop:disable Lint/DuplicateMethods
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# @private
|
84
|
+
# Parse +der+ with tracing abillity
|
85
|
+
# @see #parse!
|
86
|
+
def do_parse_with_tracing(der, ber)
|
87
|
+
ret = do_parse_without_tracing(der, ber)
|
88
|
+
RASN1.tracer.trace(self.trace)
|
89
|
+
ret
|
90
|
+
end
|
91
|
+
|
92
|
+
def do_parse_explicit_with_tracing(data)
|
93
|
+
RASN1.tracer.tracing_level += 1
|
94
|
+
do_parse_explicit_without_tracing(data)
|
95
|
+
RASN1.tracer.tracing_level -= 1
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
class Choice
|
100
|
+
class << self
|
101
|
+
# @private
|
102
|
+
# Patch {#parse!} to add tracing ability
|
103
|
+
def start_tracing
|
104
|
+
alias_method :parse_without_tracing, :parse!
|
105
|
+
alias_method :parse!, :parse_with_tracing
|
106
|
+
end
|
107
|
+
|
108
|
+
# @private
|
109
|
+
# Unpatch {#parse!} to remove tracing ability
|
110
|
+
def stop_tracing
|
111
|
+
alias_method :parse!, :parse_without_tracing # rubocop:disable Lint/DuplicateMethods
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
# @private
|
116
|
+
# Parse +der+ with tracing abillity
|
117
|
+
# @see #parse!
|
118
|
+
def parse_with_tracing(der, ber: false)
|
119
|
+
RASN1.tracer.trace(self.trace)
|
120
|
+
parse_without_tracing(der, ber: ber)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
class Sequence
|
125
|
+
class << self
|
126
|
+
# @private
|
127
|
+
# Patch {#der_to_value} to add tracing ability
|
128
|
+
def start_tracing
|
129
|
+
alias_method :der_to_value_without_tracing, :der_to_value
|
130
|
+
alias_method :der_to_value, :der_to_value_with_tracing
|
131
|
+
end
|
132
|
+
|
133
|
+
# @private
|
134
|
+
# Unpatch {#der_to_value!} to remove tracing ability
|
135
|
+
def stop_tracing
|
136
|
+
alias_method :der_to_value, :der_to_value_without_tracing # rubocop:disable Lint/DuplicateMethods
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
# @private
|
141
|
+
# der_to_value +der+ with tracing abillity
|
142
|
+
def der_to_value_with_tracing(der, ber: false)
|
143
|
+
RASN1.tracer.tracing_level += 1
|
144
|
+
der_to_value_without_tracing(der, ber: ber)
|
145
|
+
RASN1.tracer.tracing_level -= 1
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
class SequenceOf
|
150
|
+
class << self
|
151
|
+
# @private
|
152
|
+
# Patch {#der_to_value} to add tracing ability
|
153
|
+
def start_tracing
|
154
|
+
alias_method :der_to_value_without_tracing, :der_to_value
|
155
|
+
alias_method :der_to_value, :der_to_value_with_tracing
|
156
|
+
end
|
157
|
+
|
158
|
+
# @private
|
159
|
+
# Unpatch {#der_to_value!} to remove tracing ability
|
160
|
+
def stop_tracing
|
161
|
+
alias_method :der_to_value, :der_to_value_without_tracing # rubocop:disable Lint/DuplicateMethods
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
# @private
|
166
|
+
# der_to_value +der+ with tracing abillity
|
167
|
+
def der_to_value_with_tracing(der, ber: false)
|
168
|
+
RASN1.tracer.tracing_level += 1
|
169
|
+
der_to_value_without_tracing(der, ber: ber)
|
170
|
+
RASN1.tracer.tracing_level -= 1
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
data/lib/rasn1/types/any.rb
CHANGED
@@ -21,28 +21,22 @@ module RASN1
|
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
|
+
def can_build?
|
25
|
+
value? || !optional?
|
26
|
+
end
|
27
|
+
|
24
28
|
# Parse a DER string. This method updates object: {#value} will be a DER
|
25
29
|
# string.
|
26
30
|
# @param [String] der DER string
|
27
31
|
# @param [Boolean] ber if +true+, accept BER encoding
|
28
32
|
# @return [Integer] total number of parsed bytes
|
29
33
|
def parse!(der, ber: false)
|
30
|
-
|
31
|
-
return 0 if optional?
|
32
|
-
|
33
|
-
raise ASN1Error, 'Expected ANY but get nothing'
|
34
|
-
end
|
35
|
-
|
36
|
-
id_size = Types.decode_identifier_octets(der).last
|
37
|
-
total_length, = get_data(der[id_size..-1], ber)
|
38
|
-
total_length += id_size
|
39
|
-
|
40
|
-
@no_value = false
|
41
|
-
@value = der[0, total_length]
|
42
|
-
|
34
|
+
total_length, _data = do_parse(der, ber)
|
43
35
|
total_length
|
44
36
|
end
|
45
37
|
|
38
|
+
# @param [::Integer] level
|
39
|
+
# @return [String]
|
46
40
|
def inspect(level=0)
|
47
41
|
str = common_inspect(level)
|
48
42
|
str << if !value?
|
@@ -56,6 +50,16 @@ module RASN1
|
|
56
50
|
end
|
57
51
|
end
|
58
52
|
|
53
|
+
# @private Tracer private API
|
54
|
+
# @return [String]
|
55
|
+
def trace
|
56
|
+
return trace_any if value?
|
57
|
+
|
58
|
+
msg_type(no_id: true) << ' NONE'
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
59
63
|
def common_inspect(level)
|
60
64
|
lvl = level >= 0 ? level : 0
|
61
65
|
str = ' ' * lvl
|
@@ -65,6 +69,27 @@ module RASN1
|
|
65
69
|
str << "[#{id}] IMPLICIT " if implicit?
|
66
70
|
str << '(ANY) '
|
67
71
|
end
|
72
|
+
|
73
|
+
def do_parse(der, ber)
|
74
|
+
if der.empty?
|
75
|
+
return [0, ''] if optional?
|
76
|
+
|
77
|
+
raise ASN1Error, 'Expected ANY but get nothing'
|
78
|
+
end
|
79
|
+
|
80
|
+
id_size = Types.decode_identifier_octets(der).last
|
81
|
+
total_length, = get_data(der[id_size..-1], ber)
|
82
|
+
total_length += id_size
|
83
|
+
|
84
|
+
@no_value = false
|
85
|
+
@value = der[0, total_length]
|
86
|
+
|
87
|
+
[total_length, @value]
|
88
|
+
end
|
89
|
+
|
90
|
+
def trace_any
|
91
|
+
msg_type(no_id: true) << trace_data(value)
|
92
|
+
end
|
68
93
|
end
|
69
94
|
end
|
70
95
|
end
|