xmlcanonicalizer 0.0.0.pre1 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: