class Arachni::State::Framework
State
information for {Arachni::Framework}.
@author Tasos “Zapotek” Laskos <tasos.laskos@arachni-scanner.com>
Attributes
@return [Integer]
@return [Set]
@return [Support::LookUp::HashSet]
@return [Support::LookUp::HashSet]
@return [Array]
@return [RPC]
@return [Bool]
@return [Symbol]
@return [Array<String>]
@return [Support::LookUp::HashSet]
Public Class Methods
# File lib/arachni/state/framework.rb, line 420 def self.load( directory ) framework = new framework.rpc = RPC.load( "#{directory}/rpc/" ) %w(element_pre_check_filter page_queue_filter url_queue_filter browser_skip_states).each do |attribute| path = "#{directory}/#{attribute}" next if !File.exist?( path ) framework.send(attribute).merge Marshal.load( IO.binread( path ) ) end framework.audited_page_count = Marshal.load( IO.binread( "#{directory}/audited_page_count" ) ) framework end
# File lib/arachni/state/framework.rb, line 68 def initialize @rpc = RPC.new @audited_page_count = 0 @browser_skip_states = Support::LookUp::HashSet.new( hasher: :persistent_hash ) @page_queue_filter = Support::LookUp::HashSet.new( hasher: :persistent_hash ) @url_queue_filter = Support::LookUp::HashSet.new( hasher: :persistent_hash ) @element_pre_check_filter = Support::LookUp::HashSet.new( hasher: :coverage_hash ) @running = false @pre_pause_status = nil @pause_signals = Set.new @paused_signal = Queue.new @suspended_signal = Queue.new @aborted_signal = Queue.new @status_messages = [] end
Public Instance Methods
@param [Bool] block
`true` if the method should block until an abortion has completed, `false` otherwise.
@return [Bool]
`true` if the abort request was successful, `false` if the system is already {#suspended?} or is {#suspending?}.
@raise [StateNotAbortable]
When not {#running?}.
# File lib/arachni/state/framework.rb, line 225 def abort( block = true ) return false if aborting? || aborted? if !running? fail Error::StateNotAbortable, 'Cannot abort an idle state.' end set_status_message :aborting @status = :aborting @abort = true @aborted_signal.pop if block true end
@return [Bool]
`true` if a {#abort} signal is in place , `false` otherwise.
# File lib/arachni/state/framework.rb, line 242 def abort? !!@abort end
Signals a completed abort operation.
# File lib/arachni/state/framework.rb, line 247 def aborted @abort = false @status = :aborted @aborted_signal << true nil end
@return [Bool]
`true` if the system has been aborted, `false` otherwise.
# File lib/arachni/state/framework.rb, line 256 def aborted? @status == :aborted end
@return [Bool]
`true` if the system is being aborted, `false` otherwise.
# File lib/arachni/state/framework.rb, line 262 def aborting? @status == :aborting end
Pushes a message to {#status_messages}.
@param [String, Symbol] message
Status message. If `Symbol`, it will be grabbed from {#available_status_messages}.
@param [String, Numeric] sprintf
`sprintf` arguments.
# File lib/arachni/state/framework.rb, line 131 def add_status_message( message, *sprintf ) if message.is_a? Symbol if !available_status_messages.include?( message ) fail Error::InvalidStatusMessage, "Could not find status message for: '#{message}'" end message = available_status_messages[message] % sprintf end @status_messages << message.to_s end
@return [Hash{Symbol=>String}]
All possible {#status_messages} by type.
# File lib/arachni/state/framework.rb, line 100 def available_status_messages { suspending: 'Will suspend as soon as the current page is audited.', waiting_for_browser_cluster_jobs: 'Waiting for %i browser cluster jobs to finish.', suspending_plugins: 'Suspending plugins.', saving_snapshot: 'Saving snapshot at: %s', snapshot_location: 'Snapshot location: %s', browser_cluster_startup: 'Initialising the browser cluster.', browser_cluster_shutdown: 'Shutting down the browser cluster.', clearing_queues: 'Clearing the audit queues.', waiting_for_plugins: 'Waiting for the plugins to finish.', aborting: 'Aborting the scan.' } end
# File lib/arachni/state/framework.rb, line 437 def clear rpc.clear @element_pre_check_filter.clear @page_queue_filter.clear @url_queue_filter.clear @pause_signals.clear @paused_signal.clear @suspended_signal.clear @running = false @pre_pause_status = nil @browser_skip_states.clear @audited_page_count = 0 end
Clears {#status_messages}.
# File lib/arachni/state/framework.rb, line 145 def clear_status_messages @status_messages.clear end
@return [Bool]
`true` if the system has completed successfully, `false` otherwise.
# File lib/arachni/state/framework.rb, line 268 def done? @status == :done end
# File lib/arachni/state/framework.rb, line 409 def dump( directory ) FileUtils.mkdir_p( directory ) rpc.dump( "#{directory}/rpc/" ) %w(element_pre_check_filter page_queue_filter url_queue_filter browser_skip_states audited_page_count).each do |attribute| IO.binwrite( "#{directory}/#{attribute}", Marshal.dump( send(attribute) ) ) end end
@param [Page] e
Element to mark as seen.
@see element_checked?
# File lib/arachni/state/framework.rb, line 207 def element_checked( e ) @element_pre_check_filter << e end
@param [#coverage_hash] e
@return [Bool]
`true` if the element has already been seen (based on the {#element_pre_check_filter}), `false` otherwise.
@see element_checked
# File lib/arachni/state/framework.rb, line 199 def element_checked?( e ) @element_pre_check_filter.include? e end
# File lib/arachni/state/framework.rb, line 403 def force_resume @pause_signals.to_a.each do |ref| resume ref end end
@param [Page] page
Page to mark as seen.
@see page_seen?
# File lib/arachni/state/framework.rb, line 164 def page_seen( page ) @page_queue_filter << page end
@param [Page] page
@return [Bool]
`true` if the `page` has already been seen (based on the {#page_queue_filter}), `false` otherwise.
@see page_seen
# File lib/arachni/state/framework.rb, line 156 def page_seen?( page ) @page_queue_filter.include? page end
@param [Object] caller
Identification for the caller which issued the pause signal.
@param [Bool] block
`true` if the method should block until the pause has completed, `false` otherwise.
@return [TrueClass]
Pauses the framework on a best effort basis, might take a while to take effect.
# File lib/arachni/state/framework.rb, line 342 def pause( caller, block = true ) @pre_pause_status ||= @status if !paused? && !pausing? if !paused? @status = :pausing end @pause_signals << caller paused if !running? @paused_signal.pop if block && !paused? true end
@return [Bool]
`true` if the framework should pause, `false` otherwise.
# File lib/arachni/state/framework.rb, line 378 def pause? @pause_signals.any? end
Signals that the system has been paused..
# File lib/arachni/state/framework.rb, line 358 def paused clear_status_messages @status = :paused @paused_signal << nil end
@return [Bool]
`true` if the framework is paused.
# File lib/arachni/state/framework.rb, line 366 def paused? @status == :paused end
@return [Bool]
`true` if the system is being paused, `false` otherwise.
# File lib/arachni/state/framework.rb, line 372 def pausing? @status == :pausing end
Resumes a paused system
@param [Object] caller
Identification for the caller whose {#pause} signal to remove. The system is resumed once there are no more {#pause} signals left.
@return [Bool]
`true` if the system is resumed, `false` if there are more {#pause} signals pending.
# File lib/arachni/state/framework.rb, line 391 def resume( caller ) @pause_signals.delete( caller ) if @pause_signals.empty? @status = @pre_pause_status @pre_pause_status = nil return true end false end
# File lib/arachni/state/framework.rb, line 211 def running? !!@running end
@return [Bool]
`true` if the system is scanning, `false` otherwise.
# File lib/arachni/state/framework.rb, line 329 def scanning? @status == :scanning end
Sets a message as {#status_messages}.
@param (see add_status_message
) @return (see add_status_message
)
# File lib/arachni/state/framework.rb, line 119 def set_status_message( *args ) clear_status_messages add_status_message( *args ) end
# File lib/arachni/state/framework.rb, line 90 def statistics { rpc: @rpc.statistics, audited_page_count: @audited_page_count, browser_states: @browser_skip_states.size } end
@param [Bool] block
`true` if the method should block until a suspend has completed, `false` otherwise.
@return [Bool]
`true` if the suspend request was successful, `false` if the system is already {#suspended?} or is {#suspending?}.
@raise [StateNotSuspendable]
When {#paused?} or {#pausing?}.
# File lib/arachni/state/framework.rb, line 282 def suspend( block = true ) return false if suspending? || suspended? if paused? || pausing? fail Error::StateNotSuspendable, 'Cannot suspend a paused state.' end if !running? fail Error::StateNotSuspendable, 'Cannot suspend an idle state.' end set_status_message :suspending @status = :suspending @suspend = true @suspended_signal.pop if block true end
@return [Bool]
`true` if an {#abort} signal is in place , `false` otherwise.
# File lib/arachni/state/framework.rb, line 303 def suspend? !!@suspend end
Signals a completed suspension.
# File lib/arachni/state/framework.rb, line 308 def suspended @suspend = false @status = :suspended @suspended_signal << true nil end
@return [Bool]
`true` if the system has been suspended, `false` otherwise.
# File lib/arachni/state/framework.rb, line 317 def suspended? @status == :suspended end
@return [Bool]
`true` if the system is being suspended, `false` otherwise.
# File lib/arachni/state/framework.rb, line 323 def suspending? @status == :suspending end
@param [Support::LookUp::HashSet] states
# File lib/arachni/state/framework.rb, line 188 def update_browser_skip_states( states ) @browser_skip_states.merge states end
@param [Page] url
URL to mark as seen.
@see url_seen?
# File lib/arachni/state/framework.rb, line 183 def url_seen( url ) @url_queue_filter << url end
@param [String] url
@return [Bool]
`true` if the `url` has already been seen (based on the {#url_queue_filter}), `false` otherwise.
@see url_seen
# File lib/arachni/state/framework.rb, line 175 def url_seen?( url ) @url_queue_filter.include? url end