rasn1 0.8.0 → 0.9.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f4eb9957878c25e54a394fee02aab5a42aa1201ad6250f7f6a2a3992128c87d6
4
- data.tar.gz: 3b3d3c85d619ee7f78923d7f7c839874f329087b0b1a4094839b059daf94c2ec
3
+ metadata.gz: b0f5f3f69aaae20cfd16576f565bc52d198bea49921a0db15e3e2a95a4947853
4
+ data.tar.gz: c3c1f6b2d5019febcbff3812611d624094b7aaefc238bd70109d4c278be3af8c
5
5
  SHA512:
6
- metadata.gz: 9eb501aacf629355e56a4103dfc3e354bfa035c031a23f2dcc61f8add191a13960cd64ea68db36340694f3b20aba316c0088ebe91943d795405b11489be9342e
7
- data.tar.gz: 115cef9248e5251a24ec0bb6d6e977084cfb4ff78118a7f5be31ee8fea05a0c831b935fa72c18bdc08e71bb729a85cff2b394f4a84aafd56245f70908f0a4dc6
6
+ metadata.gz: 51e54a40d6608074e76ba0d18d51462e82fba109a4258b9082875bafe36476060186d2081cabb4e2d17e1140f53a4700906a053fdb05638ceb060560a337d05b
7
+ data.tar.gz: 434ca0398606fb411351a2d43b6701b70f9512043abea8768e21832a2a1800be8347efef50b17b01239ce953b49cb21b64860e2d252cc64e9c696a514de564ea
data/README.md CHANGED
@@ -1,5 +1,4 @@
1
1
  [![Gem Version](https://badge.fury.io/rb/rasn1.svg)](https://badge.fury.io/rb/rasn1)
2
- [![Build Status](https://travis-ci.org/sdaubert/rasn1.svg?branch=master)](https://travis-ci.org/sdaubert/rasn1)
3
2
 
4
3
  # Rasn1
5
4
 
data/lib/rasn1/model.rb CHANGED
@@ -58,7 +58,10 @@ module RASN1
58
58
  # All methods defined by root may be delegated by model, unless model also defines
59
59
  # this method.
60
60
  # @author Sylvain Daubert
61
- class Model
61
+ class Model # rubocop:disable Metrics/ClassLength
62
+ # @private
63
+ Elem = Struct.new(:name, :proc_or_class, :content)
64
+
62
65
  class << self
63
66
  # @return [Hash]
64
67
  attr_reader :options
@@ -66,8 +69,9 @@ module RASN1
66
69
  # Use another model in this model
67
70
  # @param [String,Symbol] name
68
71
  # @param [Class] model_klass
72
+ # @return [Elem]
69
73
  def model(name, model_klass)
70
- @root = [name, model_klass]
74
+ @root = Elem.new(name, model_klass, nil)
71
75
  end
72
76
 
73
77
  # Update options of root element.
@@ -99,14 +103,17 @@ module RASN1
99
103
  # @method sequence(name, options)
100
104
  # @param [Symbol,String] name name of object in model
101
105
  # @param [Hash] options
106
+ # @return [Elem]
102
107
  # @see Types::Sequence#initialize
103
108
  # @method set(name, options)
104
109
  # @param [Symbol,String] name name of object in model
105
110
  # @param [Hash] options
111
+ # @return [Elem]
106
112
  # @see Types::Set#initialize
107
113
  # @method choice(name, options)
108
114
  # @param [Symbol,String] name name of object in model
109
115
  # @param [Hash] options
116
+ # @return [Elem]
110
117
  # @see Types::Choice#initialize
111
118
  %w[sequence set choice].each do |type|
112
119
  class_eval "def #{type}(name, options={})\n" \
@@ -114,9 +121,7 @@ module RASN1
114
121
  " proc = proc do |opts|\n" \
115
122
  " Types::#{type.capitalize}.new(options.merge(opts))\n" \
116
123
  " end\n" \
117
- " @root = [name, proc]\n" \
118
- " @root << options[:content] unless options[:content].nil?\n" \
119
- " @root\n" \
124
+ " @root = Elem.new(name, proc, options[:content])\n" \
120
125
  'end'
121
126
  end
122
127
 
@@ -124,11 +129,13 @@ module RASN1
124
129
  # @param [Symbol,String] name name of object in model
125
130
  # @param [Model, Types::Base] type type for SEQUENCE OF
126
131
  # @param [Hash] options
132
+ # @return [Elem]
127
133
  # @see Types::SequenceOf#initialize
128
134
  # @method set_of(name, type, options)
129
135
  # @param [Symbol,String] name name of object in model
130
136
  # @param [Model, Types::Base] type type for SET OF
131
137
  # @param [Hash] options
138
+ # @return [Elem]
132
139
  # @see Types::SetOf#initialize
133
140
  %w[sequence set].each do |type|
134
141
  klass_name = "Types::#{type.capitalize}Of"
@@ -137,53 +144,64 @@ module RASN1
137
144
  " proc = proc do |opts|\n" \
138
145
  " #{klass_name}.new(type, options.merge(opts))\n" \
139
146
  " end\n" \
140
- " @root = [name, proc]\n" \
147
+ " @root = Elem.new(name, proc, nil)\n" \
141
148
  'end'
142
149
  end
143
150
 
144
151
  # @method boolean(name, options)
145
152
  # @param [Symbol,String] name name of object in model
146
153
  # @param [Hash] options
154
+ # @return [Elem]
147
155
  # @see Types::Boolean#initialize
148
156
  # @method integer(name, options)
149
157
  # @param [Symbol,String] name name of object in model
150
158
  # @param [Hash] options
159
+ # @return [Elem]
151
160
  # @see Types::Integer#initialize
152
161
  # @method bit_string(name, options)
153
162
  # @param [Symbol,String] name name of object in model
154
163
  # @param [Hash] options
164
+ # @return [Elem]
155
165
  # @see Types::BitString#initialize
156
166
  # @method octet_string(name, options)
157
167
  # @param [Symbol,String] name name of object in model
158
168
  # @param [Hash] options
169
+ # @return [Elem]
159
170
  # @see Types::OctetString#initialize
160
171
  # @method null(name, options)
161
172
  # @param [Symbol,String] name name of object in model
162
173
  # @param [Hash] options
174
+ # @return [Elem]
163
175
  # @see Types::Null#initialize
164
176
  # @method enumerated(name, options)
165
177
  # @param [Symbol,String] name name of object in model
166
178
  # @param [Hash] options
179
+ # @return [Elem]
167
180
  # @see Types::Enumerated#initialize
168
181
  # @method utf8_string(name, options)
169
182
  # @param [Symbol,String] name name of object in model
170
183
  # @param [Hash] options
184
+ # @return [Elem]
171
185
  # @see Types::Utf8String#initialize
172
186
  # @method numeric_string(name, options)
173
187
  # @param [Symbol,String] name name of object in model
174
188
  # @param [Hash] options
189
+ # @return [Elem]
175
190
  # @see Types::NumericString#initialize
176
191
  # @method printable_string(name, options)
177
192
  # @param [Symbol,String] name name of object in model
178
193
  # @param [Hash] options
194
+ # @return [Elem]
179
195
  # @see Types::PrintableString#initialize
180
196
  # @method visible_string(name, options)
181
197
  # @param [Symbol,String] name name of object in model
182
198
  # @param [Hash] options
199
+ # @return [Elem]
183
200
  # @see Types::VisibleString#initialize
184
201
  # @method ia5_string(name, options)
185
202
  # @param [Symbol,String] name name of object in model
186
203
  # @param [Hash] options
204
+ # @return [Elem]
187
205
  # @see Types::IA5String#initialize
188
206
  Types.primitives.each do |prim|
189
207
  next if prim == Types::ObjectId
@@ -194,28 +212,30 @@ module RASN1
194
212
  " proc = proc do |opts|\n" \
195
213
  " #{prim}.new(options.merge(opts))\n" \
196
214
  " end\n" \
197
- " @root = [name, proc]\n" \
215
+ " @root = Elem.new(name, proc, nil)\n" \
198
216
  'end'
199
217
  end
200
218
 
201
219
  # @param [Symbol,String] name name of object in model
202
220
  # @param [Hash] options
221
+ # @return [Elem]
203
222
  # @note This method is named +objectid+ and not +object_id+ to not override
204
223
  # +Object#object_id+.
205
224
  # @see Types::ObjectId#initialize
206
225
  def objectid(name, options={})
207
226
  options[:name] = name
208
227
  proc = proc { |opts| Types::ObjectId.new(options.merge(opts)) }
209
- @root = [name, proc]
228
+ @root = Elem.new(name, proc, nil)
210
229
  end
211
230
 
212
231
  # @param [Symbol,String] name name of object in model
213
232
  # @param [Hash] options
233
+ # @return [Elem]
214
234
  # @see Types::Any#initialize
215
235
  def any(name, options={})
216
236
  options[:name] = name
217
237
  proc = proc { |opts| Types::Any.new(options.merge(opts)) }
218
- @root = [name, proc]
238
+ @root = Elem.new(name, proc, nil)
219
239
  end
220
240
 
221
241
  # Give type name (aka class name)
@@ -233,7 +253,7 @@ module RASN1
233
253
  # @raise [ASN1Error] error on parsing
234
254
  def parse(str, ber: false)
235
255
  model = new
236
- model.parse! str, ber: ber
256
+ model.parse!(str, ber: ber)
237
257
  model
238
258
  end
239
259
  end
@@ -242,8 +262,8 @@ module RASN1
242
262
  # @param [Hash] args
243
263
  def initialize(args={})
244
264
  root = generate_root
245
- set_elements(*root)
246
- initialize_elements self, args
265
+ set_elements(root)
266
+ initialize_elements(self, args)
247
267
  end
248
268
 
249
269
  # Give access to element +name+ in model
@@ -263,10 +283,10 @@ module RASN1
263
283
  @elements[name].value = value
264
284
  end
265
285
 
266
- # Get name frm root type
286
+ # Get name from root type
267
287
  # @return [String,Symbol]
268
288
  def name
269
- @root
289
+ @root_name
270
290
  end
271
291
 
272
292
  # Get elements names
@@ -281,15 +301,15 @@ module RASN1
281
301
  private_to_h
282
302
  end
283
303
 
284
- # @return [String]
285
- def to_der
286
- @elements[@root].to_der
287
- end
288
-
289
304
  # Get root element from model
290
305
  # @return [Types::Base,Model]
291
306
  def root
292
- @elements[@root]
307
+ @elements[@root_name]
308
+ end
309
+
310
+ # @return [String]
311
+ def to_der
312
+ root.to_der
293
313
  end
294
314
 
295
315
  # Give type name (aka class name)
@@ -304,25 +324,37 @@ module RASN1
304
324
  # @return [Integer] number of parsed bytes
305
325
  # @raise [ASN1Error] error on parsing
306
326
  def parse!(str, ber: false)
307
- @elements[@root].parse!(str.dup.force_encoding('BINARY'), ber: ber)
327
+ root.parse!(str.dup.force_encoding('BINARY'), ber: ber)
308
328
  end
309
329
 
310
330
  # @overload value
311
331
  # Get value of root element
312
332
  # @return [Object,nil]
313
- # @overload value(name)
333
+ # @overload value(name, *args)
314
334
  # Direct access to the value of +name+ (nested) element of model.
315
335
  # @param [String,Symbol] name
336
+ # @param [Array<Integer,String,Symbol>] args more argument to access element. May be
337
+ # used to access content of a SequenceOf or a SetOf
316
338
  # @return [Object,nil]
317
339
  # @return [Object,nil]
340
+ # @example
341
+ # class MyModel1 < RASN1::Model
342
+ # sequence('seq', content: [boolean('boolean'), integer('int')])
343
+ # end
344
+ # class MyModel2 < RASN1::Model
345
+ # sequence('root', content: [sequence_of('list', MyModel1)])
346
+ # end
347
+ # model = MyModel2.new
348
+ # model.parse!(der)
349
+ # # access to 2nd MyModel1.int in list
350
+ # model.value('list', 1, 'int')
318
351
  def value(name=nil, *args)
319
352
  if name.nil?
320
- @elements[@root].value
353
+ root.value
321
354
  else
322
355
  elt = by_name(name)
323
356
 
324
357
  unless args.empty?
325
- elt = elt.root if elt.is_a?(Model)
326
358
  args.each do |arg|
327
359
  elt = elt.root if elt.is_a?(Model)
328
360
  elt = elt[arg]
@@ -336,8 +368,8 @@ module RASN1
336
368
  # Delegate some methods to root element
337
369
  # @param [Symbol] meth
338
370
  def method_missing(meth, *args)
339
- if @elements[@root].respond_to? meth
340
- @elements[@root].send meth, *args
371
+ if root.respond_to? meth
372
+ root.send meth, *args
341
373
  else
342
374
  super
343
375
  end
@@ -345,7 +377,7 @@ module RASN1
345
377
 
346
378
  # @return [Boolean]
347
379
  def respond_to_missing?(meth, *)
348
- @elements[@root].respond_to?(meth) || super
380
+ root.respond_to?(meth) || super
349
381
  end
350
382
 
351
383
  # @return [String]
@@ -385,6 +417,9 @@ module RASN1
385
417
  [Types::Sequence, Types::Set].include? elt.class
386
418
  end
387
419
 
420
+ # proc_or_class:
421
+ # * proc: a Types::Base subclass
422
+ # * class: a model
388
423
  def get_type(proc_or_class, options={})
389
424
  case proc_or_class
390
425
  when Proc
@@ -395,20 +430,20 @@ module RASN1
395
430
  end
396
431
 
397
432
  def generate_root
398
- root = self.class.class_eval { @root }
399
- @root = root[0]
433
+ class_element = self.class.class_eval { @root }
434
+ @root_name = class_element.name
400
435
  @elements = {}
401
- @elements[@root] = get_type(root[1], self.class.options || {})
402
- root
436
+ @elements[@root_name] = get_type(class_element.proc_or_class, self.class.options || {})
437
+ class_element
403
438
  end
404
439
 
405
- def set_elements(name, _elt, content=nil)
406
- return unless content.is_a? Array
440
+ def set_elements(element) # rubocop:disable Naming/AccessorMethodName
441
+ return unless element.content.is_a? Array
407
442
 
408
- @elements[name].value = content.map do |name2, proc_or_class, content2|
409
- subel = get_type(proc_or_class)
410
- @elements[name2] = subel
411
- set_elements(name2, proc_or_class, content2) if composed?(subel) && content2.is_a?(Array)
443
+ @elements[name].value = element.content.map do |another_element|
444
+ subel = get_type(another_element.proc_or_class)
445
+ @elements[another_element.name] = subel
446
+ set_elements(another_element) if composed?(subel) && another_element.content.is_a?(Array)
412
447
  subel
413
448
  end
414
449
  end
@@ -423,54 +458,59 @@ module RASN1
423
458
 
424
459
  initialize_elements obj[name], value
425
460
  when Array
426
- composed = if obj[name].is_a? Model
427
- obj[name].root
428
- else
429
- obj[name]
430
- end
431
- if composed.of_type.is_a? Model
432
- value.each do |el|
433
- composed << initialize_elements(composed.of_type.class.new, el)
434
- end
435
- else
436
- value.each do |el|
437
- obj[name] << el
438
- end
439
- end
461
+ initialize_element_from_array(obj[name], value)
440
462
  else
441
463
  obj[name].value = value
442
464
  end
443
465
  end
444
466
  end
445
467
 
468
+ def initialize_element_from_array(obj, value)
469
+ composed = obj.is_a?(Model) ? obj.root : obj
470
+ if composed.of_type.is_a?(Model)
471
+ value.each do |el|
472
+ composed << initialize_elements(composed.of_type.class.new, el)
473
+ end
474
+ else
475
+ value.each { |el| composed << el }
476
+ end
477
+ end
478
+
446
479
  def private_to_h(element=nil)
447
- my_element = element
448
- my_element = root if my_element.nil?
480
+ my_element = element || root
449
481
  my_element = my_element.root if my_element.is_a?(Model)
450
482
  value = case my_element
451
483
  when Types::SequenceOf
452
- if my_element.of_type < Model
453
- my_element.value.map { |el| el.to_h.values.first }
454
- else
455
- my_element.value.map { |el| private_to_h(el) }
456
- end
484
+ sequence_of_to_h(my_element)
457
485
  when Types::Sequence
458
- seq = my_element.value.map do |el|
459
- next if el.optional? && el.value.nil?
460
-
461
- name = el.is_a?(Model) ? @elements.key(el) : el.name
462
- [name, private_to_h(el)]
463
- end
464
- seq.compact!
465
- Hash[seq]
486
+ sequence_to_h(my_element)
466
487
  else
467
488
  my_element.value
468
489
  end
469
490
  if element.nil?
470
- { @root => value }
491
+ { @root_name => value }
471
492
  else
472
493
  value
473
494
  end
474
495
  end
496
+
497
+ def sequence_of_to_h(elt)
498
+ if elt.of_type < Model
499
+ elt.value.map { |el| el.to_h.values.first }
500
+ else
501
+ elt.value.map { |el| private_to_h(el) }
502
+ end
503
+ end
504
+
505
+ def sequence_to_h(seq)
506
+ ary = seq.value.map do |el|
507
+ next if el.optional? && el.value.nil?
508
+
509
+ name = el.is_a?(Model) ? @elements.key(el) : el.name
510
+ [name, private_to_h(el)]
511
+ end
512
+ ary.compact!
513
+ ary.to_h
514
+ end
475
515
  end
476
516
  end
@@ -9,13 +9,15 @@ module RASN1
9
9
  class Any < Base
10
10
  # @return [String] DER-formated string
11
11
  def to_der
12
- case @value
13
- when Base, Model
14
- @value.to_der
15
- when nil
16
- optional? ? '' : Null.new.to_der
12
+ if value?
13
+ case @value
14
+ when Base, Model
15
+ @value.to_der
16
+ else
17
+ @value.to_s
18
+ end
17
19
  else
18
- @value.to_s
20
+ optional? ? '' : Null.new.to_der
19
21
  end
20
22
  end
21
23
 
@@ -25,7 +27,7 @@ module RASN1
25
27
  # @param [Boolean] ber if +true+, accept BER encoding
26
28
  # @return [Integer] total number of parsed bytes
27
29
  def parse!(der, ber: false)
28
- if der.nil? || der.empty?
30
+ if der.empty?
29
31
  return 0 if optional?
30
32
 
31
33
  raise ASN1Error, 'Expected ANY but get nothing'
@@ -35,25 +37,34 @@ module RASN1
35
37
  total_length, = get_data(der[id_size..-1], ber)
36
38
  total_length += id_size
37
39
 
40
+ @no_value = false
38
41
  @value = der[0, total_length]
39
42
 
40
43
  total_length
41
44
  end
42
45
 
43
46
  def inspect(level=0)
44
- lvl = level >= 0 ? level : 0
45
- str = ' ' * lvl
46
- str << "#{@name} " unless @name.nil?
47
- str << if @value.nil?
48
- '(ANY) NULL'
47
+ str = common_inspect(level)
48
+ str << if !value?
49
+ 'NULL'
49
50
  elsif @value.is_a?(OctetString) || @value.is_a?(BitString)
50
- "(ANY) #{@value.type}: #{value.value.inspect}"
51
+ "#{@value.type}: #{value.value.inspect}"
51
52
  elsif @value.class < Base
52
- "(ANY) #{@value.type}: #{value.value}"
53
+ "#{@value.type}: #{value.value}"
53
54
  else
54
- "ANY: #{value.to_s.inspect}"
55
+ value.to_s.inspect
55
56
  end
56
57
  end
58
+
59
+ def common_inspect(level)
60
+ lvl = level >= 0 ? level : 0
61
+ str = ' ' * lvl
62
+ str << "#{@name} " unless @name.nil?
63
+ str << asn1_class.to_s.upcase << ' ' unless asn1_class == :universal
64
+ str << "[#{id}] EXPLICIT " if explicit?
65
+ str << "[#{id}] IMPLICIT " if implicit?
66
+ str << '(ANY) '
67
+ end
57
68
  end
58
69
  end
59
70
  end