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