File: xml.rb

package info (click to toggle)
ruby-activeldap 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye
  • size: 1,588 kB
  • sloc: ruby: 18,143; sh: 12; makefile: 5
file content (139 lines) | stat: -rw-r--r-- 3,886 bytes parent folder | download | duplicates (4)
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