lib/xml/util/xmlcanonicalizer.rb in canonix-0.1.5 vs lib/xml/util/xmlcanonicalizer.rb in canonix-0.1.7

- old
+ new

@@ -8,45 +8,43 @@ require "rexml/document" require "base64" module XML include REXML - + module Util - class NamespaceNode attr_reader :prefix, :uri def initialize(prefix, uri) @prefix = prefix @uri = uri end end - + class XmlCanonicalizer attr_accessor :prefix_list, :logger, :inclusive_namespaces - + BEFORE_DOC_ELEMENT = 0 INSIDE_DOC_ELEMENT = 1 AFTER_DOC_ELEMENT = 2 - + NODE_TYPE_ATTRIBUTE = 3 NODE_TYPE_WHITESPACE = 4 NODE_TYPE_COMMENT = 5 NODE_TYPE_PI = 6 NODE_TYPE_TEXT = 7 - - + def initialize(with_comments, excl_c14n) @with_comments = with_comments @exclusive = excl_c14n @state = BEFORE_DOC_ELEMENT @xnl = Array.new() @prevVisibleNamespacesStart = 0 @prevVisibleNamespacesEnd = 0 @visibleNamespaces = Array.new() end - + def add_inclusive_namespaces(prefix_list, element, visible_namespaces) namespaces = element.attributes() namespaces.each_attribute{|ns| if (ns.prefix=="xmlns") if (prefix_list.include?(ns.local_name())) @@ -56,15 +54,15 @@ } parent = element.parent() add_inclusive_namespaces(prefix_list, parent, visible_namespaces) if (parent) visible_namespaces end - + def canonicalize(document) write_document_node(document) end - + def canonicalize_element(element, logging = true) @preserve_document = element.document() tmp_parent = element.parent() body_string = remove_whitespace(element.to_s().gsub("\n","").gsub("\t","").gsub("\r","")) document = Document.new(body_string) @@ -74,11 +72,11 @@ document = Document.new(element.to_s()) ns = element.namespace(element.prefix()) document.root().add_namespace(element.prefix(), ns) write_document_node(document) end - + def write_document_node(document) @res = "" @state = BEFORE_DOC_ELEMENT if (document.class().to_s() == "REXML::Element") write_node(document) @@ -87,11 +85,11 @@ write_node(child) } end @res end - + def write_node(node) visible = is_node_visible(node) if ((node.node_type() == :text) && white_text?(node.value())) res = node.value() res.gsub("\r\n","\n") @@ -111,11 +109,11 @@ if (node.node_type() == :processing_instruction) end if (node.node_type() == :comment) end end - + def write_element_node(node, visible) savedPrevVisibleNamespacesStart = @prevVisibleNamespacesStart savedPrevVisibleNamespacesEnd = @prevVisibleNamespacesEnd savedVisibleNamespacesSize = @visibleNamespaces.size() state = @state @@ -131,11 +129,11 @@ @state = AFTER_DOC_ELEMENT if (visible && state == BEFORE_DOC_ELEMENT) @prevVisibleNamespacesStart = savedPrevVisibleNamespacesStart @prevVisibleNamespacesEnd = savedPrevVisibleNamespacesEnd @visibleNamespaces.slice!(savedVisibleNamespacesSize, @visibleNamespaces.size() - savedVisibleNamespacesSize) if (@visibleNamespaces.size() > savedVisibleNamespacesSize) end - + def write_namespace_axis(node, visible) doc = node.document() has_empty_namespace = false list = Array.new() cur = node @@ -155,18 +153,18 @@ has_empty_namespace = true if (prefix == nil) } if (visible && !has_empty_namespace && !is_namespace_rendered(nil, nil)) @res = @res + ' xmlns=""' end - + #: ns of inclusive_list if self.inclusive_namespaces && !self.inclusive_namespaces.empty? self.inclusive_namespaces.each{|prefix| list.push(prefix) if (!list.include?(prefix) && (node.attributes.prefixes.include?(prefix))) } end - + if list.delete('xmlns') list = ["xmlns"] + list.sort else list.sort! end @@ -180,11 +178,11 @@ if (visible) @prevVisibleNamespacesStart = @prevVisibleNamespacesEnd @prevVisibleNamespacesEnd = @visibleNamespaces.size() end end - + def node_namespaces(node) ns = Array.new() ns.push(node.prefix()) node.attributes().each_attribute{|a| if (a.prefix() != nil) @@ -194,11 +192,11 @@ ns.push("xmlns") end } ns end - + def write_attribute_axis(node) list = Array.new() node.attributes.keys.sort.each{|key| attr = node.attributes.get_attribute(key) list.push(attr) if (!is_namespace_node(attr.value()) && !is_namespace_decl(attr)) @@ -231,15 +229,15 @@ # @res = @res + " " + normalize_string(attribute.name()+'="'+attribute.to_s()+'"', NODE_TYPE_ATTRIBUTE).gsub("'",'"') end end } end - + def is_namespace_node(namespace_uri) return (namespace_uri == "http://www.w3.org/2000/xmlns/") end - + def is_namespace_rendered(prefix, uri) is_empty_ns = prefix == nil && uri == nil if (is_empty_ns) start = 0 else @@ -257,19 +255,19 @@ # # p = ns.prefix() if (ns.prefix().index("xmlns") == 0) # # return ns.uri() == uri if (p == prefix) # } # return is_empty_ns end - + def is_node_visible(node) return true if (@xnl.size() == 0) @xnl.each{|element| return true if (element == node) } return false end - + def normalize_string(input, type) sb = "" return input # input.each_byte{|b| # if (b == 60 && (type == NODE_TYPE_ATTRIBUTE || is_text_node(type))) @@ -292,33 +290,33 @@ # sb = sb.concat(b) # end # } # sb end - + def write_text_node(node, visible) if (visible) - @res = @res + normalize_string(node.value(), node.node_type()) + @res = @res + normalize_string(node.to_s, node.node_type()) end end - + def white_text?(text) return true if ((text.strip() == "") || (text.strip() == nil)) return false end - + def is_namespace_decl(attribute) # return true if (attribute.name() == "xmlns") return true if (attribute.prefix().index("xmlns") == 0) return false end - + def is_text_node(type) return true if (type == NODE_TYPE_TEXT || type == NODE_TYPE_CDATA || type == NODE_TYPE_WHITESPACE) return false end - + def remove_whitespace(string) new_string = "" in_white = false string.each_byte{|b| # if (in_white && b == 32) @@ -337,16 +335,15 @@ end end end #Util end #XML - if __FILE__ == $0 document = Document.new(File.new(ARGV[0])) body = nil c = WSS4R::Security::Util::XmlCanonicalizer.new(false, true) - + if (ARGV.size() == 3) body = ARGV[2] if (body == "true") element = XPath.match(document, "/soap:Envelope/soap:Body")[0] element = XPath.first(document, "/soap:Envelope/soap:Header/wsse:Security/Signature/SignedInfo") @@ -359,10 +356,10 @@ puts(CryptHash.new().digest_b64(result)) end else result = c.canonicalize(document) end - + file = File.new(ARGV[1], "wb") file.write(result) file.close() end