activeldap 1.0.2 → 1.0.9

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.
Files changed (109) hide show
  1. data/CHANGES +32 -0
  2. data/README +8 -1
  3. data/data/locale/en/LC_MESSAGES/active-ldap.mo +0 -0
  4. data/data/locale/ja/LC_MESSAGES/active-ldap.mo +0 -0
  5. data/examples/al-admin/app/controllers/{application.rb → application_controller.rb} +3 -1
  6. data/examples/al-admin/app/views/account/sign_up.html.erb +6 -5
  7. data/examples/al-admin/config/boot.rb +1 -0
  8. data/examples/al-admin/config/environment.rb +4 -2
  9. data/examples/al-admin/config.ru +7 -0
  10. data/examples/al-admin/lib/ldap_test_helper.rb +38 -0
  11. data/examples/al-admin/lib/tasks/gettext.rake +3 -2
  12. data/examples/al-admin/lib/tasks/testing.rake +10 -0
  13. data/examples/al-admin/po/en/al-admin.po +4 -4
  14. data/examples/al-admin/po/ja/al-admin.po +4 -4
  15. data/examples/al-admin/po/nl/al-admin.po +3 -3
  16. data/examples/al-admin/public/dispatch.cgi +2 -2
  17. data/examples/al-admin/public/dispatch.fcgi +1 -1
  18. data/examples/al-admin/public/dispatch.rb +2 -2
  19. data/examples/al-admin/test/functional/account_controller_test.rb +2 -14
  20. data/examples/al-admin/test/functional/attributes_controller_test.rb +2 -12
  21. data/examples/al-admin/test/functional/directory_controller_test.rb +2 -12
  22. data/examples/al-admin/test/functional/object_classes_controller_test.rb +2 -12
  23. data/examples/al-admin/test/functional/syntaxes_controller_test.rb +2 -12
  24. data/examples/al-admin/test/functional/users_controller_test.rb +2 -12
  25. data/examples/al-admin/test/functional/welcome_controller_test.rb +2 -12
  26. data/examples/al-admin/test/integration/sign_up_test.rb +44 -0
  27. data/examples/al-admin/test/run-test.sh +1 -1
  28. data/examples/al-admin/test/test_helper.rb +25 -1
  29. data/examples/al-admin/test/unit/user_test.rb +1 -2
  30. data/examples/groupadd +2 -2
  31. data/examples/groupdel +2 -2
  32. data/examples/groupls +2 -2
  33. data/examples/groupmod +2 -2
  34. data/examples/lpasswd +2 -2
  35. data/examples/objects/group.rb +2 -2
  36. data/examples/objects/user.rb +1 -1
  37. data/examples/ouadd +2 -2
  38. data/examples/useradd +2 -2
  39. data/examples/useradd-binary +6 -3
  40. data/examples/userdel +2 -2
  41. data/examples/userls +2 -2
  42. data/examples/usermod +2 -2
  43. data/examples/usermod-binary-add +6 -3
  44. data/examples/usermod-binary-add-time +6 -3
  45. data/examples/usermod-binary-del +2 -2
  46. data/examples/usermod-lang-add +2 -2
  47. data/lib/active_ldap/adapter/base.rb +47 -23
  48. data/lib/active_ldap/adapter/jndi.rb +30 -28
  49. data/lib/active_ldap/adapter/jndi_connection.rb +6 -0
  50. data/lib/active_ldap/adapter/ldap.rb +25 -26
  51. data/lib/active_ldap/adapter/net_ldap.rb +28 -33
  52. data/lib/active_ldap/adapter/net_ldap_ext.rb +0 -6
  53. data/lib/active_ldap/association/proxy.rb +2 -1
  54. data/lib/active_ldap/attributes.rb +31 -0
  55. data/lib/active_ldap/base.rb +75 -31
  56. data/lib/active_ldap/compatible.rb +44 -0
  57. data/lib/active_ldap/configuration.rb +3 -3
  58. data/lib/active_ldap/connection.rb +41 -12
  59. data/lib/active_ldap/distinguished_name.rb +1 -0
  60. data/lib/active_ldap/get_text.rb +0 -7
  61. data/lib/active_ldap/ldif.rb +59 -44
  62. data/lib/active_ldap/operations.rb +41 -10
  63. data/lib/active_ldap/schema.rb +41 -6
  64. data/lib/active_ldap/user_password.rb +7 -7
  65. data/lib/active_ldap/validations.rb +24 -12
  66. data/lib/active_ldap/xml.rb +2 -2
  67. data/lib/active_ldap.rb +120 -139
  68. data/po/en/active-ldap.po +5 -5
  69. data/po/ja/active-ldap.po +5 -5
  70. data/rails/README +2 -2
  71. data/rails/init.rb +2 -2
  72. data/test/al-test-utils.rb +11 -4
  73. data/test/run-test.rb +6 -2
  74. data/test/test_associations.rb +4 -4
  75. data/test/test_attributes.rb +3 -1
  76. data/test/test_base.rb +75 -15
  77. data/test/test_base_per_instance.rb +7 -1
  78. data/test/test_bind.rb +4 -4
  79. data/test/test_connection.rb +36 -14
  80. data/test/test_connection_per_class.rb +5 -5
  81. data/test/test_connection_per_dn.rb +11 -5
  82. data/test/test_groupadd.rb +2 -2
  83. data/test/test_groupdel.rb +2 -2
  84. data/test/test_groupls.rb +1 -1
  85. data/test/test_groupmod.rb +2 -2
  86. data/test/test_ldif.rb +11 -1
  87. data/test/test_schema.rb +38 -2
  88. data/test/test_syntax.rb +12 -2
  89. data/test/test_useradd-binary.rb +1 -0
  90. data/test/test_usermod-binary-add-time.rb +1 -0
  91. data/test/test_usermod-binary-add.rb +1 -0
  92. data/test/test_validation.rb +24 -13
  93. data/test-unit/lib/test/unit/assertions.rb +97 -14
  94. data/test-unit/lib/test/unit/autorunner.rb +20 -4
  95. data/test-unit/lib/test/unit/priority.rb +21 -1
  96. data/test-unit/lib/test/unit/ui/console/testrunner.rb +7 -4
  97. data/test-unit/test/test_assertions.rb +52 -5
  98. metadata +10 -14
  99. data/rails/plugin/active_ldap/README +0 -54
  100. data/rails/plugin/active_ldap/generators/README +0 -2
  101. data/rails/plugin/active_ldap/generators/model_active_ldap/USAGE +0 -17
  102. data/rails/plugin/active_ldap/generators/model_active_ldap/model_active_ldap_generator.rb +0 -70
  103. data/rails/plugin/active_ldap/generators/model_active_ldap/templates/fixtures.yml +0 -11
  104. data/rails/plugin/active_ldap/generators/model_active_ldap/templates/model_active_ldap.rb +0 -3
  105. data/rails/plugin/active_ldap/generators/model_active_ldap/templates/unit_test.rb +0 -10
  106. data/rails/plugin/active_ldap/generators/scaffold_active_ldap/scaffold_active_ldap_generator.rb +0 -7
  107. data/rails/plugin/active_ldap/generators/scaffold_al/scaffold_al_generator.rb +0 -20
  108. data/rails/plugin/active_ldap/init.rb +0 -36
  109. data/rails_generators/scaffold_al/scaffold_al_generator.rb +0 -20
