diff --git a/README.md b/README.md index 420b434..2ba69f5 100644 --- a/README.md +++ b/README.md @@ -5,17 +5,22 @@ Extract cookies from Firefox, Chrome or Chromium sqlite cookie stores into a wge ### Install ### -gem install cookie_extractor + gem install cookie_extractor ### Usage ### -cookie_extractor /path/to/firefox/cookies.sqlite > cookies.txt + cookie_extractor /path/to/firefox/cookies.sqlite > cookies.txt + + cookie_extractor --guess # Guess which browser to use and open corresponding file + + cookie_extractor --browser chrome|chromium|firefox # Open corresponding DB + Typical locations for the cookies file on Linux are: - * Firefox: ~/.mozilla/firefox/(profile directory)/cookies.sqlite - * Chrome: ~/.config/google-chrome/Default/Cookies - * Chromium: ~/.config/chromium/Default/Cookies + * Firefox: *~/.mozilla/firefox/(profile directory)/cookies.sqlite* + * Chrome: *~/.config/google-chrome/Default/Cookies* + * Chromium: *~/.config/chromium/Default/Cookies* ### License ### diff --git a/bin/cookie_extractor b/bin/cookie_extractor index 6f808b8..95a25d6 100755 --- a/bin/cookie_extractor +++ b/bin/cookie_extractor @@ -2,22 +2,46 @@ require File.expand_path(File.join(File.dirname(__FILE__), "..", "lib", "cookie_extractor")) -# TODO: Locate cookie dbs automatically -filename = ARGV.first -unless filename - puts "Usage: (Firefox) cookie_extractor /path/to/cookies.sqlite" - puts " (Chrome) cookie_extractor /path/to/Cookies" + +def usage msg=nil + puts msg if msg + puts "Usage: cookie_extractor /path/to/cookies.sqlite Open a DB file" + puts " cookie_extractor --guess Guess which browser to use and open corresponding file" + puts " cookie_extractor --browser chrome|chromium|firefox Open DB corresponding to a particular browser" exit end -if File.exists?(filename) - begin - extractor = CookieExtractor::BrowserDetector.new_extractor(filename) - puts extractor.extract.join("\n") - rescue SQLite3::NotADatabaseException, - CookieExtractor::BrowserNotDetectedException - puts "Error: File '#{filename}' is not a Firefox or Chrome cookie database" - end -else - puts "Error: File '#{filename}' does not exist" + +begin + extractor = + case ARGV.first + when '--guess', '-g' + begin + CookieExtractor::BrowserDetector.guess() + rescue CookieExtractor::NoCookieFileFoundException + abort "Error: we couldn't find any supported broswer's cookies" + end + when '--browser', '-b' + browser = ARGV[1] + usage "Error: Please supply a browser name" unless browser + begin + CookieExtractor::BrowserDetector.browser_extractor(browser) + rescue CookieExtractor::InvalidBrowserNameException + abort "Error: '#{browser}' is not a valid browser name" + rescue CookieExtractor::NoCookieFileFoundException + abort "Error: Could not locate cookie file for browser #{browser}" + end + when nil + usage + else + filename = ARGV.first + abort "Error: #{filename} does not exist" unless File.exists?(filename) + CookieExtractor::BrowserDetector.new_extractor(filename) + end + puts extractor.extract.join("\n") +rescue SQLite3::NotADatabaseException, + CookieExtractor::BrowserNotDetectedException + abort "Error: File '#{filename}' is not a Firefox or Chrome cookie database" end + + diff --git a/lib/cookie_extractor/browser_detector.rb b/lib/cookie_extractor/browser_detector.rb index b64dfd9..de67f05 100644 --- a/lib/cookie_extractor/browser_detector.rb +++ b/lib/cookie_extractor/browser_detector.rb @@ -1,7 +1,46 @@ module CookieExtractor class BrowserNotDetectedException < Exception; end + class InvalidBrowserNameException < Exception; end + class NoCookieFileFoundException < Exception; end class BrowserDetector + @cookie_locations = { + "chrome" => "~/.config/google-chrome/Default/Cookies", + "chromium" => "~/.config/chromium/Default/Cookies", + "firefox" => "~/.mozilla/firefox/*.default/cookies.sqlite" + } + + + # Returns the extractor of the most recently used browser's cookies + # or raise NoCookieFileFoundException if there are no cookies + def self.guess + full_cookie_locations = @cookie_locations.select { |browser, path| + !Dir.glob(File.expand_path(path)).empty? + }.sort_by { |browser, path| + File.mtime(Dir.glob(File.expand_path(path)).first) + }.reverse.each { |tuple| + browser = tuple.first + begin + extractor = self.browser_extractor(browser) + rescue BrowserNotDetectedException, NoCookieFileFoundException + # better try the next one... + else + return extractor + end + } + # If we make it here, we've failed... + raise NoCookieFileFoundException, "Couldn't find any browser's cookies" + end + + # Open a browser's cookie file using intelligent guesswork + def self.browser_extractor(browser) + raise InvalidBrowserNameException, "Browser must be one of: #{self.supported_browsers.join(', ')}" unless self.supported_browsers.include?(browser) + paths = Dir.glob(File.expand_path(@cookie_locations[browser])) + if paths.length < 1 or not File.exists?(paths.first) + raise NoCookieFileFoundException, "File #{paths.first} does not exist!" + end + self.new_extractor(paths.first) + end def self.new_extractor(db_filename) browser = detect_browser(db_filename) @@ -12,6 +51,10 @@ module CookieExtractor end end + def self.supported_browsers + @cookie_locations.keys + end + def self.detect_browser(db_filename) db = SQLite3::Database.new(db_filename) browser =