summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xcontrib/importers/roboform2pass.rb162
1 files changed, 162 insertions, 0 deletions
diff --git a/contrib/importers/roboform2pass.rb b/contrib/importers/roboform2pass.rb
new file mode 100755
index 0000000..df0f266
--- /dev/null
+++ b/contrib/importers/roboform2pass.rb
@@ -0,0 +1,162 @@
+#!/usr/bin/env ruby
+
+# Copyright 2015 Sergey Makridenkov <sergey@makridenkov.com>.
+# Released under MIT License.
+#
+# Usage:
+# 1. Save roboform print lists (like File > Print lists > Logins) to ~/roboform_print_lists.
+# 2. Run import: ./roboform2pass.rb ~/roboform_print_lists
+
+
+require 'nokogiri'
+
+class Login
+ def initialize
+ self.fields = {}
+ self.raw = []
+ end
+
+ attr_accessor :key
+ attr_accessor :password
+ attr_accessor :url
+ attr_accessor :fields
+ attr_accessor :raw
+
+ def ask_required_info
+ ask!(:key) if blank?(key)
+ find_password!
+ if blank?(password)
+ ask!(:password)
+ puts ''
+ end
+ end
+
+ def save
+ if valid?
+ IO.popen("pass insert -m -f '#{path}' > /dev/null", "w") do |pass_io|
+ pass_io.puts password
+ pass_io.puts "Url: #{url}" if present?(url)
+ pass_io.puts "Fields: #{fields}" if fields.any?
+ pass_io.puts "Notes: #{raw}" if raw.any?
+ end
+
+ $? == 0
+ end
+ end
+
+ private
+
+ def path
+ key = self.key.downcase.gsub(/[^\w\.\/]/, '_').gsub(/_{2,}/, '_')
+ "roboform/#{key}"
+ end
+
+ def valid?
+ present?(key) && present?(password)
+ end
+
+ def find_password!
+ fields.each do |key, val|
+ key = key.downcase
+ if key.include?('password') || key.include?('pwd') || key.include?('pass')
+ self.password = val
+ end
+ end
+ end
+
+ def ask!(field)
+ puts Colorize.red("#{field.capitalize} is empty for login:")
+ print_self
+ print Colorize.green "Please type #{field}: "
+ self.send("#{field}=", gets.chomp)
+ end
+
+ def print_self
+ puts Colorize.yellow "\tKey:\t#{key}" if present?(key)
+ puts Colorize.yellow "\tPassword:\t#{password}" if present?(password)
+ puts Colorize.yellow "\tUrl:\t#{url}" if present?(url)
+ puts Colorize.yellow "\tFields:\t#{fields}" if fields.any?
+ puts Colorize.yellow "\tRaw:\t#{raw}" if raw.any?
+ end
+
+ def blank?(str)
+ !str || str.strip.empty?
+ end
+
+ def present?(str)
+ !blank?(str)
+ end
+end
+
+class Colorize
+ class << self
+ def red(mes)
+ colorize(31, mes)
+ end
+
+ def green(mes)
+ colorize(32, mes)
+ end
+
+ def yellow(mes)
+ colorize(33, mes)
+ end
+
+ def pink(mes)
+ colorize(35, mes)
+ end
+
+ private
+
+ def colorize(color_code, mes)
+ "\e[#{color_code}m#{mes}\e[0m"
+ end
+ end
+end
+
+
+print_list_dir = ARGV.pop
+unless print_list_dir
+ raise "No dir/to/roboform/print_lists"
+end
+print_list_dir = File.expand_path(print_list_dir)
+
+# parse logins
+logins_path = Dir.glob("#{print_list_dir}/RoboForm Logins*.html").first
+unless logins_path
+ raise 'Login HTML (RoboForm Logins*.html) not found'
+end
+
+html_logins = Nokogiri::HTML(File.open(logins_path))
+
+saved_logins = 0
+
+html_logins.css('table').each do |table|
+ login = Login.new
+
+ table.css('tr').each do |tr|
+ caption = tr.at_css('.caption')
+ subcaption = tr.at_css('.subcaption')
+ key = tr.at_css('.field')
+
+ if caption
+ login.key = caption.text()
+ elsif subcaption
+ login.url = subcaption.text()
+ elsif key
+ login.fields[key.text()] = tr.at_css('.wordbreakfield').text()
+ else
+ login.raw << tr.at_css('.wordbreakfield').text()
+ end
+ end
+
+ if login.fields.any?
+ login.ask_required_info
+ if login.save
+ saved_logins += 1
+ end
+ end
+end
+
+puts "Imported passwords: #{saved_logins}"
+
'/feed2imap-go.git/commit/main.go?h=v0.3.1&id=89f46e31998dd62a52d7dd07b16f1d81d9597e3e&follow=1'>Upload mails to imapRené 'Necoro' Neumann3-35/+80 2020-04-21Move HTML template to stringRené 'Necoro' Neumann3-12/+13 2020-04-21HTML Template part of the mailRené 'Necoro' Neumann7-18/+199 2020-04-20Fixes and validationRené 'Necoro' Neumann6-28/+25 2020-04-20Fix vettingRené 'Necoro' Neumann1-1/+1 2020-04-20Started with mail creationRené 'Necoro' Neumann4-3/+126 2020-04-20FeeditemsRené 'Necoro' Neumann2-2/+14 2020-04-20GlobalOptionsRené 'Necoro' Neumann3-25/+79 2020-04-19RestructureRené 'Necoro' Neumann6-152/+177 2020-04-19Rename package 'parse' to 'feed'René 'Necoro' Neumann2-3/+3 2020-04-19SELECT is not necessary for most operations -- skip itRené 'Necoro' Neumann2-12/+1 2020-04-19Store path as array -- the delimiter is not always '.'René 'Necoro' Neumann3-36/+44 2020-04-19Split client part to client.goRené 'Necoro' Neumann2-125/+137 2020-04-19IMAP: Create foldersRené 'Necoro' Neumann1-4/+38 2020-04-19Improved IMAPRené 'Necoro' Neumann1-3/+88 2020-04-19Started IMAP connectionRené 'Necoro' Neumann4-0/+152 2020-04-19Use our own logger for debug for convenience sakeRené 'Necoro' Neumann1-2/+3 2020-04-19Fix debug logging m(René 'Necoro' Neumann1-2/+2 2020-04-19Rename util.go to log.go. Add verbose modeRené 'Necoro' Neumann4-24/+54 2020-04-19Clean go.modRené 'Necoro' Neumann2-3/+0 2020-04-19Do not print the parsedCfg anymoreRené 'Necoro' Neumann1-1/+1 2020-04-19Increase go-version to 1.14René 'Necoro' Neumann1-2/+2 2020-04-19CI: go vetRené 'Necoro' Neumann1-0/+3 2020-04-19Fetching and parsing the feedsRené 'Necoro' Neumann5-4/+113 2020-04-19Ignore all config*.ymlRené 'Necoro' Neumann1-1/+1