scashin133-net-ldap 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,208 @@
1
+ # LDAP Entry (search-result) support classes
2
+ #
3
+ #----------------------------------------------------------------------------
4
+ #
5
+ # Copyright (C) 2006 by Francis Cianfrocca. All Rights Reserved.
6
+ #
7
+ # Gmail: garbagecat10
8
+ #
9
+ # This program is free software; you can redistribute it and/or modify
10
+ # it under the terms of the GNU General Public License as published by
11
+ # the Free Software Foundation; either version 2 of the License, or
12
+ # (at your option) any later version.
13
+ #
14
+ # This program is distributed in the hope that it will be useful,
15
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
+ # GNU General Public License for more details.
18
+ #
19
+ # You should have received a copy of the GNU General Public License
20
+ # along with this program; if not, write to the Free Software
21
+ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22
+ #
23
+ #---------------------------------------------------------------------------
24
+
25
+ ##
26
+ # Objects of this class represent individual entries in an LDAP directory.
27
+ # User code generally does not instantiate this class. Net::LDAP#search
28
+ # provides objects of this class to user code, either as block parameters or
29
+ # as return values.
30
+ #
31
+ # In LDAP-land, an "entry" is a collection of attributes that are uniquely
32
+ # and globally identified by a DN ("Distinguished Name"). Attributes are
33
+ # identified by short, descriptive words or phrases. Although a directory is
34
+ # free to implement any attribute name, most of them follow rigorous
35
+ # standards so that the range of commonly-encountered attribute names is not
36
+ # large.
37
+ #
38
+ # An attribute name is case-insensitive. Most directories also restrict the
39
+ # range of characters allowed in attribute names. To simplify handling
40
+ # attribute names, Net::LDAP::Entry internally converts them to a standard
41
+ # format. Therefore, the methods which take attribute names can take Strings
42
+ # or Symbols, and work correctly regardless of case or capitalization.
43
+ #
44
+ # An attribute consists of zero or more data items called <i>values.</i> An
45
+ # entry is the combination of a unique DN, a set of attribute names, and a
46
+ # (possibly-empty) array of values for each attribute.
47
+ #
48
+ # Class Net::LDAP::Entry provides convenience methods for dealing with LDAP
49
+ # entries. In addition to the methods documented below, you may access
50
+ # individual attributes of an entry simply by giving the attribute name as
51
+ # the name of a method call. For example:
52
+ #
53
+ # ldap.search( ... ) do |entry|
54
+ # puts "Common name: #{entry.cn}"
55
+ # puts "Email addresses:"
56
+ # entry.mail.each {|ma| puts ma}
57
+ # end
58
+ #
59
+ # If you use this technique to access an attribute that is not present in a
60
+ # particular Entry object, a NoMethodError exception will be raised.
61
+ #
62
+ #--
63
+ # Ugly problem to fix someday: We key off the internal hash with a canonical
64
+ # form of the attribute name: convert to a string, downcase, then take the
65
+ # symbol. Unfortunately we do this in at least three places. Should do it in
66
+ # ONE place.
67
+ class Net::LDAP::Entry
68
+ ##
69
+ # This constructor is not generally called by user code.
70
+ def initialize(dn = nil) #:nodoc:
71
+ @myhash = {}
72
+ @myhash[:dn] = [dn]
73
+ end
74
+
75
+ ##
76
+ # Use the LDIF format for Marshal serialization.
77
+ def _dump(depth) #:nodoc:
78
+ to_ldif
79
+ end
80
+
81
+ ##
82
+ # Use the LDIF format for Marshal serialization.
83
+ def self._load(entry) #:nodoc:
84
+ from_single_ldif_string(entry)
85
+ end
86
+
87
+ class << self
88
+ ##
89
+ # Converts a single LDIF entry string into an Entry object. Useful for
90
+ # Marshal serialization. If a string with multiple LDIF entries is
91
+ # provided, an exception will be raised.
92
+ def from_single_ldif_string(ldif)
93
+ ds = Net::LDAP::Dataset.read_ldif(::StringIO.new(ldif))
94
+
95
+ return nil if ds.empty?
96
+
97
+ raise Net::LDAP::LdapError, "Too many LDIF entries" unless ds.size == 1
98
+
99
+ entry = ds.to_entries.first
100
+
101
+ return nil if entry.dn.nil?
102
+ entry
103
+ end
104
+
105
+ ##
106
+ # Canonicalizes an LDAP attribute name as a \Symbol. The name is
107
+ # lowercased and, if present, a trailing equals sign is removed.
108
+ def attribute_name(name)
109
+ name = name.to_s.downcase
110
+ name = name[0..-2] if name[-1] == ?=
111
+ name.to_sym
112
+ end
113
+ end
114
+
115
+ ##
116
+ # Sets or replaces the array of values for the provided attribute. The
117
+ # attribute name is canonicalized prior to assignment.
118
+ #
119
+ # When an attribute is set using this, that attribute is now made
120
+ # accessible through methods as well.
121
+ #
122
+ # entry = Net::LDAP::Entry.new("dc=com")
123
+ # entry.foo # => NoMethodError
124
+ # entry["foo"] = 12345 # => [12345]
125
+ # entry.foo # => [12345]
126
+ def []=(name, value)
127
+ @myhash[self.class.attribute_name(name)] = Kernel::Array(value)
128
+ end
129
+
130
+ ##
131
+ # Reads the array of values for the provided attribute. The attribute name
132
+ # is canonicalized prior to reading. Returns an empty array if the
133
+ # attribute does not exist.
134
+ def [](name)
135
+ name = self.class.attribute_name(name)
136
+ @myhash[name] || []
137
+ end
138
+
139
+ ##
140
+ # Returns the first distinguished name (dn) of the Entry as a \String.
141
+ def dn
142
+ self[:dn].first.to_s
143
+ end
144
+
145
+ ##
146
+ # Returns an array of the attribute names present in the Entry.
147
+ def attribute_names
148
+ @myhash.keys
149
+ end
150
+
151
+ ##
152
+ # Accesses each of the attributes present in the Entry.
153
+ #
154
+ # Calls a user-supplied block with each attribute in turn, passing two
155
+ # arguments to the block: a Symbol giving the name of the attribute, and a
156
+ # (possibly empty) \Array of data values.
157
+ def each # :yields: attribute-name, data-values-array
158
+ if block_given?
159
+ attribute_names.each {|a|
160
+ attr_name,values = a,self[a]
161
+ yield attr_name, values
162
+ }
163
+ end
164
+ end
165
+ alias_method :each_attribute, :each
166
+
167
+ ##
168
+ # Converts the Entry to an LDIF-formatted String
169
+ def to_ldif
170
+ Net::LDAP::Dataset.from_entry(self).to_ldif_string
171
+ end
172
+
173
+ def respond_to?(sym) #:nodoc:
174
+ return true if valid_attribute?(self.class.attribute_name(sym))
175
+ return super
176
+ end
177
+
178
+ def method_missing(sym, *args, &block) #:nodoc:
179
+ name = self.class.attribute_name(sym)
180
+
181
+ if valid_attribute?(name )
182
+ if setter?(sym) && args.size == 1
183
+ value = args.first
184
+ value = Array(value)
185
+ self[name]= value
186
+ return value
187
+ elsif args.empty?
188
+ return self[name]
189
+ end
190
+ end
191
+
192
+ super
193
+ end
194
+
195
+ # Given a valid attribute symbol, returns true.
196
+ def valid_attribute?(attr_name)
197
+ attribute_names.include?(attr_name)
198
+ end
199
+ private :valid_attribute?
200
+
201
+ # Returns true if the symbol ends with an equal sign.
202
+ def setter?(sym)
203
+ sym.to_s[-1] == ?=
204
+ end
205
+ private :setter?
206
+ end # class Entry
207
+
208
+ require 'net/ldap/dataset' unless defined? Net::LDAP::Dataset