class Rack::Cleanser::InvalidURIEncoding

Public Instance Methods

[](env) click to toggle source
# File lib/rack/cleanser/invalid_uri_encoding.rb, line 49
def [](env)
  # Check and clean up trailing % characters by replacing them with their
  # encoded equivalent %25
  %w[
    HTTP_REFERER
    PATH_INFO
    QUERY_STRING
    REQUEST_PATH
    REQUEST_URI
    HTTP_X_FORWARDED_HOST
  ].each do |key|
    unless /\A(?:%[0-9a-fA-F]{2}|[^%])*\z/.match?(env[key].to_s)
      env[key] = env[key].gsub(/%(?![0-9a-fA-F]{2})/, "%25")
    end
    raise_404_error if check_nested(env[key]) == :bad_query
  end

  # use these methods to get params as there is conflict with openresty
  # request_params = Rack::Request.new(env).params
  post_params = {}

  post_params = if env["CONTENT_TYPE"].match?(%r{\Amultipart/form-data.*boundary=\"?([^\";,]+)\"?}n)
                  {}
                else
                  Rack::Utils.parse_query(env["rack.input"].read, "&")
                end

  get_params = Rack::Utils.parse_query(env["QUERY_STRING"], "&")
  request_params = {}.merge(get_params).merge(post_params)

  # Because env['rack.input'] is String IO object, so we need to rewind
  # that to ensure it can be read again by others.
  env["rack.input"].rewind

  raise_404_error if check_encoding(request_params) == :bad_encoding

  # make sure the authenticity token is a string
  request_params.keys.each do |key|
    raise_404_error if key.match?(/\Aauthenticity_token\[(.)*\]\z/)
  end
end
all_values_for_hash(hash) click to toggle source

to get all values from a nested hash (i.e a hash contains hashes/arrays) e.g. {:a => 1, :b => {:ba => 2, :bb => [3, 4]}} gives you [1, 2, 3, 4]

# File lib/rack/cleanser/invalid_uri_encoding.rb, line 28
def all_values_for_hash(hash)
  result = []
  hash.values.each do |hash_value|
    case hash_value
    when Hash
      result += all_values_for_hash(hash_value)
    when Array
      # convert the array to hash
      sub_hash = Hash[
        hash_value.flatten.map.with_index do |value, index|
          [index, value]
        end
      ]
      result += all_values_for_hash(sub_hash)
    else
      result << hash_value
    end
  end
  result
end
check_encoding(query) click to toggle source

General Checking for user's input params throw 404 if params contain abnormal input

# File lib/rack/cleanser/invalid_uri_encoding.rb, line 11
def check_encoding(query)
  # make sure all params have valid encoding
  all_values_for_hash(query).each do |param|
    if param.respond_to?(:valid_encoding?) && !param.valid_encoding?
      return :bad_encoding
    end
  end
end
check_nested(query) click to toggle source
# File lib/rack/cleanser/invalid_uri_encoding.rb, line 20
def check_nested(query)
  Rack::Utils.parse_nested_query(query)
rescue
  :bad_query
end
raise_404_error() click to toggle source
# File lib/rack/cleanser/invalid_uri_encoding.rb, line 91
def raise_404_error
  raise ActionController::RoutingError.new("Not Found")
end