Class: Arachni::Component::Manager

Inherits:
Hash show all
Includes:
UI::Output
Defined in:
lib/arachni/component/manager.rb

Overview

Handles modules, reports, path extractor modules, plug-ins, pretty much every modular aspect of the framework.

It is usually extended to fill-in for system specific functionality.

Examples:


# create a namespace for our components
module Components
end

LIB       = "#{File.dirname( __FILE__ )}/lib/"
NAMESPACE = Components

# $ ls LIB
#   component1.rb  component2.rb
#
# $ cat LIB/component1.rb
#   class Components::Component1
#   end
#
# $ cat LIB/component2.rb
#   class Components::Component2
#   end

p components = Arachni::Component::Manager.new( LIB, NAMESPACE )
#=> {}

p components.available
#=> ["component2", "component1"]

p components.load_all
#=> ["component2", "component1"]

p components
#=> {"component2"=>Components::Component2, "component1"=>Components::Component1}

p components.clear
#=> {}

p components.load :component1
#=> ["component1"]

p components
#=> {"component1"=>Components::Component1}

p components.clear
#=> {}

p components[:component2]
#=> Components::Component2

Author:

Constant Summary collapse

WILDCARD =
'*'
EXCLUDE =
'-'

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from UI::Output

#debug?, #debug_off, #debug_on, #disable_only_positives, #error_logfile, #flush_buffer, #log_error, #mute, #muted?, old_reset_output_options, #only_positives, #only_positives?, #print_bad, #print_debug, #print_debug_backtrace, #print_debug_pp, #print_error, #print_error_backtrace, #print_info, #print_line, #print_ok, #print_status, #print_verbose, #reroute_to_file, #reroute_to_file?, reset_output_options, #set_buffer_cap, #set_error_logfile, #uncap_buffer, #unmute, #verbose, #verbose?

Methods inherited from Hash

#downcase, #find_symbol_keys_recursively, #recode, #stringify_keys, #symbolize_keys

Constructor Details

#initialize(lib, namespace) ⇒ Manager

Returns a new instance of Manager.

Parameters:

  • lib (String)

    The path to the component library/directory.

  • namespace (Module, Class)

    Namespace under which all components are directly defined.



116
117
118
119
# File 'lib/arachni/component/manager.rb', line 116

def initialize( lib, namespace )
    @lib = lib
    @namespace = namespace
end

Instance Attribute Details

#libString (readonly)

Returns The path to the component library/directory.

Returns:

  • (String)

    The path to the component library/directory.



105
106
107
# File 'lib/arachni/component/manager.rb', line 105

def lib
  @lib
end

#namespaceModule (readonly)

Returns Namespace under which all components are directly defined.

Returns:

  • (Module)

    Namespace under which all components are directly defined.



109
110
111
# File 'lib/arachni/component/manager.rb', line 109

def namespace
  @namespace
end

Instance Method Details

#[](name) ⇒ Class

Fetches a component’s class by name, loading it on the fly if need be.

Parameters:

  • name (String, Symbol)

    Component name.

Returns:

  • (Class)

    Component.



284
285
286
287
288
# File 'lib/arachni/component/manager.rb', line 284

def []( name )
    name = name.to_s
    return fetch( name ) if include?( name )
    self[name] = load_from_path( name_to_path( name ) )
end

#availableArray

Returns Names of available components.

Returns:

  • (Array)

    Names of available components.



317
318
319
# File 'lib/arachni/component/manager.rb', line 317

def available
    paths.map{ |path| path_to_name( path ) }
end

#clearObject Also known as: unload_all

Unloads all loaded components.



296
297
298
# File 'lib/arachni/component/manager.rb', line 296

def clear
    keys.each { |l| delete( l ) }
end

#delete(name) ⇒ Object Also known as: unload

Unloads a component by name.

Parameters:

  • name (String, Symbol)

    Component name.



306
307
308
309
310
311
312
313
# File 'lib/arachni/component/manager.rb', line 306

def delete( name )
    name = name.to_s
    begin
        @namespace.send( :remove_const, fetch( name ).to_s.split( ':' ).last.to_sym )
    rescue
    end
    super( name )
end

#include?(k) ⇒ Boolean Also known as: loaded?

Returns:

  • (Boolean)


290
291
292
# File 'lib/arachni/component/manager.rb', line 290

def include?( k )
    super( k.to_s )
end

#load(*components) ⇒ Array

Loads components.

Parameters:

  • components (Array<String,Symbol>)

    Components to load.

Returns:

  • (Array)

    Names of loaded components.



129
130
131
# File 'lib/arachni/component/manager.rb', line 129

