! Fixes tests for everything BUT the number conversion
This commit removes read_ber! since no one seems to be using it. YAGNI.
This commit is contained in:
parent
4c24cf239a
commit
75f37c58b9
10 changed files with 186 additions and 270 deletions
|
@ -1,5 +1,3 @@
|
|||
# $Id$
|
||||
#
|
||||
# NET::BER
|
||||
# Mixes ASN.1/BER convenience methods into several standard classes.
|
||||
# Also provides BER parsing functionality.
|
||||
|
@ -25,8 +23,6 @@
|
|||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
#---------------------------------------------------------------------------
|
||||
#
|
||||
#
|
||||
|
||||
module Net
|
||||
module BER
|
||||
|
@ -105,3 +101,4 @@ module Net
|
|||
end
|
||||
end
|
||||
|
||||
require 'net/ber/ber_parser'
|
|
@ -28,49 +28,35 @@ module Net
|
|||
}
|
||||
})
|
||||
|
||||
#
|
||||
# read_ber
|
||||
# TODO: clean this up so it works properly with partial
|
||||
# packets coming from streams that don't block when
|
||||
# we ask for more data (like StringIOs). At it is,
|
||||
# this can throw TypeErrors and other nasties.
|
||||
#--
|
||||
# BEWARE, this violates DRY and is largely equal in functionality to
|
||||
# read_ber_from_string. Eventually that method may subsume the functionality
|
||||
# of this one.
|
||||
#
|
||||
def read_ber syntax=nil
|
||||
# don't bother with this line, since IO#getc by definition returns nil on eof.
|
||||
#return nil if eof?
|
||||
|
||||
# here we'll create two different procs, one for 1.8 and one for 1.9
|
||||
# the reason being getc doesn't return a byte value in 1.9, so we need to
|
||||
# get the byte code out of the 1.9 encoded string
|
||||
|
||||
if RUBY_VERSION =~ /^1\.9/
|
||||
fetch_byte = Proc.new { getc.bytes.first }
|
||||
elsif RUBY_VERSION =~ /^1\.8/
|
||||
fetch_byte = Proc.new { getc }
|
||||
# TODO: clean this up so it works properly with partial
|
||||
# packets coming from streams that don't block when
|
||||
# we ask for more data (like StringIOs). At it is,
|
||||
# this can throw TypeErrors and other nasties.
|
||||
|
||||
# We might have been included in two kinds of things: IO-like
|
||||
# (answering to getbyte) and String-like (answering to to_s). Have
|
||||
# stream be a stream that is IO-like in both cases.
|
||||
if respond_to? :getbyte
|
||||
stream = self
|
||||
else
|
||||
stream = StringIO.new(self.to_s)
|
||||
end
|
||||
|
||||
id = stream.getbyte or return nil # don't trash this value, we'll use it later
|
||||
|
||||
id = fetch_byte.call or return nil # don't trash this value, we'll use it later
|
||||
#tag = id & 31
|
||||
#tag < 31 or raise BerError.new( "unsupported tag encoding: #{id}" )
|
||||
#tagclass = TagClasses[ id >> 6 ]
|
||||
#encoding = (id & 0x20 != 0) ? :constructed : :primitive
|
||||
|
||||
n = fetch_byte.call
|
||||
n = stream.getbyte
|
||||
lengthlength,contentlength = if n <= 127
|
||||
[1,n]
|
||||
else
|
||||
# Replaced the inject because it profiles hot.
|
||||
#j = (0...(n & 127)).inject(0) {|mem,x| mem = (mem << 8) + getc}
|
||||
# j = (0...(n & 127)).inject(0) {|mem,x| mem = (mem << 8) + getc}
|
||||
j = 0
|
||||
read( n & 127 ).each_byte {|n1| j = (j << 8) + n1}
|
||||
[1 + (n & 127), j]
|
||||
end
|
||||
|
||||
newobj = read contentlength
|
||||
newobj = stream.read contentlength
|
||||
|
||||
# This exceptionally clever and clear bit of code is verrrry slow.
|
||||
objtype = (syntax && syntax[id]) || BuiltinSyntax[id]
|
||||
|
@ -121,102 +107,11 @@ module Net
|
|||
n.ber_identifier = id
|
||||
n
|
||||
else
|
||||
#raise BerError.new( "unsupported object type: class=#{tagclass}, encoding=#{encoding}, tag=#{tag}" )
|
||||
raise BerError.new( "unsupported object type: id=#{id}" )
|
||||
end
|
||||
# Add the identifier bits into the object if it's a String or an Array.
|
||||
# We can't add extra stuff to Fixnums and booleans, not that it makes much sense anyway.
|
||||
# Replaced this mechanism with subclasses because the instance_eval profiled too hot.
|
||||
#obj and ([String,Array].include? obj.class) and obj.instance_eval "def ber_identifier; #{id}; end"
|
||||
#obj.ber_identifier = id if obj.respond_to?(:ber_identifier)
|
||||
|
||||
obj
|
||||
end
|
||||
|
||||
#--
|
||||
# Violates DRY! This replicates the functionality of #read_ber.
|
||||
# Eventually this method may replace that one.
|
||||
# This version of #read_ber behaves properly in the face of incomplete
|
||||
# data packets. If a full BER object is detected, we return an array containing
|
||||
# the detected object and the number of bytes consumed from the string.
|
||||
# If we don't detect a complete packet, return nil.
|
||||
#
|
||||
# Observe that weirdly we recursively call the original #read_ber in here.
|
||||
# That needs to be fixed if we ever obsolete the original method in favor of this one.
|
||||
def read_ber_from_string str, syntax=nil
|
||||
id = str[0].ord or return nil
|
||||
n = str[1].ord or return nil
|
||||
n_consumed = 2
|
||||
lengthlength,contentlength = if n <= 127
|
||||
[1,n]
|
||||
else
|
||||
n1 = n & 127
|
||||
return nil unless str.length >= (n_consumed + n1)
|
||||
j = 0
|
||||
n1.times {
|
||||
j = (j << 8) + str[n_consumed]
|
||||
n_consumed += 1
|
||||
}
|
||||
[1 + (n1), j]
|
||||
end
|
||||
|
||||
return nil unless str.length >= (n_consumed + contentlength)
|
||||
newobj = str[n_consumed...(n_consumed + contentlength)]
|
||||
n_consumed += contentlength
|
||||
|
||||
objtype = (syntax && syntax[id]) || BuiltinSyntax[id]
|
||||
|
||||
# == is expensive so sort this if/else so the common cases are at the top.
|
||||
obj = if objtype == :array
|
||||
seq = BerIdentifiedArray.new
|
||||
seq.ber_identifier = id
|
||||
sio = StringIO.new( newobj || "" )
|
||||
# Interpret the subobject, but note how the loop
|
||||
# is built: nil ends the loop, but false (a valid
|
||||
# BER value) does not!
|
||||
# Also, we can use the standard read_ber method because
|
||||
# we know for sure we have enough data. (Although this
|
||||
# might be faster than the standard method.)
|
||||
while (e = sio.read_ber(syntax)) != nil
|
||||
seq << e
|
||||
end
|
||||
seq
|
||||
elsif objtype == :string
|
||||
s = BerIdentifiedString.new( newobj || "" )
|
||||
s.ber_identifier = id
|
||||
s
|
||||
elsif objtype == :integer
|
||||
j = 0
|
||||
newobj.each_byte {|b| j = (j << 8) + b}
|
||||
j
|
||||
elsif objtype == :oid
|
||||
# cf X.690 pgh 8.19 for an explanation of this algorithm.
|
||||
# Potentially not good enough. We may need a BerIdentifiedOid
|
||||
# as a subclass of BerIdentifiedArray, to get the ber identifier
|
||||
# and also a to_s method that produces the familiar dotted notation.
|
||||
oid = newobj.unpack("w*")
|
||||
f = oid.shift
|
||||
g = if f < 40
|
||||
[0,f]
|
||||
elsif f < 80
|
||||
[1, f-40]
|
||||
else
|
||||
[2, f-80] # f-80 can easily be > 80. What a weird optimization.
|
||||
end
|
||||
oid.unshift g.last
|
||||
oid.unshift g.first
|
||||
oid
|
||||
elsif objtype == :boolean
|
||||
newobj != "\000"
|
||||
elsif objtype == :null
|
||||
n = BerIdentifiedNull.new
|
||||
n.ber_identifier = id
|
||||
n
|
||||
else
|
||||
raise BerError.new( "unsupported object type: id=#{id}" )
|
||||
end
|
||||
|
||||
[obj, n_consumed]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,25 +1,12 @@
|
|||
# $Id$
|
||||
#
|
||||
# Net::LDAP for Ruby
|
||||
#
|
||||
#
|
||||
# Copyright (C) 2006 by Francis Cianfrocca. All Rights Reserved.
|
||||
#
|
||||
# Written and maintained by Francis Cianfrocca, gmail: garbagecat10.
|
||||
#
|
||||
# This program is free software.
|
||||
# You may re-distribute and/or modify this program under the same terms
|
||||
# as Ruby itself: Ruby Distribution License or GNU General Public License.x
|
||||
#
|
||||
#
|
||||
# See Net::LDAP for documentation and usage samples.
|
||||
#
|
||||
require 'openssl'
|
||||
|
||||
require 'net/ber'
|
||||
require 'net/ldap/pdu'
|
||||
require 'net/ldap/filter'
|
||||
require 'net/ldap/dataset'
|
||||
require 'net/ldap/psw'
|
||||
require 'net/ldap/entry'
|
||||
require 'net/ldap/core_ext/all'
|
||||
|
||||
module Net
|
||||
|
||||
|
@ -258,7 +245,7 @@ module Net
|
|||
SearchScope_WholeSubtree = 2
|
||||
SearchScopes = [SearchScope_BaseObject, SearchScope_SingleLevel, SearchScope_WholeSubtree]
|
||||
|
||||
AsnSyntax = BER.compile_syntax({
|
||||
AsnSyntax = Net::BER.compile_syntax({
|
||||
:application => {
|
||||
:primitive => {
|
||||
2 => :null # UnbindRequest body
|
||||
|
|
|
@ -32,16 +32,15 @@ module Net
|
|||
StringIO.new(self).read_ber(syntax)
|
||||
end
|
||||
|
||||
def read_ber! syntax=nil
|
||||
obj,n_consumed = read_ber_from_string(self, syntax)
|
||||
if n_consumed
|
||||
self.slice!(0...n_consumed)
|
||||
obj
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
# def read_ber! syntax=nil
|
||||
# obj,n_consumed = read_ber_from_string(self, syntax)
|
||||
# if n_consumed
|
||||
# self.slice!(0...n_consumed)
|
||||
# obj
|
||||
# else
|
||||
# nil
|
||||
# end
|
||||
# end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -32,25 +32,26 @@ module Net
|
|||
class LDAP
|
||||
class Dataset < Hash
|
||||
attr_reader :comments
|
||||
|
||||
class IOFilter
|
||||
def initialize(io)
|
||||
@io = io
|
||||
end
|
||||
|
||||
def gets
|
||||
s = @io.gets
|
||||
s.chomp if s
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def self.read_ldif io
|
||||
ds = Dataset.new
|
||||
io = IOFilter.new(io)
|
||||
|
||||
line = io.gets
|
||||
dn = nil
|
||||
|
||||
while line
|
||||
io.gets and chomp
|
||||
new_line = io.gets
|
||||
if new_line =~ /^[\s]+/
|
||||
line << " " << $'
|
||||
else
|
||||
|
@ -75,7 +76,7 @@ module Net
|
|||
line = nextline
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
ds
|
||||
end
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue