activeldap 1.0.1 → 1.0.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/CHANGES +34 -0
- data/README +13 -0
- data/Rakefile +2 -1
- data/TODO +6 -0
- data/benchmark/bench-al.rb +68 -17
- data/examples/al-admin/app/helpers/application_helper.rb +3 -5
- data/examples/al-admin/app/views/layouts/_footer.html.erb +2 -0
- data/examples/al-admin/config/boot.rb +7 -7
- data/examples/al-admin/config/environment.rb +27 -12
- data/examples/al-admin/config/environments/development.rb +0 -1
- data/examples/al-admin/config/environments/production.rb +6 -1
- data/examples/al-admin/config/environments/test.rb +1 -1
- data/examples/al-admin/config/initializers/gettext.rb +15 -1
- data/examples/al-admin/po/en/al-admin.po +1 -1
- data/examples/al-admin/po/ja/al-admin.po +1 -1
- data/examples/al-admin/po/nl/al-admin.po +1 -1
- data/examples/al-admin/public/dispatch.cgi +0 -0
- data/examples/al-admin/public/dispatch.fcgi +0 -0
- data/examples/al-admin/public/dispatch.rb +0 -0
- data/examples/al-admin/public/javascripts/controls.js +73 -73
- data/examples/al-admin/public/javascripts/dragdrop.js +166 -165
- data/examples/al-admin/public/javascripts/effects.js +174 -166
- data/examples/al-admin/public/javascripts/prototype.js +362 -267
- data/examples/al-admin/script/about +0 -0
- data/examples/al-admin/script/console +0 -0
- data/examples/al-admin/script/dbconsole +3 -0
- data/examples/al-admin/script/destroy +0 -0
- data/examples/al-admin/script/generate +0 -0
- data/examples/al-admin/script/performance/benchmarker +0 -0
- data/examples/al-admin/script/performance/profiler +0 -0
- data/examples/al-admin/script/performance/request +0 -0
- data/examples/al-admin/script/plugin +0 -0
- data/examples/al-admin/script/process/inspector +0 -0
- data/examples/al-admin/script/process/reaper +0 -0
- data/examples/al-admin/script/process/spawner +0 -0
- data/examples/al-admin/script/runner +0 -0
- data/examples/al-admin/script/server +0 -0
- data/examples/al-admin/test/run-test.sh +0 -0
- data/examples/groupadd +0 -0
- data/examples/groupdel +0 -0
- data/examples/groupls +0 -0
- data/examples/groupmod +0 -0
- data/examples/lpasswd +0 -0
- data/examples/ouadd +0 -0
- data/examples/useradd +0 -0
- data/examples/useradd-binary +0 -0
- data/examples/userdel +0 -0
- data/examples/userls +0 -0
- data/examples/usermod +0 -0
- data/examples/usermod-binary-add +0 -0
- data/examples/usermod-binary-add-time +0 -0
- data/examples/usermod-binary-del +0 -0
- data/examples/usermod-lang-add +0 -0
- data/lib/active_ldap.rb +10 -4
- data/lib/active_ldap/action_controller/ldap_benchmarking.rb +28 -9
- data/lib/active_ldap/adapter/base.rb +30 -17
- data/lib/active_ldap/adapter/jndi.rb +5 -1
- data/lib/active_ldap/adapter/ldap.rb +5 -1
- data/lib/active_ldap/association/has_many_utils.rb +7 -1
- data/lib/active_ldap/associations.rb +10 -5
- data/lib/active_ldap/attributes.rb +6 -1
- data/lib/active_ldap/base.rb +154 -52
- data/lib/active_ldap/configuration.rb +1 -1
- data/lib/active_ldap/connection.rb +7 -4
- data/lib/active_ldap/get_text.rb +11 -3
- data/lib/active_ldap/ldif.rb +16 -4
- data/lib/active_ldap/operations.rb +13 -5
- data/lib/active_ldap/schema.rb +6 -2
- data/lib/active_ldap/schema/syntaxes.rb +15 -3
- data/lib/active_ldap/user_password.rb +4 -4
- data/lib/active_ldap/validations.rb +32 -44
- data/lib/active_ldap/xml.rb +125 -0
- data/po/en/active-ldap.po +740 -85
- data/po/ja/active-ldap.po +748 -547
- data/rails/README +54 -0
- data/rails/init.rb +33 -0
- data/rails/plugin/active_ldap/generators/README +2 -0
- data/rails/plugin/active_ldap/generators/model_active_ldap/model_active_ldap_generator.rb +1 -1
- data/rails/plugin/active_ldap/init.rb +3 -0
- data/rails_generators/model_active_ldap/USAGE +17 -0
- data/rails_generators/model_active_ldap/model_active_ldap_generator.rb +69 -0
- data/rails_generators/model_active_ldap/templates/model_active_ldap.rb +3 -0
- data/rails_generators/model_active_ldap/templates/unit_test.rb +8 -0
- data/rails_generators/scaffold_active_ldap/scaffold_active_ldap_generator.rb +7 -0
- data/rails_generators/scaffold_active_ldap/templates/ldap.yml +18 -0
- data/rails_generators/scaffold_al/scaffold_al_generator.rb +20 -0
- data/test-unit/History.txt +50 -1
- data/test-unit/Manifest.txt +22 -12
- data/test-unit/README.txt +31 -12
- data/test-unit/Rakefile +14 -1
- data/test-unit/TODO +5 -0
- data/test-unit/bin/testrb +0 -0
- data/test-unit/lib/test/unit.rb +62 -0
- data/test-unit/lib/test/unit/assertions.rb +419 -75
- data/test-unit/lib/test/unit/autorunner.rb +70 -13
- data/test-unit/lib/test/unit/collector.rb +1 -1
- data/test-unit/lib/test/unit/collector/load.rb +1 -1
- data/test-unit/lib/test/unit/color-scheme.rb +86 -0
- data/test-unit/lib/test/unit/color.rb +40 -5
- data/test-unit/lib/test/unit/diff.rb +14 -0
- data/test-unit/lib/test/unit/fixture.rb +7 -16
- data/test-unit/lib/test/unit/notification.rb +9 -0
- data/test-unit/lib/test/unit/omission.rb +14 -0
- data/test-unit/lib/test/unit/pending.rb +16 -0
- data/test-unit/lib/test/unit/priority.rb +17 -2
- data/test-unit/lib/test/unit/runner/console.rb +8 -2
- data/test-unit/lib/test/unit/testcase.rb +188 -2
- data/test-unit/lib/test/unit/ui/console/testrunner.rb +51 -26
- data/test-unit/lib/test/unit/util/method-owner-finder.rb +28 -0
- data/test-unit/lib/test/unit/version.rb +1 -1
- data/test-unit/sample/test_user.rb +22 -0
- data/test-unit/test/collector/{test_descendant.rb → test-descendant.rb} +0 -0
- data/test-unit/test/collector/{test_load.rb → test-load.rb} +1 -1
- data/test-unit/test/run-test.rb +0 -0
- data/test-unit/test/{test_attribute.rb → test-attribute.rb} +0 -0
- data/test-unit/test/test-color-scheme.rb +56 -0
- data/test-unit/test/{test_color.rb → test-color.rb} +10 -0
- data/test-unit/test/{test_diff.rb → test-diff.rb} +0 -0
- data/test-unit/test/{test_emacs_runner.rb → test-emacs-runner.rb} +0 -0
- data/test-unit/test/test-fixture.rb +287 -0
- data/test-unit/test/{test_notification.rb → test-notification.rb} +4 -4
- data/test-unit/test/{test_omission.rb → test-omission.rb} +6 -6
- data/test-unit/test/{test_pending.rb → test-pending.rb} +12 -6
- data/test-unit/test/{test_priority.rb → test-priority.rb} +30 -0
- data/test-unit/test/test_assertions.rb +411 -69
- data/test-unit/test/test_testcase.rb +70 -3
- data/test-unit/test/{testunit_test_util.rb → testunit-test-util.rb} +4 -2
- data/test-unit/test/ui/test_testrunmediator.rb +1 -1
- data/test-unit/test/util/test-method-owner-finder.rb +38 -0
- data/test/run-test.rb +0 -0
- data/test/test_adapter.rb +3 -0
- data/test/test_associations.rb +50 -7
- data/test/test_base.rb +193 -11
- data/test/test_connection_per_dn.rb +1 -1
- data/test/test_ldif.rb +86 -0
- data/test/test_load.rb +7 -0
- data/test/test_schema.rb +31 -1
- data/test/test_syntax.rb +20 -0
- data/test/test_user_password.rb +22 -14
- data/test/test_validation.rb +70 -29
- metadata +99 -77
- data/data/locale/en/LC_MESSAGES/active-ldap.mo +0 -0
- data/data/locale/ja/LC_MESSAGES/active-ldap.mo +0 -0
- data/examples/al-admin/config/initializers/ralative_url_support.rb +0 -1
- data/examples/al-admin/lib/accept_http_rails_relative_url_root.rb +0 -9
- data/test-unit-ext/misc/rd2html.rb +0 -42
- data/test-unit/test/test_fixture.rb +0 -275
|
@@ -213,11 +213,14 @@ module ActiveLdap
|
|
|
213
213
|
conn = @connection
|
|
214
214
|
return conn if conn
|
|
215
215
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
216
|
+
have_dn = !@dn.nil?
|
|
217
|
+
if !have_dn and attribute_name_resolvable_without_connection?
|
|
218
|
+
begin
|
|
219
|
+
have_dn = !get_attribute_before_type_cast(dn_attribute)[1].nil?
|
|
220
|
+
rescue DistinguishedNameInvalid
|
|
221
|
+
end
|
|
220
222
|
end
|
|
223
|
+
conn = self.class.active_connections[dn] || retrieve_connection if have_dn
|
|
221
224
|
conn || self.class.connection
|
|
222
225
|
end
|
|
223
226
|
|
data/lib/active_ldap/get_text.rb
CHANGED
|
@@ -1,7 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
require
|
|
1
|
+
if Object.const_defined?(:GetText)
|
|
2
|
+
require 'active_record/version'
|
|
3
|
+
active_record_version = [ActiveRecord::VERSION::MAJOR,
|
|
4
|
+
ActiveRecord::VERSION::MINOR,
|
|
5
|
+
ActiveRecord::VERSION::TINY]
|
|
6
|
+
if (active_record_version <=> [2, 2, 0]) < 0
|
|
7
|
+
require "gettext/active_record"
|
|
8
|
+
end
|
|
3
9
|
ActiveLdap.const_set("GetText", GetText)
|
|
4
|
-
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
unless ActiveLdap.const_defined?(:GetText)
|
|
5
13
|
require 'active_ldap/get_text_fallback'
|
|
6
14
|
end
|
|
7
15
|
|
data/lib/active_ldap/ldif.rb
CHANGED
|
@@ -31,11 +31,19 @@ module ActiveLdap
|
|
|
31
31
|
SIZE = 75
|
|
32
32
|
|
|
33
33
|
module_function
|
|
34
|
+
def binary_value?(value)
|
|
35
|
+
if /\A#{Parser::SAFE_STRING}\z/u =~ value
|
|
36
|
+
false
|
|
37
|
+
else
|
|
38
|
+
true
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
34
42
|
def encode(name, value)
|
|
35
43
|
return "#{name}:\n" if value.blank?
|
|
36
44
|
result = "#{name}:"
|
|
37
45
|
|
|
38
|
-
if value[-1, 1] == ' ' or
|
|
46
|
+
if value[-1, 1] == ' ' or binary_value?(value)
|
|
39
47
|
result << ":"
|
|
40
48
|
value = [value].pack("m").gsub(/\n/u, '')
|
|
41
49
|
end
|
|
@@ -364,6 +372,9 @@ module ActiveLdap
|
|
|
364
372
|
records << parse_record
|
|
365
373
|
break if @scanner.eos?
|
|
366
374
|
raise separator_is_missing if @scanner.scan_separator.nil?
|
|
375
|
+
|
|
376
|
+
break if @scanner.eos?
|
|
377
|
+
break if @scanner.scan_separators and @scanner.eos?
|
|
367
378
|
end
|
|
368
379
|
records
|
|
369
380
|
end
|
|
@@ -475,6 +486,7 @@ module ActiveLdap
|
|
|
475
486
|
|
|
476
487
|
class Scanner
|
|
477
488
|
SEPARATOR = /(?:\r\n|\n)/u
|
|
489
|
+
SEPARATORS = /(?:(?:^#.*)?#{SEPARATOR})+/u
|
|
478
490
|
|
|
479
491
|
def initialize(source)
|
|
480
492
|
@source = source
|
|
@@ -506,13 +518,13 @@ module ActiveLdap
|
|
|
506
518
|
end
|
|
507
519
|
|
|
508
520
|
def scan_separators
|
|
509
|
-
return @scanner.scan(
|
|
521
|
+
return @scanner.scan(SEPARATORS) if @sub_scanner.eos?
|
|
510
522
|
|
|
511
|
-
sub_result = scan(
|
|
523
|
+
sub_result = scan(SEPARATORS)
|
|
512
524
|
return nil if sub_result.nil?
|
|
513
525
|
return sub_result unless @sub_scanner.eos?
|
|
514
526
|
|
|
515
|
-
result = @scanner.scan(
|
|
527
|
+
result = @scanner.scan(SEPARATORS)
|
|
516
528
|
return sub_result if result.nil?
|
|
517
529
|
|
|
518
530
|
sub_result + result
|
|
@@ -34,7 +34,11 @@ module ActiveLdap
|
|
|
34
34
|
|
|
35
35
|
value = value.first if value.is_a?(Array) and value.first.size == 1
|
|
36
36
|
|
|
37
|
-
_attr
|
|
37
|
+
_attr = nil
|
|
38
|
+
_prefix = nil
|
|
39
|
+
if attr.nil? or attr == dn_attribute
|
|
40
|
+
_attr, value, _prefix = split_search_value(value)
|
|
41
|
+
end
|
|
38
42
|
attr ||= _attr || ensure_search_attribute
|
|
39
43
|
prefix ||= _prefix
|
|
40
44
|
filter ||= [attr, value]
|
|
@@ -117,7 +121,9 @@ module ActiveLdap
|
|
|
117
121
|
end
|
|
118
122
|
|
|
119
123
|
def ensure_base(target)
|
|
120
|
-
[truncate_base(target),
|
|
124
|
+
[truncate_base(target), base].reject do |component|
|
|
125
|
+
component.blank?
|
|
126
|
+
end.join(',')
|
|
121
127
|
end
|
|
122
128
|
|
|
123
129
|
def truncate_base(target)
|
|
@@ -383,10 +389,12 @@ module ActiveLdap
|
|
|
383
389
|
|
|
384
390
|
module ModifyRecordLoadable
|
|
385
391
|
def load(operator, options)
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
{:controls => controls}.merge(options))
|
|
392
|
+
modify_entries = operations.inject([]) do |result, operation|
|
|
393
|
+
result + operation.to_modify_entries
|
|
389
394
|
end
|
|
395
|
+
return if modify_entries.empty?
|
|
396
|
+
operator.modify_entry(dn, modify_entries,
|
|
397
|
+
{:controls => controls}.merge(options))
|
|
390
398
|
end
|
|
391
399
|
|
|
392
400
|
module AddOperationModifiable
|
data/lib/active_ldap/schema.rb
CHANGED
|
@@ -189,7 +189,7 @@ module ActiveLdap
|
|
|
189
189
|
|
|
190
190
|
def parse_attributes(str, attributes)
|
|
191
191
|
str.scan(/([A-Z\-_]+)\s+
|
|
192
|
-
(?:\(\s*([\w
|
|
192
|
+
(?:\(\s*(\w[\w\-;]*(?:\s+\$\s+\w[\w\-;]*)*)\s*\)|
|
|
193
193
|
\(\s*([^\)]*)\s*\)|
|
|
194
194
|
'([^\']*)'|
|
|
195
195
|
((?!#{RESERVED_NAMES_RE})[a-zA-Z][a-zA-Z\d\-;]*)|
|
|
@@ -611,8 +611,12 @@ module ActiveLdap
|
|
|
611
611
|
end
|
|
612
612
|
end
|
|
613
613
|
|
|
614
|
+
UNWRITABLE_MUST_ATTRIBUTES = ["nTSecurityDescriptor"]
|
|
614
615
|
def collect_attributes
|
|
615
|
-
must = attribute('MUST').
|
|
616
|
+
must = attribute('MUST').reject do |name|
|
|
617
|
+
UNWRITABLE_MUST_ATTRIBUTES.include?(name)
|
|
618
|
+
end
|
|
619
|
+
must = must.collect {|name| @schema.attribute(name)}
|
|
616
620
|
may = attribute('MAY').collect {|name| @schema.attribute(name)}
|
|
617
621
|
|
|
618
622
|
all_must = must.dup
|
|
@@ -187,9 +187,21 @@ module ActiveLdap
|
|
|
187
187
|
fraction = match_data[-2]
|
|
188
188
|
fraction = fraction.to_f if fraction
|
|
189
189
|
time_zone = match_data[-1]
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
190
|
+
begin
|
|
191
|
+
Time.send(:make_time,
|
|
192
|
+
year, month, day, hour, minute, second, fraction,
|
|
193
|
+
time_zone, Time.now)
|
|
194
|
+
rescue ArgumentError
|
|
195
|
+
raise if year >= 1700
|
|
196
|
+
out_of_range_messages = ["argument out of range",
|
|
197
|
+
"time out of range"]
|
|
198
|
+
raise unless out_of_range_messages.include?($!.message)
|
|
199
|
+
Time.at(0)
|
|
200
|
+
rescue RangeError
|
|
201
|
+
raise if year >= 1700
|
|
202
|
+
raise if $!.message != "bignum too big to convert into `long'"
|
|
203
|
+
Time.at(0)
|
|
204
|
+
end
|
|
193
205
|
else
|
|
194
206
|
value
|
|
195
207
|
end
|
|
@@ -43,7 +43,7 @@ module ActiveLdap
|
|
|
43
43
|
end
|
|
44
44
|
|
|
45
45
|
def md5(password)
|
|
46
|
-
"{MD5}#{
|
|
46
|
+
"{MD5}#{[MD5.md5(password).digest].pack('m').chomp}"
|
|
47
47
|
end
|
|
48
48
|
|
|
49
49
|
def smd5(password, salt=nil)
|
|
@@ -52,7 +52,7 @@ module ActiveLdap
|
|
|
52
52
|
end
|
|
53
53
|
salt ||= Salt.generate(4)
|
|
54
54
|
md5_hash_with_salt = "#{MD5.md5(password + salt).digest}#{salt}"
|
|
55
|
-
"{SMD5}#{
|
|
55
|
+
"{SMD5}#{[md5_hash_with_salt].pack('m').chomp}"
|
|
56
56
|
end
|
|
57
57
|
|
|
58
58
|
def extract_salt_for_smd5(smd5ed_password)
|
|
@@ -60,7 +60,7 @@ module ActiveLdap
|
|
|
60
60
|
end
|
|
61
61
|
|
|
62
62
|
def sha(password)
|
|
63
|
-
"{SHA}#{
|
|
63
|
+
"{SHA}#{[SHA1.sha1(password).digest].pack('m').chomp}"
|
|
64
64
|
end
|
|
65
65
|
|
|
66
66
|
def ssha(password, salt=nil)
|
|
@@ -69,7 +69,7 @@ module ActiveLdap
|
|
|
69
69
|
end
|
|
70
70
|
salt ||= Salt.generate(4)
|
|
71
71
|
sha1_hash_with_salt = "#{SHA1.sha1(password + salt).digest}#{salt}"
|
|
72
|
-
"{SSHA}#{
|
|
72
|
+
"{SSHA}#{[sha1_hash_with_salt].pack('m').chomp}"
|
|
73
73
|
end
|
|
74
74
|
|
|
75
75
|
def extract_salt_for_ssha(sshaed_password)
|
|
@@ -34,6 +34,7 @@ module ActiveLdap
|
|
|
34
34
|
end
|
|
35
35
|
|
|
36
36
|
validate_on_create :validate_duplicated_dn_creation
|
|
37
|
+
validate :validate_dn
|
|
37
38
|
validate :validate_excluded_classes
|
|
38
39
|
validate :validate_required_ldap_values
|
|
39
40
|
validate :validate_ldap_values
|
|
@@ -76,14 +77,24 @@ module ActiveLdap
|
|
|
76
77
|
|
|
77
78
|
private
|
|
78
79
|
def validate_duplicated_dn_creation
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
end
|
|
85
|
-
errors.add("dn", format % dn)
|
|
80
|
+
_dn = nil
|
|
81
|
+
begin
|
|
82
|
+
_dn = dn
|
|
83
|
+
rescue DistinguishedNameInvalid, DistinguishedNameNotSetError
|
|
84
|
+
return
|
|
86
85
|
end
|
|
86
|
+
if _dn and exist?
|
|
87
|
+
format = _("is duplicated: %s")
|
|
88
|
+
errors.add("dn", format % _dn)
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def validate_dn
|
|
93
|
+
dn
|
|
94
|
+
rescue DistinguishedNameInvalid
|
|
95
|
+
errors.add("dn", _("is invalid: %s") % $!.message)
|
|
96
|
+
rescue DistinguishedNameNotSetError
|
|
97
|
+
errors.add("dn", _("isn't set: %s") % $!.message)
|
|
87
98
|
end
|
|
88
99
|
|
|
89
100
|
def validate_excluded_classes
|
|
@@ -101,17 +112,9 @@ module ActiveLdap
|
|
|
101
112
|
names = unexpected_classes.collect do |object_class|
|
|
102
113
|
self.class.human_object_class_name(object_class)
|
|
103
114
|
end
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
names.size)
|
|
108
|
-
else
|
|
109
|
-
if names.size == 1
|
|
110
|
-
format = "has excluded value: %s"
|
|
111
|
-
else
|
|
112
|
-
format = "has excluded values: %s"
|
|
113
|
-
end
|
|
114
|
-
end
|
|
115
|
+
format = n_("has excluded value: %s",
|
|
116
|
+
"has excluded values: %s",
|
|
117
|
+
names.size)
|
|
115
118
|
errors.add("objectClass", format % names.join(", "))
|
|
116
119
|
end
|
|
117
120
|
|
|
@@ -129,6 +132,8 @@ module ActiveLdap
|
|
|
129
132
|
real_name = to_real_attribute_name(required_attribute.name, true)
|
|
130
133
|
raise UnknownAttribute.new(required_attribute) if real_name.nil?
|
|
131
134
|
|
|
135
|
+
next if required_attribute.read_only?
|
|
136
|
+
|
|
132
137
|
value = @data[real_name] || []
|
|
133
138
|
next unless self.class.blank_value?(value)
|
|
134
139
|
|
|
@@ -137,20 +142,12 @@ module ActiveLdap
|
|
|
137
142
|
self.class.human_attribute_name(name)
|
|
138
143
|
end
|
|
139
144
|
args = [self.class.human_object_class_name(object_class)]
|
|
140
|
-
if
|
|
141
|
-
|
|
142
|
-
format = _("%{fn} is required attribute by objectClass '%s'")
|
|
143
|
-
else
|
|
144
|
-
format = _("%{fn} is required attribute by objectClass " \
|
|
145
|
-
"'%s': aliases: %s")
|
|
146
|
-
args << aliases.join(', ')
|
|
147
|
-
end
|
|
145
|
+
if aliases.empty?
|
|
146
|
+
format = _("is required attribute by objectClass '%s'")
|
|
148
147
|
else
|
|
149
|
-
format = "is required attribute by objectClass
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
args << aliases.join(', ')
|
|
153
|
-
end
|
|
148
|
+
format = _("is required attribute by objectClass " \
|
|
149
|
+
"'%s': aliases: %s")
|
|
150
|
+
args << aliases.join(', ')
|
|
154
151
|
end
|
|
155
152
|
errors.add(real_name, format % args)
|
|
156
153
|
end
|
|
@@ -160,7 +157,7 @@ module ActiveLdap
|
|
|
160
157
|
def validate_ldap_values
|
|
161
158
|
entry_attribute.schemata.each do |name, attribute|
|
|
162
159
|
value = self[name]
|
|
163
|
-
next if value.
|
|
160
|
+
next if value.blank?
|
|
164
161
|
validate_ldap_value(attribute, name, value)
|
|
165
162
|
end
|
|
166
163
|
end
|
|
@@ -171,19 +168,10 @@ module ActiveLdap
|
|
|
171
168
|
params = [self.class.human_readable_format(value),
|
|
172
169
|
self.class.human_syntax_description(attribute.syntax),
|
|
173
170
|
failed_reason]
|
|
174
|
-
if
|
|
175
|
-
|
|
176
|
-
format =
|
|
177
|
-
_("%{fn} (%s) has invalid format: %s: required syntax: %s: %s")
|
|
178
|
-
else
|
|
179
|
-
format = _("%{fn} has invalid format: %s: required syntax: %s: %s")
|
|
180
|
-
end
|
|
171
|
+
if option
|
|
172
|
+
format = _("(%s) has invalid format: %s: required syntax: %s: %s")
|
|
181
173
|
else
|
|
182
|
-
|
|
183
|
-
format = _("(%s) has invalid format: %s: required syntax: %s: %s")
|
|
184
|
-
else
|
|
185
|
-
format = _("has invalid format: %s: required syntax: %s: %s")
|
|
186
|
-
end
|
|
174
|
+
format = _("has invalid format: %s: required syntax: %s: %s")
|
|
187
175
|
end
|
|
188
176
|
params.unshift(option) if option
|
|
189
177
|
errors.add(name, format % params)
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
require 'erb'
|
|
2
|
+
|
|
3
|
+
require 'active_ldap/ldif'
|
|
4
|
+
|
|
5
|
+
module ActiveLdap
|
|
6
|
+
class Xml
|
|
7
|
+
class Serializer
|
|
8
|
+
PRINTABLE_STRING = /[\x20-\x7e\w\s]*/um
|
|
9
|
+
|
|
10
|
+
def initialize(dn, attributes, schema, options={})
|
|
11
|
+
@dn = dn
|
|
12
|
+
@attributes = attributes
|
|
13
|
+
@schema = schema
|
|
14
|
+
@options = options
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def to_s
|
|
18
|
+
root = @options[:root]
|
|
19
|
+
result = "<#{root}>\n"
|
|
20
|
+
target_attributes.each do |key, values|
|
|
21
|
+
values = normalize_values(values).sort_by {|value, _| value}
|
|
22
|
+
if @schema.attribute(key).single_value?
|
|
23
|
+
result << " #{serialize_attribute_value(key, *values[0])}\n"
|
|
24
|
+
else
|
|
25
|
+
result << serialize_attribute_values(key, values)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
result << "</#{root}>\n"
|
|
29
|
+
result
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
private
|
|
33
|
+
def target_attributes
|
|
34
|
+
except_dn = false
|
|
35
|
+
attributes = @attributes.dup
|
|
36
|
+
(@options[:except] || []).each do |name|
|
|
37
|
+
if name == "dn"
|
|
38
|
+
except_dn = true
|
|
39
|
+
else
|
|
40
|
+
attributes.delete(name)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
attributes = attributes.sort_by {|key, values| key}
|
|
44
|
+
attributes.unshift(["dn", [@dn]]) unless except_dn
|
|
45
|
+
attributes
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def normalize_values(values)
|
|
49
|
+
targets = []
|
|
50
|
+
values.each do |value|
|
|
51
|
+
targets.concat(normalize_value(value))
|
|
52
|
+
end
|
|
53
|
+
targets
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def normalize_value(value, options=[])
|
|
57
|
+
targets = []
|
|
58
|
+
if value.is_a?(Hash)
|
|
59
|
+
value.each do |real_option, real_value|
|
|
60
|
+
targets.concat(normalize_value(real_value, options + [real_option]))
|
|
61
|
+
end
|
|
62
|
+
elsif value.is_a?(Array)
|
|
63
|
+
value.each do |real_value|
|
|
64
|
+
targets.concat(normalize_value(real_value, options))
|
|
65
|
+
end
|
|
66
|
+
else
|
|
67
|
+
if /\A#{PRINTABLE_STRING}\z/u !~ value
|
|
68
|
+
value = [value].pack("m").gsub(/\n/u, '')
|
|
69
|
+
options += ["base64"]
|
|
70
|
+
end
|
|
71
|
+
xml_attributes = {}
|
|
72
|
+
options.each do |name, val|
|
|
73
|
+
xml_attributes[name] = val || "true"
|
|
74
|
+
end
|
|
75
|
+
targets << [value, xml_attributes]
|
|
76
|
+
end
|
|
77
|
+
targets
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def serialize_attribute_values(name, values)
|
|
81
|
+
return "" if values.blank?
|
|
82
|
+
|
|
83
|
+
result = ""
|
|
84
|
+
if name == "dn" or @options[:type].to_s.downcase == "ldif"
|
|
85
|
+
values.collect do |value, xml_attributes|
|
|
86
|
+
xml = serialize_attribute_value(name, value, xml_attributes)
|
|
87
|
+
result << " #{xml}\n"
|
|
88
|
+
end
|
|
89
|
+
else
|
|
90
|
+
plural_name = name.pluralize
|
|
91
|
+
result << " <#{plural_name} type=\"array\">\n"
|
|
92
|
+
values.each do |value, xml_attributes|
|
|
93
|
+
xml = serialize_attribute_value(name, value, xml_attributes)
|
|
94
|
+
result << " #{xml}\n"
|
|
95
|
+
end
|
|
96
|
+
result << " </#{plural_name}>\n"
|
|
97
|
+
end
|
|
98
|
+
result
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def serialize_attribute_value(name, value, xml_attributes)
|
|
102
|
+
if xml_attributes.blank?
|
|
103
|
+
xml_attributes = ""
|
|
104
|
+
else
|
|
105
|
+
xml_attributes = " " + xml_attributes.collect do |n, v|
|
|
106
|
+
"#{ERB::Util.h(n)}=\"#{ERB::Util.h(v)}\""
|
|
107
|
+
end.join(" ")
|
|
108
|
+
end
|
|
109
|
+
"<#{name}#{xml_attributes}>#{ERB::Util.h(value)}</#{name}>"
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def initialize(dn, attributes, schema)
|
|
114
|
+
@dn = dn
|
|
115
|
+
@attributes = attributes
|
|
116
|
+
@schema = schema
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def to_s(options={})
|
|
120
|
+
Serializer.new(@dn, @attributes, @schema, options).to_s
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
XML = Xml
|
|
125
|
+
end
|