77
88module MultiXml
99 class ParseError < StandardError ; end
10+ class DisallowedTypeError < StandardError
11+ def initialize ( type )
12+ super "Disallowed type attribute: #{ type . inspect } "
13+ end
14+ end
1015
1116 REQUIREMENT_MAP = [
1217 [ 'ox' , :ox ] ,
@@ -54,6 +59,8 @@ class ParseError < StandardError; end
5459 'Hash' => 'hash'
5560 } unless defined? ( TYPE_NAMES )
5661
62+ DISALLOWED_XML_TYPES = %w( symbol yaml )
63+
5764 class << self
5865 # Get the current parser class.
5966 def parser
@@ -105,6 +112,8 @@ def parser=(new_parser)
105112 # <b>Options</b>
106113 #
107114 # <tt>:symbolize_keys</tt> :: If true, will use symbols instead of strings for the keys.
115+ #
116+ # <tt>:disallowed_types</tt> :: Types to disallow from being typecasted. Defaults to `['yaml', 'symbol']`. Use `[]` to allow all types.
108117 def parse ( xml , options = { } )
109118 xml ||= ''
110119
@@ -116,7 +125,9 @@ def parse(xml, options={})
116125 return { } if char . nil?
117126 xml . ungetc ( char )
118127
119- hash = typecast_xml_value ( undasherize_keys ( parser . parse ( xml ) ) ) || { }
128+ hash = typecast_xml_value ( undasherize_keys ( parser . parse ( xml ) ) , options [ :disallowed_types ] ) || { }
129+ rescue DisallowedTypeError
130+ raise
120131 rescue parser . parse_error => error
121132 raise ParseError , error . to_s , error . backtrace
122133 end
@@ -191,9 +202,15 @@ def undasherize_keys(params)
191202 end
192203 end
193204
194- def typecast_xml_value ( value )
205+ def typecast_xml_value ( value , disallowed_types = nil )
206+ disallowed_types ||= DISALLOWED_XML_TYPES
207+
195208 case value
196209 when Hash
210+ if value . include? ( 'type' ) && !value [ 'type' ] . is_a? ( Hash ) && disallowed_types . include? ( value [ 'type' ] )
211+ raise DisallowedTypeError , value [ 'type' ]
212+ end
213+
197214 if value [ 'type' ] == 'array'
198215
199216 # this commented-out suggestion helps to avoid the multiple attribute
@@ -216,9 +233,9 @@ def typecast_xml_value(value)
216233 else
217234 case entries
218235 when Array
219- entries . map { |entry | typecast_xml_value ( entry ) }
236+ entries . map { |entry | typecast_xml_value ( entry , disallowed_types ) }
220237 when Hash
221- [ typecast_xml_value ( entries ) ]
238+ [ typecast_xml_value ( entries , disallowed_types ) ]
222239 else
223240 raise "can't typecast #{ entries . class . name } : #{ entries . inspect } "
224241 end
@@ -252,7 +269,7 @@ def typecast_xml_value(value)
252269 nil
253270 else
254271 xml_value = value . inject ( { } ) do |hash , ( k , v ) |
255- hash [ k ] = typecast_xml_value ( v )
272+ hash [ k ] = typecast_xml_value ( v , disallowed_types )
256273 hash
257274 end
258275
@@ -261,7 +278,7 @@ def typecast_xml_value(value)
261278 xml_value [ 'file' ] . is_a? ( StringIO ) ? xml_value [ 'file' ] : xml_value
262279 end
263280 when Array
264- value . map! { |i | typecast_xml_value ( i ) }
281+ value . map! { |i | typecast_xml_value ( i , disallowed_types ) }
265282 value . length > 1 ? value : value . first
266283 when String
267284 value
0 commit comments