@@ -32,7 +32,10 @@ module ActiveLdap
32
32
 
33
33
  module_function
34
34
  def binary_value?(value)
35
- if /\A#{Parser::SAFE_STRING}\z/u =~ value
35
+ if value.respond_to?(:encoding)
36
+ return true if value.encoding == Encoding.find("ascii-8bit")
37
+ end
38
+ if /\A#{Parser::SAFE_STRING}\z/ =~ value
36
39
  false
37
40
  else
38
41
  true
@@ -45,7 +48,7 @@ module ActiveLdap
45
48
 
46
49
  if value[-1, 1] == ' ' or binary_value?(value)
47
50
  result << ":"
48
- value = [value].pack("m").gsub(/\n/u, '')
51
+ value = [value].pack("m").gsub(/\n/, '')
49
52
  end
50
53
  result << " "
51
54
 
@@ -61,7 +64,7 @@ module ActiveLdap
61
64
  result << "#{first_line_value}\n"
62
65
  return result if rest_value.nil?
63
66
 
64
- rest_value.scan(/.{1,#{SIZE - 1}}/u).each do |line|
67
+ rest_value.scan(/.{1,#{SIZE - 1}}/).each do |line| # FIXME
65
68
  result << " #{line}\n"
66
69
  end
67
70
  result
@@ -95,19 +98,19 @@ module ActiveLdap
95
98
  @source = source
96
99
  end
97
100
 
98
- ATTRIBUTE_TYPE_CHARS = /[a-zA-Z][a-zA-Z0-9\-]*/u
99
- SAFE_CHAR = /[\x01-\x09\x0B-\x0C\x0E-\x7F]/u
100
- SAFE_INIT_CHAR = /[\x01-\x09\x0B-\x0C\x0E-\x1F\x21-\x39\x3B\x3D-\x7F]/u
101
- SAFE_STRING = /#{SAFE_INIT_CHAR}#{SAFE_CHAR}*/u
102
- FILL = / */u
101
+ ATTRIBUTE_TYPE_CHARS = /[a-zA-Z][a-zA-Z0-9\-]*/
102
+ SAFE_CHAR = /[\x01-\x09\x0B-\x0C\x0E-\x7F]/
103
+ SAFE_INIT_CHAR = /[\x01-\x09\x0B-\x0C\x0E-\x1F\x21-\x39\x3B\x3D-\x7F]/
104
+ SAFE_STRING = /#{SAFE_INIT_CHAR}#{SAFE_CHAR}*/
105
+ FILL = / */
103
106
  def parse
104
107
  return @ldif if @ldif
105
108
 
106
109
  @scanner = Scanner.new(@source)
107
- raise version_spec_is_missing unless @scanner.scan(/version:/u)
110
+ raise version_spec_is_missing unless @scanner.scan(/version:/)
108
111
  @scanner.scan(FILL)
109
112
 
110
- version = @scanner.scan(/\d+/u)
113
+ version = @scanner.scan(/\d+/)
111
114
  raise version_number_is_missing if version.nil?
112
115
 
113
116
  version = Integer(version)
@@ -122,13 +125,19 @@ module ActiveLdap
122
125
 
123
126
  private
124
127
  def read_base64_value
125
- value = @scanner.scan(/[a-zA-Z0-9\+\/=]+/u)
128
+ value = @scanner.scan(/[a-zA-Z0-9\+\/=]+/)
126
129
  return nil if value.nil?
127
- value.unpack("m")[0].chomp
130
+ encoding = value.encoding if value.respond_to?(:encoding)
131
+ value = value.unpack("m")[0].chomp
132
+ if value.respond_to?(:force_encoding)
133
+ value.force_encoding(encoding)
134
+ value.force_encoding("ascii-8bit") unless value.valid_encoding?
135
+ end
136
+ value
128
137
  end
129
138
 
130
139
  def read_external_file
131
- uri_string = @scanner.scan(URI::REGEXP::ABS_URI)
140
+ uri_string = @scanner.scan(URI::ABS_URI)
132
141
  raise uri_is_missing if uri_string.nil?
133
142
  uri = nil
134
143
  begin
@@ -138,7 +147,7 @@ module ActiveLdap
138
147
  end
139
148
 
140
149
  if uri.scheme == "file"
141
- File.open(uri.path, "rb").read
150
+ File.open(uri.path, "rb") {|file| file.read}
142
151
  else
143
152
  uri.read
144
153
  end
@@ -196,7 +205,7 @@ module ActiveLdap
196
205
 
197
206
  def parse_options
198
207
  options = []
199
- while @scanner.scan(/;/u)
208
+ while @scanner.scan(/;/)
200
209
  option = @scanner.scan(ATTRIBUTE_TYPE_CHARS)
201
210
  raise option_is_missing if option.nil?
202
211
  options << option
@@ -205,11 +214,11 @@ module ActiveLdap
205
214
  end
206
215
 
207
216
  def parse_attribute_value(accept_external_file=true)
208
- raise attribute_value_separator_is_missing if @scanner.scan(/:/u).nil?
209
- if @scanner.scan(/:/u)
217
+ raise attribute_value_separator_is_missing if @scanner.scan(/:/).nil?
218
+ if @scanner.scan(/:/)
210
219
  @scanner.scan(FILL)
211
220
  read_base64_value
212
- elsif accept_external_file and @scanner.scan(/</u)
221
+ elsif accept_external_file and @scanner.scan(/</)
213
222
  @scanner.scan(FILL)
214
223
  read_external_file
215
224
  else
@@ -219,16 +228,16 @@ module ActiveLdap
219
228
  end
220
229
 
221
230
  def parse_control
222
- return nil if @scanner.scan(/control:/u).nil?
231
+ return nil if @scanner.scan(/control:/).nil?
223
232
  @scanner.scan(FILL)
224
- type = @scanner.scan(/\d+(?:\.\d+)*/u)
233
+ type = @scanner.scan(/\d+(?:\.\d+)*/)
225
234
  raise control_type_is_missing if type.nil?
226
235
  criticality = nil
227
- if @scanner.scan(/ +/u)
228
- criticality = @scanner.scan(/true|false/u)
236
+ if @scanner.scan(/ +/)
237
+ criticality = @scanner.scan(/true|false/)
229
238
  raise criticality_is_missing if criticality.nil?
230
239
  end
231
- value = parse_attribute_value if @scanner.check(/:/u)
240
+ value = parse_attribute_value if @scanner.check(/:/)
232
241
  raise separator_is_missing unless @scanner.scan_separator
233
242
  ChangeRecord::Control.new(type, criticality, value)
234
243
  end
@@ -244,11 +253,11 @@ module ActiveLdap
244
253
  end
245
254
 
246
255
  def parse_change_type
247
- return nil unless @scanner.scan(/changetype:/u)
256
+ return nil unless @scanner.scan(/changetype:/)
248
257
  @scanner.scan(FILL)
249
258
  type = @scanner.check(ATTRIBUTE_TYPE_CHARS)
250
259
  raise change_type_value_is_missing if type.nil?
251
- unless @scanner.scan(/add|delete|modrdn|moddn|modify/u)
260
+ unless @scanner.scan(/add|delete|modrdn|moddn|modify/)
252
261
  raise unknown_change_type(type)
253
262
  end
254
263
 
@@ -257,20 +266,20 @@ module ActiveLdap
257
266
  end
258
267
 
259
268
  def parse_modify_name_record(klass, dn, controls)
260
- raise new_rdn_mark_is_missing unless @scanner.scan(/newrdn\b/u)
269
+ raise new_rdn_mark_is_missing unless @scanner.scan(/newrdn\b/)
261
270
  new_rdn = parse_attribute_value(false)
262
271
  raise new_rdn_value_is_missing if new_rdn.nil?
263
272
  raise separator_is_missing unless @scanner.scan_separator
264
273
 
265
- unless @scanner.scan(/deleteoldrdn:/u)
274
+ unless @scanner.scan(/deleteoldrdn:/)
266
275
  raise delete_old_rdn_mark_is_missing
267
276
  end
268
277
  @scanner.scan(FILL)
269
- delete_old_rdn = @scanner.scan(/[01]/u)
278
+ delete_old_rdn = @scanner.scan(/[01]/)
270
279
  raise delete_old_rdn_value_is_missing if delete_old_rdn.nil?
271
280
  raise separator_is_missing unless @scanner.scan_separator
272
281
 
273
- if @scanner.scan(/newsuperior\b/u)
282
+ if @scanner.scan(/newsuperior\b/)
274
283
  @scanner.scan(FILL)
275
284
  new_superior = parse_attribute_value(false)
276
285
  raise new_superior_value_is_missing if new_superior.nil?
@@ -281,16 +290,16 @@ module ActiveLdap
281
290
  end
282
291
 
283
292
  def parse_modify_spec
284
- return nil unless @scanner.check(/(#{ATTRIBUTE_TYPE_CHARS}):/u)
293
+ return nil unless @scanner.check(/(#{ATTRIBUTE_TYPE_CHARS}):/)
285
294
  type = @scanner[1]
286
- unless @scanner.scan(/(?:add|delete|replace):/u)
295
+ unless @scanner.scan(/(?:add|delete|replace):/)
287
296
  raise unknown_modify_type(type)
288
297
  end
289
298
  @scanner.scan(FILL)
290
299
  attribute, options = parse_attribute_description
291
300
  raise separator_is_missing unless @scanner.scan_separator
292
- attributes = parse_attributes {@scanner.check(/-/u)}
293
- raise modify_spec_separator_is_missing unless @scanner.scan(/-/u)
301
+ attributes = parse_attributes {@scanner.check(/-/)}
302
+ raise modify_spec_separator_is_missing unless @scanner.scan(/-/)
294
303
  raise separator_is_missing unless @scanner.scan_separator
295
304
  [type, attribute, options, attributes]
296
305
  end
@@ -335,18 +344,18 @@ module ActiveLdap
335
344
  end
336
345
 
337
346
  def parse_record
338
- raise dn_mark_is_missing unless @scanner.scan(/dn:/u)
339
- if @scanner.scan(/:/u)
347
+ raise dn_mark_is_missing unless @scanner.scan(/dn:/)
348
+ if @scanner.scan(/:/)
340
349
  @scanner.scan(FILL)
341
350
  dn = read_base64_value
342
351
  raise dn_is_missing if dn.nil?
343
352
  dn = parse_dn(dn)
344
353
  else
345
354
  @scanner.scan(FILL)
346
- dn = @scanner.scan(/#{SAFE_STRING}$/u)
355
+ dn = @scanner.scan(/#{SAFE_STRING}$/)
347
356
  if dn.nil?
348
357
  partial_dn = @scanner.scan(SAFE_STRING)
349
- raise dn_has_invalid_character(@scanner.check(/./u)) if partial_dn
358
+ raise dn_has_invalid_character(@scanner.check(/./)) if partial_dn
350
359
  raise dn_is_missing
351
360
  end
352
361
  dn = parse_dn(dn)
@@ -485,8 +494,8 @@ module ActiveLdap
485
494
  end
486
495
 
487
496
  class Scanner
488
- SEPARATOR = /(?:\r\n|\n)/u
489
- SEPARATORS = /(?:(?:^#.*)?#{SEPARATOR})+/u
497
+ SEPARATOR = /(?:\r\n|\n)/
498
+ SEPARATORS = /(?:(?:^#.*)?#{SEPARATOR})+/
490
499
 
491
500
  def initialize(source)
492
501
  @source = source
@@ -543,7 +552,7 @@ module ActiveLdap
543
552
  _consumed_source = consumed_source
544
553
  return 1 if _consumed_source.empty?
545
554
 
546
- n = _consumed_source.to_a.size
555
+ n = Compatible.string_to_lines(_consumed_source).size
547
556
  n += 1 if _consumed_source[-1, 1] == "\n"
548
557
  n
549
558
  end
@@ -556,21 +565,27 @@ module ActiveLdap
556
565
  end
557
566
 
558
567
  def position
559
- @scanner.pos - (@sub_scanner.string.length - @sub_scanner.pos)
568
+ sub_scanner_string = @sub_scanner.string
569
+ if sub_scanner_string.respond_to?(:bytesize)
570
+ sub_scanner_string_size = sub_scanner_string.bytesize
571
+ else
572
+ sub_scanner_string_size = sub_scanner_string.size
573
+ end
574
+ @scanner.pos - (sub_scanner_string_size - @sub_scanner.pos)
560
575
  end
561
576
 
562
577
  private
563
578
  def next_segment
564
579
  loop do
565
- segment = @scanner.scan(/.+(?:#{SEPARATOR} .*)*#{SEPARATOR}?/u)
580
+ segment = @scanner.scan(/.+(?:#{SEPARATOR} .*)*#{SEPARATOR}?/)
566
581
  return @sub_scanner if segment.nil?
567
582
  next if segment[0, 1] == "#"
568
- return StringScanner.new(segment.gsub(/\r?\n /u, ''))
583
+ return StringScanner.new(segment.gsub(/\r?\n /, ''))
569
584
  end
570
585
  end
571
586
 
572
587
  def consumed_source
573
- @source[0, position]
588
+ @source[0, position]
574
589
  end
575
590
  end
576
591
 
@@ -62,18 +62,18 @@ module ActiveLdap
62
62
  }
63
63
 
64
64
  options[:connection] ||= connection
65
- options[:connection].search(search_options) do |dn, attrs|
65
+ values = options[:connection].search(search_options) do |dn, attrs|
66
66
  attributes = {}
67
- attrs.each do |key, value|
67
+ attrs.each do |key, _value|
68
68
  normalized_attr, normalized_value =
69
- normalize_attribute_options(key, value)
69
+ normalize_attribute_options(key, _value)
70
70
  attributes[normalized_attr] ||= []
71
71
  attributes[normalized_attr].concat(normalized_value)
72
72
  end
73
- value = [dn, attributes]
74
- value = yield(value) if block_given?
75
- value
73
+ [dn, attributes]
76
74
  end
75
+ values = values.collect {|_value| yield(_value)} if block_given?
76
+ values
77
77
  end
78
78
 
79
79
  def exist?(dn, options={})
@@ -196,14 +196,18 @@ module ActiveLdap
196
196
  #
197
197
  # Finds the first match for value where |value| is the value of some
198
198
  # |field|, or the wildcard match. This is only useful for derived classes.
199
- # usage: Subclass.find(:attribute => "cn", :value => "some*val")
200
- # Subclass.find('some*val')
199
+ # usage: Subclass.find(:all, :attribute => "cn", :value => "some*val")
200
+ # Subclass.find(:all, 'some*val')
201
201
  def find(*args)
202
202
  options = extract_options_from_args!(args)
203
203
  args = [:first] if args.empty? and !options.empty?
204
204
  case args.first
205
205
  when :first
206
+ options[:value] ||= args[1]
206
207
  find_initial(options)
208
+ when :last
209
+ options[:value] ||= args[1]
210
+ find_last(options)
207
211
  when :all
208
212
  options[:value] ||= args[1]
209
213
  find_every(options)
@@ -212,11 +216,38 @@ module ActiveLdap
212
216
  end
213
217
  end
214
218
 
219
+ # A convenience wrapper for <tt>find(:first,
220
+ # *args)</tt>. You can pass in all the same arguments
221
+ # to this method as you can to <tt>find(:first)</tt>.
222
+ def first(*args)
223
+ find(:first, *args)
224
+ end
225
+
226
+ # A convenience wrapper for <tt>find(:last,
227
+ # *args)</tt>. You can pass in all the same arguments
228
+ # to this method as you can to <tt>find(:last)</tt>.
229
+ def last(*args)
230
+ find(:last, *args)
231
+ end
232
+
233
+ # This is an alias for find(:all). You can pass in
234
+ # all the same arguments to this method as you can
235
+ # to find(:all)
236
+ def all(*args)
237
+ find(:all, *args)
238
+ end
239
+
215
240
  private
216
241
  def find_initial(options)
217
242
  find_every(options.merge(:limit => 1)).first
218
243
  end
219
244
 
245
+ def find_last(options)
246
+ order = options[:order] || self.order || 'ascend'
247
+ order = normalize_sort_order(order) == :ascend ? :descend : :ascend
248
+ find_initial(options.merge(:order => order))
249
+ end
250
+
220
251
  def normalize_sort_order(value)
221
252
  case value.to_s
222
253
  when /\Aasc(?:end)?\z/i
@@ -509,9 +540,9 @@ module ActiveLdap
509
540
  if dn.is_a?(Array)
510
541
  i = -1
511
542
  dns = dn
512
- dns.collect do |dn|
543
+ dns.collect do |_dn|
513
544
  i += 1
514
- update(dn, attributes[i], options)
545
+ update(_dn, attributes[i], options)
515
546
  end
516
547
  else
517
548
  object = find(dn, options)
@@ -1,7 +1,9 @@
1
1
  module ActiveLdap
2
2
  class Schema
3
+ include GetTextSupport
4
+
3
5
  def initialize(entries)
4
- @entries = default_entries.merge(entries || {})
6
+ @entries = normalize_entries(entries || {})
5
7
  @schema_info = {}
6
8
  @class_attributes_info = {}
7
9
  @cache = {}
@@ -123,6 +125,12 @@ module ActiveLdap
123
125
  end
124
126
  end
125
127
 
128
+ def dit_content_rule_attribute(name, attribute_name)
129
+ cache([:dit_content_rule_attribute, name, attribute_name]) do
130
+ fetch("dITContentRules", name, attribute_name)
131
+ end
132
+ end
133
+
126
134
  def ldap_syntax(name)
127
135
  cache([:ldap_syntax, name]) do
128
136
  Syntax.new(name, self)
@@ -143,6 +151,17 @@ module ActiveLdap
143
151
  end
144
152
  end
145
153
 
154
+ def dump(output=nil)
155
+ require 'pp'
156
+ output ||= STDOUT
157
+ if output.respond_to?(:write)
158
+ PP.pp(@entries, output)
159
+ else
160
+ open(output, "w") {|out| PP.pp(@entries, out)}
161
+ end
162
+ nil
163
+ end
164
+
146
165
  private
147
166
  def cache(key)
148
167
  (@cache[key] ||= [yield])[0]
@@ -242,9 +261,23 @@ module ActiveLdap
242
261
  "objectClasses" => [],
243
262
  "attributeTypes" => [],
244
263
  "ldapSyntaxes" => [],
264
+ "dITContentRules" => [],
265
+ "matchingRules" => [],
245
266
  }
246
267
  end
247
268
 
269
+ def normalize_entries(entries)
270
+ normalized_entries = default_entries
271
+ normalized_keys = normalized_entries.keys
272
+ entries.each do |name, values|
273
+ normalized_name = normalized_keys.find do |key|
274
+ key.downcase == name
275
+ end
276
+ normalized_entries[normalized_name || name] = values
277
+ end
278
+ normalized_entries
279
+ end
280
+
248
281
  class Entry
249
282
  include Comparable
250
283
 
@@ -260,11 +293,12 @@ module ActiveLdap
260
293
 
261
294
  def eql?(other)
262
295
  self.class == other.class and
263
- id == other.id
296
+ (id == other.id or
297
+ (id.nil? and other.nil? and name == other.name))
264
298
  end
265
299
 
266
300
  def hash
267
- id.hash
301
+ id.nil? ? name.hash : id.hash
268
302
  end
269
303
 
270
304
  def <=>(other)
@@ -615,9 +649,9 @@ module ActiveLdap
615
649
  def collect_attributes
616
650
  must = attribute('MUST').reject do |name|
617
651
  UNWRITABLE_MUST_ATTRIBUTES.include?(name)
618
- end
652
+ end.uniq
619
653
  must = must.collect {|name| @schema.attribute(name)}
620
- may = attribute('MAY').collect {|name| @schema.attribute(name)}
654
+ may = attribute('MAY').uniq.collect {|name| @schema.attribute(name)}
621
655
 
622
656
  all_must = must.dup
623
657
  all_may = may.dup
@@ -634,7 +668,8 @@ module ActiveLdap
634
668
  end
635
669
 
636
670
  def attribute(attribute_name, name=@name)
637
- @schema.object_class_attribute(name, attribute_name)
671
+ @schema.object_class_attribute(name, attribute_name) +
672
+ @schema.dit_content_rule_attribute(name, attribute_name)
638
673
  end
639
674
  end
640
675
  end
@@ -1,6 +1,6 @@
1
1
  require 'English'
2
- require 'md5'
3
- require 'sha1'
2
+ require 'digest/md5'
3
+ require 'digest/sha1'
4
4
 
5
5
  module ActiveLdap
6
6
  module UserPassword
@@ -43,7 +43,7 @@ module ActiveLdap
43
43
  end
44
44
 
45
45
  def md5(password)
46
- "{MD5}#{[MD5.md5(password).digest].pack('m').chomp}"
46
+ "{MD5}#{[Digest::MD5.digest(password)].pack('m').chomp}"
47
47
  end
48
48
 
49
49
  def smd5(password, salt=nil)
@@ -51,7 +51,7 @@ module ActiveLdap
51
51
  raise ArgumentError, _("salt size must be == 4: %s") % salt.inspect
52
52
  end
53
53
  salt ||= Salt.generate(4)
54
- md5_hash_with_salt = "#{MD5.md5(password + salt).digest}#{salt}"
54
+ md5_hash_with_salt = "#{Digest::MD5.digest(password + salt)}#{salt}"
55
55
  "{SMD5}#{[md5_hash_with_salt].pack('m').chomp}"
56
56
  end
57
57
 
@@ -60,7 +60,7 @@ module ActiveLdap
60
60
  end
61
61
 
62
62
  def sha(password)
63
- "{SHA}#{[SHA1.sha1(password).digest].pack('m').chomp}"
63
+ "{SHA}#{[Digest::SHA1.digest(password)].pack('m').chomp}"
64
64
  end
65
65
 
66
66
  def ssha(password, salt=nil)
@@ -68,7 +68,7 @@ module ActiveLdap
68
68
  raise ArgumentError, _("salt size must be == 4: %s") % salt.inspect
69
69
  end
70
70
  salt ||= Salt.generate(4)
71
- sha1_hash_with_salt = "#{SHA1.sha1(password + salt).digest}#{salt}"
71
+ sha1_hash_with_salt = "#{Digest::SHA1.digest(password + salt)}#{salt}"
72
72
  "{SSHA}#{[sha1_hash_with_salt].pack('m').chomp}"
73
73
  end
74
74
 
@@ -77,7 +77,7 @@ module ActiveLdap
77
77
  end
78
78
 
79
79
  module Salt
80
- CHARS = ['.', '/', '0'..'9', 'A'..'Z', 'a'..'z'].collect do |x|
80
+ CHARS = ['.', '/'] + ['0'..'9', 'A'..'Z', 'a'..'z'].collect do |x|
81
81
  x.to_a
82
82
  end.flatten
83
83
 
@@ -1,5 +1,3 @@
1
- require 'active_record/validations'
2
-
3
1
  module ActiveLdap
4
2
  module Validations
5
3
  def self.append_features(base)
@@ -84,7 +82,10 @@ module ActiveLdap
84
82
  return
85
83
  end
86
84
  if _dn and exist?
87
- format = _("is duplicated: %s")
85
+ format = _("%{fn} is duplicated: %s")
86
+ unless ActiveLdap.get_text_supported?
87
+ format = format.sub(/^%\{fn\} /, '')
88
+ end
88
89
  errors.add("dn", format % _dn)
89
90
  end
90
91
  end
@@ -92,9 +93,13 @@ module ActiveLdap
92
93
  def validate_dn
93
94
  dn
94
95
  rescue DistinguishedNameInvalid
95
- errors.add("dn", _("is invalid: %s") % $!.message)
96
+ format = _("%{fn} is invalid: %s")
97
+ format = format.sub(/^%\{fn\} /, '') unless ActiveLdap.get_text_supported?
98
+ errors.add("dn", format % $!.message)
96
99
  rescue DistinguishedNameNotSetError
97
- errors.add("dn", _("isn't set: %s") % $!.message)
100
+ format = _("%{fn} isn't set: %s")
101
+ format = format.sub(/^%\{fn\} /, '') unless ActiveLdap.get_text_supported?
102
+ errors.add("dn", format % $!.message)
98
103
  end
99
104
 
100
105
  def validate_excluded_classes
@@ -112,9 +117,10 @@ module ActiveLdap
112
117
  names = unexpected_classes.collect do |object_class|
113
118
  self.class.human_object_class_name(object_class)
114
119
  end
115
- format = n_("has excluded value: %s",
116
- "has excluded values: %s",
120
+ format = n_("%{fn} has excluded value: %s",
121
+ "%{fn} has excluded values: %s",
117
122
  names.size)
123
+ format = format.sub(/^%\{fn\} /, '') unless ActiveLdap.get_text_supported?
118
124
  errors.add("objectClass", format % names.join(", "))
119
125
  end
120
126
 
@@ -143,12 +149,15 @@ module ActiveLdap
143
149
  end
144
150
  args = [self.class.human_object_class_name(object_class)]
145
151
  if aliases.empty?
146
- format = _("is required attribute by objectClass '%s'")
152
+ format = _("%{fn} is required attribute by objectClass '%s'")
147
153
  else
148
- format = _("is required attribute by objectClass " \
154
+ format = _("%{fn} is required attribute by objectClass " \
149
155
  "'%s': aliases: %s")
150
156
  args << aliases.join(', ')
151
157
  end
158
+ unless ActiveLdap.get_text_supported?
159
+ format = format.sub(/^%\{fn\} /, '')
160
+ end
152
161
  errors.add(real_name, format % args)
153
162
  end
154
163
  end
@@ -157,7 +166,7 @@ module ActiveLdap
157
166
  def validate_ldap_values
158
167
  entry_attribute.schemata.each do |name, attribute|
159
168
  value = self[name]
160
- next if value.blank?
169
+ next if self.class.blank_value?(value)
161
170
  validate_ldap_value(attribute, name, value)
162
171
  end
163
172
  end
@@ -169,11 +178,14 @@ module ActiveLdap
169
178
  self.class.human_syntax_description(attribute.syntax),
170
179
  failed_reason]
171
180
  if option
172
- format = _("(%s) has invalid format: %s: required syntax: %s: %s")
181
+ format = _("%{fn}(%s) has invalid format: %s: required syntax: %s: %s")
173
182
  else
174
- format = _("has invalid format: %s: required syntax: %s: %s")
183
+ format = _("%{fn} has invalid format: %s: required syntax: %s: %s")
175
184
  end
176
185
  params.unshift(option) if option
186
+ unless ActiveLdap.get_text_supported?
187
+ format = format.sub(/^%\{fn\} ?/, '')
188
+ end
177
189
  errors.add(name, format % params)
178
190
  end
179
191
  end
@@ -5,7 +5,7 @@ require 'active_ldap/ldif'
5
5
  module ActiveLdap
6
6
  class Xml
7
7
  class Serializer
8
- PRINTABLE_STRING = /[\x20-\x7e\w\s]*/um
8
+ PRINTABLE_STRING = /[\x20-\x7e\w\s]*/
9
9
 
10
10
  def initialize(dn, attributes, schema, options={})
11
11
  @dn = dn
@@ -64,7 +64,7 @@ module ActiveLdap
64
64
  targets.concat(normalize_value(real_value, options))
65
65
  end
66
66
  else
67
- if /\A#{PRINTABLE_STRING}\z/u !~ value
67
+ if /\A#{PRINTABLE_STRING}\z/ !~ value
68
68
  value = [value].pack("m").gsub(/\n/u, '')
69
69
  options += ["base64"]
70
70
  end