xmlcanonicalizer 0.0.0.pre1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.0.pre1
1
+ 0.1.0
@@ -0,0 +1,429 @@
1
+ #require "rexml/document"
2
+ #require "base64"
3
+ #require "log4r"
4
+
5
+ #include REXML
6
+ #include Log4r
7
+
8
+ require "rexml/document"
9
+ require "base64"
10
+
11
+ module XML
12
+ include REXML
13
+
14
+ module Util
15
+
16
+ class REXML::Instruction
17
+ def write(writer, indent=-1, transitive=false, ie_hack=false)
18
+ indent(writer, indent)
19
+ writer << START.sub(/\\/u, '')
20
+ writer << @target
21
+ writer << ' '
22
+ writer << @content if @content != nil
23
+ writer << STOP.sub(/\\/u, '')
24
+ end
25
+ end
26
+
27
+ class REXML::Attribute
28
+ def <=>(a2)
29
+ if (self === a2)
30
+ return 0
31
+ elsif (self == nil)
32
+ return -1
33
+ elsif (a2 == nil)
34
+ return 1
35
+ elsif (self.prefix() == a2.prefix())
36
+ return self.name()<=>a2.name()
37
+ end
38
+ if (self.prefix() == nil)
39
+ return -1
40
+ elsif (a2.prefix() == nil)
41
+ return 1
42
+ end
43
+ ret = self.namespace()<=>a2.namespace()
44
+ if (ret == 0)
45
+ ret = self.prefix()<=>a2.prefix()
46
+ end
47
+ return ret
48
+ end
49
+ end
50
+
51
+ class REXML::Element
52
+ def search_namespace(prefix)
53
+ if (self.namespace(prefix) == nil)
54
+ return (self.parent().search_namespace(prefix)) if (self.parent() != nil)
55
+ else
56
+ return self.namespace(prefix)
57
+ end
58
+ end
59
+ def rendered=(rendered)
60
+ @rendered = rendered
61
+ end
62
+ def rendered?()
63
+ return @rendered
64
+ end
65
+ def node_namespaces()
66
+ ns = Array.new()
67
+ ns.push(self.prefix())
68
+ self.attributes().each_attribute{|a|
69
+ if (a.prefix() != nil)
70
+ ns.push(a.prefix())
71
+ end
72
+ if (a.prefix() == "" && a.local_name() == "xmlns")
73
+ ns.push("xmlns")
74
+ end
75
+ }
76
+ ns
77
+ end
78
+ end
79
+
80
+ class NamespaceNode
81
+ attr_reader :prefix, :uri
82
+ def initialize(prefix, uri)
83
+ @prefix = prefix
84
+ @uri = uri
85
+ end
86
+ end
87
+
88
+ class XmlCanonicalizer
89
+ attr_accessor :prefix_list, :logger
90
+
91
+ BEFORE_DOC_ELEMENT = 0
92
+ INSIDE_DOC_ELEMENT = 1
93
+ AFTER_DOC_ELEMENT = 2
94
+
95
+ NODE_TYPE_ATTRIBUTE = 3
96
+ NODE_TYPE_WHITESPACE = 4
97
+ NODE_TYPE_COMMENT = 5
98
+ NODE_TYPE_PI = 6
99
+ NODE_TYPE_TEXT = 7
100
+
101
+
102
+ def initialize(with_comments, excl_c14n)
103
+ @with_comments = with_comments
104
+ @exclusive = excl_c14n
105
+ @res = ""
106
+ @state = BEFORE_DOC_ELEMENT
107
+ @xnl = Array.new()
108
+ @prevVisibleNamespacesStart = 0
109
+ @prevVisibleNamespacesEnd = 0
110
+ @visibleNamespaces = Array.new()
111
+ @inclusive_namespaces = Array.new()
112
+ @prefix_list = nil
113
+ @rendered_prefixes = Array.new()
114
+ end
115
+
116
+ def add_inclusive_namespaces(prefix_list, element, visible_namespaces)
117
+ namespaces = element.attributes()
118
+ namespaces.each_attribute{|ns|
119
+ if (ns.prefix=="xmlns")
120
+ if (prefix_list.include?(ns.local_name()))
121
+ visible_namespaces.push(NamespaceNode.new("xmlns:"+ns.local_name(), ns.value()))
122
+ end
123
+ end
124
+ }
125
+ parent = element.parent()
126
+ add_inclusive_namespaces(prefix_list, parent, visible_namespaces) if (parent)
127
+ visible_namespaces
128
+ end
129
+
130
+ def canonicalize(document)
131
+ write_document_node(document)
132
+ @res
133
+ end
134
+
135
+ def canonicalize_element(element, logging = true)
136
+ @inclusive_namespaces = add_inclusive_namespaces(@prefix_list, element, @inclusive_namespaces) if (@prefix_list)
137
+ @preserve_document = element.document()
138
+ tmp_parent = element.parent()
139
+ body_string = remove_whitespace(element.to_s().gsub("\n","").gsub("\t","").gsub("\r",""))
140
+ document = Document.new(body_string)
141
+ tmp_parent.delete_element(element)
142
+ element = tmp_parent.add_element(document.root())
143
+ @preserve_element = element
144
+ document = Document.new(element.to_s())
145
+ ns = element.namespace(element.prefix())
146
+ document.root().add_namespace(element.prefix(), ns)
147
+ write_document_node(document)
148
+ @res
149
+ end
150
+
151
+ def write_document_node(document)
152
+ @state = BEFORE_DOC_ELEMENT
153
+ if (document.class().to_s() == "REXML::Element")
154
+ write_node(document)
155
+ else
156
+ document.each_child{|child|
157
+ write_node(child)
158
+ }
159
+ end
160
+ @res
161
+ end
162
+
163
+ def write_node(node)
164
+ visible = is_node_visible(node)
165
+ if ((node.node_type() == :text) && white_text?(node.value()))
166
+ res = node.value()
167
+ res.gsub("\r\n","\n")
168
+ #res = res.delete(" ").delete("\t")
169
+ res.delete("\r")
170
+ @res = @res + res
171
+ #write_text_node(node,visible) if (@state == INSIDE_DOC_ELEMENT)
172
+ return
173
+ end
174
+ if (node.node_type() == :text)
175
+ write_text_node(node, visible)
176
+ return
177
+ end
178
+ if (node.node_type() == :element)
179
+ write_element_node(node, visible) if (!node.rendered?())
180
+ node.rendered=(true)
181
+ end
182
+ if (node.node_type() == :processing_instruction)
183
+ end
184
+ if (node.node_type() == :comment)
185
+ end
186
+ end
187
+
188
+ def write_element_node(node, visible)
189
+ savedPrevVisibleNamespacesStart = @prevVisibleNamespacesStart
190
+ savedPrevVisibleNamespacesEnd = @prevVisibleNamespacesEnd
191
+ savedVisibleNamespacesSize = @visibleNamespaces.size()
192
+ state = @state
193
+ state = INSIDE_DOC_ELEMENT if (visible && state == BEFORE_DOC_ELEMENT)
194
+ @res = @res + "<" + node.expanded_name() if (visible)
195
+ write_namespace_axis(node, visible)
196
+ write_attribute_axis(node)
197
+ @res = @res + ">" if (visible)
198
+ node.each_child{|child|
199
+ write_node(child)
200
+ }
201
+ @res = @res + "</" +node.expanded_name() + ">" if (visible)
202
+ @state = AFTER_DOC_ELEMENT if (visible && state == BEFORE_DOC_ELEMENT)
203
+ @prevVisibleNamespacesStart = savedPrevVisibleNamespacesStart
204
+ @prevVisibleNamespacesEnd = savedPrevVisibleNamespacesEnd
205
+ @visibleNamespaces.slice!(savedVisibleNamespacesSize, @visibleNamespaces.size() - savedVisibleNamespacesSize) if (@visibleNamespaces.size() > savedVisibleNamespacesSize)
206
+ end
207
+
208
+ def write_namespace_axis(node, visible)
209
+ doc = node.document()
210
+ has_empty_namespace = false
211
+ list = Array.new()
212
+ cur = node
213
+ #while ((cur != nil) && (cur != doc) && (cur.node_type() != :document))
214
+ namespaces = cur.node_namespaces()
215
+ namespaces.each{|prefix|
216
+ next if ((prefix == "xmlns") && (node.namespace(prefix) == ""))
217
+ namespace = cur.namespace(prefix)
218
+ next if (is_namespace_node(namespace))
219
+ next if (node.namespace(prefix) != cur.namespace(prefix))
220
+ next if (prefix == "xml" && namespace == "http://www.w3.org/XML/1998/namespace")
221
+ next if (!is_node_visible(cur))
222
+ rendered = is_namespace_rendered(prefix, namespace)
223
+ @visibleNamespaces.push(NamespaceNode.new("xmlns:"+prefix,namespace)) if (visible)
224
+ if ((!rendered) && !list.include?(prefix))
225
+ list.push(prefix)
226
+ end
227
+ has_empty_namespace = true if (prefix == nil)
228
+ }
229
+ if (visible && !has_empty_namespace && !is_namespace_rendered(nil, nil))
230
+ @res = @res + ' xmlns=""'
231
+ end
232
+ #TODO: ns of inclusive_list
233
+ #=begin
234
+ if ((@prefix_list) && (node.to_s() == node.parent().to_s()))
235
+ #list.push(node.prefix())
236
+ @inclusive_namespaces.each{|ns|
237
+ prefix = ns.prefix().split(":")[1]
238
+ list.push(prefix) if (!list.include?(prefix) && (!node.attributes.prefixes.include?(prefix)))
239
+ }
240
+ @prefix_list = nil
241
+ end
242
+ #=end
243
+ list.sort!()
244
+ list.each{|prefix|
245
+ next if (prefix == "")
246
+ next if (@rendered_prefixes.include?(prefix))
247
+ @rendered_prefixes.push(prefix)
248
+ ns = node.namespace(prefix)
249
+ ns = @preserve_element.namespace(prefix) if (ns == nil)
250
+ @res = @res + normalize_string(" " + prefix + '="' + ns + '"', NODE_TYPE_TEXT) if (prefix == "xmlns")
251
+ @res = @res + normalize_string(" xmlns:" + prefix + '="' + ns + '"', NODE_TYPE_TEXT) if (prefix != nil && prefix != "xmlns")
252
+ }
253
+ if (visible)
254
+ @prevVisibleNamespacesStart = @prevVisibleNamespacesEnd
255
+ @prevVisibleNamespacesEnd = @visibleNamespaces.size()
256
+ end
257
+ end
258
+
259
+ def write_attribute_axis(node)
260
+ list = Array.new()
261
+ node.attributes.keys.sort.each{|key|
262
+ attr = node.attributes.get_attribute(key)
263
+ list.push(attr) if (!is_namespace_node(attr.value()) && !is_namespace_decl(attr))
264
+ }
265
+ if (!@exclusive && node.parent() != nil && node.parent().parent() != nil)
266
+ cur = node.parent()
267
+ while (cur != nil)
268
+ #next if (cur.attributes() == nil)
269
+ cur.each_attribute{|attribute|
270
+ next if (attribute.prefix() != "xml")
271
+ next if (attribute.prefix().index("xmlns") == 0)
272
+ next if (node.namespace(attribute.prefix()) == attribute.value())
273
+ found = true
274
+ list.each{|n|
275
+ if (n.prefix() == "xml" && n.value() == attritbute.value())
276
+ found = true
277
+ break
278
+ end
279
+ }
280
+ next if (found)
281
+ list.push(attribute)
282
+ }
283
+ end
284
+ end
285
+ list.each{|attribute|
286
+ if (attribute != nil)
287
+ if (attribute.name() != "xmlns")
288
+ @res = @res + " " + normalize_string(attribute.to_string(), NODE_TYPE_ATTRIBUTE).gsub("'",'"')
289
+ end
290
+ # else
291
+ # @res = @res + " " + normalize_string(attribute.name()+'="'+attribute.to_s()+'"', NODE_TYPE_ATTRIBUTE).gsub("'",'"')
292
+ #end
293
+ end
294
+ }
295
+ end
296
+
297
+ def is_namespace_node(namespace_uri)
298
+ return (namespace_uri == "http://www.w3.org/2000/xmlns/")
299
+ end
300
+
301
+ def is_namespace_rendered(prefix, uri)
302
+ is_empty_ns = prefix == nil && uri == nil
303
+ if (is_empty_ns)
304
+ start = 0
305
+ else
306
+ start = @prevVisibleNamespacesStart
307
+ end
308
+ @visibleNamespaces.each{|ns|
309
+ if (ns.prefix() == "xmlns:"+prefix.to_s() && ns.uri() == uri)
310
+ return true
311
+ end
312
+ }
313
+ return is_empty_ns
314
+ #(@visibleNamespaces.size()-1).downto(start) {|i|
315
+ # ns = @visibleNamespaces[i]
316
+ # return true if (ns.prefix() == "xmlns:"+prefix.to_s() && ns.uri() == uri)
317
+ # #p = ns.prefix() if (ns.prefix().index("xmlns") == 0)
318
+ # #return ns.uri() == uri if (p == prefix)
319
+ #}
320
+ #return is_empty_ns
321
+ end
322
+
323
+ def is_node_visible(node)
324
+ return true if (@xnl.size() == 0)
325
+ @xnl.each{|element|
326
+ return true if (element == node)
327
+ }
328
+ return false
329
+ end
330
+
331
+ def normalize_string(input, type)
332
+ sb = ""
333
+ return input
334
+ end
335
+ #input.each_byte{|b|
336
+ # if (b ==60 && (type == NODE_TYPE_ATTRIBUTE || is_text_node(type)))
337
+ # sb = sb + "&lt;"
338
+ # elsif (b == 62 && is_text_node(type))
339
+ # sb = sb + "&gt;"
340
+ # elsif (b == 38 && (is_text_node(type) || is_text_node(type))) #Ampersand
341
+ # sb = sb + "&amp;"
342
+ # elsif (b == 34 && is_text_node(type)) #Quote
343
+ # sb = sb + "&quot;"
344
+ # elsif (b == 9 && is_text_node(type)) #Tabulator
345
+ # sb = sb + "&#x9;"
346
+ # elsif (b == 11 && is_text_node(type)) #CR
347
+ # sb = sb + "&#xA;"
348
+ # elsif (b == 13 && (type == NODE_TYPE_ATTRIBUTE || (is_text_node(type) && type != NODE_TYPE_WHITESPACE) || type == NODE_TYPE_COMMENT || type == NODE_TYPE_PI))
349
+ # sb = sb + "&#xD;"
350
+ # elsif (b == 13)
351
+ # next
352
+ # else
353
+ # sb = sb.concat(b)
354
+ # end
355
+ #}
356
+ #sb
357
+ #end
358
+
359
+ def write_text_node(node, visible)
360
+ if (visible)
361
+ @res = @res + normalize_string(node.value(), node.node_type())
362
+ end
363
+ end
364
+
365
+ def white_text?(text)
366
+ return true if ((text.strip() == "") || (text.strip() == nil))
367
+ return false
368
+ end
369
+
370
+ def is_namespace_decl(attribute)
371
+ #return true if (attribute.name() == "xmlns")
372
+ return true if (attribute.prefix().index("xmlns") == 0)
373
+ return false
374
+ end
375
+
376
+ def is_text_node(type)
377
+ return true if (type == NODE_TYPE_TEXT || type == NODE_TYPE_CDATA || type == NODE_TYPE_WHITESPACE)
378
+ return false
379
+ end
380
+
381
+ def remove_whitespace(string)
382
+ new_string = ""
383
+ in_white = false
384
+ string.each_byte{|b|
385
+ #if (in_white && b == 32)
386
+ #else
387
+ if !(in_white && b == 32)
388
+ new_string = new_string + b.chr()
389
+ end
390
+ if (b == 62) #>
391
+ in_white = true
392
+ end
393
+ if (b == 60) #<
394
+ in_white = false
395
+ end
396
+ }
397
+ new_string
398
+ end
399
+ end
400
+ end #Util
401
+ end #XML
402
+
403
+
404
+ if __FILE__ == $0
405
+ document = Document.new(File.new(ARGV[0]))
406
+ body = nil
407
+ c = WSS4R::Security::Util::XmlCanonicalizer.new(false, true)
408
+
409
+ if (ARGV.size() == 3)
410
+ body = ARGV[2]
411
+ if (body == "true")
412
+ element = XPath.match(document, "/soap:Envelope/soap:Body")[0]
413
+ element = XPath.first(document, "/soap:Envelope/soap:Header/wsse:Security/Signature/SignedInfo")
414
+ result = c.canonicalize_element(element)
415
+ puts("-----")
416
+ puts(result)
417
+ puts("-----")
418
+ puts(result.size())
419
+ puts("-----")
420
+ puts(CryptHash.new().digest_b64(result))
421
+ end
422
+ else
423
+ result = c.canonicalize(document)
424
+ end
425
+
426
+ file = File.new(ARGV[1], "wb")
427
+ file.write(result)
428
+ file.close()
429
+ end
@@ -0,0 +1 @@
1
+ require 'xml/util/xmlcanonicalizer'
data/test/complex.xml ADDED
@@ -0,0 +1,23 @@
1
+ <samlp:ArtifactResponse IssueInstant='2010-09-10T00:00:50-05:00' Version='2.0' xmlns:samlp='urn:oasis:names:tc:SAML:2.0:protocol' ID='122401A9D1742640618954CDD50CEC459150836A' xmlns='urn:oasis:names:tc:SAML:2.0:assertion'><samlp:Status><samlp:StatusCode ID='A6B45394506685EAD93131AD335775015C49B52C' Value='urn:oasis:names:tc:SAML:2.0:status:Failure'/></samlp:Status><samlp:Assertion IssueInstant='2010-09-10T00:00:50-05:00' ID='11B542652811C7A1AC8B8265D92AB293CCA66B26'><Issuer>example.net</Issuer><Subject><NameID Format='urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress'/><SubjectConfirmation Method='urn:oasis:names:tc:SAML:2.0:cm:bearer'/></Subject><Conditions NotBefore='2010-09-10T00:00:50-05:00' NotOnOrAfter='2010-09-10T12:00:50-05:00'/><AuthnStatement AuthnInstant='2010-09-10T00:00:50-05:00'><AuthnContext><AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PreviousSession</AuthnContextClassRef></AuthnContext></AuthnStatement><AttributeStatement><Attribute Name='urn:example:profiles'><AttributeValue FriendlyName='type' type='example:profile:attribute'>Person</AttributeValue><AttributeValue FriendlyName='SessionID' type='example:profile:attribute'>02b5e2df689b97067dc51a0cd2029510</AttributeValue><AttributeValue FriendlyName='Role' type='example:profile:role'>Public</AttributeValue></Attribute></AttributeStatement></samlp:Assertion><ds:Signature xmlns:ds='http://www.w3.org/2000/09/xmldsig#'><ds:SignedInfo><ds:CanonicalizationMethod Algorithm='http://www.w3.org/2001/10/xml-exc-c14n#'/><ds:SignatureMethod Algorithm='http://www.w3.org/2000/09/xmldsig#rsa-sha1'/><ds:Reference URI='122401A9D1742640618954CDD50CEC459150836A'><ds:Transforms><ds:Transform Algorithm='http://www.w3.org/2000/09/xmldsig#enveloped-signature'/><ds:Transform Algorithm='http://www.w3.org/2001/10/xml-exc-c14n#'><InclusiveNamespaces PrefixList='#default saml ds xs xsi'/></ds:Transform></ds:Transforms><ds:DigestMethod Algorithm='http://www.w3.org/2000/09/xmldsig#sha1'/><ds:DigestValue>dQskOs0c6N7GbFJ13SbozqhEQTM=
2
+ </ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>d2rgUtclTSl7q68kZTkaFo8/rBZk/NEmkeKT7qM5doiVhHF4FrMuv7NdQVbQ
3
+ Vi//wyYk6i9u8s13tsYnliSo+4xGbWl112LrAp8U2E8pLjMxqLYQHXw6qV3h
4
+ TLhKw/k8sYS54nOye9t7M0VxHl+sKfX+YZFr8EI3ST2/BKFqm5c=
5
+ </ds:SignatureValue><ds:KeyInfo><ds:X509Data><ds:X509Certificate>MIIDFTCCAn4CAQAwDQYJKoZIhvcNAQEEBQAwgdIxCzAJBgNVBAYTAlVTMRIw
6
+ EAYDVQQIEwlNaW5uZXNvdGExEjAQBgNVBAcTCVJvY2hlc3RlcjElMCMGA1UE
7
+ ChMcQ29ycG9yYXRlIFdlYiBTZXJ2aWNlcywgSW5jLjFAMD4GA1UECxM3TWF5
8
+ byBNZWRpY2FsIExhYm9yYXRvcmllcyBQcm9maWxlIE1hbmFnZXIgSG9zdGVk
9
+ IGJ5IENXUzEVMBMGA1UEAxMMbWF5by5jd3MubmV0MRswGQYJKoZIhvcNAQkB
10
+ FgxseWxlQGN3cy5uZXQwHhcNMDcwODAxMTg1ODUzWhcNMzIwNzI1MTg1ODUz
11
+ WjCB0jELMAkGA1UEBhMCVVMxEjAQBgNVBAgTCU1pbm5lc290YTESMBAGA1UE
12
+ BxMJUm9jaGVzdGVyMSUwIwYDVQQKExxDb3Jwb3JhdGUgV2ViIFNlcnZpY2Vz
13
+ LCBJbmMuMUAwPgYDVQQLEzdNYXlvIE1lZGljYWwgTGFib3JhdG9yaWVzIFBy
14
+ b2ZpbGUgTWFuYWdlciBIb3N0ZWQgYnkgQ1dTMRUwEwYDVQQDEwxtYXlvLmN3
15
+ cy5uZXQxGzAZBgkqhkiG9w0BCQEWDGx5bGVAY3dzLm5ldDCBnzANBgkqhkiG
16
+ 9w0BAQEFAAOBjQAwgYkCgYEA2+1yxxQTeBR+/ducTSVj7eR8krq/OI2LnYxh
17
+ un18kVplOiDwUauqxZZL+ItZhC19/48k3f9YyGsRS1r2YNgOvWKXT8/GEMyI
18
+ /Wk44l/7aUbNeVvdtXBdGdexy972RYH9jOkp4LRWQoJ4l6y1Bt7XesU8p/8Q
19
+ Yd1V/LqUNHQmcq0CAwEAATANBgkqhkiG9w0BAQQFAAOBgQAdSKl3LDTh6Z/p
20
+ P31zMKHOx5VEHnyUmzfd5vl0tfB8a6uMv3NKe2knwHjx7vwwGboVsCS7X6Uu
21
+ x+scXbkA8Rod34PyMQAKqzN8ePTlWywPrtbFJzRROj/7Du2uz83osacuW0bv
22
+ 0AoM/vII4Xbyc/f1OTZvI1ygIVlnbmGI+xJATQ==
23
+ </ds:X509Certificate></ds:X509Data></ds:KeyInfo></ds:Signature></samlp:ArtifactResponse>
data/test/expected.xml ADDED
@@ -0,0 +1,23 @@
1
+ <samlp:ArtifactResponse xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns="urn:oasis:names:tc:SAML:2.0:assertion" ID="122401A9D1742640618954CDD50CEC459150836A" IssueInstant="2010-09-10T00:00:50-05:00" Version="2.0"><samlp:Status><samlp:StatusCode ID="A6B45394506685EAD93131AD335775015C49B52C" Value="urn:oasis:names:tc:SAML:2.0:status:Failure"></samlp:StatusCode></samlp:Status><samlp:Assertion ID="11B542652811C7A1AC8B8265D92AB293CCA66B26" IssueInstant="2010-09-10T00:00:50-05:00"><Issuer>example.net</Issuer><Subject><NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"></NameID><SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"></SubjectConfirmation></Subject><Conditions NotBefore="2010-09-10T00:00:50-05:00" NotOnOrAfter="2010-09-10T12:00:50-05:00"></Conditions><AuthnStatement AuthnInstant="2010-09-10T00:00:50-05:00"><AuthnContext><AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PreviousSession</AuthnContextClassRef></AuthnContext></AuthnStatement><AttributeStatement><Attribute Name="urn:example:profiles"><AttributeValue FriendlyName="type" type="example:profile:attribute">Person</AttributeValue><AttributeValue FriendlyName="SessionID" type="example:profile:attribute">02b5e2df689b97067dc51a0cd2029510</AttributeValue><AttributeValue FriendlyName="Role" type="example:profile:role">Public</AttributeValue></Attribute></AttributeStatement></samlp:Assertion><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:SignedInfo><ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></ds:CanonicalizationMethod><ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"></ds:SignatureMethod><ds:Reference URI="122401A9D1742640618954CDD50CEC459150836A"><ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"></ds:Transform><ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"><InclusiveNamespaces PrefixList="#default saml ds xs xsi"></InclusiveNamespaces></ds:Transform></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></ds:DigestMethod><ds:DigestValue>dQskOs0c6N7GbFJ13SbozqhEQTM=
2
+ </ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>d2rgUtclTSl7q68kZTkaFo8/rBZk/NEmkeKT7qM5doiVhHF4FrMuv7NdQVbQ
3
+ Vi//wyYk6i9u8s13tsYnliSo+4xGbWl112LrAp8U2E8pLjMxqLYQHXw6qV3h
4
+ TLhKw/k8sYS54nOye9t7M0VxHl+sKfX+YZFr8EI3ST2/BKFqm5c=
5
+ </ds:SignatureValue><ds:KeyInfo><ds:X509Data><ds:X509Certificate>MIIDFTCCAn4CAQAwDQYJKoZIhvcNAQEEBQAwgdIxCzAJBgNVBAYTAlVTMRIw
6
+ EAYDVQQIEwlNaW5uZXNvdGExEjAQBgNVBAcTCVJvY2hlc3RlcjElMCMGA1UE
7
+ ChMcQ29ycG9yYXRlIFdlYiBTZXJ2aWNlcywgSW5jLjFAMD4GA1UECxM3TWF5
8
+ byBNZWRpY2FsIExhYm9yYXRvcmllcyBQcm9maWxlIE1hbmFnZXIgSG9zdGVk
9
+ IGJ5IENXUzEVMBMGA1UEAxMMbWF5by5jd3MubmV0MRswGQYJKoZIhvcNAQkB
10
+ FgxseWxlQGN3cy5uZXQwHhcNMDcwODAxMTg1ODUzWhcNMzIwNzI1MTg1ODUz
11
+ WjCB0jELMAkGA1UEBhMCVVMxEjAQBgNVBAgTCU1pbm5lc290YTESMBAGA1UE
12
+ BxMJUm9jaGVzdGVyMSUwIwYDVQQKExxDb3Jwb3JhdGUgV2ViIFNlcnZpY2Vz
13
+ LCBJbmMuMUAwPgYDVQQLEzdNYXlvIE1lZGljYWwgTGFib3JhdG9yaWVzIFBy
14
+ b2ZpbGUgTWFuYWdlciBIb3N0ZWQgYnkgQ1dTMRUwEwYDVQQDEwxtYXlvLmN3
15
+ cy5uZXQxGzAZBgkqhkiG9w0BCQEWDGx5bGVAY3dzLm5ldDCBnzANBgkqhkiG
16
+ 9w0BAQEFAAOBjQAwgYkCgYEA2+1yxxQTeBR+/ducTSVj7eR8krq/OI2LnYxh
17
+ un18kVplOiDwUauqxZZL+ItZhC19/48k3f9YyGsRS1r2YNgOvWKXT8/GEMyI
18
+ /Wk44l/7aUbNeVvdtXBdGdexy972RYH9jOkp4LRWQoJ4l6y1Bt7XesU8p/8Q
19
+ Yd1V/LqUNHQmcq0CAwEAATANBgkqhkiG9w0BAQQFAAOBgQAdSKl3LDTh6Z/p
20
+ P31zMKHOx5VEHnyUmzfd5vl0tfB8a6uMv3NKe2knwHjx7vwwGboVsCS7X6Uu
21
+ x+scXbkA8Rod34PyMQAKqzN8ePTlWywPrtbFJzRROj/7Du2uz83osacuW0bv
22
+ 0AoM/vII4Xbyc/f1OTZvI1ygIVlnbmGI+xJATQ==
23
+ </ds:X509Certificate></ds:X509Data></ds:KeyInfo></ds:Signature></samlp:ArtifactResponse>
@@ -1,7 +1,35 @@
1
- require 'helper'
1
+ require File.dirname(File.expand_path(__FILE__))+'/helper'
2
2
 
