ruby-activeldap 0.4.1 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
data/lib/activeldap.rb CHANGED
@@ -9,7 +9,7 @@
9
9
  # Ruby/ActiveLDAP is a novel way of interacting with LDAP. Most interaction with
10
10
  # LDAP is done using clunky LDIFs, web interfaces, or with painful APIs that
11
11
  # required a thick reference manual nearby. Ruby/ActiveLDAP aims to fix that.
12
- # Inspired by ActiveRecord[http://activerecord.rubyonrails.com], Ruby/ActiveLDAP provides an
12
+ # Inspired by ActiveRecord[http://activerecord.rubyonrails.org], Ruby/ActiveLDAP provides an
13
13
  # object oriented interface to LDAP entries.
14
14
  #
15
15
  # The target audience is system administrators and LDAP users everywhere that
@@ -27,8 +27,8 @@
27
27
  # against Microsoft's ActiveDirectory, despite what the name implies.)
28
28
  #
29
29
  # Further reading:
30
- # * RFC1777[http://www.faqs.com/rfcs/rfc1777.html] - Lightweight Directory Access Protocol
31
- # * OpenLDAP[http://www.openldap.com]
30
+ # * RFC1777[http://www.faqs.org/rfcs/rfc1777.html] - Lightweight Directory Access Protocol
31
+ # * OpenLDAP[http://www.openldap.org]
32
32
  #
33
33
  # === So why use Ruby/ActiveLDAP?
34
34
  #
@@ -51,18 +51,18 @@
51
51
  #
52
52
  # === Requirements
53
53
  #
54
- # * Ruby[http://www.ruby-lang.com] 1.8.x
55
- # * Ruby/LDAP[http://ruby-ldap.sourcefcome.net]
56
- # * Log4r[http://log4r.sourcefcome.net]
57
- # * (Optional) Ruby/LDAP+GSSAPI[http://caliban.com/files/redhat/RPMS/i386/ruby-ldap-0.8.2-4.i386.rpm]
58
- # * An LDAP server compatible with Ruby/LDAP: OpenLDAP[http://www.openldap.com], etc
54
+ # * Ruby[http://www.ruby-lang.org] 1.8.x
55
+ # * Ruby/LDAP[http://ruby-ldap.sourceforge.net]
56
+ # * Log4r[http://log4r.sourceforge.net]
57
+ # * (Optional) Ruby/LDAP+GSSAPI[http://caliban.org/files/redhat/RPMS/i386/ruby-ldap-0.8.2-4.i386.rpm]
58
+ # * An LDAP server compatible with Ruby/LDAP: OpenLDAP[http://www.openldap.org], etc
59
59
  # - Your LDAP server must allow root_dse queries to allow for schema queries
60
- # * Examples also require: Ruby/Password[http://raa.ruby-lang.com/project/ruby-password/]
60
+ # * Examples also require: Ruby/Password[http://raa.ruby-lang.org/project/ruby-password/]
61
61
  #
62
62
  # === Installation
63
63
  #
64
64
  # Assuming all the requirements are installed, you can install by grabbing the latest tgz file from
65
- # the download site[http://projects.example.com/libraries/ruby/activeldap/download.html].
65
+ # the download site[http://projects.dataspill.org/libraries/ruby/activeldap/download.html].
66
66
  #
67
67
  # The following steps will get the Ruby/ActiveLDAP installed in no time!
68
68
  #
@@ -184,23 +184,23 @@
184
184
  # As you can see, this method is used for defining how this class maps in to LDAP. Let's say that
185
185
  # my LDAP tree looks something like this:
186
186
  #
187
- # * dc=example,dc=com
188
- # |- ou=People,dc=example,dc=com
189
- # |+ ou=Groups,dc=example,dc=com
187
+ # * dc=dataspill,dc=org
188
+ # |- ou=People,dc=dataspill,dc=org
189
+ # |+ ou=Groups,dc=dataspill,dc=org
190
190
  # \
