class Arachni::Element::LinkTemplate

Represents an auditable link element whose inputs have been extracted based on an externally provided template.

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

Attributes

template[R]

@return [Regexp]

Regular expressions with named captures, serving as templates used to
identify and manipulate inputs in {#action}.

Private Class Methods

decode( *args ) click to toggle source
# File lib/arachni/element/link_template.rb, line 213
def decode( *args )
    Link.decode( *args )
end
encode( string ) click to toggle source
# File lib/arachni/element/link_template.rb, line 209
def encode( string )
    Link.encode string
end
extract_inputs( url, templates = Arachni::Options.audit.link_templates ) click to toggle source

Extracts inputs from a URL based on the given templates.

@param [String] url @param [Array<Regexp>] templates

@return [Array[Regexp, Hash]]

Matched template and inputs.
# File lib/arachni/element/link_template.rb, line 194
def extract_inputs( url, templates = Arachni::Options.audit.link_templates )
    return [] if !url || templates.empty?

    templates.each do |template|
        if (match = url.scan_in_groups( template )).any?
            return [
                template,
                match.inject({}){ |h, (k, v)| h[k] = decode(v); h }
            ]
        end
    end

    []
end
from_parser( parser, templates = Arachni::Options.audit.link_templates ) click to toggle source

Extracts link with inputs based on the provided {Arachni::OptionGroups::Audit#link_templates templates} from a document.

@param [Arachni::Parser] parser @param [Array<Regexp>] templates

@return [Array<LinkTemplate>]

# File lib/arachni/element/link_template.rb, line 163
def from_parser( parser, templates = Arachni::Options.audit.link_templates )
    return [] if templates.empty?

    parser.document.nodes_by_name( :a ).map do |link|
        next if too_big?( link['href'] )
        next if !(href = to_absolute( link['href'], parser.base ))

        template, inputs = extract_inputs( href, templates )
        next if !template && !self::DOM.data_from_node( link )

        if (parsed_url = Arachni::URI( href ))
            next if parsed_url.scope.out?
        end

        new(
            url:      parser.url,
            action:   href.freeze,
            inputs:   inputs || {},
            template: template,
            source:   link.to_html.freeze
        )
    end.compact
end
from_response( response, templates = Arachni::Options.audit.link_templates ) click to toggle source

Extracts links from an HTTP response.

@param [Arachni::HTTP::Response] response @param [Array<Regexp>] templates

@return [Array<Link>]

# File lib/arachni/element/link_template.rb, line 137
def from_response( response, templates = Arachni::Options.audit.link_templates )
    url = response.url

    links = from_parser( Arachni::Parser.new( response ) , templates )

    template, inputs = extract_inputs( url, templates )
    if template
        links << new(
            url:      url.freeze,
            action:   url.freeze,
            inputs:   inputs,
            template: template
        )
    end

    links
end
from_rpc_data( data ) click to toggle source
Calls superclass method Arachni::Element::Base::from_rpc_data
# File lib/arachni/element/link_template.rb, line 118
def from_rpc_data( data )
    if data['initialization_options']['template']
        data['initialization_options']['template'] =
            Regexp.new( data['initialization_options']['template'] )
    end

    if data['template']
        data['template'] = Regexp.new( data['template'] )
    end

    super data
end
new( options ) click to toggle source

@param [Hash] options @option options [String] :url

URL of the page which includes the link.

@option options [String] :action

Link URL -- defaults to `:url`.

@option options [Hash] :inputs

Query parameters as `name => value` pairs. If none have been provided
they will automatically be extracted from {#action}.
# File lib/arachni/element/link_template.rb, line 51
def initialize( options )
    super( options )

    @template = options[:template]

    if options[:inputs]
        self.inputs = options[:inputs]
    else
        if @template
            _, inputs = self.class.extract_inputs( self.action, [@template] )
            self.inputs = inputs if inputs
        else
            @template, inputs = self.class.extract_inputs( self.action )

            if @template
                self.inputs = inputs
            end
        end
    end

    self.inputs ||= {}
    @default_inputs = self.inputs.dup.freeze
end
type() click to toggle source
# File lib/arachni/element/link_template.rb, line 217
def type
    :link_template
end

Private Instance Methods

decode( *args ) click to toggle source
# File lib/arachni/element/link_template.rb, line 96
def decode( *args )
    self.class.decode( *args )
end
encode( string ) click to toggle source
# File lib/arachni/element/link_template.rb, line 92
def encode( string )
    self.class.encode( string )
end
http_request( opts, &block ) click to toggle source
# File lib/arachni/element/link_template.rb, line 224
def http_request( opts, &block )
    opts.delete :parameters

    self.method != :get ?
        http.post( to_s, opts, &block ) :
        http.get( to_s, opts, &block )
end
id() click to toggle source
# File lib/arachni/element/link_template.rb, line 100
def id
    dom_data ? "#{super}:#{dom_data[:inputs].sort_by { |k,_| k }}" : super
end
simple() click to toggle source

@return [Hash]

Simple representation of self in the form of `{ {#action} => {#inputs} }`.
# File lib/arachni/element/link_template.rb, line 77
def simple
    { self.action => self.inputs }
end
to_rpc_data() click to toggle source
# File lib/arachni/element/link_template.rb, line 104
def to_rpc_data
    data = super
    data.delete 'dom_data'

    return data if !@template

    data.merge!( 'template' => @template.source )
    data['initialization_options']['template'] = data['template']

    data
end
to_s() click to toggle source

@return [String]

URL updated with the configured {#inputs}.
# File lib/arachni/element/link_template.rb, line 83
def to_s
    return self.action if self.inputs.empty?

    self.action.sub_in_groups(
        @template,
        inputs.inject({}) { |h, (k, v)| h[k] = encode(v); h }
    )
end