Class: Zxcvbn::Matchers::Spatial
- Inherits:
-
Object
- Object
- Zxcvbn::Matchers::Spatial
- Defined in:
- lib/zxcvbn/matchers/spatial.rb
Instance Method Summary collapse
-
#initialize(graphs) ⇒ Spatial
constructor
A new instance of Spatial.
- #matches(password) ⇒ Object
- #matches_for_graph(graph, graph_name, password) ⇒ Object
Constructor Details
#initialize(graphs) ⇒ Spatial
Returns a new instance of Spatial.
4 5 6 |
# File 'lib/zxcvbn/matchers/spatial.rb', line 4 def initialize(graphs) @graphs = graphs end |
Instance Method Details
#matches(password) ⇒ Object
8 9 10 11 12 13 14 |
# File 'lib/zxcvbn/matchers/spatial.rb', line 8 def matches(password) results = [] @graphs.each do |graph_name, graph| results += matches_for_graph(graph, graph_name, password) end results end |
#matches_for_graph(graph, graph_name, password) ⇒ Object
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 |
# File 'lib/zxcvbn/matchers/spatial.rb', line 16 def matches_for_graph(graph, graph_name, password) result = [] i = 0 while i < password.length - 1 j = i + 1 last_direction = nil turns = 0 shifted_count = 0 loop do prev_char = password[j-1] found = false found_direction = -1 cur_direction = -1 adjacents = graph[prev_char] || [] # consider growing pattern by one character if j hasn't gone over the edge. if j < password.length cur_char = password[j] adjacents.each do |adj| cur_direction += 1 if adj && adj.index(cur_char) found = true found_direction = cur_direction if adj.index(cur_char) == 1 # index 1 in the adjacency means the key is shifted, 0 means unshifted: A vs a, % vs 5, etc. # for example, 'q' is adjacent to the entry '2@'. @ is shifted w/ index 1, 2 is unshifted. shifted_count += 1 end if last_direction != found_direction # adding a turn is correct even in the initial case when last_direction is null: # every spatial pattern starts with a turn. turns += 1 last_direction = found_direction end break end end end # if the current pattern continued, extend j and try to grow again if found j += 1 else # otherwise push the pattern discovered so far, if any... if j - i > 2 # don't consider length 1 or 2 chains. result << Match.new( :pattern => 'spatial', :i => i, :j => j-1, :token => password[i...j], :graph => graph_name, :turns => turns, :shifted_count => shifted_count ) end # ...and then start a new search for the rest of the password. i = j break end end end result end |