Module: Ronin::Support::Encoding::XML
- Defined in:
- lib/ronin/support/encoding/xml.rb
Overview
Contains methods for encoding/decoding escaping/unescaping XML data.
Features
- Supports lowercase (ex:
&
) and uppercase (ex:&
) encoding. - Supports decimal (ex:
A
) and hexadecimal (ex:A
) character encoding. - Supports zero-padding (ex:
A
).
Core-Ext Methods
Constant Summary collapse
- ESCAPE_BYTES =
Special bytes and their escaped XML characters.
{ 39 => ''', 38 => '&', 34 => '"', 60 => '<', 62 => '>' }
- ESCAPE_BYTES_UPPERCASE =
Special bytes and their escaped XML characters, but in uppercase.
{ 39 => ''', 38 => '&', 34 => '"', 60 => '<', 62 => '>' }
- ESCAPED_CHARS =
XML escaped characters and their unescaped forms.
{ ''' => "'", '&' => '&', '"' => '"', '<' => '<', '>' => '>' }
Class Method Summary collapse
-
.decode(data) ⇒ String
Alias for XML.unescape.
-
.encode(data, **kwargs) ⇒ String
Encodes each character in the given data as an XML character.
-
.encode_byte(byte, format: :decimal, zero_pad: false, **kwargs) ⇒ String
Encodes the byte as a XML decimal character.
-
.escape(data, **kwargs) ⇒ String
XML escapes the data.
-
.escape_byte(byte, **kwargs) ⇒ String
Escapes the byte as a XML decimal character.
-
.unescape(data) ⇒ String
Unescapes the XML encoded data.
Class Method Details
.decode(data) ⇒ String
Alias for unescape.
243 244 245 |
# File 'lib/ronin/support/encoding/xml.rb', line 243 def self.decode(data) unescape(data) end |
.encode(data, **kwargs) ⇒ String
Encodes each character in the given data as an XML character.
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 |
# File 'lib/ronin/support/encoding/xml.rb', line 216 def self.encode(data,**kwargs) encoded = String.new if data.valid_encoding? data.each_codepoint do |codepoint| encoded << encode_byte(codepoint,**kwargs) end else data.each_byte do |byte| encoded << encode_byte(byte,**kwargs) end end return encoded end |
.encode_byte(byte, format: :decimal, zero_pad: false, **kwargs) ⇒ String
Encodes the byte as a XML decimal character.
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 |
# File 'lib/ronin/support/encoding/xml.rb', line 150 def self.encode_byte(byte, format: :decimal, zero_pad: false, **kwargs) case format when :decimal if zero_pad then "&#%.7d;" % byte else "&#%d;" % byte end when :hex case kwargs[:case] when :upper if zero_pad then "&#X%.7X;" % byte else "&#X%.2X;" % byte end when :lower, nil if zero_pad then "&#x%.7x;" % byte else "&#x%.2x;" % byte end else raise(ArgumentError,"case (#{kwargs[:case].inspect}) keyword argument must be either :lower, :upper, or nil") end else raise(ArgumentError,"format (#{format.inspect}) must be :decimal or :hex") end end |
.escape(data, **kwargs) ⇒ String
XML escapes the data.
274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 |
# File 'lib/ronin/support/encoding/xml.rb', line 274 def self.escape(data,**kwargs) escaped = String.new if data.valid_encoding? data.each_codepoint do |codepoint| escaped << escape_byte(codepoint,**kwargs) end else data.each_byte do |byte| escaped << escape_byte(byte,**kwargs) end end return escaped end |
.escape_byte(byte, **kwargs) ⇒ String
Escapes the byte as a XML decimal character.
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/ronin/support/encoding/xml.rb', line 91 def self.escape_byte(byte,**kwargs) table = case kwargs[:case] when :upper then ESCAPE_BYTES_UPPERCASE when :lower, nil then ESCAPE_BYTES else raise(ArgumentError,"case (#{kwargs[:case].inspect}) keyword argument must be either :lower, :upper, or nil") end table.fetch(byte) do if (byte >= 0 && byte <= 0xff) byte.chr(Encoding::ASCII_8BIT) else byte.chr(Encoding::UTF_8) end end end |
.unescape(data) ⇒ String
Unescapes the XML encoded data.
314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 |
# File 'lib/ronin/support/encoding/xml.rb', line 314 def self.unescape(data) unescaped = String.new(encoding: Encoding::UTF_8) scanner = StringScanner.new(data) until scanner.eos? unescaped << if (named_char = scanner.scan(/&(?:apos|amp|quot|lt|gt);/i)) ESCAPED_CHARS.fetch(named_char.downcase) elsif (decimal_char = scanner.scan(/&#\d+;/)) decimal_char[2..-2].to_i.chr(Encoding::UTF_8) elsif (hex_char = scanner.scan(/&#x[a-f0-9]+;/i)) hex_char[3..-2].to_i(16).chr(Encoding::UTF_8) else scanner.getch end end return unescaped end |