File Coverage

blib/lib/Lingua/Alphabet/Phonetic/Password.pm
Criterion Covered Total %
statement 23 24 95.8
branch 7 8 87.5
condition 1 3 33.3
subroutine 5 5 100.0
pod n/a
total 36 40 90.0


line stmt bran cond sub pod time code
1             #
2             # $Id: Password.pm 142 2004-11-30 19:42:11Z james $
3             #
4              
5             =head1 NAME
6              
7             Lingua::Alphabet::Phonetic::Password - enunciate a password as words
8              
9             =head1 SYNOPSIS
10              
11             This is a specialization of Lingua::Alphabet::Phonetic. You should not use
12             this module; all interaction should be done with an object of type
13             Lingua::Alphabet::Phonetic.
14              
15             use Lingua::Alphabet::Phonetic;
16             my $phonetic = new Lingua::Alphabet::Phonetic('Password');
17             my @phonetic_pw = $phonetic->enunciate('qOusiENi');
18              
19             =head1 DESCRIPTION
20              
21             This module is a dictionary for Lingua::Alphabet::Phonetic. It allows for
22             enunciation of passwords, using the following rules:
23              
24             =over 4
25              
26             =item * lowercase letters
27              
28             enunciated using the NATO alphabet per Lingua::Alphabet::Phonetic::NATO, but
29             the word will be lowercased.
30              
31             =item * uppercase letters
32              
33             enunciated using the NATO alphabet per Lingua::Alphabet::Phonetic::NATO, but
34             the word will be uppercased.
35              
36             =item * numbers
37              
38             enunciated as an initialcaps word for the english pronuciation of the number.
39              
40             =item * special characters
41              
42             enunciated as a mixedcaps word for the english punctuation of the character:
43              
44             @ At
45             ? Question
46             _ Underscore
47             # Hash
48             & Ampersand
49             ! Exclamation
50             - Dash
51             * Asterisk
52             + Plus
53             = Equals
54             " DoubleQuote
55             % Percent
56             ' SingleQuote
57             ( LeftParens
58             ) RightParens
59             , Comma
60             . Period
61             / ForeSlash
62             \ BackSlash
63             : Colon
64             ; SemiColon
65             < LessThan
66             > GreaterThan
67             [ LeftBracket
68             ] RightBracket
69             { LeftBrace
70             } RightBrace
71             ^ Caret
72             ` Backtick
73             | Pipe
74             ~ Tilde
75              
76             =back
77              
78             A character which does not fall into any of these categories is dispatched
79             back to the base class for conversion. In the case of
80             Lingua::Alphabet::Phonetic, this returns the character unchanged.
81              
82             =cut
83              
84             package Lingua::Alphabet::Phonetic::Password;
85              
86 3     3   66556 use strict;
  3         9  
  3         145  
87 3     3   21 use warnings;
  3         8  
  3         108  
88              
89             # if you really need to support lower, mail me
90 3     3   111 use 5.006_001;
  3         188  
  3         626  
91              
92             # we are but a lowly subclass
93 3     3   28 use base 'Lingua::Alphabet::Phonetic';
  3         6  
  3         4282  
94              
95             # our version
96             our $VERSION = '0.11';
97              
98             # a Lingua::Alphabet::Phonetic::NATO object for use later
99             my $nato;
100             eval { $nato = Lingua::Alphabet::Phonetic->new('NATO') };
101             if( $@ ) {
102             require Carp;
103             Carp::croak "cannot instantiate Lingua::Alphabet::" .
104             "Phonetic::NATO object: $@";
105             }
106              
107             # regex to determine if a character is uppercase
108             my $isupper = qr/^[[:upper:]]$/;
109              
110             # number to name mappings
111             my %number_map = (
112             0 => 'Zero',
113             1 => 'One',
114             2 => 'Two',
115             3 => 'Three',
116             4 => 'Four',
117             5 => 'Five',
118             6 => 'Six',
119             7 => 'Seven',
120             8 => 'Eight',
121             9 => 'Nine',
122             );
123              
124             # special character to name mappings
125             my %special_map = (
126             '@' => 'At',
127             '?' => 'Question',
128             '_' => 'Underscore',
129             '#' => 'Hash',
130             '&' => 'Ampersand',
131             '!' => 'Exclamation',
132             '-' => 'Dash',
133             '*' => 'Asterisk',
134             '+' => 'Plus',
135             '=' => 'Equals',
136             '"' => 'DoubleQuote',
137             '%' => 'Percent',
138             '$' => 'Dollars',
139             q/'/ => 'SingleQuote',
140             '(' => 'LeftParens',
141             ')' => 'RightParens',
142             ',' => 'Comma',
143             '.' => 'Period',
144             '/' => 'ForeSlash',
145             '\\' => 'BackSlash',
146             ':' => 'Colon',
147             ';' => 'SemiColon',
148             '<' => 'LessThan',
149             '>' => 'GreaterThan',
150             '[' => 'LeftBracket',
151             ']' => 'RightBracket',
152             '{' => 'LeftBrace',
153             '}' => 'RightBrace',
154             '^' => 'Caret',
155             '`' => 'Backtick',
156             '|' => 'Pipe',
157             '~' => 'Tilde',
158             );
159              
160             sub _name_of_letter
161             {
162              
163 160     160   16294 my $self = shift;
164 160         176 my $s = shift;
165             # If we get more than one character, ignore the rest:
166 160         204 my $c = substr($s, 0, 1);
167            
168 160         151 my $word;
169            
170             # first we handle special characters
171 160 100 33     510 if( exists $special_map{$c} ) {
    100          
    50          
172 26         35 $word = $special_map{$c};
173             }
174            
175             # then numbers
176             elsif( exists $number_map{$c} ) {
177 21         33 $word = $number_map{$c};
178             }
179              
180             # then if it's in the NATO dictionary, we upper or lowercase
181             elsif( ($word = ($nato->enunciate($c))[0]) && $word ne $c ) {
182 113 100       7968 if( $c =~ m/$isupper/ ) {
183 22         39 $word = uc $word;
184             }
185             else {
186 91         142 $word = lc $word;
187             }
188             }
189              
190             # otherwise we dispatch back to our base class
191             else {
192 0         0 $word = $self->SUPER::_name_of_letter($c);
193             }
194            
195 160         484 return $word;
196              
197             }
198              
199             # keep require happy
200             1;
201              
202              
203             __END__