191
- # |- cn=develop,ou=Groups,dc=example,dc=com
192
- # |- cn=root,ou=Groups,dc=example,dc=com
191
+ # |- cn=develop,ou=Groups,dc=dataspill,dc=org
192
+ # |- cn=root,ou=Groups,dc=dataspill,dc=org
193
193
  # |- ...
194
194
  #
195
195
  # Under ou=People I store user objects, and under ou=Groups, I store group
196
196
  # objects. What |ldap_mapping| has done is mapped the class in to the LDAP tree
197
197
  # abstractly. With the given :dnattr and :prefix, it will only work for entries
198
- # under ou=Groups,dc=example,dc=com using the primary attribute 'cn' as the
198
+ # under ou=Groups,dc=dataspill,dc=org using the primary attribute 'cn' as the
199
199
  # beginning of the distinguished name.
200
200
  #
201
201
  # Just for clarity, here's how the arguments map out:
202
202
  #
203
- # cn=develop,ou=Groups,dc=example,dc=com
203
+ # cn=develop,ou=Groups,dc=dataspill,dc=org
204
204
  # ^^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^
205
205
  # :dnattr | |
206
206
  # :prefix |
@@ -228,11 +228,11 @@
228
228
  # tying objects together across the LDAP tree. Often, user objects will be
229
229
  # members of, or belong_to, Group objects.
230
230
  #
231
- # * dc=example,dc=com
232
- # |+ ou=People,dc=example,dc=com
231
+ # * dc=dataspill,dc=org
232
+ # |+ ou=People,dc=dataspill,dc=org
233
233
  # \
234
- # |- uid=drewry,ou=People,dc=example,dc=com
235
- # |- ou=Groups,dc=example,dc=com
234
+ # |- uid=drewry,ou=People,dc=dataspill,dc=org
235
+ # |- ou=Groups,dc=dataspill,dc=org
236
236
  #
237
237
  #
238
238
  # In the above tree, one such example would be user 'drewry' who is a part of the
@@ -382,7 +382,7 @@
382
382
  #
383
383
  # irb> Base.search(:base => 'dc=example,dc=com', :filter => '(uid=roo*)',
384
384
  # :scope => LDAP::LDAP_SCOPE_SUBTREE, :attrs => ['uid', 'cn'])
385
- # => [{"dn"=>"uid=root,ou=People,dc=example,dc=com","cn"=>["root"], "uidNumber"=>["0"]}]
385
+ # => [{"dn"=>"uid=root,ou=People,dc=dataspill,dc=org","cn"=>["root"], "uidNumber"=>["0"]}]
386
386
  # You can specify the :filter, :base, :scope, and :attrs, but they all have defaults --
387
387
  # * :filter defaults to objectClass=* - usually this isn't what you want
388
388
  # * :base defaults to the base of the class this is executed from (as set in ldap_mapping)
@@ -438,10 +438,10 @@
438
438
  # won't need to call Base.connect. Here is a fully parameterized call:
439
439
  #
440
440
  # Base.connect(
441
- # :host => 'ldap.example.com',
441
+ # :host => 'ldap.dataspill.org',
442
442
  # :port => 389,
443
- # :base => 'dc=example,dc=com',
444
- # :bind_format => "uid=%s,ou=People,dc=example,dc=com",
443
+ # :base => 'dc=dataspill,dc=org',
444
+ # :bind_format => "uid=%s,ou=People,dc=dataspill,dc=org",
445
445
  # :logger => log4r_obj,
446
446
  # :user => 'drewry',
447
447
  # :password_block => Proc.new { 'password12345' },
@@ -880,7 +880,7 @@ require 'activeldap/configuration'
880
880
  require 'activeldap/schema2'
881
881
 
882
882
  module ActiveLDAP
883
- VERSION = "0.4.1"
883
+ VERSION = "0.4.2"
884
884
  end
885
885
 
