lib/xml/util/xmlcanonicalizer.rb in canonix-0.1.3 vs lib/xml/util/xmlcanonicalizer.rb in canonix-0.1.4

- old
+ new

@@ -1,86 +1,22 @@ -#require "rexml/document" -#require "base64" -#require "log4r" +# require "rexml/document" +# require "base64" +# require "log4r" -#include REXML -#include Log4r +# include REXML +# include Log4r require "rexml/document" require "base64" module XML include REXML - + module Util - class REXML::Instruction - def write(writer, indent=-1, transitive=false, ie_hack=false) - indent(writer, indent) - writer << START.sub(/\\/u, '') - writer << @target - writer << ' ' - writer << @content if @content != nil - writer << STOP.sub(/\\/u, '') - end - end - - class REXML::Attribute - def <=>(a2) - if (self === a2) - return 0 - elsif (self == nil) - return -1 - elsif (a2 == nil) - return 1 - elsif (self.prefix() == a2.prefix()) - return self.name()<=>a2.name() - end - if (self.prefix() == nil) - return -1 - elsif (a2.prefix() == nil) - return 1 - end - ret = self.namespace()<=>a2.namespace() - if (ret == 0) - ret = self.prefix()<=>a2.prefix() - end - return ret - end - end - - class REXML::Element - def search_namespace(prefix) - if (self.namespace(prefix) == nil) - return (self.parent().search_namespace(prefix)) if (self.parent() != nil) - else - return self.namespace(prefix) - end - end - def rendered=(rendered) - @rendered = rendered - end - def rendered?() - return @rendered - end - def node_namespaces() - ns = Array.new() - ns.push(self.prefix()) - self.attributes().each_attribute{|a| - if (a.prefix() != nil) - ns.push(a.prefix()) - end - if (a.prefix() == "" && a.local_name() == "xmlns") - ns.push("xmlns") - end - } - ns - end - end - class NamespaceNode - attr_reader :prefix, :uri + attr_reader :prefix, :uri def initialize(prefix, uri) @prefix = prefix @uri = uri end end @@ -100,11 +36,10 @@ def initialize(with_comments, excl_c14n) @with_comments = with_comments @exclusive = excl_c14n - @res = "" @state = BEFORE_DOC_ELEMENT @xnl = Array.new() @prevVisibleNamespacesStart = 0 @prevVisibleNamespacesEnd = 0 @visibleNamespaces = Array.new() @@ -124,11 +59,10 @@ visible_namespaces end def canonicalize(document) write_document_node(document) - @res end def canonicalize_element(element, logging = true) @preserve_document = element.document() tmp_parent = element.parent() @@ -139,14 +73,14 @@ @preserve_element = element document = Document.new(element.to_s()) ns = element.namespace(element.prefix()) document.root().add_namespace(element.prefix(), ns) write_document_node(document) - @res end def write_document_node(document) + @res = "" @state = BEFORE_DOC_ELEMENT if (document.class().to_s() == "REXML::Element") write_node(document) else document.each_child{|child| @@ -159,23 +93,22 @@ 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") - #res = res.delete(" ").delete("\t") + # res = res.delete(" ").delete("\t") res.delete("\r") @res = @res + res - #write_text_node(node,visible) if (@state == INSIDE_DOC_ELEMENT) + # write_text_node(node,visible) if (@state == INSIDE_DOC_ELEMENT) return end if (node.node_type() == :text) write_text_node(node, visible) return - end + end if (node.node_type() == :element) - write_element_node(node, visible) if (!node.rendered?()) - node.rendered=(true) + write_element_node(node, visible) end if (node.node_type() == :processing_instruction) end if (node.node_type() == :comment) end @@ -190,28 +123,27 @@ @res = @res + "<" + node.expanded_name() if (visible) write_namespace_axis(node, visible) write_attribute_axis(node) @res = @res + ">" if (visible) node.each_child{|child| - write_node(child) - } + write_node(child) + } @res = @res + "</" +node.expanded_name() + ">" if (visible) @state = AFTER_DOC_ELEMENT if (visible && state == BEFORE_DOC_ELEMENT) @prevVisibleNamespacesStart = savedPrevVisibleNamespacesStart @prevVisibleNamespacesEnd = savedPrevVisibleNamespacesEnd - @visibleNamespaces.slice!(savedVisibleNamespacesSize, @visibleNamespaces.size() - savedVisibleNamespacesSize) if (@visibleNamespaces.size() > savedVisibleNamespacesSize) + @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 - #while ((cur != nil) && (cur != doc) && (cur.node_type() != :document)) - namespaces = cur.node_namespaces() - namespaces.each{|prefix| - next if ((prefix == "xmlns") && (node.namespace(prefix) == "")) + # while ((cur != nil) && (cur != doc) && (cur.node_type() != :document)) + node_namespaces(cur).each{|prefix| + next if ((prefix == "xmlns") && (node.namespace(prefix) == "")) namespace = cur.namespace(prefix) next if (is_namespace_node(namespace)) next if (node.namespace(prefix) != cur.namespace(prefix)) next if (prefix == "xml" && namespace == "http://www.w3.org/XML/1998/namespace") next if (!is_node_visible(cur)) @@ -220,18 +152,18 @@ if ((!rendered) && !list.include?(prefix)) list.push(prefix) end has_empty_namespace = true if (prefix == nil) } - if (visible && !has_empty_namespace && !is_namespace_rendered(nil, 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))) + list.push(prefix) if (!list.include?(prefix) && (node.attributes.prefixes.include?(prefix))) } end list.sort!() list.each{|prefix| @@ -241,24 +173,38 @@ @res = @res + normalize_string(" " + prefix + '="' + ns + '"', NODE_TYPE_TEXT) if (prefix == "xmlns") @res = @res + normalize_string(" xmlns:" + prefix + '="' + ns + '"', NODE_TYPE_TEXT) if (prefix != nil && prefix != "xmlns") } if (visible) @prevVisibleNamespacesStart = @prevVisibleNamespacesEnd - @prevVisibleNamespacesEnd = @visibleNamespaces.size() + @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) + ns.push(a.prefix()) + end + if (a.prefix() == "" && a.local_name() == "xmlns") + 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)) } if (!@exclusive && node.parent() != nil && node.parent().parent() != nil) cur = node.parent() while (cur != nil) - #next if (cur.attributes() == nil) + # next if (cur.attributes() == nil) cur.each_attribute{|attribute| next if (attribute.prefix() != "xml") next if (attribute.prefix().index("xmlns") == 0) next if (node.namespace(attribute.prefix()) == attribute.value()) found = true @@ -275,14 +221,13 @@ end list.each{|attribute| if (attribute != nil) if (attribute.name() != "xmlns") @res = @res + " " + normalize_string(attribute.to_string(), NODE_TYPE_ATTRIBUTE).gsub("'",'"') + # else + # @res = @res + " " + normalize_string(attribute.name()+'="'+attribute.to_s()+'"', NODE_TYPE_ATTRIBUTE).gsub("'",'"') end - # else - # @res = @res + " " + normalize_string(attribute.name()+'="'+attribute.to_s()+'"', NODE_TYPE_ATTRIBUTE).gsub("'",'"') - #end end } end def is_namespace_node(namespace_uri) @@ -300,17 +245,17 @@ if (ns.prefix() == "xmlns:"+prefix.to_s() && ns.uri() == uri) return true end } return is_empty_ns - #(@visibleNamespaces.size()-1).downto(start) {|i| + # (@visibleNamespaces.size()-1).downto(start) {|i| # ns = @visibleNamespaces[i] - # return true if (ns.prefix() == "xmlns:"+prefix.to_s() && ns.uri() == uri) - # #p = ns.prefix() if (ns.prefix().index("xmlns") == 0) - # #return ns.uri() == uri if (p == prefix) - #} - #return is_empty_ns + # return true if (ns.prefix() == "xmlns:"+prefix.to_s() && ns.uri() == uri) + # # 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| @@ -320,34 +265,33 @@ end def normalize_string(input, type) sb = "" return input + # input.each_byte{|b| + # if (b == 60 && (type == NODE_TYPE_ATTRIBUTE || is_text_node(type))) + # sb = sb + "&lt;" + # elsif (b == 62 && is_text_node(type)) + # sb = sb + "&gt;" + # elsif (b == 38 && (is_text_node(type) || is_text_node(type))) #Ampersand + # sb = sb + "&amp;" + # elsif (b == 34 && is_text_node(type)) #Quote + # sb = sb + "&quot;" + # elsif (b == 9 && is_text_node(type)) #Tabulator + # sb = sb + "&#x9;" + # elsif (b == 11 && is_text_node(type)) #CR + # sb = sb + "&#xA;" + # elsif (b == 13 && (type == NODE_TYPE_ATTRIBUTE || (is_text_node(type) && type != NODE_TYPE_WHITESPACE) || type == NODE_TYPE_COMMENT || type == NODE_TYPE_PI)) + # sb = sb + "&#xD;" + # elsif (b == 13) + # next + # else + # sb = sb.concat(b) + # end + # } + # sb end - #input.each_byte{|b| - # if (b ==60 && (type == NODE_TYPE_ATTRIBUTE || is_text_node(type))) - # sb = sb + "&lt;" - # elsif (b == 62 && is_text_node(type)) - # sb = sb + "&gt;" - # elsif (b == 38 && (is_text_node(type) || is_text_node(type))) #Ampersand - # sb = sb + "&amp;" - # elsif (b == 34 && is_text_node(type)) #Quote - # sb = sb + "&quot;" - # elsif (b == 9 && is_text_node(type)) #Tabulator - # sb = sb + "&#x9;" - # elsif (b == 11 && is_text_node(type)) #CR - # sb = sb + "&#xA;" - # elsif (b == 13 && (type == NODE_TYPE_ATTRIBUTE || (is_text_node(type) && type != NODE_TYPE_WHITESPACE) || type == NODE_TYPE_COMMENT || type == NODE_TYPE_PI)) - # sb = sb + "&#xD;" - # elsif (b == 13) - # next - # else - # sb = sb.concat(b) - # end - #} - #sb - #end def write_text_node(node, visible) if (visible) @res = @res + normalize_string(node.value(), node.node_type()) end @@ -357,11 +301,11 @@ 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.name() == "xmlns") return true if (attribute.prefix().index("xmlns") == 0) return false end def is_text_node(type) @@ -371,12 +315,12 @@ def remove_whitespace(string) new_string = "" in_white = false string.each_byte{|b| - #if (in_white && b == 32) - #else + # if (in_white && b == 32) + # else if !(in_white && b == 32) new_string = new_string + b.chr() end if (b == 62) #> in_white = true @@ -386,35 +330,35 @@ end } new_string end end - end #Util + 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) + 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") result = c.canonicalize_element(element) puts("-----") puts(result) puts("-----") - puts(result.size()) + puts(result.size()) puts("-----") puts(CryptHash.new().digest_b64(result)) end - else + else result = c.canonicalize(document) end file = File.new(ARGV[1], "wb") file.write(result) file.close() -end \ No newline at end of file +end