net-ldap 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of net-ldap might be problematic. Click here for more details.

@@ -1,4 +1,7 @@
1
- === Net::LDAP 0.1.0 / 2010-03-08
1
+ === Net::LDAP 0.1.1 / 2010-03-18
2
+ * Fixing a critical problem with sockets.
3
+
4
+ === Net::LDAP 0.1.0 / 2010-03-17
2
5
  * Small fixes throughout, more to come.
3
6
  * Ruby 1.9 support added.
4
7
  * Ruby 1.8.6 and below support removed. If we can figure out a compatible way
data/Rakefile CHANGED
@@ -1,14 +1,10 @@
1
1
  require "rubygems"
2
- require 'hanna/rdoctask'
3
2
  require 'hoe'
4
3
 
5
4
  $LOAD_PATH.unshift('lib')
6
5
 
7
6
  require 'net/ldap'
8
7
 
9
- require "rake/gempackagetask"
10
- require "rake/rdoctask"
11
-
12
8
  PKG_NAME = 'net-ldap'
13
9
  PKG_VERSION = Net::LDAP::VERSION
14
10
  PKG_DIST = "#{PKG_NAME}-#{PKG_VERSION}"
@@ -1,5 +1,6 @@
1
1
  require 'openssl'
2
2
  require 'ostruct'
3
+ require 'socket'
3
4
 
4
5
  require 'net/ber'
5
6
  require 'net/ldap/pdu'
@@ -232,9 +233,9 @@ module Net
232
233
  # to the server and then keeps it open while it executes a user-supplied block. Net::LDAP#open
233
234
  # closes the connection on completion of the block.
234
235
  class LDAP
235
- class LdapError < StandardError; end
236
+ VERSION = "0.1.1"
236
237
 
237
- VERSION = "0.1.0"
238
+ class LdapError < StandardError; end
238
239
 
239
240
  SearchScope_BaseObject = 0
240
241
  SearchScope_SingleLevel = 1
@@ -1120,8 +1121,10 @@ module Net
1120
1121
  def initialize server
1121
1122
  begin
1122
1123
  @conn = TCPSocket.new( server[:host], server[:port] )
1123
- rescue
1124
- raise LdapError.new( "no connection to server" )
1124
+ rescue SocketError
1125
+ raise LdapError, "No such address or other socket error."
1126
+ rescue Errno::ECONNREFUSED
1127
+ raise LdapError, "Server #{server[:host]} refused connection on port #{server[:port]}."
1125
1128
  end
1126
1129
 
1127
1130
  if server[:encryption]
@@ -4,9 +4,9 @@ module Net
4
4
  module Bignum
5
5
 
6
6
  def to_ber
7
- # NOTE: Array#pack's 'w' is a BER _compressed_ integer. We need uncompressed
8
- # BER integers, so we're not using that.
9
- # See also: http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/228864
7
+ # NOTE: Array#pack's 'w' is a BER _compressed_ integer. We need
8
+ # uncompressed BER integers, so we're not using that. See also:
9
+ # http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/228864
10
10
  result = []
11
11
 
12
12
  n = self
@@ -36,23 +36,33 @@ module Net
36
36
  end
37
37
 
38
38
  #--
39
- # Called internally to BER-encode the length and content bytes of a Fixnum.
40
- # The caller will prepend the tag byte.
39
+ # Called internally to BER-encode the length and content bytes of a
40
+ # Fixnum. The caller will prepend the tag byte.
41
+ #
41
42
  MAX_SIZE = 0.size
42
43
  def to_ber_internal
44
+ # CAUTION: Bit twiddling ahead. You might want to shield your eyes
45
+ # or something.
46
+
47
+ # Looks for the first byte in the fixnum that is not all zeroes. It
48
+ # does this by masking one byte after another, checking the result
49
+ # for bits that are left on.
43
50
  size = MAX_SIZE
44
51
  while size>1
45
- break if (self & (0xff << (size-1)*8)) > 0
46
- size -= 1
52
+ break if (self & (0xff << (size-1)*8)) > 0
53
+ size -= 1
47
54
  end
48
-
55
+
56
+ # Store the size of the fixnum in the result
49
57
  result = [size]
50
58
 