886
886
  ActiveLDAP::Base.class_eval do
@@ -34,7 +34,7 @@ require 'ldap/schema'
34
34
  require 'log4r'
35
35
 
36
36
  module ActiveLDAP
37
- # OO-interface to LDAP assuming pam/nss_ldap-style comanization with Active specifics
37
+ # OO-interface to LDAP assuming pam/nss_ldap-style organization with Active specifics
38
38
  # Each subclass does a ldapsearch for the matching entry.
39
39
  # If no exact match, raise an error.
40
40
  # If match, change all LDAP attributes in accessor attributes on the object.
@@ -161,7 +161,7 @@ module ActiveLDAP
161
161
  # +config+ must be a hash that may contain any of the following fields:
162
162
  # :user, :password_block, :logger, :host, :port, :base, :bind_format, :try_sasl, :allow_anonymous
163
163
  # :user specifies the username to bind with.
164
- # :bind_format specifies the string to substitute the username into on bind. e.g. uid=%s,ou=People,dc=example,dc=com. Overrides @@bind_format.
164
+ # :bind_format specifies the string to substitute the username into on bind. e.g. uid=%s,ou=People,dc=dataspill,dc=org. Overrides @@bind_format.
165
165
  # :password_block specifies a Proc object that will yield a String to be used as the password when called.
166
166
  # :logger specifies a preconfigured Log4r::Logger to be used for all logging
167
167
  # :host overrides the configuration.rb @@host setting with the LDAP server hostname
@@ -466,6 +466,7 @@ module ActiveLDAP
466
466
  # If multiple values exist for dnattr, the first one put here will be authoritative
467
467
  # TODO: Add support for relative distinguished names
468
468
  def initialize(val='')
469
+ @@logger.debug("stub: initialize(#{val.inspect}) called")
469
470
  if val.class != String
470
471
  raise TypeError, "Object key must be a String"
471
472
  end
@@ -510,9 +511,12 @@ module ActiveLDAP
510
511
  # Save DN
511
512
  @dn = m.dn
512
513
  # Load up data into tmp
514
+ @@logger.debug("loading entry: #{@dn}")
513
515
  m.attrs.each do |attr|
514
516
  # Load with subtypes just like @data
517
+ @@logger.debug("calling make_subtypes for m.vals(attr).dup")
515
518
  safe_attr, value = make_subtypes(attr, m.vals(attr).dup)
519
+ @@logger.debug("finished make_subtypes for #{attr}")
516
520
  @ldap_data[safe_attr] = value
517
521
  end
518
522
  end
@@ -546,6 +550,7 @@ module ActiveLDAP
546
550
  # Return attribute methods so that a program can determine available
547
551
  # attributes dynamically without schema awareness
548
552
  def attributes
553
+ @@logger.debug("stub: attributes called")
549
554
  return @attr_methods.keys
550
555
  end
551
556
 
@@ -557,6 +562,7 @@ module ActiveLDAP
557
562
  # removing defined attributes that are no longer valid
558
563
  # given the new objectclasses.
559
564
  def objectClass=(val)
565
+ @@logger.debug("stub: objectClass=(#{val.inspect}) called")
560
566
  if val.class != Array
561
567
  raise TypeError, 'objectClass must be an Array'
562
568
  end
@@ -622,6 +628,7 @@ module ActiveLDAP
622
628
  #
623
629
  # Return whether the entry exists in LDAP or not
624
630
  def exists?
631
+ @@logger.debug("stub: exists? called")
625
632
  return @exists
626
633
  end
627
634
 
@@ -629,6 +636,7 @@ module ActiveLDAP
629
636
  #
630
637
  # Return the authoritative dn
631
638
  def dn
639
+ @@logger.debug("stub: dn called")
632
640
  return @dn.dup
633
641
  end
634
642
 
@@ -638,6 +646,7 @@ module ActiveLDAP
638
646
  # - Verify that every 'MUST' specified in the schema has a value defined
