#!/usr/bin/env jruby

require ‘buby’ require ‘irb’ require ‘optparse’

args = {}

begin

opts = OptionParser.new do |o|
  o.banner = "Usage: #{File.basename $0} [options]"

  o.on_tail("-h", "--help", "Show this help message") do
    raise opts.to_s
  end

  o.on("-i", "--interactive", "Start IRB") { args[:interactive] = :irb }

  o.on("-p", "--pry", "Start pry") { args[:interactive] = :pry }

  o.on("-d", "--debug", "Debug info") { args[:debug] = true }

  o.on("-B", "--load-burp=PATH", "Load Burp Jar from PATH") do |b|
    args[:load_burp] = b
  end

  o.on("-P", "--proxy-interception", "Enable intercept on load") {args[:proxy_interception] = true}

  o.on('-s', '--state=FILE', "Restore burp state file on startup") do |r|
    args[:restore] = r
  end

  o.on('-r', '--require=LIB', 
       'load a ruby lib (or jar) after Burp loads') do |i|
    (args[:requires] ||= []).push(i)
  end

  o.on('-e', '--extend=MOD', 
       'Extend Buby with a module (loaded via -r?)') do |m|
    (args[:extensions] ||= []).push(m)
  end

  o.on('-v', '--version', 'Prints version and exits.') do 
    puts "#{File.basename $0} v#{Buby::VERSION}"
    exit 0
  end
end

opts.parse!(ARGV)

if jar=args[:load_burp]
  raise "Load Burp Error: #{jar} did not provide burp.StartBurp" unless Buby.load_burp(jar)
end

raise "Load Burp Error: Specify a path to your burp.jar with -B" unless Buby.burp_loaded?

rescue

STDERR.puts $!
exit 1

end

$DEBUG=true if args

$burp = Buby#start_burp

until $burp.burp_callbacks

puts 'Waiting for burp callbacks...' if $DEBUG
sleep 0.1

end

if libs=args

libs.each {|lib| STDERR.puts "Loading: #{lib.inspect}"; require(lib)}

end

def resolve_const(str)

raise "can't resolve empty name #{str.inspect}" if str.empty?
names = str.split('::')
obj = ::Object
names.each do |name|
  raise "#{name.inspect} is not defined" unless obj.const_defined?(name)
  obj = obj.const_get(name)
end
return obj if obj != ::Object

end

if mods=args

mods.each do |mod|
  obj = resolve_const(mod)
  raise "#{obj.name} is not a module" unless obj.kind_of? Module
  STDERR.puts "Extending $burp with: #{obj.name}"
  $burp.extend(obj)
  if $burp.respond_to?(imeth=:"init_#{mod.split('::').last}")
    $burp.__send__ imeth
  end
end

end

if f=args

raise "no such file #{f.inspect}" unless File.exists?(f)
STDERR.puts "Restoring burp state from: #{f.inspect}"
$burp.restore_state(f)

end

$burp.proxy_interception = false unless args

case args when :irb

# yucky hack...
IRB.setup(nil)
IRB.conf[:IRB_NAME] = File.basename($0, ".rb")
module IRB
  class <<self
    def setup(*args); end
  end
end
puts "Starting IRB: Global $burp is set to #{$burp.inspect}",
     " Important Note: exit with $burp.close"
IRB.start()

when :pry

require 'pry'
puts "Starting Pry: Global $burp is set to #{$burp.inspect}",
     " Important Note: exit with $burp.close"
Pry.start

end