activeldap 1.0.2 → 1.0.9

Sign up to get free protection for your applications and to get access to all the features.
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