639
647
  # - Enforcement of undefined attributes is handled in the objectClass= method
640
648
  def validate
649
+ @@logger.debug("stub: validate called")
641
650
  @must.each do |oc|
642
651
  oc[1].each do |req_attr|
643
652
  # TODO: should I ever check if key exists? bug if it doesnt...
@@ -648,6 +657,7 @@ module ActiveLDAP
648
657
  end
649
658
  end
650
659
  end
660
+ @@logger.debug("stub: validate finished")
651
661
  end
652
662
 
653
663
 
@@ -655,6 +665,7 @@ module ActiveLDAP
655
665
  #
656
666
  # Delete this entry from LDAP
657
667
  def delete
668
+ @@logger.debug("stub: delete called")
658
669
  begin
659
670
  @@conn.delete(@dn)
660
671
  @exists = false
@@ -671,6 +682,7 @@ module ActiveLDAP
671
682
  # TODO: Binary data support
672
683
  # TODO: Relative DN support
673
684
  def write
685
+ @@logger.debug("stub: write called")
674
686
  # Validate against the objectClass requirements
675
687
  validate
676
688
 
@@ -686,7 +698,10 @@ module ActiveLDAP
686
698
  # Expand subtypes to real ldap_data entries
687
699
  # We can't reuse @ldap_data because an exception would leave
688
700
  # an object in an unknown state
701
+ @@logger.debug("#write: dup'ing @ldap_data")
689
702
  ldap_data = @ldap_data.dup
703
+ @@logger.debug("#write: dup finished @ldap_data")
704
+ @@logger.debug("#write: expanding subtypes in @ldap_data")
690
705
  ldap_data.keys.each do |key|
691
706
  ldap_data[key].each do |value|
692
707
  if value.class == Hash
@@ -700,9 +715,13 @@ module ActiveLDAP
700
715
  end
701
716
  end
702
717
  end
718
+ @@logger.debug("#write: subtypes expanded for @ldap_data")
703
719
 
704
720
  # Expand subtypes to real data entries, but leave @data alone
721
+ @@logger.debug("#write: dup'ing @data")
705
722
  data = @data.dup
723
+ @@logger.debug("#write: finished dup'ing @data")
724
+ @@logger.debug("#write: expanding subtypes for @data")
706
725
  data.keys.each do |key|
707
726
  data[key].each do |value|
708
727
  if value.class == Hash
@@ -716,10 +735,12 @@ module ActiveLDAP
716
735
  end
717
736
  end
718
737
  end
738
+ @@logger.debug("#write: subtypes expanded for @data")
719
739
 
720
740
  # Now that all the subtypes will be treated as unique attributes
721
741
  # we can see what's changed and add anything that is brand-spankin'
722
742
  # new.
743
+ @@logger.debug("#write: traversing ldap_data determining replaces and deletes")
723
744
  ldap_data.each do |pair|
724
745
  suffix = ''
725
746
  binary = 0
@@ -749,6 +770,8 @@ module ActiveLDAP
749
770
  end
750
771
  end
751
772
  end
773
+ @@logger.debug("#write: finished traversing ldap_data")
774
+ @@logger.debug("#write: traversing data determining adds")
752
775
  data.each do |pair|
753
776
  suffix = ''
754
777
  binary = 0
@@ -766,14 +789,20 @@ module ActiveLDAP
766
789
  entry.push(LDAP.mod(LDAP::LDAP_MOD_ADD|binary, name + suffix, value)) unless value.empty?
767
790
  end
768
791
  end
792
+ @@logger.debug("#write: traversing data complete")
769
793
  begin
794
+ @@logger.debug("#write: modifying #{@dn}")
770
795
  @@conn.modify(@dn, entry)
796
+ @@logger.debug("#write: modify successful")
771
797
  rescue => detail
772
798
  raise WriteError, "Could not update LDAP entry: #{detail}"
773
799
  end
