1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
|
require 'erb'
require 'builder'
require 'active_ldap/ldif'
module ActiveLdap
class Xml
class Serializer
PRINTABLE_STRING = /[\x20-\x7e\t\r\n]*/n
def initialize(dn, attributes, schema, options={})
@dn = dn
@attributes = attributes
@schema = schema
@options = options
end
def to_s
root = @options[:root]
indent = @options[:indent] || 2
xml = @options[:builder] || Builder::XmlMarkup.new(:indent => indent)
xml.tag!(root) do
target_attributes.each do |key, values|
values = normalize_values(values).sort_by {|value, _| value}
if @schema.attribute(key).single_value?
next if values.empty?
serialize_attribute_value(xml, key, *values[0])
else
serialize_attribute_values(xml, key, values)
end
end
end
end
private
def target_attributes
except_dn = false
only = @options[:only] || []
except = @options[:except] || []
if !only.empty?
attributes = []
except_dn = true
only.each do |name|
if name == "dn"
except_dn = false
elsif @attributes.has_key?(name)
attributes << [name, @attributes[name]]
end
end
elsif !except.empty?
attributes = @attributes.dup
except.each do |name|
if name == "dn"
except_dn = true
else
attributes.delete(name)
end
end
else
attributes = @attributes.dup
end
attributes = attributes.sort_by {|key, values| key}
attributes.unshift(["dn", [@dn]]) unless except_dn
attributes
end
def normalize_values(values)
targets = []
values.each do |value|
targets.concat(normalize_value(value))
end
targets
end
def normalize_value(value, options=[])
targets = []
case value
when Hash
value.each do |real_option, real_value|
targets.concat(normalize_value(real_value, options + [real_option]))
end
when Array
value.each do |real_value|
targets.concat(normalize_value(real_value, options))
end
when DN
targets.concat(normalize_value(value.to_s, options))
when nil
# ignore
else
if /\A#{PRINTABLE_STRING}\z/ !~ value
value = [value].pack("m").gsub(/\n/u, '')
options += ["base64"]
end
xml_attributes = {}
options.each do |name, val|
xml_attributes[name] = val || "true"
end
targets << [value, xml_attributes]
end
targets
end
def serialize_attribute_values(xml, name, values)
return if values.blank?
if name == "dn" or @options[:type].to_s.downcase == "ldif"
values.each do |value, xml_attributes|
serialize_attribute_value(xml, name, value, xml_attributes)
end
else
plural_name = name.pluralize
attributes = @options[:skip_types] ? {} : {"type" => "array"}
xml.tag!(plural_name, attributes) do
values.each do |value, xml_attributes|
serialize_attribute_value(xml, name, value, xml_attributes)
end
end
end
end
def serialize_attribute_value(xml, name, value, xml_attributes)
xml.tag!(name, value, xml_attributes)
end
end
def initialize(dn, attributes, schema)
@dn = dn
@attributes = attributes
@schema = schema
end
def to_s(options={})
Serializer.new(@dn, @attributes, @schema, options).to_s
end
end
XML = Xml
end
|