net-ldap 0.1.0 → 0.1.1

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.

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