774
800
  else # add everything!
801
+ @@logger.debug("#write: adding all attribute value pairs")
802
+ @@logger.debug("#write: adding #{@attr_methods[dnattr()].inspect} = #{data[@attr_methods[dnattr()]].inspect}")
775
803
  entry.push(LDAP.mod(LDAP::LDAP_MOD_ADD, @attr_methods[dnattr()],
776
804
  data[@attr_methods[dnattr()]]))
805
+ @@logger.debug("#write: adding objectClass = #{data[@attr_methods['objectClass']].inspect}")
777
806
  entry.push(LDAP.mod(LDAP::LDAP_MOD_ADD, 'objectClass',
778
807
  data[@attr_methods['objectClass']]))
779
808
  @data.each do |pair|
@@ -785,13 +814,18 @@ module ActiveLDAP
785
814
  end
786
815
  end
787
816
  begin
817
+ @@logger.debug("#write: adding #{@dn}")
788
818
  @@conn.add(@dn, entry)
819
+ @@logger.debug("#write: add successful")
789
820
  @exists = true
790
821
  rescue LDAP::ResultError => detail
791
822
  raise WriteError, "Could not add LDAP entry: #{detail}"
792
823
  end
793
824
  end
825
+ @@logger.debug("#write: resetting @ldap_data to a dup of @data")
794
826
  @ldap_data = @data.dup
827
+ @@logger.debug("#write: @ldap_data reset complete")
828
+ @@logger.debug("stub: write exitted")
795
829
  end
796
830
 
797
831
 
@@ -803,6 +837,7 @@ module ActiveLDAP
803
837
  # using class_eval instead of using method_missing. This would
804
838
  # give tab completion in irb.
805
839
  def method_missing(name, *args)
840
+ @@logger.debug("stub: called method_missing(#{name.inspect}, #{args.inspect})")
806
841
  key = name.to_s
807
842
  case key
808
843
  when /^(\S+)=$/
@@ -827,6 +862,7 @@ module ActiveLDAP
827
862
  # Hashes are for subtypes
828
863
  # Arrays are for multiple entries
829
864
  def attribute_input_handler(attr, value)
865
+ @@logger.debug("stub: called attribute_input_handler(#{attr.inspect}, #{value.inspect})")
830
866
  if attr.nil?
831
867
  raise RuntimeError, 'attr argument must not be nil.'
832
868
  end
@@ -871,6 +907,7 @@ module ActiveLDAP
871
907
  # e.g. userCertificate;binary => "some_bin"
872
908
  # becomes userCertificate => {"binary" => "some_bin"}
873
909
  def make_subtypes(attr, value)
910
+ @@logger.debug("stub: called make_subtypes(#{attr.inspect}, #{value.inspect})")
874
911
  return [attr, value] unless attr.match(/;/)
875
912
 
876
913
  ret_attr, *subtypes = attr.split(/;/)
@@ -882,6 +919,7 @@ module ActiveLDAP
882
919
  # This is a recursive function for building
883
920
  # nested hashed from multi-subtyped values
884
921
  def make_subtypes_helper(subtypes, value)
922
+ @@logger.debug("stub: called make_subtypes_helper(#{subtypes.inspect}, #{value.inspect})")
885
923
  return value if subtypes.size == 0
886
924
  return {subtypes[0] => make_subtypes_helper(subtypes[1..-1], value)}
887
925
  end
@@ -891,6 +929,7 @@ module ActiveLDAP
891
929
  # Extracts all of the subtypes from a given set of nested hashes
892
930
  # and returns the attribute suffix and the final true value
893
931
  def extract_subtypes(value)
932
+ @@logger.debug("stub: called extract_subtypes(#{value.inspect})")
894
933
  subtype = ''
895
934
  ret_val = value
896
935
  if value.class == Hash
@@ -969,7 +1008,7 @@ module ActiveLDAP
969
1008
  mechanisms = @@conn.root_dse[0]['supportedSASLMechanisms']