59
+ # Appends bytes to result, starting with higher orders first.
60
+ # Extraction of bytes is done by right shifting the original fixnum
61
+ # by an amount and then masking that with 0xff.
51
62
  while size>0
52
- # right shift size-1 bytes, mask with 0xff
53
- result << ((self >> ((size-1)*8)) & 0xff)
54
-
55
- size -= 1
63
+ # right shift size-1 bytes, mask with 0xff
64
+ result << ((self >> ((size-1)*8)) & 0xff)
65
+ size -= 1
56
66
  end
57
67
 
58
68
  result.pack('C*')
@@ -27,60 +27,53 @@ module Net
27
27
  class LDAP
28
28
 
29
29
 
30
- # Objects of this class represent individual entries in an LDAP
31
- # directory. User code generally does not instantiate this class.
32
- # Net::LDAP#search provides objects of this class to user code,
33
- # either as block parameters or as return values.
30
+ # Objects of this class represent individual entries in an LDAP directory.
31
+ # User code generally does not instantiate this class. Net::LDAP#search
32
+ # provides objects of this class to user code, either as block parameters or
33
+ # as return values.
34
34
  #
35
- # In LDAP-land, an "entry" is a collection of attributes that are
36
- # uniquely and globally identified by a DN ("Distinguished Name").
37
- # Attributes are identified by short, descriptive words or phrases.
38
- # Although a directory is
35
+ # In LDAP-land, an "entry" is a collection of attributes that are uniquely
36
+ # and globally identified by a DN ("Distinguished Name"). Attributes are
37
+ # identified by short, descriptive words or phrases. Although a directory is
39
38
  # free to implement any attribute name, most of them follow rigorous
40
- # standards so that the range of commonly-encountered attribute
41
- # names is not large.
39
+ # standards so that the range of commonly-encountered attribute names is not
40
+ # large.
42
41
  #
43
- # An attribute name is case-insensitive. Most directories also
44
- # restrict the range of characters allowed in attribute names.
45
- # To simplify handling attribute names, Net::LDAP::Entry
46
- # internally converts them to a standard format. Therefore, the
47
- # methods which take attribute names can take Strings or Symbols,
48
- # and work correctly regardless of case or capitalization.
42
+ # An attribute name is case-insensitive. Most directories also restrict the
43
+ # range of characters allowed in attribute names. To simplify handling
44
+ # attribute names, Net::LDAP::Entry internally converts them to a standard
45
+ # format. Therefore, the methods which take attribute names can take Strings
46
+ # or Symbols, and work correctly regardless of case or capitalization.
49
47
  #
50
- # An attribute consists of zero or more data items called
51
- # <i>values.</i> An entry is the combination of a unique DN, a set of attribute
52
- # names, and a (possibly-empty) array of values for each attribute.
48
+ # An attribute consists of zero or more data items called <i>values.</i> An
49
+ # entry is the combination of a unique DN, a set of attribute names, and a
50
+ # (possibly-empty) array of values for each attribute.
53
51
  #
54
- # Class Net::LDAP::Entry provides convenience methods for dealing
55
- # with LDAP entries.
56
- # In addition to the methods documented below, you may access individual
57
- # attributes of an entry simply by giving the attribute name as
52
+ # Class Net::LDAP::Entry provides convenience methods for dealing with LDAP
53
+ # entries. In addition to the methods documented below, you may access
54
+ # individual attributes of an entry simply by giving the attribute name as
58
55
  # the name of a method call. For example:
59
- # ldap.search( ... ) do |entry|
60
- # puts "Common name: #{entry.cn}"
61
- # puts "Email addresses:"
62
- # entry.mail.each {|ma| puts ma}
63
- # end
64
- # If you use this technique to access an attribute that is not present
65
- # in a particular Entry object, a NoMethodError exception will be raised.
56
+ #
57
+ # ldap.search( ... ) do |entry|
58
+ # puts "Common name: #{entry.cn}"
59
+ # puts "Email addresses:"
60
+ # entry.mail.each {|ma| puts ma}
61
+ # end
62
+ #
63
+ # If you use this technique to access an attribute that is not present in a
64
+ # particular Entry object, a NoMethodError exception will be raised.
66
65
  #
67
66
  #--
68
- # Ugly problem to fix someday: We key off the internal hash with
69
- # a canonical form of the attribute name: convert to a string,
70
- # downcase, then take the symbol. Unfortunately we do this in
71
- # at least three places. Should do it in ONE place.
67
+ # Ugly problem to fix someday: We key off the internal hash with a canonical
68
+ # form of the attribute name: convert to a string, downcase, then take the
69
+ # symbol. Unfortunately we do this in at least three places. Should do it in
70
+ # ONE place.
71
+ #
72
72
  class Entry
73
-
74
-
75
73
  # This constructor is not generally called by user code.
76
- #--
77
- # Originally, myhash took a block so we wouldn't have to
78
- # make sure its elements returned empty arrays when necessary.
79
- # Got rid of that to enable marshalling of Entry objects,
80
- # but that doesn't work anyway, because Entry objects have
81
- # singleton methods. So we define a custom dump and load.
74
+ #
82
75
  def initialize dn = nil # :nodoc:
83
- @myhash = {} # originally: Hash.new {|k,v| k[v] = [] }
76
+ @myhash = {}
84
77
  @myhash[:dn] = [dn]
85
78
  end
86
79
 
@@ -97,20 +90,18 @@ class LDAP
97
90
  #--
98
91
  # Discovered bug, 26Aug06: I noticed that we're not converting the
99
92
  # incoming value to an array if it isn't already one.
100
- def []= name, value # :nodoc:
101
- sym = name.to_s.downcase.intern
93
+ def []=(name, value) # :nodoc:
94
+ sym = attribute_name(name)
102
95
  value = [value] unless value.is_a?(Array)
103
96
  @myhash[sym] = value
104
97
  end
105
98
 
106
-
107
99
  #--
108
- # We have to deal with this one as we do with []=
109
- # because this one and not the other one gets called
110
- # in formulations like entry["CN"] << cn.
100
+ # We have to deal with this one as we do with []= because this one and not
101
+ # the other one gets called in formulations like entry["CN"] << cn.
111
102
  #
112
- def [] name # :nodoc:
113
- name = name.to_s.downcase.intern unless name.is_a?(Symbol)
103
+ def [](name) # :nodoc:
104
+ name = attribute_name(name) unless name.is_a?(Symbol)
114
105
  @myhash[name] || []
115
106
  end
116
107
 
@@ -141,8 +132,6 @@ class LDAP
141
132
 
142
133
  alias_method :each_attribute, :each
143
134
 
144
-
145
-
146
135
  # Converts the Entry to a String, representing the
147
136
  # Entry's attributes in LDIF format.
148
137
  #--
@@ -168,24 +157,15 @@ class LDAP
168
157
 
169
158
  #--
170
159
  # TODO, doesn't support broken lines.
171
- # It generates a SINGLE Entry object from an incoming LDIF stream
172
- # which is of course useless for big LDIF streams that encode
173
- # many objects.
160
+ # It generates a SINGLE Entry object from an incoming LDIF stream which is
161
+ # of course useless for big LDIF streams that encode many objects.
162
+ #
174
163
  # DO NOT DOCUMENT THIS METHOD UNTIL THESE RESTRICTIONS ARE LIFTED.
175
- # As it is, it's useful for unmarshalling objects that we create,
176
- # but not for reading arbitrary LDIF files.
177
- # Eventually, we should have a class method that parses large LDIF
178
- # streams into individual LDIF blocks (delimited by blank lines)
179
- # and passes them here.
180
164
  #
181
- # There is one oddity, noticed by Matthias Tarasiewicz: as originally
182
- # written, this code would return an Entry object in which the DN
183
- # attribute consisted of a two-element array, and the first element was
184
- # nil. That's because Entry#initialize doesn't like to create an object
185
- # without a DN attribute so it adds one: nil. The workaround here is
186
- # to wipe out the nil DN after creating the Entry object, and trust the
187
- # LDIF string to fill it in. If it doesn't we return a nil at the end.
188
- # (30Sep06, FCianfrocca)
165
+ # As it is, it's useful for unmarshalling objects that we create, but not
166
+ # for reading arbitrary LDIF files. Eventually, we should have a class
167
+ # method that parses large LDIF streams into individual LDIF blocks
168
+ # (delimited by blank lines) and passes them here.
189
169
  #
190
170
  class << self
191
171
  def from_single_ldif_string ldif
@@ -204,35 +184,42 @@ class LDAP
204
184
  entry.dn ? entry : nil
205
185
  end
206
186
  end
187
+
188
+ #--
189
+ # Part of the support for getter and setter style access to attributes.
190
+ #
191
+ def respond_to?(sym)
192
+ name = attribute_name(sym)
193
+ return true if valid_attribute?(name)
194
+ return super
195
+ end
207
196
 
208
197
  #--
209
- # Convenience method to convert unknown method names
210
- # to attribute references. Of course the method name
211
- # comes to us as a symbol, so let's save a little time
212
- # and not bother with the to_s.downcase two-step.
213
- # Of course that means that a method name like mAIL
214
- # won't work, but we shouldn't be encouraging that
215
- # kind of bad behavior in the first place.
216
- # Maybe we should thow something if the caller sends
217
- # arguments or a block...
198
+ # Supports getter and setter style access for all the attributes that this
199
+ # entry holds.
218
200
  #
219
- def method_missing *args, &block # :nodoc:
220
- s = args[0].to_s.downcase.intern
221
- if attribute_names.include?(s)
222
- self[s]
223
- elsif s.to_s[-1] == 61 and s.to_s.length > 1
224
- value = args[1] or raise RuntimeError.new( "unable to set value" )
225
- value = [value] unless value.is_a?(Array)
226
- name = s.to_s[0..-2].intern
227
- self[name] = value
228
- else
229
- raise NoMethodError.new( "undefined method '#{s}'" )
201
+ def method_missing sym, *args, &block # :nodoc:
202
+ name = attribute_name(sym)
203
+
204
+ if valid_attribute? name
205
+ if setter?(sym) && args.size == 1
206
+ value = args.first
207
+ value = [value] unless value.instance_of?(Array)
208
+ self[name]= value
209
+
210
+ return value
211
+ elsif args.empty?
212
+ return self[name]
213
+ end
230
214
  end
215
+
216
+ super
231
217
  end
232
218
 
233
219
  def write
234
220
  end
235
221
 
222
+ private
236
223
 
237
224
  #--
238
225
  # Internal convenience method. It seems like the standard
@@ -251,8 +238,27 @@ class LDAP
251
238
  end
252
239
  false
253
240
  end
254
- private :is_attribute_value_binary?
255
-
241
+
242
+ # Returns the symbol that can be used to access the attribute that
243
+ # sym_or_str designates.
244
+ #
245
+ def attribute_name(sym_or_str)
246
+ str = sym_or_str.to_s.downcase
247
+
248
+ # Does str match 'something='? Still only returns :something
249
+ return str[0...-1].to_sym if str.size>1 && str[-1] == ?=
250
+ return str.to_sym
251
+ end
252
+
253
+ # Given a valid attribute symbol, returns true.
254
+ #
255
+ def valid_attribute?(attr_name)
256
+ attribute_names.include?(attr_name)
257
+ end
258
+
259
+ def setter?(sym)
260
+ sym.to_s[-1] == ?=
261
+ end
256
262
  end # class Entry
257
263
 
258
264
 
@@ -1,8 +1,5 @@
1
1
  require 'spec_helper'
2
2
 
3
- require 'socket'
4
- require 'openssl'
5
-
6
3
  require 'net/ldap'
7
4
 
8
5
  describe "BER serialisation (SSL)" do
@@ -1,3 +1,5 @@
1
+ require 'net/ldap'
2
+
1
3
  Spec::Runner.configure do |config|
2
4
  config.mock_with :flexmock
3
5
  end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 1
8
- - 0
9
- version: 0.1.0
8
+ - 1
9
+ version: 0.1.1
10
10
  platform: ruby
11
11
  authors:
12
12
  - Francis Cianfrocca
@@ -18,7 +18,7 @@ autorequire:
18
18
  bindir: bin
19
19
  cert_chain: []
20
20
 
21
- date: 2010-03-17 00:00:00 -04:00
21
+ date: 2010-03-18 00:00:00 -04:00
22
22
  default_executable:
23
23
  dependencies:
24
24
  - !ruby/object:Gem::Dependency