xml_mini 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3 @@
1
+ module XmlMini
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,202 @@
1
+ require 'test_helper'
2
+ # require 'active_support/xml_mini'
3
+ # require 'active_support/core_ext/hash/conversions'
4
+
5
+ begin
6
+ require 'libxml'
7
+ rescue LoadError
8
+ # Skip libxml tests
9
+ else
10
+
11
+ class LibxmlEngineTest < MiniTest::Unit::TestCase
12
+
13
+ def setup
14
+ @default_backend = XmlMini.backend
15
+ XmlMini.backend = 'LibXML'
16
+
17
+ LibXML::XML::Error.set_handler(&lambda { |error| }) #silence libxml, exceptions will do
18
+ end
19
+
20
+ def teardown
21
+ XmlMini.backend = @default_backend
22
+ end
23
+
24
+ def test_exception_thrown_on_expansion_attack
25
+ assert_raises LibXML::XML::Error do
26
+ attack_xml = %{<?xml version="1.0" encoding="UTF-8"?>
27
+ <!DOCTYPE member [
28
+ <!ENTITY a "&b;&b;&b;&b;&b;&b;&b;&b;&b;&b;">
29
+ <!ENTITY b "&c;&c;&c;&c;&c;&c;&c;&c;&c;&c;">
30
+ <!ENTITY c "&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;">
31
+ <!ENTITY d "&e;&e;&e;&e;&e;&e;&e;&e;&e;&e;">
32
+ <!ENTITY e "&f;&f;&f;&f;&f;&f;&f;&f;&f;&f;">
33
+ <!ENTITY f "&g;&g;&g;&g;&g;&g;&g;&g;&g;&g;">
34
+ <!ENTITY g "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx">
35
+ ]>
36
+ <member>
37
+ &a;
38
+ </member>
39
+ }
40
+ Hash.from_minixml(attack_xml)
41
+ end
42
+ end
43
+
44
+ def test_setting_libxml_as_backend
45
+ XmlMini.backend = 'LibXML'
46
+ assert_equal XmlMini_LibXML, XmlMini.backend
47
+ end
48
+
49
+ def test_blank_returns_empty_hash
50
+ assert_equal({}, XmlMini.parse(nil))
51
+ assert_equal({}, XmlMini.parse(''))
52
+ end
53
+
54
+ def test_array_type_makes_an_array
55
+ assert_equal_rexml(<<-eoxml)
56
+ <blog>
57
+ <posts type="array">
58
+ <post>a post</post>
59
+ <post>another post</post>
60
+ </posts>
61
+ </blog>
62
+ eoxml
63
+ end
64
+
65
+ def test_one_node_document_as_hash
66
+ assert_equal_rexml(<<-eoxml)
67
+ <products/>
68
+ eoxml
69
+ end
70
+
71
+ def test_one_node_with_attributes_document_as_hash
72
+ assert_equal_rexml(<<-eoxml)
73
+ <products foo="bar"/>
74
+ eoxml
75
+ end
76
+
77
+ def test_products_node_with_book_node_as_hash
78
+ assert_equal_rexml(<<-eoxml)
79
+ <products>
80
+ <book name="awesome" id="12345" />
81
+ </products>
82
+ eoxml
83
+ end
84
+
85
+ def test_products_node_with_two_book_nodes_as_hash
86
+ assert_equal_rexml(<<-eoxml)
87
+ <products>
88
+ <book name="awesome" id="12345" />
89
+ <book name="america" id="67890" />
90
+ </products>
91
+ eoxml
92
+ end
93
+
94
+ def test_single_node_with_content_as_hash
95
+ assert_equal_rexml(<<-eoxml)
96
+ <products>
97
+ hello world
98
+ </products>
99
+ eoxml
100
+ end
101
+
102
+ def test_children_with_children
103
+ assert_equal_rexml(<<-eoxml)
104
+ <root>
105
+ <products>
106
+ <book name="america" id="67890" />
107
+ </products>
108
+ </root>
109
+ eoxml
110
+ end
111
+
112
+ def test_children_with_text
113
+ assert_equal_rexml(<<-eoxml)
114
+ <root>
115
+ <products>
116
+ hello everyone
117
+ </products>
118
+ </root>
119
+ eoxml
120
+ end
121
+
122
+ def test_children_with_non_adjacent_text
123
+ assert_equal_rexml(<<-eoxml)
124
+ <root>
125
+ good
126
+ <products>
127
+ hello everyone
128
+ </products>
129
+ morning
130
+ </root>
131
+ eoxml
132
+ end
133
+
134
+ def test_parse_from_io
135
+ io = StringIO.new(<<-eoxml)
136
+ <root>
137
+ good
138
+ <products>
139
+ hello everyone
140
+ </products>
141
+ morning
142
+ </root>
143
+ eoxml
144
+ XmlMini.parse(io)
145
+ end
146
+
147
+ def test_children_with_simple_cdata
148
+ assert_equal_rexml(<<-eoxml)
149
+ <root>
150
+ <products>
151
+ <![CDATA[cdatablock]]>
152
+ </products>
153
+ </root>
154
+ eoxml
155
+ end
156
+
157
+ def test_children_with_multiple_cdata
158
+ assert_equal_rexml(<<-eoxml)
159
+ <root>
160
+ <products>
161
+ <![CDATA[cdatablock1]]><![CDATA[cdatablock2]]>
162
+ </products>
163
+ </root>
164
+ eoxml
165
+ end
166
+
167
+ def test_children_with_text_and_cdata
168
+ assert_equal_rexml(<<-eoxml)
169
+ <root>
170
+ <products>
171
+ hello <![CDATA[cdatablock]]>
172
+ morning
173
+ </products>
174
+ </root>
175
+ eoxml
176
+ end
177
+
178
+ def test_children_with_blank_text
179
+ assert_equal_rexml(<<-eoxml)
180
+ <root>
181
+ <products> </products>
182
+ </root>
183
+ eoxml
184
+ end
185
+
186
+ def test_children_with_blank_text_and_attribute
187
+ assert_equal_rexml(<<-eoxml)
188
+ <root>
189
+ <products type="file"> </products>
190
+ </root>
191
+ eoxml
192
+ end
193
+
194
+
195
+ private
196
+ def assert_equal_rexml(xml)
197
+ hash = XmlMini.with_backend('REXML') { XmlMini.parse(xml) }
198
+ assert_equal(hash, XmlMini.parse(xml))
199
+ end
200
+ end
201
+
202
+ end
@@ -0,0 +1,193 @@
1
+ require 'test_helper'
2
+ # require 'active_support/xml_mini'
3
+ # require 'active_support/core_ext/hash/conversions'
4
+
5
+ begin
6
+ require 'libxml'
7
+ rescue LoadError
8
+ # Skip libxml tests
9
+ else
10
+
11
+ class LibXMLSAXEngineTest < MiniTest::Unit::TestCase
12
+
13
+ def setup
14
+ @default_backend = XmlMini.backend
15
+ XmlMini.backend = 'LibXMLSAX'
16
+ end
17
+
18
+ def teardown
19
+ XmlMini.backend = @default_backend
20
+ end
21
+
22
+ def test_exception_thrown_on_expansion_attack
23
+ assert_raises LibXML::XML::Error do
24
+ attack_xml = <<-EOT
25
+ <?xml version="1.0" encoding="UTF-8"?>
26
+ <!DOCTYPE member [
27
+ <!ENTITY a "&b;&b;&b;&b;&b;&b;&b;&b;&b;&b;">
28
+ <!ENTITY b "&c;&c;&c;&c;&c;&c;&c;&c;&c;&c;">
29
+ <!ENTITY c "&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;">
30
+ <!ENTITY d "&e;&e;&e;&e;&e;&e;&e;&e;&e;&e;">
31
+ <!ENTITY e "&f;&f;&f;&f;&f;&f;&f;&f;&f;&f;">
32
+ <!ENTITY f "&g;&g;&g;&g;&g;&g;&g;&g;&g;&g;">
33
+ <!ENTITY g "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx">
34
+ ]>
35
+ <member>
36
+ &a;
37
+ </member>
38
+ EOT
39
+
40
+ Hash.from_minixml(attack_xml)
41
+ end
42
+ end
43
+
44
+ def test_setting_libxml_as_backend
45
+ XmlMini.backend = 'LibXMLSAX'
46
+ assert_equal XmlMini_LibXMLSAX, XmlMini.backend
47
+ end
48
+
49
+ def test_blank_returns_empty_hash
50
+ assert_equal({}, XmlMini.parse(nil))
51
+ assert_equal({}, XmlMini.parse(''))
52
+ end
53
+
54
+ def test_array_type_makes_an_array
55
+ assert_equal_rexml(<<-eoxml)
56
+ <blog>
57
+ <posts type="array">
58
+ <post>a post</post>
59
+ <post>another post</post>
60
+ </posts>
61
+ </blog>
62
+ eoxml
63
+ end
64
+
65
+ def test_one_node_document_as_hash
66
+ assert_equal_rexml(<<-eoxml)
67
+ <products/>
68
+ eoxml
69
+ end
70
+
71
+ def test_one_node_with_attributes_document_as_hash
72
+ assert_equal_rexml(<<-eoxml)
73
+ <products foo="bar"/>
74
+ eoxml
75
+ end
76
+
77
+ def test_products_node_with_book_node_as_hash
78
+ assert_equal_rexml(<<-eoxml)
79
+ <products>
80
+ <book name="awesome" id="12345" />
81
+ </products>
82
+ eoxml
83
+ end
84
+
85
+ def test_products_node_with_two_book_nodes_as_hash
86
+ assert_equal_rexml(<<-eoxml)
87
+ <products>
88
+ <book name="awesome" id="12345" />
89
+ <book name="america" id="67890" />
90
+ </products>
91
+ eoxml
92
+ end
93
+
94
+ def test_single_node_with_content_as_hash
95
+ assert_equal_rexml(<<-eoxml)
96
+ <products>
97
+ hello world
98
+ </products>
99
+ eoxml
100
+ end
101
+
102
+ def test_children_with_children
103
+ assert_equal_rexml(<<-eoxml)
104
+ <root>
105
+ <products>
106
+ <book name="america" id="67890" />
107
+ </products>
108
+ </root>
109
+ eoxml
110
+ end
111
+
112
+ def test_children_with_text
113
+ assert_equal_rexml(<<-eoxml)
114
+ <root>
115
+ <products>
116
+ hello everyone
117
+ </products>
118
+ </root>
119
+ eoxml
120
+ end
121
+
122
+ def test_children_with_non_adjacent_text
123
+ assert_equal_rexml(<<-eoxml)
124
+ <root>
125
+ good
126
+ <products>
127
+ hello everyone
128
+ </products>
129
+ morning
130
+ </root>
131
+ eoxml
132
+ end
133
+
134
+ def test_parse_from_io
135
+ io = StringIO.new(<<-eoxml)
136
+ <root>
137
+ good
138
+ <products>
139
+ hello everyone
140
+ </products>
141
+ morning
142
+ </root>
143
+ eoxml
144
+ XmlMini.parse(io)
145
+ end
146
+
147
+ def test_children_with_simple_cdata
148
+ assert_equal_rexml(<<-eoxml)
149
+ <root>
150
+ <products>
151
+ <![CDATA[cdatablock]]>
152
+ </products>
153
+ </root>
154
+ eoxml
155
+ end
156
+
157
+ def test_children_with_multiple_cdata
158
+ assert_equal_rexml(<<-eoxml)
159
+ <root>
160
+ <products>
161
+ <![CDATA[cdatablock1]]><![CDATA[cdatablock2]]>
162
+ </products>
163
+ </root>
164
+ eoxml
165
+ end
166
+
167
+ def test_children_with_text_and_cdata
168
+ assert_equal_rexml(<<-eoxml)
169
+ <root>
170
+ <products>
171
+ hello <![CDATA[cdatablock]]>
172
+ morning
173
+ </products>
174
+ </root>
175
+ eoxml
176
+ end
177
+
178
+ def test_children_with_blank_text
179
+ assert_equal_rexml(<<-eoxml)
180
+ <root>
181
+ <products> </products>
182
+ </root>
183
+ eoxml
184
+ end
185
+
186
+ private
187
+ def assert_equal_rexml(xml)
188
+ hash = XmlMini.with_backend('REXML') { XmlMini.parse(xml) }
189
+ assert_equal(hash, XmlMini.parse(xml))
190
+ end
191
+ end
192
+
193
+ end
@@ -0,0 +1,215 @@
1
+ require 'test_helper'
2
+ # require 'active_support/xml_mini'
3
+ # require 'active_support/core_ext/hash/conversions'
4
+
5
+ begin
6
+ require 'nokogiri'
7
+ rescue LoadError
8
+ # Skip nokogiri tests
9
+ else
10
+
11
+ class NokogiriEngineTest < MiniTest::Unit::TestCase
12
+
13
+ def setup
14
+ @default_backend = XmlMini.backend
15
+ XmlMini.backend = 'Nokogiri'
16
+ end
17
+
18
+ def teardown
19
+ XmlMini.backend = @default_backend
20
+ end
21
+
22
+ def test_file_from_xml
23
+ hash = Hash.from_minixml(<<-eoxml)
24
+ <blog>
25
+ <logo type="file" name="logo.png" content_type="image/png">
26
+ </logo>
27
+ </blog>
28
+ eoxml
29
+ assert hash.has_key?('blog')
30
+ assert hash['blog'].has_key?('logo')
31
+
32
+ file = hash['blog']['logo']
33
+ assert_equal 'logo.png', file.original_filename
34
+ assert_equal 'image/png', file.content_type
35
+ end
36
+
37
+ def test_exception_thrown_on_expansion_attack
38
+ assert_raises Nokogiri::XML::SyntaxError do
39
+ attack_xml = <<-EOT
40
+ <?xml version="1.0" encoding="UTF-8"?>
41
+ <!DOCTYPE member [
42
+ <!ENTITY a "&b;&b;&b;&b;&b;&b;&b;&b;&b;&b;">
43
+ <!ENTITY b "&c;&c;&c;&c;&c;&c;&c;&c;&c;&c;">
44
+ <!ENTITY c "&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;">
45
+ <!ENTITY d "&e;&e;&e;&e;&e;&e;&e;&e;&e;&e;">
46
+ <!ENTITY e "&f;&f;&f;&f;&f;&f;&f;&f;&f;&f;">
47
+ <!ENTITY f "&g;&g;&g;&g;&g;&g;&g;&g;&g;&g;">
48
+ <!ENTITY g "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx">
49
+ ]>
50
+ <member>
51
+ &a;
52
+ </member>
53
+ EOT
54
+ Hash.from_minixml(attack_xml)
55
+ end
56
+ end
57
+
58
+ def test_setting_nokogiri_as_backend
59
+ XmlMini.backend = 'Nokogiri'
60
+ assert_equal XmlMini_Nokogiri, XmlMini.backend
61
+ end
62
+
63
+ def test_blank_returns_empty_hash
64
+ assert_equal({}, XmlMini.parse(nil))
65
+ assert_equal({}, XmlMini.parse(''))
66
+ end
67
+
68
+ def test_array_type_makes_an_array
69
+ assert_equal_rexml(<<-eoxml)
70
+ <blog>
71
+ <posts type="array">
72
+ <post>a post</post>
73
+ <post>another post</post>
74
+ </posts>
75
+ </blog>
76
+ eoxml
77
+ end
78
+
79
+ def test_one_node_document_as_hash
80
+ assert_equal_rexml(<<-eoxml)
81
+ <products/>
82
+ eoxml
83
+ end
84
+
85
+ def test_one_node_with_attributes_document_as_hash
86
+ assert_equal_rexml(<<-eoxml)
87
+ <products foo="bar"/>
88
+ eoxml
89
+ end
90
+
91
+ def test_products_node_with_book_node_as_hash
92
+ assert_equal_rexml(<<-eoxml)
93
+ <products>
94
+ <book name="awesome" id="12345" />
95
+ </products>
96
+ eoxml
97
+ end
98
+
99
+ def test_products_node_with_two_book_nodes_as_hash
100
+ assert_equal_rexml(<<-eoxml)
101
+ <products>
102
+ <book name="awesome" id="12345" />
103
+ <book name="america" id="67890" />
104
+ </products>
105
+ eoxml
106
+ end
107
+
108
+ def test_single_node_with_content_as_hash
109
+ assert_equal_rexml(<<-eoxml)
110
+ <products>
111
+ hello world
112
+ </products>
113
+ eoxml
114
+ end
115
+
116
+ def test_children_with_children
117
+ assert_equal_rexml(<<-eoxml)
118
+ <root>
119
+ <products>
120
+ <book name="america" id="67890" />
121
+ </products>
122
+ </root>
123
+ eoxml
124
+ end
125
+
126
+ def test_children_with_text
127
+ assert_equal_rexml(<<-eoxml)
128
+ <root>
129
+ <products>
130
+ hello everyone
131
+ </products>
132
+ </root>
133
+ eoxml
134
+ end
135
+
136
+ def test_children_with_non_adjacent_text
137
+ assert_equal_rexml(<<-eoxml)
138
+ <root>
139
+ good
140
+ <products>
141
+ hello everyone
142
+ </products>
143
+ morning
144
+ </root>
145
+ eoxml
146
+ end
147
+
148
+ def test_parse_from_io
149
+ io = StringIO.new(<<-eoxml)
150
+ <root>
151
+ good
152
+ <products>
153
+ hello everyone
154
+ </products>
155
+ morning
156
+ </root>
157
+ eoxml
158
+ XmlMini.parse(io)
159
+ end
160
+
161
+ def test_children_with_simple_cdata
162
+ assert_equal_rexml(<<-eoxml)
163
+ <root>
164
+ <products>
165
+ <![CDATA[cdatablock]]>
166
+ </products>
167
+ </root>
168
+ eoxml
169
+ end
170
+
171
+ def test_children_with_multiple_cdata
172
+ assert_equal_rexml(<<-eoxml)
173
+ <root>
174
+ <products>
175
+ <![CDATA[cdatablock1]]><![CDATA[cdatablock2]]>
176
+ </products>
177
+ </root>
178
+ eoxml
179
+ end
180
+
181
+ def test_children_with_text_and_cdata
182
+ assert_equal_rexml(<<-eoxml)
183
+ <root>
184
+ <products>
185
+ hello <![CDATA[cdatablock]]>
186
+ morning
187
+ </products>
188
+ </root>
189
+ eoxml
190
+ end
191
+
192
+ def test_children_with_blank_text
193
+ assert_equal_rexml(<<-eoxml)
194
+ <root>
195
+ <products> </products>
196
+ </root>
197
+ eoxml
198
+ end
199
+
200
+ def test_children_with_blank_text_and_attribute
201
+ assert_equal_rexml(<<-eoxml)
202
+ <root>
203
+ <products type="file"> </products>
204
+ </root>
205
+ eoxml
206
+ end
207
+
208
+ private
209
+ def assert_equal_rexml(xml)
210
+ hash = XmlMini.with_backend('REXML') { XmlMini.parse(xml) }
211
+ assert_equal(hash, XmlMini.parse(xml))
212
+ end
213
+ end
214
+
215
+ end