970
1009
  # Use GSSAPI if available
971
1010
  # Currently only GSSAPI is supported with Ruby/LDAP from
972
- # http://caliban.com/files/redhat/RPMS/i386/ruby-ldap-0.8.2-4.i386.rpm
1011
+ # http://caliban.org/files/redhat/RPMS/i386/ruby-ldap-0.8.2-4.i386.rpm
973
1012
  # TODO: Investigate further SASL support
974
1013
  if mechanisms.respond_to? :member? and mechanisms.member? 'GSSAPI'
975
1014
  begin
@@ -989,6 +1028,7 @@ module ActiveLDAP
989
1028
  # Returns the value of self.class.base
990
1029
  # This is just syntactic sugar
991
1030
  def base
1031
+ @@logger.debug("stub: called base")
992
1032
  self.class.base
993
1033
  end
994
1034
 
@@ -997,6 +1037,7 @@ module ActiveLDAP
997
1037
  # Returns the value of self.class.required_classes
998
1038
  # This is just syntactic sugar
999
1039
  def required_classes
1040
+ @@logger.debug("stub: called required_classes")
1000
1041
  self.class.required_classes
1001
1042
  end
1002
1043
 
@@ -1005,6 +1046,7 @@ module ActiveLDAP
1005
1046
  # Returns the value of self.class.dnattr
1006
1047
  # This is just syntactic sugar
1007
1048
  def dnattr
1049
+ @@logger.debug("stub: called dnattr")
1008
1050
  self.class.dnattr
1009
1051
  end
1010
1052
 
@@ -1012,6 +1054,7 @@ module ActiveLDAP
1012
1054
  #
1013
1055
  # Return the value of the attribute called by method_missing?
1014
1056
  def attribute_method(method, arrays = false)
1057
+ @@logger.debug("stub: called attribute_method(#{method.inspect}, #{arrays.inspect}")
1015
1058
  attr = @attr_methods[method]
1016
1059
 
1017
1060
  # Return a copy of the stored data
@@ -1024,6 +1067,7 @@ module ActiveLDAP
1024
1067
  #
1025
1068
  # Set the value of the attribute called by method_missing?
1026
1069
  def attribute_method=(method, arg)
1070
+ @@logger.debug("stub: called attribute_method=(#{method.inspect}, #{arg.inspect}")
1027
1071
  # Copy input
1028
1072
  begin
1029
1073
  value = arg.dup
@@ -1039,6 +1083,7 @@ module ActiveLDAP
1039
1083
  @data[attr] = value
1040
1084
 
1041
1085
  # Return a copy of what got saved
1086
+ @@logger.debug("stub: exitting attribute_method=")
1042
1087
  return @data[attr].dup
1043
1088
  end
1044
1089
 
@@ -1048,6 +1093,7 @@ module ActiveLDAP
1048
1093
  # Make a method entry for _every_ alias of a valid attribute and map it
1049
1094
  # onto the first attribute passed in.
1050
1095
  def define_attribute_methods(attr)
1096
+ @@logger.debug("stub: called define_attribute_methods(#{attr.inspect})")
1051
1097
  if @attr_methods.has_key? attr
1052
1098
  return
1053
1099
  end
@@ -1062,6 +1108,7 @@ module ActiveLDAP
1062
1108
  # Returns the array form of a value, or not an array if
1063
1109
  # false is passed in.
1064
1110
  def array_of(value, to_a = true)
1111
+ @@logger.debug("stub: called array_of(#{value.inspect}, #{to_a.inspect})")
1065
1112
  if to_a
1066
1113
  case value.class.to_s
1067
1114
  when 'Array'
@@ -8,11 +8,11 @@ module ActiveLDAP
8
8
  module Configuration
9
9
  @@host = "localhost"
10
10
  @@port = 389
