Class: Arachni::Browser::ElementLocator

Inherits:
Object
  • Object
show all
Defined in:
lib/arachni/browser/element_locator.rb

Overview

Lazy-loaded, Arachni::Browser element representation.

Author:

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

Constant Summary collapse

ARACHNI_ID =
'data-arachni-id'

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ ElementLocator

Returns a new instance of ElementLocator.

Parameters:

  • options (Hash) (defaults to: {})

    Data used to set attributes via setters.



29
30
31
32
# File 'lib/arachni/browser/element_locator.rb', line 29

def initialize( options = {} )
    options.each { |k, v| send( "#{k}=", v ) }
    @attributes ||= {}
end

Instance Attribute Details

#attributesHash

Returns Attributes of the element.

Returns:

  • (Hash)

    Attributes of the element.



25
26
27
# File 'lib/arachni/browser/element_locator.rb', line 25

def attributes
  @attributes
end

#tag_nameSymbol

Returns Tag name of the element.

Returns:

  • (Symbol)

    Tag name of the element.



21
22
23
# File 'lib/arachni/browser/element_locator.rb', line 21

def tag_name
  @tag_name
end

Class Method Details

.from_html(html) ⇒ Object



139
140
141
# File 'lib/arachni/browser/element_locator.rb', line 139

def self.from_html( html )
    from_node Parser.parse_fragment( html )
end

.from_node(node) ⇒ Object



143
144
145
146
147
148
149
150
# File 'lib/arachni/browser/element_locator.rb', line 143

def self.from_node( node )
    attributes = node.attributes.inject({}) do |h, (k, v)|
        h[k.to_s] = v.to_s
        h
    end

    new tag_name: node.name, attributes: attributes
end

.from_rpc_data(data) ⇒ ElementLocator

Parameters:

Returns:



127
128
129
# File 'lib/arachni/browser/element_locator.rb', line 127

def self.from_rpc_data( data )
    new data
end

.supported_element_attributes_for(tag_name) ⇒ Set<Symbol>

Returns List of attributes supported by Watir.

Parameters:

  • tag_name (String)

    Opening HTML tag of the element.

Returns:

  • (Set<Symbol>)

    List of attributes supported by Watir.



156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/arachni/browser/element_locator.rb', line 156

def self.supported_element_attributes_for( tag_name )
    @supported_element_attributes_for ||= {}

    tag_name = tag_name.to_sym

    if (klass = Watir.tag_to_class[tag_name])
        @supported_element_attributes_for[tag_name] ||=
            Set.new( klass.attribute_list )
    else
        @supported_element_attributes_for[tag_name] ||= Set.new
    end
end

Instance Method Details

#==(other) ⇒ Object



135
136
137
# File 'lib/arachni/browser/element_locator.rb', line 135

def ==( other )
    hash == other.hash
end

#cssObject



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/arachni/browser/element_locator.rb', line 73

def css
    attrs = {}

    # If there's an ID attribute that's good enough, don't include anything
    # else to avoid risking broken selectors due to dynamic attributes and
    # values.
    if attributes['id']
        attrs['id'] = attributes['id']

    # If we have our own attribute trust it more than the rest,
    # 'class' attributes and others can change dynamically.
    elsif attributes[ARACHNI_ID]
        attrs[ARACHNI_ID] = attributes[ARACHNI_ID]

    # Alternatively, exclude data attributes (except from ours ) to prevent
    # issues and use whatever other attributes are available.
    else
        attrs = attributes.reject do |k, v|
            k.to_s.start_with?( 'data-' )
        end
    end

    "#{tag_name}#{attrs.map { |k, v| "[#{k}=\"#{v.escape_double_quote}\"]"}.join}"
end

#dupObject



106
107
108
# File 'lib/arachni/browser/element_locator.rb', line 106

def dup
    self.class.new to_h
end

#hashObject



131
132
133
# File 'lib/arachni/browser/element_locator.rb', line 131

def hash
    to_hash.hash
end

#locatable_attributesHash

Returns Hash with attributes supported by `Watir` when locating elements.

Returns:

  • (Hash)

    Hash with attributes supported by `Watir` when locating elements.



52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/arachni/browser/element_locator.rb', line 52

def locatable_attributes
    attributes.inject({}) do |h, (k, v)|
        string_key = k.to_s
        attribute  = string_key.gsub( '-' ,'_' ).to_sym

        if !self.class.supported_element_attributes_for( tag_name ).include?( attribute ) &&
            !string_key.start_with?( 'data-' )
            next h
        end

        h[attribute] = v.to_s
        h
    end
end

#locate(browser) ⇒ Selenium::WebDriver::Element

Returns Locates and returns the element based on #css.

Returns:



69
70
71
# File 'lib/arachni/browser/element_locator.rb', line 69

def locate( browser )
    browser.selenium.find_element( :css, css )
end

#to_hashHash Also known as: to_h

Returns:



111
112
113
114
115
116
# File 'lib/arachni/browser/element_locator.rb', line 111

def to_hash
    {
        tag_name:   tag_name,
        attributes: attributes
    }
end

#to_rpc_dataHash

Returns Data representing this instance that are suitable the RPC transmission.

Returns:

  • (Hash)

    Data representing this instance that are suitable the RPC transmission.



121
122
123
# File 'lib/arachni/browser/element_locator.rb', line 121

def to_rpc_data
    to_h.my_stringify_keys
end

#to_sString Also known as: inspect

Returns Locator as an HTML opening tag.

Returns:

  • (String)

    Locator as an HTML opening tag.



100
101
102
103
# File 'lib/arachni/browser/element_locator.rb', line 100

def to_s
    "<#{tag_name}#{' ' if attributes.any?}" <<
        attributes.map { |k, v| "#{k}=\"#{v.escape_double_quote}\"" }.join( ' ' ) << '>'
end