Methods

Net::BER::BERParser

Constants

VERSION
TagClasses

The order of these follows the class-codes in BER. Maybe this should have been a hash.

BuiltinSyntax

Public Instance Methods

read_ber(syntax=nil) click to toggle source
     # File lib/net/ber/ber_parser.rb, line 35
 35:       def read_ber syntax=nil
 36:         # TODO: clean this up so it works properly with partial
 37:         # packets coming from streams that don't block when
 38:         # we ask for more data (like StringIOs). At it is,
 39:         # this can throw TypeErrors and other nasties.
 40:                 
 41:         id = getbyte or return nil  # don't trash this value, we'll use it later
 42: 
 43:         n = getbyte
 44:         lengthlength,contentlength = if n <= 127
 45:           [1,n]
 46:         else
 47:           # Replaced the inject because it profiles hot.
 48:           #   j = (0...(n & 127)).inject(0) {|mem,x| mem = (mem << 8) + getc}
 49:           j = 0
 50:           read( n & 127 ).each_byte {|n1| j = (j << 8) + n1}
 51:           [1 + (n & 127), j]
 52:         end
 53: 
 54:         newobj = read contentlength
 55: 
 56:         # This exceptionally clever and clear bit of code is verrrry slow.
 57:         objtype = (syntax && syntax[id]) || BuiltinSyntax[id]
 58: 
 59:         # == is expensive so sort this if/else so the common cases are at the top.
 60:         obj = if objtype == :string
 61:           #(newobj || "").dup
 62:           s = BerIdentifiedString.new( newobj || "" )
 63:           s.ber_identifier = id
 64:           s
 65:         elsif objtype == :integer
 66:           j = 0
 67:           newobj.each_byte {|b| j = (j << 8) + b}
 68:           j
 69:         elsif objtype == :oid
 70:           # cf X.690 pgh 8.19 for an explanation of this algorithm.
 71:           # Potentially not good enough. We may need a BerIdentifiedOid
 72:           # as a subclass of BerIdentifiedArray, to get the ber identifier
 73:           # and also a to_s method that produces the familiar dotted notation.
 74:           oid = newobj.unpack("w*")
 75:           f = oid.shift
 76:           g = if f < 40
 77:             [0, f]
 78:           elsif f < 80
 79:             [1, f-40]
 80:           else
 81:             [2, f-80] # f-80 can easily be > 80. What a weird optimization.
 82:           end
 83:           oid.unshift g.last
 84:           oid.unshift g.first
 85:           oid
 86:         elsif objtype == :array
 87:           #seq = []
 88:           seq = BerIdentifiedArray.new
 89:           seq.ber_identifier = id
 90:           sio = StringIO.new( newobj || "" )
 91:           # Interpret the subobject, but note how the loop
 92:           # is built: nil ends the loop, but false (a valid
 93:           # BER value) does not!
 94:           while (e = sio.read_ber(syntax)) != nil
 95:             seq << e
 96:           end
 97:           seq
 98:         elsif objtype == :boolean
 99:           newobj != "\0000"
100:         elsif objtype == :null
101:           n = BerIdentifiedNull.new
102:           n.ber_identifier = id
103:           n
104:         else
105:           raise BerError.new( "unsupported object type: id=#{id}" )
106:         end
107: 
108:         obj
109:       end

Disabled; run with --debug to generate this.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.