Module: Ronin::Support::Encoding::HTTP

Defined in:
lib/ronin/support/encoding/http.rb

Overview

Contains methods for encoding/decoding escaping/unescaping HTTP data.

Features

  • Supports uppercase (ex: %FF) and lowercase (ex: %ff) URI encoding.

Core-Ext Methods

Since:

  • 1.0.0

Class Method Summary collapse

Class Method Details

.decode(data) ⇒ String

HTTP decodes the HTTP encoded String.

Examples:

Encoding::HTTP.decode("sweet+%26+sour")
# => "sweet & sour"

Parameters:

  • data (String)

    The HTTP encoded data to decode.

Returns:

  • (String)

    The decoded String.

Since:

  • 1.0.0



242
243
244
# File 'lib/ronin/support/encoding/http.rb', line 242

def self.decode(data)
  unescape(data)
end

.encode(data, **kwargs) ⇒ String

HTTP encodes each byte of the String.

Examples:

Encoding::HTTP.encode("hello")
# => "%68%65%6c%6c%6f"

Lowercase encoding:

Encoding::HTTP.encode("hello")
# => "%68%65%6c%6c%6f"

Parameters:

  • data (String)

    The data to HTTP encode.

  • kwargs (Hash{Symbol => Object})

    Additional keyword arguments.

Options Hash (**kwargs):

  • :case (:lower, :upper, nil)

    Controls whether to output lowercase or uppercase hexadecimal. Defaults to uppercase hexadecimal.

Returns:

  • (String)

    The HTTP hexadecimal encoded form of the String.

Raises:

  • (ArgumentError)

    The case: keyword argument was not :lower, :upper, or nil.

Since:

  • 1.0.0



219
220
221
222
223
224
225
226
227
# File 'lib/ronin/support/encoding/http.rb', line 219

def self.encode(data,**kwargs)
  encoded = String.new

  data.each_byte do |byte|
    encoded << encode_byte(byte,**kwargs)
  end

  return encoded
end

.encode_byte(byte, **kwargs) ⇒ String

Encodes the byte as an escaped HTTP decimal character.

Examples:

Encoding::HTTP.encode_byte(0x41)
# => "%41"

Lowercase encoding:

Encoding::HTTP.encode_byte(0xff, case: :lower)
# => "%ff"

Parameters:

  • byte (Integer)

    The byte toe HTTP encode.

  • kwargs (Hash{Symbol => Object})

    Additional keyword arguments.

Options Hash (**kwargs):

  • :case (:lower, :upper, nil)

    Controls whether to output lowercase or uppercase hexadecimal. Defaults to uppercase hexadecimal.

Returns:

  • (String)

    The encoded HTTP byte.

Raises:

  • (ArgumentError)

    The case: keyword argument was not :lower, :upper, or nil.

  • (RangeError)

    The byte value is negative or greater than 255.

Since:

  • 1.0.0



71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/ronin/support/encoding/http.rb', line 71

def self.encode_byte(byte,**kwargs)
  if (byte >= 0) && (byte <= 0xff)
    case kwargs[:case]
    when :lower
      "%%%.2x" % byte
    when :upper, nil
      "%%%.2X" % byte
    else
      raise(ArgumentError,"case (#{kwargs[:case].inspect}) keyword argument must be either :lower, :upper, or nil")
    end
  else
    raise(RangeError,"#{byte.inspect} out of char range")
  end
end

.escape(data, **kwargs) ⇒ String

HTTP escapes the special characters in the given data.

Examples:

Encoding::HTTP.escape("x > y")
# => "x+%3E+y"

Lowercase encoding:

Encoding::HTTP.escape("x > y", case: :lower)
# => "x+%3e+y"

Parameters:

  • data (String)

    The data to HTTP escape.

  • kwargs (Hash{Symbol => Object})

    Additional keyword arguments.

Options Hash (**kwargs):

  • :case (:lower, :upper, nil)

    Controls whether to output lowercase or uppercase hexadecimal. Defaults to uppercase hexadecimal.

Returns:

  • (String)

    The HTTP escaped form of the String.

Raises:

  • (ArgumentError)

    The case: keyword argument was not :lower, :upper, or nil.

Since:

  • 1.0.0



159
160
161
162
163
164
165
166
167
# File 'lib/ronin/support/encoding/http.rb', line 159

def self.escape(data,**kwargs)
  escaped = String.new

  data.each_byte do |byte|
    escaped << escape_byte(byte,**kwargs)
  end

  return escaped
end

.escape_byte(byte, **kwargs) ⇒ String

HTTP escapes the Integer.

Examples:

Encoding::HTTP.escape_byte(0x41)
# => "A"
Encoding::HTTP.escape_byte(62)
# => "%3E"

Lowercase encoding:

Encoding::HTTP.escape_byte(0xff, case: :lower)
# => "%ff"

Parameters:

  • byte (Integer)

    The byte toe HTTP escape.

  • kwargs (Hash{Symbol => Object})

    Additional keyword arguments.

Options Hash (**kwargs):

  • :case (:lower, :upper, nil)

    Controls whether to output lowercase or uppercase hexadecimal. Defaults to uppercase hexadecimal.

Returns:

  • (String)

    The HTTP escaped form of the Integer.

Raises:

  • (ArgumentError)

    The case: keyword argument was not :lower, :upper, or nil.

  • (RangeError)

    The byte value is negative or greater than 255.

Since:

  • 1.0.0



118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/ronin/support/encoding/http.rb', line 118

def self.escape_byte(byte,**kwargs)
  if (byte >= 0) && (byte <= 0xff)
    if (byte == 45) || (byte == 46) || ((byte >= 48) && (byte <= 57)) || ((byte >= 65) && (byte <= 90)) || (byte == 95) || ((byte >= 97) && (byte <= 122)) || (byte == 126)
      byte.chr
    elsif byte == 0x20
      '+'
    else
      encode_byte(byte,**kwargs)
    end
  else
    raise(RangeError,"#{byte.inspect} out of char range")
  end
end

.unescape(data) ⇒ String

HTTP unescapes the String.

Examples:

Encoding::HTTP.unescape("sweet+%26+sour")
# => "sweet & sour"

Parameters:

  • data (String)

    The data to unescape.

Returns:

  • (String)

    The raw String.

Since:

  • 1.0.0



182
183
184
185
186
187
188
189
190
# File 'lib/ronin/support/encoding/http.rb', line 182

def self.unescape(data)
  data.gsub(/(?:\+|%[A-Fa-f0-9]{2})/) do |escaped_char|
    if escaped_char == '+'
      ' '
    else
      escaped_char[1..].to_i(16).chr
    end
  end
end