haddock 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt ADDED
@@ -0,0 +1,28 @@
1
+ === 0.2.0 / 2009-03-29
2
+
3
+ * 1 major enhancement
4
+
5
+ * Changed "haddock" to "ha-gen" for Haskell compliance.
6
+
7
+
8
+ === 0.1.1 / 2009-03-29
9
+
10
+ * 2 minor enhancements
11
+
12
+ * Add version option to command-line utility.
13
+ * Bumping up version numbers to improve credibility.
14
+
15
+
16
+ === 0.1.0 / 2009-03-29
17
+
18
+ * 2 minor enhancements
19
+
20
+ * Friendlier command-line errors.
21
+ * General cleanup.
22
+
23
+
24
+ === 0.0.1 / 2009-03-28
25
+
26
+ * 1 major enhancement
27
+
28
+ * Birthday!
data/Manifest.txt ADDED
@@ -0,0 +1,8 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ bin/ha-gen
6
+ lib/haddock.rb
7
+ test/names.txt
8
+ test/test_haddock.rb
data/README.txt ADDED
@@ -0,0 +1,81 @@
1
+ = haddock
2
+
3
+ http://github.com/stephencelis/haddock
4
+
5
+
6
+ == DESCRIPTION
7
+
8
+ A more memorable password generator. Swordfish? No, I got tired of that. I
9
+ changed it.
10
+
11
+
12
+ == FEATURES/PROBLEMS
13
+
14
+ * Secure!
15
+
16
+
17
+ == SYNOPSIS
18
+
19
+ In your apps:
20
+
21
+ require "rubygems"
22
+ require "haddock"
23
+ include Haddock
24
+ Password.generate # => "bowl9&bracky"
25
+ Password.generate(30) # => "Phlebotomus2473?nonconditioned"
26
+ Password.generate(8) # => "amy7@rax"
27
+
28
+
29
+ On the command line:
30
+
31
+ % ha-gen
32
+ bowl9&bracky
33
+ % ha-gen -l31
34
+ symbolistically5<overthwartways
35
+
36
+
37
+ == REQUIREMENTS
38
+
39
+ A newline-delimited words file. By default, it uses "/usr/share/dict/words" or
40
+ "/usr/share/words".
41
+
42
+ Otherwise:
43
+
44
+ Haddock::Password.diction = "/path/to/words"
45
+
46
+
47
+ Or:
48
+
49
+ % ha-gen -f /path/to/words
50
+
51
+
52
+ == INSTALL
53
+
54
+ GitHub:
55
+
56
+ % gem install stephencelis-haddock --source=http://gems.github.com
57
+
58
+
59
+ == LICENSE
60
+
61
+ (The MIT License)
62
+
63
+ (c) 2009-* Stephen Celis, stephen@stephencelis.com.
64
+
65
+ Permission is hereby granted, free of charge, to any person obtaining a copy
66
+ of this software and associated documentation files (the "Software"), to deal
67
+ in the Software without restriction, including without limitation the rights
68
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
69
+ copies of the Software, and to permit persons to whom the Software is
70
+ furnished to do so, subject to the following conditions:
71
+
72
+ The above copyright notice and this permission notice shall be included in all
73
+ copies or substantial portions of the Software.
74
+
75
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
76
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
77
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
78
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
79
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
80
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
81
+ SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ $: << File.dirname(__FILE__) + "/lib"
2
+ require "rubygems"
3
+ require "hoe"
4
+ require "haddock"
5
+
6
+ Hoe.new('haddock', Haddock::VERSION) do |p|
7
+ p.developer('Stephen Celis', 'stephen@stephencelis.com')
8
+ p.remote_rdoc_dir = ''
9
+ end
data/bin/ha-gen ADDED
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $: << File.dirname(__FILE__) + "/../lib"
4
+ require "optparse"
5
+ require "haddock"
6
+ include Haddock
7
+
8
+ parser = OptionParser.new do |opts|
9
+ opts.banner = "usage: #{File.basename($0)} [options]"
10
+
11
+ opts.on("-V", "--version") do
12
+ require 'capistrano/version'
13
+ puts "#{File.basename($0)}: v#{Haddock::VERSION}"
14
+ exit
15
+ end
16
+
17
+ opts.on("-h", "--help") do
18
+ puts opts
19
+ exit
20
+ end
21
+
22
+ opts.on("-l", "--length [length]") do |value|
23
+ raise Password::LengthError, "Invalid length" if value.match(/\D/)
24
+ @length = value.to_i
25
+ end
26
+
27
+ opts.on("-f", "--words [words file]") do |value|
28
+ Password.diction = value
29
+ end
30
+ end
31
+
32
+ begin
33
+ parser.parse!
34
+ puts @length ? Password.generate(@length) : Password.generate
35
+ rescue OptionParser::ParseError, Password::LengthError => error
36
+ warn "#{File.basename($0)}: #{error.message} " +
37
+ "(must be between #{Password::MINIMUM} and #{Password::MAXIMUM})."
38
+ puts parser
39
+ exit 1
40
+ rescue Password::NoWordsError => error
41
+ warn "#{File.basename($0)}: #{error.message}."
42
+ puts "Word lists are available here: http://wordlist.sourceforge.net"
43
+ puts parser
44
+ exit 1
45
+ end
data/lib/haddock.rb ADDED
@@ -0,0 +1,81 @@
1
+ # A more memorable password generator. Swordfish? No, I got tired of that. I
2
+ # changed it.
3
+ module Haddock
4
+ VERSION = '0.2.0'
5
+
6
+ module Password
7
+ MINIMUM = 8
8
+ MAXIMUM = 31
9
+ DEFAULT = 12
10
+
11
+ SYMBOLS = '`~!@#$%^&*()-_=+[{]}\\|;:\'",<.>/?'
12
+
13
+ class << self
14
+ @@paths = %w(/usr/share/dict/words /usr/share/words)
15
+
16
+ # Generates a more memorable password. Its one optional argument
17
+ # determines the length of the generated password, and cannot be less
18
+ # than 8 or greater than 31 characters (default: 12).
19
+ #
20
+ # Password.generate # => "bowl9&bracky"
21
+ # Password.generate(30) # => "Phlebotomus2473?nonconditioned"
22
+ # Password.generate(8) # => "amy7@rax"
23
+ def generate(length = DEFAULT)
24
+ unless defined? @@diction
25
+ self.diction = @@paths.find { |path| File.exist? path }
26
+ end
27
+
28
+ raise LengthError, "Invalid length" unless length.is_a? Integer
29
+ raise LengthError, "Password length is too short" if length < MINIMUM
30
+ raise LengthError, "Password length is too long" if length > MAXIMUM
31
+
32
+ words_limit = length * 0.75 # Ensure over-proportionate word lengths.
33
+
34
+ begin
35
+ words = %W(#{random_word} #{random_symbol}#{random_word})
36
+ words_length = words.to_s.length
37
+ end until words_length < length && words_length > words_limit
38
+
39
+ words.join random_number(length - words_length)
40
+ end
41
+
42
+ # Sets the dictionary. Uses "/usr/share/dict/words" or
43
+ # "/usr/share/words" otherwise.
44
+ #
45
+ # Password.diction = File.expand_path(__FILE__) + "/my_words.txt"
46
+ def diction=(path)
47
+ @@diction = IO.readlines path
48
+ rescue TypeError
49
+ raise NoWordsError, "No words file found"
50
+ rescue Errno::ENOENT
51
+ raise NoWordsError, "No words file at #{path.inspect}"
52
+ end
53
+
54
+ private
55
+
56
+ def random_word
57
+ @@diction[rand(@@diction.length)].chomp
58
+ end
59
+
60
+ def random_symbol
61
+ SYMBOLS[rand(SYMBOLS.length), 1]
62
+ end
63
+
64
+ def random_number(digits)
65
+ begin
66
+ number = rand(10 ** digits).to_s
67
+ end until number.length == digits
68
+
69
+ number
70
+ end
71
+ end
72
+
73
+ # Raised if a password is generated with too few or too many characters.
74
+ class LengthError < ArgumentError
75
+ end
76
+
77
+ # Raised if no words file is found.
78
+ class NoWordsError < StandardError
79
+ end
80
+ end
81
+ end
data/test/names.txt ADDED
@@ -0,0 +1,2 @@
1
+ Mary
2
+ sturgeon
@@ -0,0 +1,60 @@
1
+ require "test/unit"
2
+ require "haddock"
3
+
4
+ class TestHaddock < Test::Unit::TestCase
5
+ include Haddock
6
+
7
+ def test_generates_password
8
+ password = Password.generate
9
+ assert_instance_of String, password
10
+ assert_equal Password::DEFAULT, password.length
11
+ end
12
+
13
+ def test_password_format
14
+ symbols = "[#{Regexp.quote Password::SYMBOLS}]"
15
+ pattern = /^[a-z]+[0-9]+#{symbols}{1}[a-z]+/i
16
+ assert_match(pattern, Password.generate)
17
+ end
18
+
19
+ def test_generates_variable_password
20
+ assert_equal Password.generate(18).length, 18
21
+ end
22
+
23
+ def test_accepts_alternate_wordlist
24
+ Password.diction = path = File.dirname(__FILE__) + "/names.txt"
25
+ pattern = Regexp.new File.read(path).split.join("|")
26
+ assert_match(pattern, Password.generate(14))
27
+ ensure
28
+ Password.diction = "/usr/share/dict/words"
29
+ end
30
+
31
+ def test_fail_on_too_short
32
+ assert_raise Password::LengthError do
33
+ Password.generate(Password::MINIMUM - 1)
34
+ end
35
+ end
36
+
37
+ def test_fail_on_too_long
38
+ assert_raise Password::LengthError do
39
+ Password.generate(Password::MAXIMUM + 1)
40
+ end
41
+ end
42
+
43
+ def test_fail_on_invalid
44
+ assert_raise Password::LengthError do
45
+ Password.generate("invalid")
46
+ end
47
+ end
48
+
49
+ def test_fail_on_invalid_path
50
+ assert_raise Password::NoWordsError do
51
+ Password.diction = "invalid/path"
52
+ end
53
+ end
54
+
55
+ def test_fail_on_nil_path
56
+ assert_raise Password::NoWordsError do
57
+ Password.diction = nil
58
+ end
59
+ end
60
+ end
metadata ADDED
@@ -0,0 +1,73 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: haddock
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Stephen Celis
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-04-01 00:00:00 -05:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: hoe
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 1.11.0
24
+ version:
25
+ description: A more memorable password generator. Swordfish? No, I got tired of that. I changed it.
26
+ email:
27
+ - stephen@stephencelis.com
28
+ executables:
29
+ - ha-gen
30
+ extensions: []
31
+
32
+ extra_rdoc_files:
33
+ - History.txt
34
+ - Manifest.txt
35
+ - README.txt
36
+ files:
37
+ - History.txt
38
+ - Manifest.txt
39
+ - README.txt
40
+ - Rakefile
41
+ - bin/ha-gen
42
+ - lib/haddock.rb
43
+ - test/names.txt
44
+ - test/test_haddock.rb
45
+ has_rdoc: true
46
+ homepage: http://github.com/stephencelis/haddock
47
+ post_install_message:
48
+ rdoc_options:
49
+ - --main
50
+ - README.txt
51
+ require_paths:
52
+ - lib
53
+ required_ruby_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: "0"
58
+ version:
59
+ required_rubygems_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: "0"
64
+ version:
65
+ requirements: []
66
+
67
+ rubyforge_project: haddock
68
+ rubygems_version: 1.3.1
69
+ signing_key:
70
+ specification_version: 2
71
+ summary: A more memorable password generator
72
+ test_files:
73
+ - test/test_haddock.rb