oro 1.0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE.textile +21 -0
- data/README.md +72 -0
- data/Rakefile +19 -0
- data/bin/oro +3 -0
- data/lib/oro.rb +80 -0
- data/lib/oro/defaults.yml +19 -0
- data/lib/oro/errors.rb +18 -0
- data/lib/oro/helpers.rb +62 -0
- data/lib/oro/parts.rb +128 -0
- data/lib/oro/parts/braille.yml +259 -0
- data/lib/oro/parts/emoticon.yml +824 -0
- data/lib/oro/parts/english.yml +59645 -0
- data/lib/oro/parts/german.yml +29644 -0
- data/lib/oro/parts/latin.yml +35590 -0
- data/lib/oro/parts/linnaeus.yml +33511 -0
- data/lib/oro/parts/number.yml +13 -0
- data/lib/oro/parts/punctuation.yml +34 -0
- data/lib/oro/password.rb +114 -0
- data/lib/oro/settings.rb +44 -0
- data/lib/oro/settings_parser.rb +105 -0
- data/oro.gemspec +16 -0
- data/test/preference_test.rb +40 -0
- metadata +67 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: d0380ef86c093d775e831662d68f3704eefef9c8
|
4
|
+
data.tar.gz: 6045e214724254cfc7909ade545dea77bda2e2d4
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 62361ea62f0e5664aec526025ac35bb20bf4e904958d2a923c1400bf27f55b04eeea7c3c426195c8dd182c92bf45a25afc26177c5a7f4c1ee652ce3d203cb281
|
7
|
+
data.tar.gz: 7cf0c7bb8cd3377235b86d5912878bb3c0d2643fa149fcf05ff9306ca04e135fbcf4e312af47c29b18ec43c9bcc6cee98c0c384a5287cfb50e29f6d338e99458
|
data/LICENSE.textile
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2015 Joel Wagener
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
# Oro
|
2
|
+
|
3
|
+
_**"The enemy knows the system"** ([Claude Shannon](http://en.wikipedia.org/wiki/Claude_Shannon) / [Auguste Kerckhoffs](http://en.wikipedia.org/wiki/Auguste_Kerckhoffs))_
|
4
|
+
|
5
|
+
A flexible, command-line utility which generates memorable passwords.
|
6
|
+
|
7
|
+
## Usage
|
8
|
+
|
9
|
+
Usage: oro [settings]
|
10
|
+
|
11
|
+
Part settings (all lengths optional)
|
12
|
+
p[n] Punctuation part
|
13
|
+
n[n] Number part
|
14
|
+
l[n] Linnaeus part
|
15
|
+
a[n] Latin part
|
16
|
+
g[n] German part
|
17
|
+
e[n] English part
|
18
|
+
m[n] Emoticon part
|
19
|
+
b[n] Braille part
|
20
|
+
|
21
|
+
Config settings
|
22
|
+
-i, --iterations=MANDATORY The number of passwords to generate
|
23
|
+
-c, --[no-]capitalize Capitalize every word part
|
24
|
+
-r, --[no-]capitalize-random Randomly capitalize one letter in every word part
|
25
|
+
-l, --[no-]l33t Make one l33t-style replacement per word part
|
26
|
+
-s, --[no-]shuffle Randomize map parts
|
27
|
+
-f, --format=MANDATORY Results format: string, json, yaml
|
28
|
+
-e, --separator[=OPTIONAL] Separator characters
|
29
|
+
|
30
|
+
Action settings
|
31
|
+
--lists Show all available lists
|
32
|
+
--prefs, --preferences Show your current preferences
|
33
|
+
--defaults Show system defaults
|
34
|
+
--set Set passed settings as your preferences
|
35
|
+
--reset Reset your preferences to system defaults
|
36
|
+
-v, --verbose Provide verbose feedback, dictionary metadata, and statistics when run
|
37
|
+
-h, --help Print this dialog
|
38
|
+
--version Show version
|
39
|
+
|
40
|
+
Examples
|
41
|
+
oro e9 p1 n3 -s --set
|
42
|
+
oro n4 -e"-" -i4
|
43
|
+
oro n99 -i10
|
44
|
+
oro e10 n5 -fjson
|
45
|
+
|
46
|
+
See dictionary source files for associated license attributions.
|
47
|
+
|
48
|
+
## License
|
49
|
+
|
50
|
+
http://opensource.org/licenses/mit-license.php
|
51
|
+
|
52
|
+
The MIT License (MIT)
|
53
|
+
|
54
|
+
Copyright (c) 2015 Joel Wagener
|
55
|
+
|
56
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
57
|
+
of this software and associated documentation files (the "Software"), to deal
|
58
|
+
in the Software without restriction, including without limitation the rights
|
59
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
60
|
+
copies of the Software, and to permit persons to whom the Software is
|
61
|
+
furnished to do so, subject to the following conditions:
|
62
|
+
|
63
|
+
The above copyright notice and this permission notice shall be included in
|
64
|
+
all copies or substantial portions of the Software.
|
65
|
+
|
66
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
67
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
68
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
69
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
70
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
71
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
72
|
+
THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'rake/testtask'
|
2
|
+
|
3
|
+
namespace :oro do
|
4
|
+
|
5
|
+
Rake::TestTask.new do |task|
|
6
|
+
Dir.glob(File.dirname(File.absolute_path(__FILE__)) + 'lib/oro/*.rb') {|file| require file} # FIXME Seemingly fails to load shit.
|
7
|
+
task.libs << 'lib/oro/*.rb' # FIXME Have no idea if this is doing anything.
|
8
|
+
task.test_files = FileList['test/*_test.rb']
|
9
|
+
task.verbose = true
|
10
|
+
end
|
11
|
+
|
12
|
+
desc 'Say Hola!'
|
13
|
+
task :hola do
|
14
|
+
puts 'Hola, Señora!'
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
task :default => 'oro:test'
|
data/bin/oro
ADDED
data/lib/oro.rb
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'benchmark'
|
4
|
+
require 'yaml'
|
5
|
+
require 'json'
|
6
|
+
# require 'byebug'
|
7
|
+
require_relative 'oro/settings'
|
8
|
+
require_relative 'oro/password'
|
9
|
+
|
10
|
+
# LET'S make passwords
|
11
|
+
|
12
|
+
time = Benchmark.measure do
|
13
|
+
begin
|
14
|
+
|
15
|
+
# Create ~/.oro preferences file if missing
|
16
|
+
Preferences.instance
|
17
|
+
|
18
|
+
# Set settings, parse clio
|
19
|
+
password = Password.new(ARGV)
|
20
|
+
|
21
|
+
# Manage actions here (and retain single responsibility principle for SettingsParser)
|
22
|
+
password.actions.each_pair do |action, val|
|
23
|
+
case action
|
24
|
+
when :lists
|
25
|
+
puts Password.installed_parts_summary
|
26
|
+
exit
|
27
|
+
when :preferences
|
28
|
+
puts Preferences.instance.clio
|
29
|
+
exit
|
30
|
+
when :defaults
|
31
|
+
puts Defaults.instance.clio
|
32
|
+
exit
|
33
|
+
when :set
|
34
|
+
Preferences.instance.settings = password.virgin_settings
|
35
|
+
puts "Saved preferences\n#{Preferences.instance.clio}"
|
36
|
+
when :reset
|
37
|
+
Preferences.instance.reset_defaults
|
38
|
+
puts "Reset preferences to defaults\n#{Preferences.instance.clio}"
|
39
|
+
exit
|
40
|
+
when :verbose
|
41
|
+
$VERBOSE = true
|
42
|
+
when :help
|
43
|
+
puts val
|
44
|
+
exit
|
45
|
+
when :version
|
46
|
+
puts val
|
47
|
+
exit
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Be verbose if requested
|
52
|
+
warn(Preferences.instance.to_s, "Merged settings: #{ClioHelper.clioize(password.settings)}", "Password lengths will be: #{password.length}") if $VERBOSE
|
53
|
+
|
54
|
+
@passwords = []
|
55
|
+
time_passwords = Benchmark.measure do
|
56
|
+
(1..password.config[:iterations]).each { @passwords << password.result }
|
57
|
+
end
|
58
|
+
|
59
|
+
warn("Time to generate #{password.config[:iterations]} passwords: #{time_passwords.real}, #{time_passwords.real / password.config[:iterations]} per password") if $VERBOSE
|
60
|
+
|
61
|
+
# We are done
|
62
|
+
case password.config[:format]
|
63
|
+
when 'json'
|
64
|
+
@passwords = @passwords.to_json
|
65
|
+
when 'yaml', 'yml'
|
66
|
+
@passwords = @passwords.to_yaml
|
67
|
+
when 'string'
|
68
|
+
@passwords = @passwords.join(password.config[:separator]).strip
|
69
|
+
end
|
70
|
+
|
71
|
+
rescue OptionParser::InvalidOption, OptionParser::AmbiguousOption, OptionParser::MissingArgument, OptionParser::InvalidArgument => e
|
72
|
+
puts "Error: #{e.message}"
|
73
|
+
rescue NoMatchingListError, ListIsNonContiguousError, MatchlessLengthWordError => e
|
74
|
+
puts e.message
|
75
|
+
end
|
76
|
+
end # end Benchmark
|
77
|
+
|
78
|
+
# Return results
|
79
|
+
warn("Time to run: #{time.real}") if $VERBOSE
|
80
|
+
puts @passwords
|
@@ -0,0 +1,19 @@
|
|
1
|
+
--- !ruby/object:OpenStruct
|
2
|
+
table:
|
3
|
+
:plan:
|
4
|
+
- - English
|
5
|
+
- 8
|
6
|
+
- - Punctuation
|
7
|
+
- 1
|
8
|
+
- - Number
|
9
|
+
- 3
|
10
|
+
:config:
|
11
|
+
:iterations: 5
|
12
|
+
:capitalize: true
|
13
|
+
:capitalize_random: false
|
14
|
+
:l33t: false
|
15
|
+
:shuffle: false
|
16
|
+
:format: 'string'
|
17
|
+
:separator: "\n" # Requires double quotes
|
18
|
+
|
19
|
+
modifiable: true
|
data/lib/oro/errors.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# Oro error classes
|
2
|
+
class OroError < Exception
|
3
|
+
def initialize(msg)
|
4
|
+
@msg = msg
|
5
|
+
end
|
6
|
+
|
7
|
+
def message
|
8
|
+
"Error: #{@msg}"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class PartInstantiationError < OroError; end
|
13
|
+
|
14
|
+
class MatchlessLengthWordError < OroError; end
|
15
|
+
|
16
|
+
class NoMatchingListError < OroError; end
|
17
|
+
|
18
|
+
class ListIsNonContiguousError < OroError; end
|
data/lib/oro/helpers.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
# Rails-style string helpers
|
2
|
+
module Helpers
|
3
|
+
refine String do
|
4
|
+
def camelize
|
5
|
+
dup.split(/_/).map(&:capitalize).join('') # Modified from: http://yehudakatz.com/2010/11/30/ruby-2-0-refinements-in-practice/
|
6
|
+
end
|
7
|
+
|
8
|
+
# Not presently used
|
9
|
+
def underscore
|
10
|
+
gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').gsub(/([a-z\d])([A-Z])/, '\1_\2').tr('-', '_').downcase
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# Mixed in to the singleton Defaults and Preference classes, and the Password class
|
16
|
+
module SettingsAccessors
|
17
|
+
def plan
|
18
|
+
settings.plan
|
19
|
+
end
|
20
|
+
|
21
|
+
def plan=(val)
|
22
|
+
@settings.plan = val
|
23
|
+
end
|
24
|
+
|
25
|
+
def config
|
26
|
+
settings.config
|
27
|
+
end
|
28
|
+
|
29
|
+
def config=(val)
|
30
|
+
@settings.config = val
|
31
|
+
end
|
32
|
+
|
33
|
+
def actions
|
34
|
+
settings.actions
|
35
|
+
end
|
36
|
+
|
37
|
+
def actions=(val)
|
38
|
+
@settings.actions = val
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Helper methods for turning settings back into clio
|
43
|
+
# FIXME: This *helper* method requires knowledge of the Password class
|
44
|
+
module ClioHelper
|
45
|
+
def self.clioize(settings)
|
46
|
+
clio = []
|
47
|
+
settings.plan.each { |part| Password.installed_part_switches.include?(part[0]) ? clio << "w#{part[1]}" : clio << "#{part[0][0].downcase}#{part[1]}" }
|
48
|
+
settings.config.each { |part| clio << "--#{part[0].to_s.gsub('_', '-')}=#{part[1].to_s.gsub(/\n|\t|\r/, "\n" => '"\n"', "\t" => '"\t"', "\r" => '"\r"')}" }
|
49
|
+
clio.join(' ')
|
50
|
+
end
|
51
|
+
|
52
|
+
def clio
|
53
|
+
ClioHelper.clioize(settings)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# Custom inspection
|
58
|
+
module SettingsInspector
|
59
|
+
def to_s
|
60
|
+
"#{self.class.name}: #{self.clio} (#{self.class::FILE})"
|
61
|
+
end
|
62
|
+
end
|
data/lib/oro/parts.rb
ADDED
@@ -0,0 +1,128 @@
|
|
1
|
+
# Class representing a password plan part, which map to installed psrt lists
|
2
|
+
class Part
|
3
|
+
LEET = { 'a' => ['@'], 'b' => ['|3'], 'd' => ['|)'], 'e' => ['3'], 'f' => ['ph'], 'i' => ['|'], 'k' => ['|<'],
|
4
|
+
'l' => ['|_'], 'o' => ['0'], 'p' => ['|*'], 's' => ['$', '5'], 'w' => ["'//"] }
|
5
|
+
|
6
|
+
def self.list_location
|
7
|
+
@list_location
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.list_location=(location)
|
11
|
+
@list_location = location
|
12
|
+
end
|
13
|
+
|
14
|
+
# instance_exec (vs. instance_eval) to pass params, define_singleton_method to add the class method
|
15
|
+
def self.listify
|
16
|
+
list = YAML.load_file(@list_location)
|
17
|
+
instance_exec(list) { |l| define_singleton_method('list') { @list ||= l } }
|
18
|
+
self.respond_to?(:list) ? true : false
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.single_character_list?
|
22
|
+
(shortest == 1 && longest == 1) ? true : false
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.count
|
26
|
+
list.size
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.shortest
|
30
|
+
@shortest ||= list.empty? ? 0 : list.min { |a, b| a.length <=> b.length }.length
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.longest
|
34
|
+
@longest ||= list.empty? ? 0 : list.max { |a, b| a.length <=> b.length }.length
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.middle
|
38
|
+
(shortest + longest) / 2
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.distinct?
|
42
|
+
list.size == list.uniq.size ? true : false
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.descendants
|
46
|
+
ObjectSpace.each_object(Class).select { |klass| klass < self }
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.contiguous?
|
50
|
+
absences.empty?
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.absences
|
54
|
+
length_exists = proc { |length| list.select { |w| w.length == length }.empty? ? false : true }
|
55
|
+
lengths = []
|
56
|
+
(shortest..longest).each do |len|
|
57
|
+
lengths << len if !length_exists.call(len)
|
58
|
+
end
|
59
|
+
lengths
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.get_one
|
63
|
+
list.sample
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.get(size, config = {})
|
67
|
+
single_character_list? ? get_for_single_character_part(size) : get_for_word_part(size, config)
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.get_for_single_character_part(size)
|
71
|
+
result = []
|
72
|
+
size.times { result << get_one }
|
73
|
+
result.join
|
74
|
+
end
|
75
|
+
|
76
|
+
def self.get_for_word_part(size, config = {})
|
77
|
+
fail MatchlessLengthWordError, "Matchless length of #{size} requested from:\n#{self}" if size < shortest || size > longest
|
78
|
+
|
79
|
+
# FIXME: The performance benefit of refactoring to use Array#reject, or possibly reject!, should be tested.
|
80
|
+
get_proc, attempt = proc { get_one }, ''
|
81
|
+
|
82
|
+
until attempt.length == size do attempt = get_proc.call end
|
83
|
+
|
84
|
+
attempt.capitalize! if config[:capitalize]
|
85
|
+
|
86
|
+
if config[:capitalize_random]
|
87
|
+
temp = attempt.chars
|
88
|
+
temp[rand(temp.length)].upcase!
|
89
|
+
attempt = temp.join
|
90
|
+
end
|
91
|
+
|
92
|
+
# An index histogram of matching leetables; ex: {"a"=>[9], "e"=>[0, 6], "i"=>[8]}
|
93
|
+
if config[:l33t]
|
94
|
+
leetables = {}
|
95
|
+
LEET.keys.each do |l|
|
96
|
+
matches = (0...attempt.length).find_all { |i| attempt[i, 1] == l }
|
97
|
+
leetables[l] = matches unless matches.empty?
|
98
|
+
end
|
99
|
+
|
100
|
+
unless leetables.empty?
|
101
|
+
leeted = leetables.to_a.sample(1).flatten.first # Get a random key from the histogram
|
102
|
+
attempt.sub!(leeted, LEET[leeted][rand(LEET[leeted].length)]) # Change to gsub to replace all matches
|
103
|
+
end
|
104
|
+
end
|
105
|
+
attempt
|
106
|
+
end
|
107
|
+
|
108
|
+
def self.to_s
|
109
|
+
"List #{name} > count:#{count}, shortest:#{shortest}, longest:#{longest}, middle:#{middle}, distinct:#{distinct?}, get one:'#{get_one}', contiguous:#{contiguous?}" + (absences.empty? ? '' : ", absences:#{absences}")
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
# Initialize list-less parts classes from all installed <list>.yml files, * at load time *
|
114
|
+
begin
|
115
|
+
require_relative 'helpers'
|
116
|
+
using Helpers
|
117
|
+
|
118
|
+
PARTS_DIRECTORY = 'parts'
|
119
|
+
|
120
|
+
Dir.glob(File.join(File.dirname(__FILE__), PARTS_DIRECTORY, '**', '*.yml')) do |list|
|
121
|
+
klass_name = File.basename(list, '.yml').camelize
|
122
|
+
instantiated = Object.const_set(klass_name, Class.new(Part)) # Creates subclasses of Part
|
123
|
+
instantiated.list_location = list
|
124
|
+
end
|
125
|
+
|
126
|
+
rescue PartInstantiationError => e
|
127
|
+
puts e.message
|
128
|
+
end # End part class initilization
|
@@ -0,0 +1,259 @@
|
|
1
|
+
# http://unicodeemoticons.com/symbols_all.htm ; Unknown license ; Formatting.
|
2
|
+
|
3
|
+
---
|
4
|
+
- ⠁
|
5
|
+
- ⠂
|
6
|
+
- ⠃
|
7
|
+
- ⠄
|
8
|
+
- ⠅
|
9
|
+
- ⠆
|
10
|
+
- ⠇
|
11
|
+
- ⠈
|
12
|
+
- ⠉
|
13
|
+
- ⠊
|
14
|
+
- ⠋
|
15
|
+
- ⠌
|
16
|
+
- ⠍
|
17
|
+
- ⠎
|
18
|
+
- ⠏
|
19
|
+
- ⠐
|
20
|
+
- ⠑
|
21
|
+
- ⠒
|
22
|
+
- ⠓
|
23
|
+
- ⠔
|
24
|
+
- ⠕
|
25
|
+
- ⠖
|
26
|
+
- ⠗
|
27
|
+
- ⠘
|
28
|
+
- ⠙
|
29
|
+
- ⠚
|
30
|
+
- ⠛
|
31
|
+
- ⠜
|
32
|
+
- ⠝
|
33
|
+
- ⠞
|
34
|
+
- ⠟
|
35
|
+
- ⠠
|
36
|
+
- ⠡
|
37
|
+
- ⠢
|
38
|
+
- ⠣
|
39
|
+
- ⠤
|
40
|
+
- ⠥
|
41
|
+
- ⠦
|
42
|
+
- ⠧
|
43
|
+
- ⠨
|
44
|
+
- ⠩
|
45
|
+
- ⠪
|
46
|
+
- ⠫
|
47
|
+
- ⠬
|
48
|
+
- ⠭
|
49
|
+
- ⠮
|
50
|
+
- ⠯
|
51
|
+
- ⠰
|
52
|
+
- ⠱
|
53
|
+
- ⠲
|
54
|
+
- ⠳
|
55
|
+
- ⠴
|
56
|
+
- ⠵
|
57
|
+
- ⠶
|
58
|
+
- ⠷
|
59
|
+
- ⠸
|
60
|
+
- ⠹
|
61
|
+
- ⠺
|
62
|
+
- ⠻
|
63
|
+
- ⠼
|
64
|
+
- ⠽
|
65
|
+
- ⠾
|
66
|
+
- ⠿
|
67
|
+
- ⡀
|
68
|
+
- ⡁
|
69
|
+
- ⡂
|
70
|
+
- ⡃
|
71
|
+
- ⡄
|
72
|
+
- ⡅
|
73
|
+
- ⡆
|
74
|
+
- ⡇
|
75
|
+
- ⡈
|
76
|
+
- ⡉
|
77
|
+
- ⡊
|
78
|
+
- ⡋
|
79
|
+
- ⡌
|
80
|
+
- ⡍
|
81
|
+
- ⡎
|
82
|
+
- ⡏
|
83
|
+
- ⡐
|
84
|
+
- ⡑
|
85
|
+
- ⡒
|
86
|
+
- ⡓
|
87
|
+
- ⡔
|
88
|
+
- ⡕
|
89
|
+
- ⡖
|
90
|
+
- ⡗
|
91
|
+
- ⡘
|
92
|
+
- ⡙
|
93
|
+
- ⡚
|
94
|
+
- ⡛
|
95
|
+
- ⡜
|
96
|
+
- ⡝
|
97
|
+
- ⡞
|
98
|
+
- ⡟
|
99
|
+
- ⡠
|
100
|
+
- ⡡
|
101
|
+
- ⡢
|
102
|
+
- ⡣
|
103
|
+
- ⡤
|
104
|
+
- ⡥
|
105
|
+
- ⡦
|
106
|
+
- ⡧
|
107
|
+
- ⡨
|
108
|
+
- ⡩
|
109
|
+
- ⡪
|
110
|
+
- ⡫
|
111
|
+
- ⡬
|
112
|
+
- ⡭
|
113
|
+
- ⡮
|
114
|
+
- ⡯
|
115
|
+
- ⡰
|
116
|
+
- ⡱
|
117
|
+
- ⡲
|
118
|
+
- ⡳
|
119
|
+
- ⡴
|
120
|
+
- ⡵
|
121
|
+
- ⡶
|
122
|
+
- ⡷
|
123
|
+
- ⡸
|
124
|
+
- ⡹
|
125
|
+
- ⡺
|
126
|
+
- ⡻
|
127
|
+
- ⡼
|
128
|
+
- ⡽
|
129
|
+
- ⡾
|
130
|
+
- ⡿
|
131
|
+
- ⢀
|
132
|
+
- ⢁
|
133
|
+
- ⢂
|
134
|
+
- ⢃
|
135
|
+
- ⢄
|
136
|
+
- ⢅
|
137
|
+
- ⢆
|
138
|
+
- ⢇
|
139
|
+
- ⢈
|
140
|
+
- ⢉
|
141
|
+
- ⢊
|
142
|
+
- ⢋
|
143
|
+
- ⢌
|
144
|
+
- ⢍
|
145
|
+
- ⢎
|
146
|
+
- ⢏
|
147
|
+
- ⢐
|
148
|
+
- ⢑
|
149
|
+
- ⢒
|
150
|
+
- ⢓
|
151
|
+
- ⢔
|
152
|
+
- ⢕
|
153
|
+
- ⢖
|
154
|
+
- ⢗
|
155
|
+
- ⢘
|
156
|
+
- ⢙
|
157
|
+
- ⢚
|
158
|
+
- ⢛
|
159
|
+
- ⢜
|
160
|
+
- ⢝
|
161
|
+
- ⢞
|
162
|
+
- ⢟
|
163
|
+
- ⢠
|
164
|
+
- ⢡
|
165
|
+
- ⢢
|
166
|
+
- ⢣
|
167
|
+
- ⢤
|
168
|
+
- ⢥
|
169
|
+
- ⢦
|
170
|
+
- ⢧
|
171
|
+
- ⢨
|
172
|
+
- ⢩
|
173
|
+
- ⢪
|
174
|
+
- ⢫
|
175
|
+
- ⢬
|
176
|
+
- ⢭
|
177
|
+
- ⢮
|
178
|
+
- ⢯
|
179
|
+
- ⢰
|
180
|
+
- ⢱
|
181
|
+
- ⢲
|
182
|
+
- ⢳
|
183
|
+
- ⢴
|
184
|
+
- ⢵
|
185
|
+
- ⢶
|
186
|
+
- ⢷
|
187
|
+
- ⢸
|
188
|
+
- ⢹
|
189
|
+
- ⢺
|
190
|
+
- ⢻
|
191
|
+
- ⢼
|
192
|
+
- ⢽
|
193
|
+
- ⢾
|
194
|
+
- ⢿
|
195
|
+
- ⣀
|
196
|
+
- ⣁
|
197
|
+
- ⣂
|
198
|
+
- ⣃
|
199
|
+
- ⣄
|
200
|
+
- ⣅
|
201
|
+
- ⣆
|
202
|
+
- ⣇
|
203
|
+
- ⣈
|
204
|
+
- ⣉
|
205
|
+
- ⣊
|
206
|
+
- ⣋
|
207
|
+
- ⣌
|
208
|
+
- ⣍
|
209
|
+
- ⣎
|
210
|
+
- ⣏
|
211
|
+
- ⣐
|
212
|
+
- ⣑
|
213
|
+
- ⣒
|
214
|
+
- ⣓
|
215
|
+
- ⣔
|
216
|
+
- ⣕
|
217
|
+
- ⣖
|
218
|
+
- ⣗
|
219
|
+
- ⣘
|
220
|
+
- ⣙
|
221
|
+
- ⣚
|
222
|
+
- ⣛
|
223
|
+
- ⣜
|
224
|
+
- ⣝
|
225
|
+
- ⣞
|
226
|
+
- ⣟
|
227
|
+
- ⣠
|
228
|
+
- ⣡
|
229
|
+
- ⣢
|
230
|
+
- ⣣
|
231
|
+
- ⣤
|
232
|
+
- ⣥
|
233
|
+
- ⣦
|
234
|
+
- ⣧
|
235
|
+
- ⣨
|
236
|
+
- ⣩
|
237
|
+
- ⣪
|
238
|
+
- ⣫
|
239
|
+
- ⣬
|
240
|
+
- ⣭
|
241
|
+
- ⣮
|
242
|
+
- ⣯
|
243
|
+
- ⣰
|
244
|
+
- ⣱
|
245
|
+
- ⣲
|
246
|
+
- ⣳
|
247
|
+
- ⣴
|
248
|
+
- ⣵
|
249
|
+
- ⣶
|
250
|
+
- ⣷
|
251
|
+
- ⣸
|
252
|
+
- ⣹
|
253
|
+
- ⣺
|
254
|
+
- ⣻
|
255
|
+
- ⣼
|
256
|
+
- ⣽
|
257
|
+
- ⣾
|
258
|
+
- ⣿
|
259
|
+
|