ruby-activeldap 0.4.1 → 0.4.2

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.
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