def load( *components )
    parse( [components].flatten ).each { |component| self.[]( component ) }
end

#load_allArray

Loads all components, equivalent of ‘load ’*‘`.

Returns:

  • (Array)

    Names of loaded components.



138
139
140
# File 'lib/arachni/component/manager.rb', line 138

def load_all
    load '*'
end

#load_by_tags(tags) ⇒ Array

Loads components by the tags found in the ‘Hash` returned by their `.info` method (tags should be in either: `:tags` or `:issue`).

Parameters:

  • tags (Array)

    Tags to look for in components.

Returns:

  • (Array)

    Components loaded.



150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/arachni/component/manager.rb', line 150

def load_by_tags( tags )
    return [] if !tags

    tags = [tags].flatten.compact.map( &:to_s )
    return [] if tags.empty?

    load_all
    map do |k, v|
        component_tags  = [v.info[:tags]]
        component_tags |= [v.info[:issue][:tags]] if v.info[:issue]
        component_tags  = [component_tags].flatten.uniq.compact

        if !component_tags.includes_tags?( tags )
            delete( k )
            next
        end
        k
    end.compact
end

#loadedArray

Returns Names of loaded components.

Returns:

  • (Array)

    Names of loaded components.



322
323
324
# File 'lib/arachni/component/manager.rb', line 322

def loaded
    keys
end

#name_to_path(name) ⇒ String

Converts the name of a component to a its file’s path.

Parameters:

  • name (String)

    Name of the component.

Returns:

  • (String)

    Path to component file.



333
334
335
336
# File 'lib/arachni/component/manager.rb', line 333

def name_to_path( name )
    paths.each { |path| return path if name.to_s == path_to_name( path ) }
    nil
end

#parse(components) ⇒ Array

It parses the component array making sure that its structure is valid and takes into consideration wildcard and exclusion modifiers.

Parameters:

  • components (Array<String,Symbol>)

    Component names.

Returns:

  • (Array)

    Components to load.



227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
# File 'lib/arachni/component/manager.rb', line 227

def parse( components )
    unload = []
    load   = []

    components = [components].flatten.map( &:to_s )

    return load if components[0] == EXCLUDE

    components = components.deep_clone

    components.each do |component|
        if component[0] == EXCLUDE
            component[0] = ''

            if component[WILDCARD]
                unload |= wilcard_to_names( component )
            else
                unload << component
            end

        end
    end

    if !components.include?( WILDCARD )

        avail_components  = available(  )

        components.each do |component|

            if component.substring?( WILDCARD )
                load |= wilcard_to_names( component )
            else

                if avail_components.include?( component )
                    load << component
                else
                    fail Error::NotFound,
                         "Component '#{component}' could not be found."
                end
            end
        end

        load.flatten!
    else
        available.each{ |component| load << component }
    end

    load - unload
end

#path_to_name(path) ⇒ String

Converts the path of a component to a component name.

Parameters:

  • path (String)

    File-path of the component.

Returns:

  • (String)

    Component name.



345
346
347
# File 'lib/arachni/component/manager.rb', line 345

def path_to_name( path )
    File.basename( path, '.rb' )
end

#pathsArray

Returns Paths of all available components (excluding helper files).

Returns:

  • (Array)

    Paths of all available components (excluding helper files).



351
352
353
# File 'lib/arachni/component/manager.rb', line 351

def paths
    Dir.glob( File.join( "#{@lib}**", "*.rb" ) ).reject{ |path| helper?( path ) }
end

#prep_opts(component_name, component, user_opts = {}) ⇒ Hash

Validates and prepares options for a given component.

Parameters:

  • component_name (String)

    Name of the component.

  • component (Class)

    Component.

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

    User options.

Returns:

  • (Hash)

    Prepared options to be passed to the component.

Raises:



182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
# File 'lib/arachni/component/manager.rb', line 182

def prep_opts( component_name, component, user_opts = {} )
    info = component.info
    return {} if !info.include?( :options ) || info[:options].empty?

    user_opts ||= {}
    options = {}
    errors  = {}
    info[:options].each do |opt|
        name = opt.name
        val  = user_opts[name] || opt.default

        if opt.empty_required_value?( val )
            errors[name] = {
                opt:   opt,
                value: val,
                type:  :empty_required_value
            }
        elsif !opt.valid?( val )
            errors[name] = {
                opt:   opt,
                value: val,
                type:  :invalid
            }
        end

        options[name] = opt.normalize( val )
    end

    if !errors.empty?
        fail Component::Options::Error::Invalid,
             format_error_string( component_name, errors )
    end

    options
end