11
- @@bind_format = "uid=%s,ou=People,dc=example,dc=com"
11
+ @@bind_format = "uid=%s,ou=People,dc=dataspill,dc=org"
12
12
 
13
13
  # Make the return value the string that is your LDAP base
14
14
  def Base.base
15
- 'dc=example,dc=com'
15
+ 'dc=dataspill,dc=org'
16
16
  end
17
17
 
18
18
  # This is optionally set to the array of objectClass names
@@ -3,6 +3,7 @@ require 'ldap/schema'
3
3
 
4
4
  module LDAP
5
5
  class Schema2 < Schema
6
+ @@cache = {}
6
7
 
7
8
  # attr
8
9
  #
@@ -16,13 +17,29 @@ module LDAP
16
17
  return '' if type.empty?
17
18
  return '' if at.empty?
18
19
 
20
+ # Check already parsed options first
21
+ if @@cache.has_key? sub \
22
+ and @@cache[sub].has_key? type \
23
+ and @@cache[sub][type].has_key? at
24
+ return @@cache[sub][type][at].dup
25
+ end
26
+
27
+ # Initialize anything that is required
28
+ unless @@cache.has_key? sub
29
+ @@cache[sub] = {}
30
+ end
31
+
32
+ unless @@cache[sub].has_key? type
33
+ @@cache[sub][type] = {}
34
+ end
35
+
19
36
  at = at.upcase
20
37
  self[sub].each do |s|
21
38
  line = ''
22
39
  if type[0..0] =~ /[0-9]/
23
- line = s if s =~ /\(\s+#{type}\s+([A-Z]|\))/
40
+ line = s if s =~ /\(\s+#{type}\s+(?:[A-Z]|\))/
24
41
  else
25
- line = s if s =~ /NAME\s+\(?.*'#{type}'.*\)?\s+([A-Z]|\))/
42
+ line = s if s =~ /NAME\s+\(?.*'#{type}'.*\)?\s+(?:[A-Z]|\))/
26
43
  end
27
44
 
28
45
  # I need to check, but I think some of these matchs
@@ -30,25 +47,31 @@ module LDAP
30
47
  multi = ''
31
48
  case line
32
49
  when /#{at}\s+[\)A-Z]/
50
+ @@cache[sub][type][at] = ['TRUE']
33
51
  return ['TRUE']
34
52
  when /#{at}\s+'(.+?)'/
53
+ @@cache[sub][type][at] = [$1]
35
54
  return [$1]
36
55
  when /#{at}\s+\((.+?)\)/
37
56
  multi = $1
38
57
  when /#{at}\s+\(([\w\d\s\.]+)\)/
39
58
  multi = $1
40
59
  when /#{at}\s+([\w\d\.]+)/
60
+ @@cache[sub][type][at] = [$1]
41
61
  return [$1]
42
62
  end
43
63
  # Split up multiple matches
44
64
  # if oc then it is sep'd by $
45
65
  # if attr then bu spaces
46
66
  if multi.match(/\$/)
47
- return multi.split("$").collect{|attr| attr.strip}
67
+ @@cache[sub][type][at] = multi.split("$").collect{|attr| attr.strip}
68
+ return @@cache[sub][type][at].dup
48
69
  elsif not multi.empty?
49
- return multi.gsub(/'/, '').split(' ').collect{|attr| attr.strip}
70
+ @@cache[sub][type][at] = multi.gsub(/'/, '').split(' ').collect{|attr| attr.strip}
71
+ return @@cache[sub][type][at].dup
50
72
  end
51
73
  end
74
+ @@cache[sub][type][at] = []
52
75
  return []
53
76
  end
54
77
 
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.1
3
3
  specification_version: 1
4
4
  name: ruby-activeldap
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.4.1
7
- date: 2004-10-06
6
+ version: 0.4.2
7
+ date: 2004-10-07
8
8
  summary: Ruby/ActiveLDAP is a object-oriented API to LDAP
9
9
  require_paths:
10
10
  - lib