module Arachni::Element::Capabilities::Inputtable

@author Tasos “Zapotek” Laskos <tasos.laskos@arachni-scanner.com>

Constants

INPUTTABLE_CACHE

Attributes

default_inputs[R]

Frozen version of {#inputs}, has all the original names and values.

@return [Hash]

inputs[R]

@note Can be modified via {#update}, {#[]=} or {#inputs=}.

@return [Hash]

Frozen effective inputs.
raw_inputs[R]

@note Null-bytes will always be encoded.

@return [Array]

List of input names which should have their values submitted in raw
form, without encoding.

Public Class Methods

inputtable_id( inputs, raw_inputs ) click to toggle source
# File lib/arachni/element/capabilities/inputtable.rb, line 271
def self.inputtable_id( inputs, raw_inputs )
    INPUTTABLE_CACHE[:inputtable_id].fetch [inputs, raw_inputs] do
        id  = inputs ? inputs.sort_by { |k, _| k }.hash.to_s : ''
        id << ':'
        id << (raw_inputs ? raw_inputs.sort.hash.to_s : '')
    end
end
new( options ) click to toggle source
Calls superclass method
# File lib/arachni/element/capabilities/inputtable.rb, line 62
def initialize( options )
    super
    @raw_inputs = []
end

Public Instance Methods

[]( name ) click to toggle source

Shorthand {#inputs} reader.

@param [#to_s] name

Name.

@return [String]

# File lib/arachni/element/capabilities/inputtable.rb, line 155
def []( name )
    @inputs[name.to_s]
end
[]=( name, value ) click to toggle source

Shorthand {#inputs} writer.

@param [#to_s] name

Name.

@param [#to_s] value

Value.

@raise [Error::InvalidData::Name] @raise [Error::InvalidData::Value]

# File lib/arachni/element/capabilities/inputtable.rb, line 168
def []=( name, value )
    update( name.to_s => value.to_s )
    self[name]
end
changes() click to toggle source

@return [Hash]

Returns changes make to the {#inputs}'s inputs.
# File lib/arachni/element/capabilities/inputtable.rb, line 128
def changes
    (@default_inputs.keys | @inputs.keys).inject( {} ) do |h, k|
        if @default_inputs[k] != @inputs[k]
            h[k] = @inputs[k]
        end
        h
    end
end
dup() click to toggle source
Calls superclass method
# File lib/arachni/element/capabilities/inputtable.rb, line 261
def dup
    copy_inputtable( super )
end
has_inputs?( *args ) click to toggle source

Checks whether or not the given inputs match the inputs ones.

@param [Hash, Array, String, Symbol] args

Names of inputs to check (also accepts var-args).

@return [Bool]

# File lib/arachni/element/capabilities/inputtable.rb, line 116
def has_inputs?( *args )
    if (h = args.first).is_a?( Hash )
        h.each { |k, v| return false if self[k] != v }
        true
    else
        keys = args.flatten.compact.map { |a| [a].map(&:to_s) }.flatten
        (@inputs.keys & keys).size == keys.size
    end
end
inputs=( hash ) click to toggle source

@note Will convert keys and values to strings.

@param [Hash] hash

Input data.

@raise [Error::InvalidData::Name] @raise [Error::InvalidData::Value]

# File lib/arachni/element/capabilities/inputtable.rb, line 95
def inputs=( hash )
    sanitized = {}

    (hash || {}).each do |name, value|
        name  = name.to_s
        value = value.to_s

        fail_if_invalid( name, value )

        sanitized[name.freeze] = value.freeze
    end

    @inputs = sanitized.freeze
end
inputtable_id() click to toggle source

@return [String]

Uniquely identifies the {#inputs}.
# File lib/arachni/element/capabilities/inputtable.rb, line 267
def inputtable_id
    Arachni::Element::Capabilities::Inputtable.inputtable_id( inputs, raw_inputs )
end
raw_input?( name ) click to toggle source

@param [String] name

Name of the input to check.

@return [Boolean]

`true` if the input `name` is in {#raw_inputs}, `false` otherwise.
# File lib/arachni/element/capabilities/inputtable.rb, line 72
def raw_input?( name )
    @raw_inputs.include? name
end
raw_inputs=( raw ) click to toggle source

@note Will convert names to strings.

@param [Array] raw

Input names whose values should not be encoded during submission.

@raise [Error::InvalidData::Name]

# File lib/arachni/element/capabilities/inputtable.rb, line 82
def raw_inputs=( raw )
    names = raw.map(&:to_s)
    names.each { |name| fail_if_invalid_name( name ) }
    @raw_inputs = raw.map(&:to_s)
end
reset() click to toggle source

Resets the inputs to their original format/values.

Calls superclass method
# File lib/arachni/element/capabilities/inputtable.rb, line 142
def reset
    super if defined?( super )
    self.inputs = @default_inputs.rpc_clone
    self.raw_inputs = []
    self
end
to_h() click to toggle source
Calls superclass method
# File lib/arachni/element/capabilities/inputtable.rb, line 279
def to_h
    (defined?( super ) ? super : {}).merge(
        inputs:         inputs,
        raw_inputs:     raw_inputs,
        default_inputs: default_inputs
    )
end
try_input( &block ) click to toggle source

Performs an input operation and silently handles {Error::InvalidData}.

@param [Block] block

Input operation to try to perform.

@return [Bool]

`true` if the operation was successful, `false` otherwise.
# File lib/arachni/element/capabilities/inputtable.rb, line 250
def try_input( &block )
    block.call
    true
rescue Error::InvalidData => e
    return false if !respond_to?( :print_debug_level_1 )

    print_debug_level_1 e.to_s
    e.backtrace.each { |l| print_debug_level_1 l }
    false
end
update( hash ) click to toggle source

@param [Hash] hash

Inputs with which to update the {#inputs} inputs.

@return [Auditable] ‘self`

@raise [Error::InvalidData::Name] @raise [Error::InvalidData::Value]

# File lib/arachni/element/capabilities/inputtable.rb, line 180
def update( hash )
    return self if hash.empty?

    self.inputs = @inputs.merge( hash )
    self
end
updated?() click to toggle source
# File lib/arachni/element/capabilities/inputtable.rb, line 137
def updated?
    @default_inputs != self.inputs
end
valid_input_data?( data ) click to toggle source

@param [String] data

Data to check.

@return [Bool]

`true` if the data can be carried by the element's inputs, `false`
otherwise.

@abstract

# File lib/arachni/element/capabilities/inputtable.rb, line 239
def valid_input_data?( data )
    true
end
valid_input_name?( name ) click to toggle source

@param [String] name

Name to check.

@return [Bool]

`true` if the name can be carried by the element's inputs, `false`
otherwise.

@abstract

# File lib/arachni/element/capabilities/inputtable.rb, line 195
def valid_input_name?( name )
    true
end
valid_input_name_data?( name ) click to toggle source

@param [String] name

Name to check.

@return [Bool]

`true` if `name` is both a {#valid_input_name?} and contains
{#valid_input_data?}.
# File lib/arachni/element/capabilities/inputtable.rb, line 205
def valid_input_name_data?( name )
    valid_input_name?( name ) && valid_input_data?( name )
end
valid_input_value?( value ) click to toggle source

@param [String] value

Value to check.

@return [Bool]

`true` if the value can be carried by the element's inputs, `false`
otherwise.

@abstract

# File lib/arachni/element/capabilities/inputtable.rb, line 217
def valid_input_value?( value )
    true
end
valid_input_value_data?( value ) click to toggle source

@param [String] value

Value to check.

@return [Bool]

`true` if `value` is both a {#valid_input_value?} and contains
{#valid_input_data?}.
# File lib/arachni/element/capabilities/inputtable.rb, line 227
def valid_input_value_data?( value )
    valid_input_value?( value ) && valid_input_data?( value )
end

Private Instance Methods

copy_inputtable( other ) click to toggle source
# File lib/arachni/element/capabilities/inputtable.rb, line 318
def copy_inputtable( other )
    other.inputs     = self.inputs.dup
    other.raw_inputs = self.raw_inputs.dup
    other
end
fail_if_invalid( name, value ) click to toggle source
# File lib/arachni/element/capabilities/inputtable.rb, line 313
def fail_if_invalid( name, value )
    fail_if_invalid_name( name )
    fail_if_invalid_value( value )
end
fail_if_invalid_name( name ) click to toggle source
# File lib/arachni/element/capabilities/inputtable.rb, line 289
def fail_if_invalid_name( name )
    if !valid_input_data?( name.to_s )
        fail Error::InvalidData::Name,
             "Invalid data in input name for #{self.class}: #{name.inspect}"
    end

    if !valid_input_name?( name.to_s )
        fail Error::InvalidData::Name,
             "Invalid name for #{self.class}: #{name.inspect}"
    end
end
fail_if_invalid_value( value ) click to toggle source
# File lib/arachni/element/capabilities/inputtable.rb, line 301
def fail_if_invalid_value( value )
    if !valid_input_data?( value.to_s )
        fail Error::InvalidData::Value,
             "Invalid data in input value for #{self.class}: #{value.inspect}"
    end

    if !valid_input_value?( value.to_s )
        fail Error::InvalidData::Value,
             "Invalid value for #{self.class}: #{value.inspect}"
    end
end