Sha256: 45256f7e4c330234596010b9997ee34e928c157e10d5ccb8f1003d9644d32fe8

Contents?: true

Size: 1.48 KB

Versions: 1

Compression:

Stored size: 1.48 KB

Contents

# frozen_string_literal: true

class MiniDefender::Rules::Integer < MiniDefender::Rule
  attr_reader :mode
  attr_reader :parsed

  DIGIT_MAP = {
    # Arabic-Indic Digits
    "\u0660" => '0',
    "\u0661" => '1',
    "\u0662" => '2',
    "\u0663" => '3',
    "\u0664" => '4',
    "\u0665" => '5',
    "\u0666" => '6',
    "\u0667" => '7',
    "\u0668" => '8',
    "\u0669" => '9',

    # Extended Arabic-Indic Digits
    "\u06F0" => '0',
    "\u06F1" => '1',
    "\u06F2" => '2',
    "\u06F3" => '3',
    "\u06F4" => '4',
    "\u06F5" => '5',
    "\u06F6" => '6',
    "\u06F7" => '7',
    "\u06F8" => '8',
    "\u06F9" => '9',
  }

  def initialize(mode = 'strict')
    @mode = mode
  end

  def self.signature
    'integer'
  end

  def self.make(args)
    new(args[0] || 'strict')
  end

  def coerce(value)
    @parsed
  end

  def passes?(attribute, value, validator)
    # Avoid converting integers to string and back
    if value.is_a?(Integer)
      @parsed = value
      return true
    end

    value = value.to_s

    if @mode == 'relaxed'
      value = normalize_digits(value)
    end

    @parsed = Integer(value)
  rescue
    false
  end

  def message(attribute, value, validator)
    "The value must be an integer."
  end

  def normalize_digits(data)
    # Check if arabic digits exist or avoid expensive string creation operation
    unless data.match?(/[\u0660-\u0669\u06F0-\u06F9]/)
      return data
    end

    DIGIT_MAP.each do |k, v|
      data = data.gsub(k, v)
    end

    data
  end
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
mini_defender-0.6.0 lib/mini_defender/rules/integer.rb