class Arachni::Snapshot

Stores and provides access to the state of the system.

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

Attributes

location[RW]

@return [String]

Location of the {.load loaded} snapshot.
metadata[RW]

@return [Hash]

Metadata associated with the {.load loaded} snapshot.

Public Class Methods

dump( location ) click to toggle source

@param [String] location

Location of the snapshot.

@return [String]

Location of the snapshot.
# File lib/arachni/snapshot.rb, line 71
def dump( location )
    FileUtils.rm_rf( location )

    directory = get_temporary_directory

    FileUtils.rm_rf( directory )
    FileUtils.mkdir_p( directory )

    begin
        Data.dump( "#{directory}/data/" )
        State.dump( "#{directory}/state/" )

        compress directory, location

        # Append metadata to the end of the file.
        metadata = Marshal.dump( prepare_metadata )
        File.open( location, 'ab' ) do |f|
            f.write [metadata, metadata.size].pack( 'a*N' )
        end

        location
    ensure
        FileUtils.rm_rf( directory )
    end
end
load( snapshot ) click to toggle source

@param [String] snapshot

Location of the snapshot to load.

@return [Snapshot]

`self`

@raise [Error::InvalidFile]

When trying to read an invalid file.
# File lib/arachni/snapshot.rb, line 105
def load( snapshot )
    directory = get_temporary_directory

    @location = snapshot
    @metadata = read_metadata( snapshot )

    extract( snapshot, directory )

    Data.load( "#{directory}/data/" )
    State.load( "#{directory}/state/" )

    self
end
read_metadata( snapshot ) click to toggle source

@param [String] snapshot

Location of the snapshot.

@return [Hash]

Metadata associated with the given snapshot.

@raise [Error::InvalidFile]

When trying to read an invalid file.
# File lib/arachni/snapshot.rb, line 127
def read_metadata( snapshot )
    File.open( snapshot, 'rb' ) do |f|
        f.seek -4, IO::SEEK_END
        metadata_size = f.read( 4 ).unpack( 'N' ).first

        f.seek -metadata_size-4, IO::SEEK_END
        Marshal.load( f.read( metadata_size ) )
    end
rescue => e
    ne = Error::InvalidFile.new( "Invalid snapshot: #{snapshot} (#{e})" )
    ne.set_backtrace e.backtrace
    raise ne
end
reset() click to toggle source
# File lib/arachni/snapshot.rb, line 46
def reset
    @metadata = nil
    @location = nil
end
restored?() click to toggle source

@return [Bool]

`true` if this is a restored snapshot, `false` otherwise.
# File lib/arachni/snapshot.rb, line 53
def restored?
    !!location
end
summary() click to toggle source

@return [Hash]

Snapshot summary information.
# File lib/arachni/snapshot.rb, line 59
def summary
    {
        data:  Data.statistics,
        state: State.statistics
    }
end

Private Class Methods

compress( directory, archive ) click to toggle source
# File lib/arachni/snapshot.rb, line 167
def compress( directory, archive )
    # Globs on Windows don't accept \ as a separator since it's an escape character.
    directory = directory.gsub( '\\', '/' ) + '/'
    directory.gsub!( /\/+/, '/' )

    Zip::File.open( archive, Zip::File::CREATE ) do |zipfile|
        Dir[directory + '**/**'].each do |file|
            zipfile.add( file.sub( directory, '' ), file )
        end
    end

    archive
end
extract( archive, directory ) click to toggle source
# File lib/arachni/snapshot.rb, line 155
def extract( archive, directory )
    Zip::File.open( archive ) do |zip_file|
        zip_file.each do |f|
            f_path = File.join( directory, f.name )
            FileUtils.mkdir_p( File.dirname( f_path ) )
            zip_file.extract( f, f_path ) unless File.exist?( f_path )
        end
    end

    directory
end
get_temporary_directory() click to toggle source
# File lib/arachni/snapshot.rb, line 151
def get_temporary_directory
    "#{Options.paths.tmpdir}/Arachni_Snapshot_#{Utilities.generate_token}/"
end
prepare_metadata() click to toggle source
# File lib/arachni/snapshot.rb, line 143
def prepare_metadata
    {
        timestamp: Time.now,
        version:   Arachni::VERSION,
        summary:   summary
    }
end