module Msf::Exploit::SQLi::Utils

  #
  # This module provides utilities used by the SQL injection library, none of the utilities are specific to SQL injection
  #
  module Common
    BIT_COUNTS = { 0 => 0, 0b1 => 1, 0b11 => 2, 0b111 => 3, 0b1111 => 4, 0b11111 => 5, 0b111111 => 6, 0b1111111 => 7, 0b11111111 => 8 }.freeze

    #
    #   Helper method, from a range of characters, returns the MSBs that are common to all of them, and the number of changing bits
    #   @param range [Range] the range of characters you expect in the output of the query
    #   @return [Array] an array with two integers, the bitmask consisting of bits not changing between characters in the range, and the number of bits changing
    #
    def self.get_bitmask(range)
      if range.begin.is_a?(String)
        range = range.map(&:ord)
      else
        range = range.to_a
      end
      raise ArgumentError, 'Invalid range' unless range.first >= 0 && range.last <= 255

      # the low bits that change between the ascii codes
      bitmask = range.each_cons(2).inject(0) { |m, (v1, v2)| m | (v1 ^ v2) }
      # the bits that remain the same
      known_bits = range[0] & ~bitmask
      bits_to_guess = BIT_COUNTS[bitmask]
      [known_bits, bits_to_guess]
    end
  end
end
