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