class Cruncher::Commands::Scan

Public Class Methods

new(url, options) click to toggle source
# File lib/cruncher/commands/scan.rb, line 8
def initialize(url, options)
  @url = url
  @options = options
end

Public Instance Methods

execute(input: $stdin, output: $stdout) click to toggle source
# File lib/cruncher/commands/scan.rb, line 13
def execute(input: $stdin, output: $stdout)
  require 'tty-box'

  box = TTY::Box.frame "Cookie Cruncher", padding: [0,2], align: :center, border: :thick
  output.puts(box + "\n")

  require 'sitemaps'
  require 'phantomjs'
  require 'json'
  require 'pastel'
  require 'tty-spinner'
  require 'tty-progressbar'
  require 'tty-table'

  pastel = Pastel.new
  phantomjs_file = File.join(File.dirname(__FILE__), "./fetch.js")

  spinner = TTY::Spinner.new("[:spinner] Fetching sitemap from #{pastel.white.bold(@url)}", format: :dots, hide_cursor: true)
  spinner.auto_spin 

  sitemap = Sitemaps.fetch(@url)
  
  nb_pages = sitemap.entries.length
  spinner.success("(done - #{nb_pages} pages found)")
  cookies = {}

  spinner = TTY::Spinner.new("[:spinner] #{pastel.dim('(:current/:total)')} scanning :title", format: :dots, hide_cursor: true)
  spinner.auto_spin 

  sitemap.entries.map(&:loc).each_with_index do |loc,i|
    spinner.update(title: pastel.white.bold(loc.to_s), current: i + 1, total: nb_pages)

    s = StringIO.new
  
    Phantomjs.run(phantomjs_file, loc.to_s) { |line| s << line }
    json = JSON.parse(s.string)
  
    cookies_for_page = Array(json.fetch('cookies'))
    cookies_for_page.each do |cookie|
      domain = cookie["domain"].to_s.gsub(/^\./,'')
      name = cookie["name"]
      cookies[name] ||= cookie
      cookies[name]['domain'] = domain
      cookies[name]['found_on'] ||= []
      cookies[name]['found_on'] << loc.path.to_s
    end
  end
  spinner.success("(done)\n")

  data_for_table = cookies.keys.sort.map do |name|
    cookie = cookies[name]
    [
      cookie["domain"],
      cookie["name"],
      cookie["expires"],
      cookie['found_on'].length == nb_pages ? pastel.dim('all pages') : cookie['found_on'].join("\n")
    ]
  end.sort_by(&:first)
  table = TTY::Table.new(['Domain','Name','Expiration','Found on'], data_for_table)
  
  output.puts table.render(:ascii, padding: [0,1], multiline: true)
end