ptj 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
|