cipher_bureau 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +20 -0
- data/README.md +160 -0
- data/Rakefile +38 -0
- data/db/seeds/norwegian/wordloader.rb +47 -0
- data/lib/cipher_bureau.rb +59 -0
- data/lib/cipher_bureau/data_loader.rb +65 -0
- data/lib/cipher_bureau/dictionary.rb +63 -0
- data/lib/cipher_bureau/exceptions.rb +25 -0
- data/lib/cipher_bureau/password.rb +114 -0
- data/lib/cipher_bureau/password_meter.rb +183 -0
- data/lib/cipher_bureau/statistic.rb +48 -0
- data/lib/cipher_bureau/version.rb +3 -0
- data/lib/generators/cipher_bureau/create_migration_generator.rb +40 -0
- data/lib/generators/cipher_bureau/load_data_generator.rb +36 -0
- data/lib/generators/templates/create_cipher_bureau_dictionaries.rb +41 -0
- data/lib/generators/templates/create_cipher_bureau_statistics.rb +39 -0
- data/lib/tasks/cipher_bureau_tasks.rake +40 -0
- data/test/dummy/README.rdoc +261 -0
- data/test/dummy/Rakefile +7 -0
- data/test/dummy/app/assets/javascripts/application.js +15 -0
- data/test/dummy/app/assets/stylesheets/application.css +13 -0
- data/test/dummy/app/controllers/application_controller.rb +3 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +59 -0
- data/test/dummy/config/boot.rb +10 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +37 -0
- data/test/dummy/config/environments/production.rb +67 -0
- data/test/dummy/config/environments/test.rb +37 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/inflections.rb +15 -0
- data/test/dummy/config/initializers/mime_types.rb +5 -0
- data/test/dummy/config/initializers/secret_token.rb +7 -0
- data/test/dummy/config/initializers/session_store.rb +8 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +5 -0
- data/test/dummy/config/routes.rb +58 -0
- data/test/dummy/db/migrate/201301290819401_create_cipher_bureau_dictionaries.rb +19 -0
- data/test/dummy/db/migrate/201301290819402_create_cipher_bureau_statistics.rb +17 -0
- data/test/dummy/db/schema.rb +46 -0
- data/test/dummy/public/404.html +26 -0
- data/test/dummy/public/422.html +26 -0
- data/test/dummy/public/500.html +25 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/dummy/script/rails +6 -0
- data/test/fixtures/cipher_bureau_dictionaries.yml +704 -0
- data/test/fixtures/cipher_bureau_statistics.yml +40 -0
- data/test/test_helper.rb +15 -0
- data/test/units/cipher_bureau/dictionary_test.rb +74 -0
- data/test/units/cipher_bureau/password_meter_test.rb +128 -0
- data/test/units/cipher_bureau/password_test.rb +188 -0
- data/test/units/cipher_bureau/statistic_test.rb +78 -0
- data/test/units/cipher_bureau_test.rb +45 -0
- metadata +197 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2012 YOURNAME
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,160 @@
|
|
1
|
+
# CipherBureau
|
2
|
+
|
3
|
+
### CipherBureau is a simple gem for password generation
|
4
|
+
|
5
|
+
Sometimes you need to generate passwords in your application.
|
6
|
+
This gem does exactly that. It also has the ability to measure the strength of passwords.
|
7
|
+
In addition it contains a dictionary for creating ```memorable``` passwords. Currently the dictionary is only in Norwegian, but you can easily load dictionaries yourself. See separate explanation on how to load dictionaries, setting up defaults etc.
|
8
|
+
|
9
|
+
|
10
|
+
# Install and Setup
|
11
|
+
|
12
|
+
Install the gem
|
13
|
+
|
14
|
+
gem install cipher_bureau
|
15
|
+
|
16
|
+
Or, in your Gemfile
|
17
|
+
|
18
|
+
gem 'cipher_bureau'
|
19
|
+
|
20
|
+
|
21
|
+
## Generating migration and loading dictionary
|
22
|
+
|
23
|
+
If you want to use the ```memorable method```, you will need to create a couple of tables for holding the dictionary.
|
24
|
+
CipherBureau includes two generators, one for generating the migration, and one for loading the dictionary.
|
25
|
+
|
26
|
+
Generate the migration:
|
27
|
+
|
28
|
+
rails generate cipher_bureau:create_migration
|
29
|
+
|
30
|
+
Load the data
|
31
|
+
|
32
|
+
rails generate cipher_bureau:load_data
|
33
|
+
|
34
|
+
Loading the data will take some time as there are more than 600,000 words, including grammar and names.
|
35
|
+
|
36
|
+
# Using the password interface
|
37
|
+
|
38
|
+
## Basic interface
|
39
|
+
|
40
|
+
Generate a password, using random as an example
|
41
|
+
|
42
|
+
```Ruby
|
43
|
+
# Generate a single random password with length 10 characters
|
44
|
+
CipherBureau::Password.random(:length => 10)
|
45
|
+
=> "ZnipfcIByq"
|
46
|
+
|
47
|
+
# Generate two random passwords with length 10 characters
|
48
|
+
CipherBureau::Password.random(2, :length => 10)
|
49
|
+
=> ["4X^gb1}oLP", "g%JJJ:Y`O."]
|
50
|
+
|
51
|
+
# Generate a random password and measure its strength
|
52
|
+
CipherBureau::Password.random(:length => 10, :strength => true)
|
53
|
+
=> ["]KF|O4vANP", 90]
|
54
|
+
|
55
|
+
# Generate two random passwords and measure their strength
|
56
|
+
CipherBureau::Password.random(2, :length => 10, :strength => true)
|
57
|
+
=> [[")1^flZvQ^4", 100], ["^DGAf83B`s", 98]]
|
58
|
+
```
|
59
|
+
|
60
|
+
## Configuring default password length
|
61
|
+
|
62
|
+
If you want you can configure the default password length
|
63
|
+
|
64
|
+
```Ruby
|
65
|
+
# Set deault length to 10 characters
|
66
|
+
CipherBureau.password_length = 10
|
67
|
+
```
|
68
|
+
|
69
|
+
## Basic methods
|
70
|
+
|
71
|
+
### Password generation methods
|
72
|
+
|
73
|
+
You can use the same parameters for all password functions, except memorable which takes more parameters
|
74
|
+
|
75
|
+
```Ruby
|
76
|
+
CipherBureau::Password.random
|
77
|
+
=> "dv$w1eD<5T"
|
78
|
+
|
79
|
+
CipherBureau::Password.letters_and_numbers
|
80
|
+
=> "qoQIfSrElc"
|
81
|
+
|
82
|
+
CipherBureau::Password.numbers_only
|
83
|
+
=> "6924908575"
|
84
|
+
|
85
|
+
CipherBureau::Password.symbols_and_numbers
|
86
|
+
=> "<~%2`!-452"
|
87
|
+
|
88
|
+
CipherBureau::Password.memorable
|
89
|
+
=> "acti)}flik"
|
90
|
+
```
|
91
|
+
|
92
|
+
The memorable password emphasize on generating passwords with symbols and numbers in the middle, as this ranks higher in security.
|
93
|
+
|
94
|
+
The memorable method accepts more arguments:
|
95
|
+
|
96
|
+
* ```:country_code``` - a numerical value of country_code, e.g. Norway 47
|
97
|
+
* ```:ascii``` - true of false. Use false to get words outside 7-bits range, such as nordic characters
|
98
|
+
* ```:camelize``` - true. Only names has first letter capitalized
|
99
|
+
* ```:grammar``` - legal values are: 'adjective','adverb','conjunction','determiner','interjection','name','noun',
|
100
|
+
'musical','numeral','preposition','pronoun','subjunctive','verb','verbalsubst',
|
101
|
+
* ```:name_tupe``` - if grammar is specified, you can optionally specify: 'boysname','girlsname', 'surname'
|
102
|
+
|
103
|
+
|
104
|
+
Example:
|
105
|
+
|
106
|
+
```Ruby
|
107
|
+
CipherBureau::Password.memorable(:length => 12, :grammar => 'name', :name_type => 'girlsname')
|
108
|
+
=> "Hedda[)*Turi"
|
109
|
+
|
110
|
+
CipherBureau::Password.memorable(:length => 12, :grammar => 'noun', :camelize => true)
|
111
|
+
=> "Aktor2]%Hott"
|
112
|
+
```
|
113
|
+
|
114
|
+
### Measuring strength of passwords
|
115
|
+
|
116
|
+
The PasswordMeter module is a ruby implementation of the javascript algorithm found at http://www.passwordmeter.com
|
117
|
+
It will return a range from 0 to 100 depending on the complexity of the password.
|
118
|
+
|
119
|
+
Examples:
|
120
|
+
|
121
|
+
```Ruby
|
122
|
+
CipherBureau::PasswordMeter.strength('aaaaaaaa')
|
123
|
+
=> 0
|
124
|
+
CipherBureau::PasswordMeter.strength('abcdaaa1')
|
125
|
+
=> 15
|
126
|
+
CipherBureau::PasswordMeter.strength('<~%2`!-452')
|
127
|
+
=> 100
|
128
|
+
CipherBureau::PasswordMeter.strength('Aktor2]%Hott')
|
129
|
+
=> 97
|
130
|
+
CipherBureau::PasswordMeter.strength('test123')
|
131
|
+
=> 36
|
132
|
+
```
|
133
|
+
|
134
|
+
|
135
|
+
# Configuring defaults
|
136
|
+
|
137
|
+
You can configure defaults for passwrd_length and memorable passwords by placing a file in your initializers directory:
|
138
|
+
|
139
|
+
```Ruby
|
140
|
+
# config/initializers/cipher_bureau.rb
|
141
|
+
CipherBureau.configure do |config|
|
142
|
+
config.password_length = 10
|
143
|
+
config.default_memorable_options = {
|
144
|
+
country_code: 47,
|
145
|
+
camelize: true,
|
146
|
+
grammar: 'name'
|
147
|
+
}
|
148
|
+
end
|
149
|
+
```
|
150
|
+
|
151
|
+
# Loading your own dictionary
|
152
|
+
|
153
|
+
See the file db/seeds/norwegian/wordloader.rb
|
154
|
+
|
155
|
+
This file loads the Norwegian wordlist and Norwegian names into the database. It explains how to load grammars and names into the database.
|
156
|
+
It is recommended to use the same facilities as that source is using.
|
157
|
+
CipherBureau::DataLoader is loading data in chunked transactions.
|
158
|
+
|
159
|
+
The default repository for dictionaries is located on http://dictionaries.cipher-bureau.net
|
160
|
+
You can control the location of the dictionaries by setting the configuration ```language_repository```.
|
data/Rakefile
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
begin
|
3
|
+
require 'bundler/setup'
|
4
|
+
rescue LoadError
|
5
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
6
|
+
end
|
7
|
+
begin
|
8
|
+
require 'rdoc/task'
|
9
|
+
rescue LoadError
|
10
|
+
require 'rdoc/rdoc'
|
11
|
+
require 'rake/rdoctask'
|
12
|
+
RDoc::Task = Rake::RDocTask
|
13
|
+
end
|
14
|
+
|
15
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
16
|
+
rdoc.rdoc_dir = 'rdoc'
|
17
|
+
rdoc.title = 'CipherBureau'
|
18
|
+
rdoc.options << '--line-numbers'
|
19
|
+
rdoc.rdoc_files.include('README.rdoc')
|
20
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
21
|
+
end
|
22
|
+
|
23
|
+
Dir.glob('lib/tasks/*.rake').each { |r| import r }
|
24
|
+
|
25
|
+
|
26
|
+
Bundler::GemHelper.install_tasks
|
27
|
+
|
28
|
+
require 'rake/testtask'
|
29
|
+
|
30
|
+
Rake::TestTask.new(:test) do |t|
|
31
|
+
t.libs << 'lib'
|
32
|
+
t.libs << 'test'
|
33
|
+
t.pattern = 'test/**/*_test.rb'
|
34
|
+
t.verbose = false
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
task :default => :test
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'unicode_utils'
|
3
|
+
|
4
|
+
country_code = 47
|
5
|
+
|
6
|
+
grammar_map = {
|
7
|
+
'prep' => 'preposition',
|
8
|
+
'verb' => 'verb',
|
9
|
+
'adj' => 'adjective',
|
10
|
+
'adv' => 'adverb',
|
11
|
+
'subst' => 'noun',
|
12
|
+
'interj' => 'interjection',
|
13
|
+
'det' => 'determiner',
|
14
|
+
'pron' => 'pronoun',
|
15
|
+
'verbalsubst' => 'verbalsubst',
|
16
|
+
'musikkuttr' => 'musical',
|
17
|
+
'konj' => 'conjunction',
|
18
|
+
'numeral' => 'numeral',
|
19
|
+
'sbu' => 'subjunctive',
|
20
|
+
'adjektiv' => 'adjective',
|
21
|
+
'CLB' => 'conjunction', # or correlative conjunction
|
22
|
+
'nominal' => 'determiner'
|
23
|
+
}
|
24
|
+
|
25
|
+
loader = CipherBureau::DataLoader.new(:norwegian, 1000)
|
26
|
+
|
27
|
+
puts "Loading grammar"
|
28
|
+
loader.process 'NSF-ordlisten', 'NSF-ordlisten.txt' do |str|
|
29
|
+
word, grammar = str.split(' ')
|
30
|
+
word = UnicodeUtils.downcase(word)
|
31
|
+
CipherBureau::Dictionary.create word: word.chomp, grammar: grammar_map[grammar], country_code: country_code
|
32
|
+
end
|
33
|
+
|
34
|
+
names_map = {
|
35
|
+
'surname' => 'etternavn',
|
36
|
+
'boysname' => 'guttenavn',
|
37
|
+
'girlsname' => 'jentenavn'
|
38
|
+
}
|
39
|
+
loader.chunks = 100
|
40
|
+
names_map.each do |name_type, file|
|
41
|
+
puts "Loading #{name_type}"
|
42
|
+
loader.process 'norske-navn', "#{file}.txt" do |name|
|
43
|
+
CipherBureau::Dictionary.create word: name, grammar: 'name', name_type: name_type, country_code: country_code
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
puts "Total words loaded: #{loader.words}"
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# Copyright (c) 2013 Dynamic Project Management AS
|
2
|
+
# Copyright (c) 2013 Knut I. Stenmark
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
|
23
|
+
require 'cipher_bureau/exceptions'
|
24
|
+
module CipherBureau
|
25
|
+
def self.table_name_prefix
|
26
|
+
'cipher_bureau_'
|
27
|
+
end
|
28
|
+
|
29
|
+
autoload :Statistic, 'cipher_bureau/statistic'
|
30
|
+
autoload :Dictionary, 'cipher_bureau/dictionary'
|
31
|
+
autoload :Password, 'cipher_bureau/password'
|
32
|
+
autoload :PasswordMeter, 'cipher_bureau/password_meter'
|
33
|
+
autoload :DataLoader, 'cipher_bureau/data_loader'
|
34
|
+
|
35
|
+
include ActiveSupport::Configurable
|
36
|
+
|
37
|
+
# Default password length
|
38
|
+
config_accessor :password_length
|
39
|
+
|
40
|
+
# Oprions to use for memorable passwords
|
41
|
+
#
|
42
|
+
# Valid options:
|
43
|
+
#
|
44
|
+
# :country_code - a numerical value of country_code, e.g. Norway 47
|
45
|
+
# :ascii - true of false. Use false to get words outside 7-bits range, such as nordic characters
|
46
|
+
# :grammar - legal values are: 'adjective','adverb','conjunction','determiner','interjection','name','noun',
|
47
|
+
# 'musical','numeral','preposition','pronoun','subjunctive','verb','verbalsubst',
|
48
|
+
# :name_tupe - if grammar is specified, you can optionally specify: 'boysname','girlsname', 'surname'
|
49
|
+
#
|
50
|
+
config_accessor :default_memorable_options
|
51
|
+
|
52
|
+
self.default_memorable_options ||= {}
|
53
|
+
|
54
|
+
# Sets repository location for langage files
|
55
|
+
config_accessor :language_repository
|
56
|
+
|
57
|
+
self.language_repository ||= "http://dictionaries.cipher-bureau.net"
|
58
|
+
|
59
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# Copyright (c) 2013 Dynamic Project Management AS
|
2
|
+
# Copyright (c) 2013 Knut I. Stenmark
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
|
23
|
+
require 'open-uri'
|
24
|
+
|
25
|
+
module CipherBureau
|
26
|
+
class DataLoader
|
27
|
+
attr_reader :words, :language
|
28
|
+
attr_accessor :chunks
|
29
|
+
|
30
|
+
def initialize(language, chunks = 100, words = 0, verbose = true)
|
31
|
+
@language, @chunks, @words, @verbose = language, chunks, words, verbose
|
32
|
+
end
|
33
|
+
|
34
|
+
def reader(filename)
|
35
|
+
Fiber.new do
|
36
|
+
puts "Reading file #{filename}" if @verbose
|
37
|
+
open(filename).readlines.each do |str|
|
38
|
+
Fiber.yield str
|
39
|
+
end
|
40
|
+
puts "\r#{@words}" if @verbose
|
41
|
+
nil
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def writer(fiber, &block)
|
46
|
+
str = nil
|
47
|
+
begin
|
48
|
+
chunks.times do
|
49
|
+
ActiveRecord::Base.transaction do
|
50
|
+
break unless str = fiber.resume
|
51
|
+
yield str.chomp
|
52
|
+
@words += 1
|
53
|
+
end
|
54
|
+
return unless str
|
55
|
+
end
|
56
|
+
print "\r#{@words}" if @verbose
|
57
|
+
end while str
|
58
|
+
end
|
59
|
+
|
60
|
+
def process(*directories_and_filename, &block)
|
61
|
+
filename = ([CipherBureau.language_repository, language.to_s] + directories_and_filename).join('/')
|
62
|
+
writer(reader(filename), &block)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# Copyright (c) 2013 Dynamic Project Management AS
|
2
|
+
# Copyright (c) 2013 Knut I. Stenmark
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
|
23
|
+
require 'unicode_utils'
|
24
|
+
class CipherBureau::Dictionary < ActiveRecord::Base
|
25
|
+
attr_accessible :word, :grammar, :country_code, :name_type
|
26
|
+
|
27
|
+
validates_presence_of :word, :grammar, :country_code
|
28
|
+
|
29
|
+
before_save do
|
30
|
+
self.length = word.length
|
31
|
+
self.ascii = !!(word =~ /^[a-z]+$/)
|
32
|
+
true
|
33
|
+
end
|
34
|
+
|
35
|
+
after_create do
|
36
|
+
CipherBureau::Statistic.register(self)
|
37
|
+
end
|
38
|
+
|
39
|
+
class << self
|
40
|
+
def random(*args)
|
41
|
+
criteria = args.extract_options!
|
42
|
+
camelize = criteria.delete(:camelize)
|
43
|
+
criteria.merge!(:length => args.first) if args.first
|
44
|
+
r = fetch_random_word(criteria)
|
45
|
+
r && (camelize ? capitalize(r.word) : r.word)
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
def randomized_offset(offset)
|
50
|
+
rand(offset)
|
51
|
+
end
|
52
|
+
|
53
|
+
def fetch_random_word(criteria)
|
54
|
+
n = CipherBureau::Statistic.word_count(criteria) # get number of elements satisfying criteria
|
55
|
+
where(criteria).offset(randomized_offset(n)).limit(1).first
|
56
|
+
end
|
57
|
+
|
58
|
+
def capitalize(word)
|
59
|
+
UnicodeUtils.upcase(word[0]) + word[1..-1]
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|