# -*- coding: binary -*-
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# https://metasploit.com/framework/

require 'net/https'
require 'net/http'
require 'uri'

module Msf

module Auxiliary::Web

class Fuzzable

  # load and include all available analysis/audit techniques
  lib = File.dirname( __FILE__ ) + '/analysis/*.rb'
  Dir.glob( lib ).each { |f| require f }
  Analysis.constants.each { |technique| include Analysis.const_get( technique ) }

  attr_accessor :fuzzer

  def fuzzed?( opts = {} )
    fuzzer.checked? fuzz_id( opts )
  end

  def fuzzed( opts = {} )
    fuzzer.checked fuzz_id( opts )
  end

  def fuzz_id( opts = {} )
    "#{opts[:type]}:#{fuzzer.shortname}:#{method}:#{action}:#{params.keys.sort.to_s}:#{altered}=#{altered_value}"
  end

  def fuzz( cfuzzer = nil, &callback )
    fuzz_wrapper( cfuzzer ) { |p| callback.call( p.submit, p ) }
  end

  def fuzz_async( cfuzzer = nil, &callback )
    fuzz_wrapper( cfuzzer ) { |p| p.submit_async { |res| callback.call( res, p ) } }
  end

  def submit( opts = {} )
    fuzzer.increment_request_counter if fuzzer

    http.request( *request( opts ) )
  end

  def submit_async( opts = {}, &callback )
    fuzzer.increment_request_counter

    http.request_async( *request( opts ) ) do |resp|
      callback.call resp if callback
    end

    nil
  end

  def http
    fuzzer.http
  end

  def hash
    to_hash.hash
  end

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

  def dup
    cf = self.fuzzer
    self.fuzzer = nil
    ce = Marshal.load( Marshal.dump( self ) )
    self.fuzzer = ce.fuzzer = cf
    ce
  end

  private
  def fuzz_wrapper( cfuzzer = nil, &block )
    self.fuzzer ||= cfuzzer
    permutations.each do |p|
      block.call p
    end
  end

end

end
end