3
3
  class TestXmlcanonicalizer < Test::Unit::TestCase
4
- should "probably rename this file and start testing for real" do
5
- flunk "hey buddy, you should probably rename this file and start testing for real"
4
+
5
+ should "canonicalize a simple xml file" do
6
+ xml_canonicalizer = XML::Util::XmlCanonicalizer.new(true,true)
7
+ xml = "<foo bar='test'/>";
8
+ rexml = REXML::Document.new(xml);
9
+ xml_canonicalized = xml_canonicalizer.canonicalize(rexml);
10
+ xml_expect = "<foo bar=\"test\"></foo>";
11
+ assert_equal xml_expect, xml_canonicalized
12
+ end
13
+
14
+ should "canonicalize a complex xml file" do
15
+ fp = File.new(File.dirname(File.expand_path(__FILE__))+'/complex.xml','r')
16
+ xml = ''
17
+ while (l = fp.gets)
18
+ xml += l
19
+ end
20
+ fp.close
21
+
22
+ xml_canonicalizer = XML::Util::XmlCanonicalizer.new(true,true)
23
+ rexml = REXML::Document.new(xml);
24
+ xml_canonicalized = xml_canonicalizer.canonicalize(rexml);
25
+
26
+ fp = File.new(File.dirname(File.expand_path(__FILE__))+'/expected.xml','r')
27
+ xml_expect = ''
28
+ while (l = fp.gets)
29
+ xml_expect += l
30
+ end
31
+ fp.close
32
+
33
+ assert_equal xml_expect, xml_canonicalized
6
34
  end
