<commit_before>=begin
                  Arachni
  Copyright (c) 2010 Tasos "Zapotek" Laskos <<EMAIL>>

  This is free software; you can copy and distribute and modify
  this program under the term of the GPL v2.0 License
  (See LICENSE file for details)

=end

module Arachni

#
# Arachni::AuditStore class
#
# Represents a finished audit session.<br/>
# It holds information about the runtime environment,
# the results of the audit etc...
#
# @author: Tasos "Zapotek" Laskos
#                                      <<EMAIL>>
#                                      <<EMAIL>>
# @version: 0.1.1
#
class AuditStore

    #
    # @return    [String]    the version of the framework
    #
    attr_reader :version

    #
    # @return    [String]    the revision of the framework class
    #
    attr_reader :revision

    #
    # @return    [Hash]    the runtime arguments/options of the environment
    #
    attr_reader :options

    #
    # @return    [Array]   all the urls crawled
    #
    attr_reader :sitemap

    #
    # @return    [Array<Vulnerability>]  the discovered vulnerabilities
    #
    attr_reader :vulns

    #
    # @return    [String]    the date and time when the audit started
    #
    attr_reader :start_datetime

    #
    # @return    [String]    the date and time when the audit finished
    #
    attr_reader :finish_datetime

    #
    # @return    [String]    how long the audit took
    #
    attr_reader :delta_time

    def initialize( audit = {} )

        # set instance variables from audit opts
        audit.each {
            |k, v|
            self.instance_variable_set( '@' + k.to_s, v )
        }

        @options         = prepare_options( @options )
        @vulns           = prepare_variations( @vulns )
        @start_datetime  = @options['start_datetime'].asctime

        if @options['finish_datetime']
            @finish_datetime = @options['finish_datetime'].asctime
        else
            @finish_datetime = Time.now.asctime
        end

        @delta_time      = secs_to_hms( @options['delta_time'] )
    end

    #
    # Loads and returns an AuditStore object from file
    #
    # @param    [String]    file    the file to load
    #
    # @return    [AuditStore]
    #
    def AuditStore.load( file )
         Marshal.load( IO.read( file ) )
    end

    #
    # Saves 'self' to file
    #
    # @param    [String]    file
    #
    def save( file )
        f = File.open( file, 'w' )
        Marshal.dump( self, f )
    end

    #
    # Returns 'self' and all objects in its instance vars as hashes
    #
    # @return    [Hash]
    #
    def to_h

        hash = obj_to_hash( self )

        vulns = []
        hash['vulns'].each {
            |vuln|
            vulns << obj_to_hash( vuln )
        }

        hash['vulns'] = vulns
        return hash
    end

    private

    #
    # Converts obj to hash
    #
    # @param    [Object]  obj    instance of an object
    #
    # @return    [Hash]
    #
    def obj_to_hash( obj )
        hash = Hash.new
        obj.instance_variables.each {
            |var|

            key       = var.to_s.gsub( /@/, '' )
            hash[key] = obj.instance_variable_get( var )

        }

        return hash
    end

    #
    # Prepares the hash to be stored in {AuditStore#options}
    #
    # The 'options' dimention of the array that initializes AuditObjects<br/>
    # needs some more processing before being saved in {AuditStore#options}.
    #
    # @param    [Hash]<commit_msg>added vulnerability sorting<commit_after>=begin
                  Arachni
  Copyright (c) 2010 <NAME>" Laskos <<EMAIL>>

  This is free software; you can copy and distribute and modify
  this program under the term of the GPL v2.0 License
  (See LICENSE file for details)

=end

module Arachni

require Options.instance.dir['lib'] + 'vulnerability'

#
# Arachni::AuditStore class
#
# Represents a finished audit session.<br/>
# It holds information about the runtime environment,
# the results of the audit etc...
#
# @author: Tasos "Zapotek" Laskos
#                                      <<EMAIL>>
#                                      <<EMAIL>>
# @version: 0.1.1
#
class AuditStore

    #
    # @return    [String]    the version of the framework
    #
    attr_reader :version

    #
    # @return    [String]    the revision of the framework class
    #
    attr_reader :revision

    #
    # @return    [Hash]    the runtime arguments/options of the environment
    #
    attr_reader :options

    #
    # @return    [Array]   all the urls crawled
    #
    attr_reader :sitemap

    #
    # @return    [Array<Vulnerability>]  the discovered vulnerabilities
    #
    attr_reader :vulns

    #
    # @return    [String]    the date and time when the audit started
    #
    attr_reader :start_datetime

    #
    # @return    [String]    the date and time when the audit finished
    #
    attr_reader :finish_datetime

    #
    # @return    [String]    how long the audit took
    #
    attr_reader :delta_time


    ORDER = [
        ::Arachni::Vulnerability::Severity::HIGH,
        ::Arachni::Vulnerability::Severity::MEDIUM,
        ::Arachni::Vulnerability::Severity::LOW,
        ::Arachni::Vulnerability::Severity::INFORMATIONAL
    ]

    def initialize( audit = {} )

        # set instance variables from audit opts
        audit.each {
            |k, v|
            self.instance_variable_set( '@' + k.to_s, v )
        }

        @options         = prepare_options( @options )
        @vulns           = sort( prepare_variations( @vulns ) )
        @start_datetime  = @options['start_datetime'].asctime

        if @options['finish_datetime']
            @finish_datetime = @options['finish_datetime'].asctime
        else
            @finish_datetime = Time.now.asctime
        end

        @delta_time      = secs_to_hms( @options['delta_time'] )

    end

    #
    # Loads and returns an AuditStore object from file
    #
    # @param    [String]    file    the file to load
    #
    # @return    [AuditStore]
    #
    def AuditStore.load( file )
         Marshal.load( IO.read( file ) )
    end

    #
    # Saves 'self' to file
    #
    # @param    [String]    file
    #
    def save( file )
        f = File.open( file, 'w' )
        Marshal.dump( self, f )
    end

    #
    # Returns 'self' and all objects in its instance vars as hashes
    #
    # @return    [Hash]
    #
    def to_h

        hash = obj_to_hash( self )

        vulns = []
        hash['vulns'].each {
            |vuln|
            vulns << obj_to_hash( vuln )
        }

        hash['vulns'] = vulns
        return hash
    end

    private

    def sort( vulns )
        sorted = []
        vulns.each {
            |vuln|
            sorted[ORDER.rindex( vuln.severity )] ||= []
            sorted[ORDER.rindex( vuln.severity )] << vuln
        }

        return sorted.flatten.reject{ |vuln| vuln.nil? }
    end


    #
    # Converts obj to hash
    #
    # @param    [Object]  obj    instance of an object
    #
    # @return    [Hash]
    #
    def obj_to_hash( obj )
        hash = Hash.new
        obj.instance_variables.each {
            |var|

            key       = var.to_s.gsub( /@/, '' )
            hash[key] = obj.instance_variable_get( var )

        }

        return hash
    end

    #
    # Prepares the hash to be stored in {AuditStore#options}
    #
    # The 'options' dimention of the array that initializes AuditObjects<br/>
    # needs some more processing before being saved in {AuditStore#options}.
    #
    # @param    [Hash]
{'fraction_non_alphanumeric': 0.09621492853361567, 'fraction_numerical': 0.002382212811011117, 'mean_word_length': 1.768131868131868, 'pattern_counts': {'":': 0, '<': 28, '<?xml version=': 0, '>': 22, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2712341', 'n_tokens_mistral': 2411, 'n_tokens_neox': 2329, 'n_words': 641}