ptj 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/Gemfile +24 -0
- data/Gemfile.lock +84 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +96 -0
- data/Rakefile +51 -0
- data/VERSION +1 -0
- data/etc/config.yml +23 -0
- data/lib/ptj.rb +5 -0
- data/lib/ptj/default_setup.rb +10 -0
- data/lib/ptj/environment.rb +115 -0
- data/lib/ptj/ext.rb +1 -0
- data/lib/ptj/ext/datamapper_collection.rb +74 -0
- data/lib/ptj/model.rb +65 -0
- data/lib/ptj/model/password.rb +116 -0
- data/lib/ptj/model/tag.rb +19 -0
- data/lib/ptj/model/tasks.rb +38 -0
- data/lib/ptj/parser.rb +1 -0
- data/lib/ptj/parser/fileparser.rb +24 -0
- data/lib/ptj/parser/fileparser/countpassonly.rb +27 -0
- data/lib/ptj/parser/fileparser/hashpassonlycolon.rb +26 -0
- data/lib/ptj/parser/fileparser/passhashonly.rb +26 -0
- data/lib/ptj/parser/fileparser/passonly.rb +26 -0
- data/lib/ptj/parser/fileparser/passthreecolons.rb +26 -0
- data/ptj.gemspec +120 -0
- data/scripts/analyze.rb +129 -0
- data/scripts/generate_wordlist.rb +121 -0
- data/scripts/import.rb +111 -0
- data/scripts/ptj_libpath.rb +2 -0
- data/spec/.helper.rb.swp +0 -0
- data/spec/.test_ptj.rb.swp +0 -0
- data/spec/model/password_spec.rb +46 -0
- data/spec/model/shared_behaviors.rb +23 -0
- data/spec/model/tag_spec.rb +27 -0
- data/spec/spec_helper.rb +18 -0
- data/spec/spec_ptj.rb +16 -0
- data/tasks/db.rake +68 -0
- data/tasks/irb.rake +8 -0
- metadata +263 -0
@@ -0,0 +1,26 @@
|
|
1
|
+
module PTJ
|
2
|
+
module Parser
|
3
|
+
# FileParser class which allows you to parse a file line by line.
|
4
|
+
#
|
5
|
+
class PassThreeColons < FileParser
|
6
|
+
|
7
|
+
# Expecting the following format:
|
8
|
+
# something ::: pass ::: something
|
9
|
+
# something ::: pass ::: something
|
10
|
+
# something ::: pass ::: something
|
11
|
+
#
|
12
|
+
# @param line
|
13
|
+
# Individual line from a text file
|
14
|
+
#
|
15
|
+
# @return Hash Password, Password Hash
|
16
|
+
def parse_line(line)
|
17
|
+
if line =~ /\s*\S*\s*:::\s*(\S+)\s*:::/
|
18
|
+
pass = $~[1]
|
19
|
+
hash = nil
|
20
|
+
end
|
21
|
+
{:mypass => pass, :myhash => hash}
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/ptj.gemspec
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{ptj}
|
8
|
+
s.version = "0.1.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Josh Grunzweig"]
|
12
|
+
s.date = %q{2011-08-29}
|
13
|
+
s.description = %q{An easy way to collect and analyze data about password
|
14
|
+
databases.}
|
15
|
+
s.email = %q{jgrunzweig@gmail.com}
|
16
|
+
s.extra_rdoc_files = [
|
17
|
+
"LICENSE.txt",
|
18
|
+
"README.rdoc"
|
19
|
+
]
|
20
|
+
s.files = [
|
21
|
+
".document",
|
22
|
+
"Gemfile",
|
23
|
+
"Gemfile.lock",
|
24
|
+
"LICENSE.txt",
|
25
|
+
"README.rdoc",
|
26
|
+
"Rakefile",
|
27
|
+
"VERSION",
|
28
|
+
"etc/config.yml",
|
29
|
+
"lib/ptj.rb",
|
30
|
+
"lib/ptj/default_setup.rb",
|
31
|
+
"lib/ptj/environment.rb",
|
32
|
+
"lib/ptj/ext.rb",
|
33
|
+
"lib/ptj/ext/datamapper_collection.rb",
|
34
|
+
"lib/ptj/model.rb",
|
35
|
+
"lib/ptj/model/password.rb",
|
36
|
+
"lib/ptj/model/tag.rb",
|
37
|
+
"lib/ptj/model/tasks.rb",
|
38
|
+
"lib/ptj/parser.rb",
|
39
|
+
"lib/ptj/parser/fileparser.rb",
|
40
|
+
"lib/ptj/parser/fileparser/countpassonly.rb",
|
41
|
+
"lib/ptj/parser/fileparser/hashpassonlycolon.rb",
|
42
|
+
"lib/ptj/parser/fileparser/passhashonly.rb",
|
43
|
+
"lib/ptj/parser/fileparser/passonly.rb",
|
44
|
+
"lib/ptj/parser/fileparser/passthreecolons.rb",
|
45
|
+
"ptj.gemspec",
|
46
|
+
"scripts/analyze.rb",
|
47
|
+
"scripts/generate_wordlist.rb",
|
48
|
+
"scripts/import.rb",
|
49
|
+
"scripts/ptj_libpath.rb",
|
50
|
+
"spec/.helper.rb.swp",
|
51
|
+
"spec/.test_ptj.rb.swp",
|
52
|
+
"spec/model/password_spec.rb",
|
53
|
+
"spec/model/shared_behaviors.rb",
|
54
|
+
"spec/model/tag_spec.rb",
|
55
|
+
"spec/spec_helper.rb",
|
56
|
+
"spec/spec_ptj.rb",
|
57
|
+
"tasks/db.rake",
|
58
|
+
"tasks/irb.rake"
|
59
|
+
]
|
60
|
+
s.homepage = %q{http://github.com/jgrunzweig/ptj}
|
61
|
+
s.licenses = ["MIT"]
|
62
|
+
s.require_paths = ["lib"]
|
63
|
+
s.rubygems_version = %q{1.6.2}
|
64
|
+
s.summary = %q{Password analysis and collection database.}
|
65
|
+
|
66
|
+
if s.respond_to? :specification_version then
|
67
|
+
s.specification_version = 3
|
68
|
+
|
69
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
70
|
+
s.add_development_dependency(%q<shoulda>, [">= 0"])
|
71
|
+
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
72
|
+
s.add_development_dependency(%q<jeweler>, ["~> 1.6.2"])
|
73
|
+
s.add_development_dependency(%q<rcov>, [">= 0"])
|
74
|
+
s.add_development_dependency(%q<rspec>, ["~> 2.3.0"])
|
75
|
+
s.add_development_dependency(%q<dm-core>, [">= 0"])
|
76
|
+
s.add_development_dependency(%q<dm-migrations>, [">= 0"])
|
77
|
+
s.add_development_dependency(%q<dm-types>, [">= 0"])
|
78
|
+
s.add_development_dependency(%q<dm-transactions>, [">= 0"])
|
79
|
+
s.add_development_dependency(%q<dm-aggregates>, [">= 0"])
|
80
|
+
s.add_development_dependency(%q<dm-validations>, [">= 0"])
|
81
|
+
s.add_development_dependency(%q<dm-serializer>, [">= 0"])
|
82
|
+
s.add_development_dependency(%q<dm-timestamps>, [">= 0"])
|
83
|
+
s.add_development_dependency(%q<dm-sqlite-adapter>, [">= 0"])
|
84
|
+
s.add_development_dependency(%q<dm-postgres-adapter>, [">= 0"])
|
85
|
+
else
|
86
|
+
s.add_dependency(%q<shoulda>, [">= 0"])
|
87
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
88
|
+
s.add_dependency(%q<jeweler>, ["~> 1.6.2"])
|
89
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
90
|
+
s.add_dependency(%q<rspec>, ["~> 2.3.0"])
|
91
|
+
s.add_dependency(%q<dm-core>, [">= 0"])
|
92
|
+
s.add_dependency(%q<dm-migrations>, [">= 0"])
|
93
|
+
s.add_dependency(%q<dm-types>, [">= 0"])
|
94
|
+
s.add_dependency(%q<dm-transactions>, [">= 0"])
|
95
|
+
s.add_dependency(%q<dm-aggregates>, [">= 0"])
|
96
|
+
s.add_dependency(%q<dm-validations>, [">= 0"])
|
97
|
+
s.add_dependency(%q<dm-serializer>, [">= 0"])
|
98
|
+
s.add_dependency(%q<dm-timestamps>, [">= 0"])
|
99
|
+
s.add_dependency(%q<dm-sqlite-adapter>, [">= 0"])
|
100
|
+
s.add_dependency(%q<dm-postgres-adapter>, [">= 0"])
|
101
|
+
end
|
102
|
+
else
|
103
|
+
s.add_dependency(%q<shoulda>, [">= 0"])
|
104
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
105
|
+
s.add_dependency(%q<jeweler>, ["~> 1.6.2"])
|
106
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
107
|
+
s.add_dependency(%q<rspec>, ["~> 2.3.0"])
|
108
|
+
s.add_dependency(%q<dm-core>, [">= 0"])
|
109
|
+
s.add_dependency(%q<dm-migrations>, [">= 0"])
|
110
|
+
s.add_dependency(%q<dm-types>, [">= 0"])
|
111
|
+
s.add_dependency(%q<dm-transactions>, [">= 0"])
|
112
|
+
s.add_dependency(%q<dm-aggregates>, [">= 0"])
|
113
|
+
s.add_dependency(%q<dm-validations>, [">= 0"])
|
114
|
+
s.add_dependency(%q<dm-serializer>, [">= 0"])
|
115
|
+
s.add_dependency(%q<dm-timestamps>, [">= 0"])
|
116
|
+
s.add_dependency(%q<dm-sqlite-adapter>, [">= 0"])
|
117
|
+
s.add_dependency(%q<dm-postgres-adapter>, [">= 0"])
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
data/scripts/analyze.rb
ADDED
@@ -0,0 +1,129 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'pp'
|
3
|
+
require 'optparse'
|
4
|
+
|
5
|
+
require_relative('ptj_libpath')
|
6
|
+
require 'ptj/default_setup'
|
7
|
+
|
8
|
+
DataMapper::Model.raise_on_save_failure = true if $DEBUG
|
9
|
+
|
10
|
+
include PTJ
|
11
|
+
|
12
|
+
#FILTER = {:fields => [:id, :password, :upper, :lower, :special, :number, :size]}
|
13
|
+
FILTER = {}
|
14
|
+
CFG = {
|
15
|
+
:tags => [],
|
16
|
+
:file => nil,
|
17
|
+
:includecount => false
|
18
|
+
}
|
19
|
+
|
20
|
+
opts = OptionParser.new do |o|
|
21
|
+
o.banner = "Usage: #{File.basename $0} [opts]"
|
22
|
+
|
23
|
+
o.on_tail("-h", "--help", "Show this message") do
|
24
|
+
puts o
|
25
|
+
exit 1
|
26
|
+
end
|
27
|
+
|
28
|
+
o.on("-t", "--tags TAGS", "Tags to be used to when querying passwords (separated by a comma)") do |t|
|
29
|
+
t = t.split(",").each{|x| x.strip!}
|
30
|
+
t=[t] unless t.is_a?(Array)
|
31
|
+
t.each do |tag|
|
32
|
+
CFG[:tags] << tag
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
o.on("--max-size SIZE", Integer, "Maximum size of the resulting passords") do |f|
|
37
|
+
FILTER[:size.lt] = f
|
38
|
+
end
|
39
|
+
|
40
|
+
o.on("--min-size SIZE", Integer, "Minimum size of the resulting passwords") do |f|
|
41
|
+
FILTER[:size.gt] = f
|
42
|
+
end
|
43
|
+
|
44
|
+
o.on("--[no-]upper", "Query based on upper-case letters") do |f|
|
45
|
+
FILTER[:upper] = f
|
46
|
+
end
|
47
|
+
|
48
|
+
o.on("--[no-]lower", "Query based on lower-case letters") do |f|
|
49
|
+
FILTER[:lower] = f
|
50
|
+
end
|
51
|
+
|
52
|
+
o.on("--[no-]special", "Query based on special charaters") do |f|
|
53
|
+
FILTER[:special] = f
|
54
|
+
end
|
55
|
+
|
56
|
+
o.on("--[no-]number", "Query based on numbers") do |f|
|
57
|
+
FILTER[:number] = f
|
58
|
+
end
|
59
|
+
|
60
|
+
end.parse!(ARGV)
|
61
|
+
|
62
|
+
def top5_pass(object, my_hash)
|
63
|
+
my_hash.delete(:fields) if my_hash[:fields]
|
64
|
+
my_hash.delete(:order) if my_hash[:order]
|
65
|
+
return object.aggregate(:password, :password.count, my_hash).sort {|x,y| y[1] <=> x[1]}.first(5)
|
66
|
+
end
|
67
|
+
|
68
|
+
def size_count(object, my_hash)
|
69
|
+
my_hash.delete(:fields) if my_hash[:fields]
|
70
|
+
my_hash.delete(:order) if my_hash[:order]
|
71
|
+
return object.aggregate(:size, :size.count, my_hash).sort {|x,y| x[0] <=> y[0]}
|
72
|
+
end
|
73
|
+
|
74
|
+
def cat_result(object, my_hash)
|
75
|
+
my_hash.delete(:fields) if my_hash[:fields]
|
76
|
+
my_hash.delete(:order) if my_hash[:order]
|
77
|
+
return_hash = {}
|
78
|
+
return_hash["Lower"] = object.all(my_hash).count(:upper => false, :special => false, :lower => true, :number => false)
|
79
|
+
return_hash["Upper"] = object.all(my_hash).count(:upper => true, :special => false, :lower => false, :number => false)
|
80
|
+
return_hash["Number"] = object.all(my_hash).count(:upper => false, :special => false, :lower => false, :number => true)
|
81
|
+
return_hash["Special"] = object.all(my_hash).count(:upper => false, :special => true, :lower => false, :number => false)
|
82
|
+
return_hash["Lower/Upper"] = object.all(my_hash).count(:upper => true, :special => false, :lower => true, :number => false)
|
83
|
+
return_hash["Lower/Number"] = object.all(my_hash).count(:upper => false, :special => false, :lower => true, :number => true)
|
84
|
+
return_hash["Upper/Number"] = object.all(my_hash).count(:upper => true, :special => false, :lower => false, :number => true)
|
85
|
+
return_hash["Lower/Special"] = object.all(my_hash).count(:upper => false, :special => true, :lower => true, :number => false)
|
86
|
+
return_hash["Upper/Special"] = object.all(my_hash).count(:upper => true, :special => true, :lower => false, :number => false)
|
87
|
+
return_hash["Number/Special"] = object.all(my_hash).count(:upper => false, :special => true, :lower => false, :number =>true)
|
88
|
+
return_hash["Lower/Upper/Number"] = object.all(my_hash).count(:upper => true, :special => false, :lower => true, :number => true)
|
89
|
+
return_hash["Lower/Upper/Special"] = object.all(my_hash).count(:upper => true, :special => true, :lower => true, :number => false)
|
90
|
+
return_hash["Lower/Number/Special"] = object.all(my_hash).count(:upper => false, :special => true, :lower => true, :number => true)
|
91
|
+
return_hash["Upper/Number/Special"] = object.all(my_hash).count(:upper => true, :special => true, :lower => false, :number =>true)
|
92
|
+
return_hash["Lower/Upper/Number/Special"] = object.all(my_hash).count(:upper => true, :special => true, :lower => true, :number => true)
|
93
|
+
return_hash
|
94
|
+
end
|
95
|
+
|
96
|
+
time_now = Time.now
|
97
|
+
if CFG[:tags]
|
98
|
+
top5 = top5_pass(PTJ::Tag.all(:tag => CFG[:tags]).passwords, FILTER)
|
99
|
+
my_count = size_count(PTJ::Tag.all(:tag => CFG[:tags]).passwords, FILTER)
|
100
|
+
split_up = cat_result(PTJ::Tag.all(:tag => CFG[:tags]).passwords, FILTER)
|
101
|
+
else
|
102
|
+
top5 = top5_pass(PTJ::Passwords.all, FILTER)
|
103
|
+
my_count = size_count(PTJ::Passwords.all, FILTER)
|
104
|
+
split_up = cat_result(PTJ::Passwords.all, FILTER)
|
105
|
+
end
|
106
|
+
|
107
|
+
|
108
|
+
puts "-=-=-=-=-=- Top 5 Passwords -=-=-=-=-=-"
|
109
|
+
top5.each do |pass, count|
|
110
|
+
printf("%-30s : %d", pass, count)
|
111
|
+
puts ""
|
112
|
+
end
|
113
|
+
|
114
|
+
total_size = 0
|
115
|
+
my_count.each{|result| total_size += result[1] }
|
116
|
+
puts "\n-=-=-=-=-=- Password Length -=-=-=-=-=-"
|
117
|
+
my_count.each do |result|
|
118
|
+
percent = "%.2f" % ((result[1].to_f/total_size.to_f)*100).to_f
|
119
|
+
printf("%-30s %s", ("Password Length: #{result[0]}"), ("Count: #{result[1]} (#{percent}%)") )
|
120
|
+
puts ""
|
121
|
+
end
|
122
|
+
puts "Total: #{total_size}"
|
123
|
+
|
124
|
+
puts "\n-=-=-=-=-=- Password Type -=-=-=-=-=-"
|
125
|
+
split_up.sort_by{|k,v| k.length}.each do |result|
|
126
|
+
printf("Type: %-30s %s", result[0], ("Result: #{result[1]}"))
|
127
|
+
puts ""
|
128
|
+
end
|
129
|
+
p "Time taken: #{Time.now - time_now}"
|
@@ -0,0 +1,121 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'pp'
|
3
|
+
require 'optparse'
|
4
|
+
|
5
|
+
require_relative('ptj_libpath')
|
6
|
+
require 'ptj/default_setup'
|
7
|
+
|
8
|
+
DataMapper::Model.raise_on_save_failure = true if $DEBUG
|
9
|
+
|
10
|
+
include PTJ
|
11
|
+
|
12
|
+
FILTER = {:fields => [:password, :id]}
|
13
|
+
|
14
|
+
CFG = {
|
15
|
+
:tags => [],
|
16
|
+
:file => nil,
|
17
|
+
:includecount => false
|
18
|
+
}
|
19
|
+
|
20
|
+
opts = OptionParser.new do |o|
|
21
|
+
o.banner = "Usage: #{File.basename $0} [opts]"
|
22
|
+
|
23
|
+
o.on_tail("-h", "--help", "Show this message") do
|
24
|
+
puts o
|
25
|
+
exit 1
|
26
|
+
end
|
27
|
+
|
28
|
+
o.on("-t", "--tags TAGS", "Tags to be used to when querying passwords (separated by a comma)") do |t|
|
29
|
+
t = t.split(",").each{|x| x.strip!}
|
30
|
+
t=[t] unless t.is_a?(Array)
|
31
|
+
t.each do |tag|
|
32
|
+
CFG[:tags] << tag
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
o.on("-o", "--output FILENAME", String, "Where to output results (Default outputs to screen)") do |f|
|
37
|
+
CFG[:file] = f
|
38
|
+
end
|
39
|
+
|
40
|
+
o.on("--max-size SIZE", Integer, "Maximum size of the resulting passords") do |f|
|
41
|
+
FILTER[:size.lt] = f
|
42
|
+
end
|
43
|
+
|
44
|
+
o.on("--min-size SIZE", Integer, "Minimum size of the resulting passwords") do |f|
|
45
|
+
FILTER[:size.gt] = f
|
46
|
+
end
|
47
|
+
|
48
|
+
o.on("--max-results SIZE", Integer, "Maximum number of results to return") do |f|
|
49
|
+
CFG[:max_results] = f
|
50
|
+
end
|
51
|
+
|
52
|
+
o.on("--include-count", "Include the counts of passwords identified") do |f|
|
53
|
+
CFG[:includecount] = f
|
54
|
+
end
|
55
|
+
|
56
|
+
o.on("--[no-]upper", "Query based on upper-case letters") do |f|
|
57
|
+
FILTER[:upper] = f
|
58
|
+
end
|
59
|
+
|
60
|
+
o.on("--[no-]lower", "Query based on lower-case letters") do |f|
|
61
|
+
FILTER[:lower] = f
|
62
|
+
end
|
63
|
+
|
64
|
+
o.on("--[no-]special", "Query based on special charaters") do |f|
|
65
|
+
FILTER[:special] = f
|
66
|
+
end
|
67
|
+
|
68
|
+
o.on("--[no-]number", "Query based on numbers") do |f|
|
69
|
+
FILTER[:number] = f
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
end.parse!(ARGV)
|
74
|
+
|
75
|
+
time_now = Time.now
|
76
|
+
|
77
|
+
#raise(OptionParser::MissingArgument, "Must specify file with -f or password with -p") if (CFG[:file].nil? and CFG[:password].nil?)
|
78
|
+
def top_pass(object, my_hash)
|
79
|
+
my_hash.delete(:fields) if my_hash[:fields]
|
80
|
+
my_hash.delete(:order) if my_hash[:order]
|
81
|
+
return object.aggregate(:password, :password.count, my_hash).sort {|x,y| y[1] <=> x[1]}
|
82
|
+
end
|
83
|
+
|
84
|
+
if CFG[:tags]
|
85
|
+
if CFG[:max_results]
|
86
|
+
o_pass = top_pass(PTJ::Tag.all(:tag => CFG[:tags]).passwords, FILTER).first(CFG[:max_results])
|
87
|
+
else
|
88
|
+
o_pass = top_pass(PTJ::Tag.all(:tag => CFG[:tags]).passwords, FILTER)
|
89
|
+
end
|
90
|
+
else
|
91
|
+
if CFG[:max_results]
|
92
|
+
o_pass = top_pass(PTJ::Passwords.all, FILTER).first(CFG[:max_results])
|
93
|
+
else
|
94
|
+
o_pass = top_pass(PTJ::Passwords.all, FILTER)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
|
99
|
+
if CFG[:file]
|
100
|
+
File.open(CFG[:file], "w+") do |file_handle|
|
101
|
+
o_pass.each do |tiny_array|
|
102
|
+
if CFG[:includecount]
|
103
|
+
file_handle.puts "#{tiny_array[0]}, #{tiny_array[1]}"
|
104
|
+
else
|
105
|
+
file_handle.puts "#{tiny_array[0]}"
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
else
|
110
|
+
o_pass.each do |tiny_array|
|
111
|
+
if CFG[:includecount]
|
112
|
+
puts "#{tiny_array[0]}, #{tiny_array[1]}"
|
113
|
+
else
|
114
|
+
puts "#{tiny_array[0]}"
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
puts "Time Taken: #{Time.now - time_now}"
|
119
|
+
exit
|
120
|
+
|
121
|
+
|
data/scripts/import.rb
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'pp'
|
3
|
+
require 'optparse'
|
4
|
+
|
5
|
+
require_relative('ptj_libpath')
|
6
|
+
require 'ptj/default_setup'
|
7
|
+
|
8
|
+
DataMapper::Model.raise_on_save_failure = true if $DEBUG
|
9
|
+
|
10
|
+
include PTJ
|
11
|
+
|
12
|
+
FILTER = {}
|
13
|
+
|
14
|
+
CFG = {
|
15
|
+
:password => nil,
|
16
|
+
:pw_hash => "",
|
17
|
+
:tags => [],
|
18
|
+
:basename => true,
|
19
|
+
:file => nil
|
20
|
+
}
|
21
|
+
|
22
|
+
opts = OptionParser.new do |o|
|
23
|
+
o.banner = "Usage: #{File.basename $0} [opts] -f file|-p password"
|
24
|
+
|
25
|
+
o.on_tail("-h", "--help", "Show this message.") do
|
26
|
+
puts o
|
27
|
+
exit 1
|
28
|
+
end
|
29
|
+
|
30
|
+
o.on("-t", "--tag TAGS", "Tags to be used to identify imported passwords (separated by a comma)") do |t|
|
31
|
+
t = t.split(",").each{|x| x.strip!}
|
32
|
+
t=[t] unless t.is_a?(Array)
|
33
|
+
t.each do |tag|
|
34
|
+
mytag=(Tag.get(tag) || Tag.create(:tag => tag.to_s))
|
35
|
+
CFG[:tags] << mytag
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
o.on("--[no-]strict", "Enable/Disable Strict Mode") do |s|
|
40
|
+
DataMapper::Model.raise_on_save_failure = s
|
41
|
+
end
|
42
|
+
|
43
|
+
o.on("-f", "--file FILENAME", String, "File to import.") do |f|
|
44
|
+
CFG[:file] = f
|
45
|
+
end
|
46
|
+
|
47
|
+
o.on("-r", "--parser NUMBER", Integer, "File parser to use:", "1 - Password Only", "2 - Hash:Password", "3 - Count, Password", "4 - Something ::: Password ::: Something") do |f|
|
48
|
+
case f
|
49
|
+
when 1
|
50
|
+
CFG[:parser] = Parser::PassOnly.new
|
51
|
+
when 2
|
52
|
+
CFG[:parser] = Parser::HashPassOnlyColon.new
|
53
|
+
when 3
|
54
|
+
CFG[:parser] = Parser::CountPassOnly.new
|
55
|
+
when 4
|
56
|
+
CFG[:parser] = Parser::PassThreeColons.new
|
57
|
+
else
|
58
|
+
raise(OptionParser::InvalidOption, "Incorrect parsing number specified.")
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
o.on("-p", "--password PASSWORD", String, "Password to import.") do |f|
|
63
|
+
CFG[:file] = f
|
64
|
+
end
|
65
|
+
|
66
|
+
o.on("-a", "--hash HASH", String, "Hash to import (Use in conjunction with -p).") do |f|
|
67
|
+
CFG[:file] = f
|
68
|
+
end
|
69
|
+
|
70
|
+
end.parse!(ARGV)
|
71
|
+
|
72
|
+
raise(OptionParser::MissingArgument, "Must specify file with -f or password with -p") if (CFG[:file].nil? and CFG[:password].nil?)
|
73
|
+
|
74
|
+
#o_pass_count = Password.all(:fields => [:id]).size
|
75
|
+
|
76
|
+
|
77
|
+
def import_file
|
78
|
+
file = Pathname.new(CFG[:file])
|
79
|
+
parser = CFG[:parser]
|
80
|
+
tags = CFG[:tags]
|
81
|
+
file = File.open(CFG[:file], "r")
|
82
|
+
lines = file.readlines
|
83
|
+
lines.each do |line|
|
84
|
+
begin
|
85
|
+
line = line.force_encoding("BINARY")
|
86
|
+
parsed = parser.parse_line(line)
|
87
|
+
mypass = parsed[:mypass]
|
88
|
+
myhash = parsed[:myhash]
|
89
|
+
next if mypass.to_s.empty?
|
90
|
+
if parsed[:count]
|
91
|
+
parsed[:count].to_i.times do
|
92
|
+
pass = Password.add_single(mypass, myhash)
|
93
|
+
tags.each{|tag| pass.tags << tag}
|
94
|
+
pass.save
|
95
|
+
#puts "Adding #{mypass}"
|
96
|
+
end
|
97
|
+
else
|
98
|
+
pass = Password.add_single(mypass, myhash)
|
99
|
+
tags.each{|tag| pass.tags << tag}
|
100
|
+
pass.save
|
101
|
+
#puts "Adding #{mypass}"
|
102
|
+
end
|
103
|
+
rescue
|
104
|
+
next
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
import_file
|
110
|
+
|
111
|
+
|