7
35
  end
@@ -5,9 +5,9 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{xmlcanonicalizer}
8
- s.version = "0.0.0.pre1"
8
+ s.version = "0.1.0"
9
9
 
10
- s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Andrew Ferk"]
12
12
  s.date = %q{2010-09-12}
13
13
  s.description = %q{This is taken from XMLCanonicalizer/WSS4R and http://github.com/borisnadion/xml-canonicalizer}
@@ -23,7 +23,10 @@ Gem::Specification.new do |s|
23
23
  "README.rdoc",
24
24
  "Rakefile",
25
25
  "VERSION",
26
+ "lib/xml/util/xmlcanonicalizer.rb",
26
27
  "lib/xmlcanonicalizer.rb",
28
+ "test/complex.xml",
29
+ "test/expected.xml",
27
30
  "test/helper.rb",
28
31
  "test/test_xmlcanonicalizer.rb",
29
32
  "xmlcanonicalizer.gemspec"
metadata CHANGED
@@ -1,13 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: xmlcanonicalizer
3
3
  version: !ruby/object:Gem::Version
4
- prerelease: true
4
+ prerelease: false
5
5
  segments:
6
6
  - 0
7
+ - 1
7
8
  - 0
8
- - 0
9
- - pre1
10
- version: 0.0.0.pre1
9
+ version: 0.1.0
11
10
  platform: ruby
12
11
  authors:
13
12
  - Andrew Ferk
@@ -47,7 +46,10 @@ files:
47
46
  - README.rdoc
48
47
  - Rakefile
49
48
  - VERSION
49
+ - lib/xml/util/xmlcanonicalizer.rb
50
50
  - lib/xmlcanonicalizer.rb
51
+ - test/complex.xml
52
+ - test/expected.xml
51
53
  - test/helper.rb
52
54
  - test/test_xmlcanonicalizer.rb
53
55
  - xmlcanonicalizer.gemspec
@@ -71,13 +73,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
71
73
  required_rubygems_version: !ruby/object:Gem::Requirement
72
74
  none: false
73
75
  requirements:
74
- - - ">"
76
+ - - ">="
75
77
  - !ruby/object:Gem::Version
76
78
  segments:
77
- - 1
78
- - 3
79
- - 1
80
- version: 1.3.1
79
+ - 0
80
+ version: "0"
81
81
  requirements: []
82
82
 
83
83
  rubyforge_project: