line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Parser::AAMVA::License; |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
$VERSION = "0.55"; |
4
|
1
|
|
|
1
|
|
15278
|
use strict; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
38
|
|
5
|
1
|
|
|
1
|
|
4
|
use warnings; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
23
|
|
6
|
1
|
|
|
1
|
|
4
|
use Carp; |
|
1
|
|
|
|
|
8
|
|
|
1
|
|
|
|
|
1098
|
|
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
=head1 NAME |
9
|
|
|
|
|
|
|
Parser::AAMVA::License - AAMVA Driver's License Magnetic Stripe Parser |
10
|
|
|
|
|
|
|
=cut |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
my @track1fields = ( 'state', 'city', 'name', 'address' ); |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
my @track2fields = ( 'id', 'license', 'exyy', 'exmm', 'bcc', 'byy', 'bmm', 'bdd', 'dlx' ); |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
my @track3fields = ('cdsversion', 'jdversion', 'postalcode', 'dlclass', |
17
|
|
|
|
|
|
|
'restrictions', 'endorsements', 'sex', 'height', |
18
|
|
|
|
|
|
|
'weight', 'haircolor', 'eyecolor', 'did' |
19
|
|
|
|
|
|
|
); |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
my $exyear; |
22
|
|
|
|
|
|
|
my $dim; |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
sub haircolor |
25
|
|
|
|
|
|
|
{ |
26
|
|
|
|
|
|
|
# Hair Color per Ansi D20 |
27
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
28
|
0
|
|
|
|
|
|
my %hc = ( |
29
|
|
|
|
|
|
|
'BAL' => 'Bald', |
30
|
|
|
|
|
|
|
'BLK' => 'Black', |
31
|
|
|
|
|
|
|
'BLN' => 'Blond', |
32
|
|
|
|
|
|
|
'BRO' => 'Brown', |
33
|
|
|
|
|
|
|
'GRY' => 'Grey', |
34
|
|
|
|
|
|
|
'RED' => 'Red/Auburn', |
35
|
|
|
|
|
|
|
'SDY' => 'Sandy', |
36
|
|
|
|
|
|
|
'WHI' => 'White', |
37
|
|
|
|
|
|
|
'UNK' => 'Unknown' |
38
|
|
|
|
|
|
|
); |
39
|
0
|
|
|
|
|
|
return $hc{ $self->{'haircolor'} }; |
40
|
|
|
|
|
|
|
} |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
sub monthdays |
43
|
|
|
|
|
|
|
{ |
44
|
0
|
|
|
0
|
0
|
|
my $year = shift; |
45
|
0
|
|
|
|
|
|
my $month = shift; |
46
|
|
|
|
|
|
|
|
47
|
0
|
0
|
0
|
|
|
|
if ( $month == 4 || $month == 6 || $month == 9 || $month == 11 ) |
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
48
|
|
|
|
|
|
|
{ |
49
|
0
|
|
|
|
|
|
return 30; |
50
|
|
|
|
|
|
|
} |
51
|
0
|
0
|
|
|
|
|
if ( $month == 2 ) |
52
|
|
|
|
|
|
|
{ |
53
|
0
|
0
|
|
|
|
|
if ( ( $year / 4 ) == int( $year / 4 ) ) |
54
|
|
|
|
|
|
|
{ |
55
|
0
|
|
|
|
|
|
return 29; |
56
|
|
|
|
|
|
|
} |
57
|
|
|
|
|
|
|
else |
58
|
|
|
|
|
|
|
{ |
59
|
0
|
|
|
|
|
|
return 28; |
60
|
|
|
|
|
|
|
} |
61
|
|
|
|
|
|
|
} |
62
|
0
|
|
|
|
|
|
return 31; |
63
|
|
|
|
|
|
|
} |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
sub parse_magstripe |
66
|
|
|
|
|
|
|
{ |
67
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
68
|
0
|
|
|
|
|
|
my $i; |
69
|
|
|
|
|
|
|
my @results; |
70
|
0
|
|
|
|
|
|
my $n; |
71
|
|
|
|
|
|
|
|
72
|
0
|
0
|
|
|
|
|
if ( $self->{'track1'}) |
73
|
0
|
|
|
|
|
|
{ |
74
|
0
|
|
|
|
|
|
@results = ( $self->{'track1'} =~ m/^\%?([A-Z]{2})([^\^]{1,13})\^?([^\^]{1,35})\^?([^\^]+)\^?\?/i ); |
75
|
|
|
|
|
|
|
|
76
|
0
|
|
|
|
|
|
for ( $i = 0 ; $i < scalar @track1fields ; $i++ ) |
77
|
|
|
|
|
|
|
{ |
78
|
0
|
|
|
|
|
|
$self->{ $track1fields[$i] } = $results[$i]; |
79
|
|
|
|
|
|
|
} |
80
|
|
|
|
|
|
|
|
81
|
0
|
|
|
|
|
|
( $self->{'lname'}, $self->{'fname'}, $self->{'middle'} ) = split( /\$/, $self->{'name'} ); |
82
|
|
|
|
|
|
|
|
83
|
0
|
|
|
|
|
|
( $self->{'address1'}, $self->{'address2'} ) = split(/\$/,$self->{'address'}); |
84
|
|
|
|
|
|
|
|
85
|
0
|
|
|
|
|
|
foreach $n ('lname','fname','middle','address1','address2') |
86
|
|
|
|
|
|
|
{ |
87
|
0
|
|
|
|
|
|
$self->{$n}=stripblanks($self->{$n}); |
88
|
|
|
|
|
|
|
} |
89
|
|
|
|
|
|
|
} |
90
|
|
|
|
|
|
|
else |
91
|
|
|
|
|
|
|
{carp "Track one is empty";} |
92
|
|
|
|
|
|
|
|
93
|
0
|
0
|
|
|
|
|
if ( $self->{'track2'}) |
94
|
|
|
|
|
|
|
{ |
95
|
0
|
|
|
|
|
|
@results = ( $self->{'track2'} =~ m/;?(6[0-9]{5})([0-9]+)=([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([^=]{0,5})=\??/i ); |
96
|
|
|
|
|
|
|
|
97
|
0
|
|
|
|
|
|
for ( $i = 0 ; $i < scalar @track2fields ; $i++ ) |
98
|
|
|
|
|
|
|
{ |
99
|
0
|
|
|
|
|
|
$self->{ $track2fields[$i] } = $results[$i]; |
100
|
|
|
|
|
|
|
} |
101
|
0
|
|
|
|
|
|
$self->{'license'} .= $self->{'dlx'}; |
102
|
0
|
|
|
|
|
|
$self->{'birthyear'}=$self->{'bcc'}.$self->{'byy'}; |
103
|
0
|
|
|
|
|
|
$self->{'birthmonth'}=$self->{'bmm'}; |
104
|
0
|
|
|
|
|
|
$self->{'birthday'}=$self->{'bdd'}; |
105
|
0
|
|
|
|
|
|
$self->{'birthdate'}=sprintf('%4d-%02d-%02d',$self->{'birthyear'},$self->{'birthmonth'},$self->{'birthday'}); |
106
|
|
|
|
|
|
|
|
107
|
0
|
|
|
|
|
|
$exyear=2000+($self->{'exyy'}+1); |
108
|
|
|
|
|
|
|
|
109
|
0
|
|
|
|
|
|
$dim = monthdays($exyear, $self->{'bmm'}); |
110
|
|
|
|
|
|
|
|
111
|
0
|
0
|
|
|
|
|
if ($self->{'exmm'}==88) |
112
|
|
|
|
|
|
|
{ |
113
|
0
|
|
|
|
|
|
$self->{'expdate'}=sprintf('%4d-%02d-%02d',$exyear,$self->{'bmm'},$dim); |
114
|
|
|
|
|
|
|
} |
115
|
|
|
|
|
|
|
else |
116
|
|
|
|
|
|
|
{ |
117
|
0
|
|
|
|
|
|
$self->{'expdate'}=sprintf('%4d-%02d-%02d',$self->{'exyy'}+2000,$self->{'exmm'},$dim); |
118
|
|
|
|
|
|
|
} |
119
|
|
|
|
|
|
|
} |
120
|
|
|
|
|
|
|
|
121
|
0
|
0
|
|
|
|
|
if ( $self->{'track3'}) |
122
|
|
|
|
|
|
|
{ |
123
|
0
|
|
|
|
|
|
@results = ( $self->{'track3'} =~ m/%?([0-9]{1})([0-9]{1})([A-Z0-9 ]{11})([A-Z0-9 ]{2})([A-Z0-9 ]{10})([A-Z0-9 ]{4})([1-2]{1})([0-9]{3})([0-9]{3})([A-Z ]{3})([A-Z ]{3})(.*)\?/i ); |
124
|
|
|
|
|
|
|
|
125
|
0
|
|
|
|
|
|
for ( $i = 0 ; $i < scalar @track3fields ; $i++ ) |
126
|
|
|
|
|
|
|
{ |
127
|
0
|
|
|
|
|
|
$self->{ $track3fields[$i] } = $results[$i]; |
128
|
|
|
|
|
|
|
} |
129
|
|
|
|
|
|
|
} |
130
|
|
|
|
|
|
|
} |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
sub stripblanks |
133
|
|
|
|
|
|
|
{ |
134
|
0
|
|
|
0
|
0
|
|
my $s=shift; |
135
|
0
|
0
|
|
|
|
|
if ($s) |
|
0
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
{$s=~s/ +$//; |
137
|
0
|
|
|
|
|
|
$s=~s/^ +//; |
138
|
|
|
|
|
|
|
} |
139
|
0
|
|
|
|
|
|
return $s; |
140
|
|
|
|
|
|
|
} |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
sub loadtrack |
144
|
|
|
|
|
|
|
{ |
145
|
0
|
|
|
0
|
1
|
|
my $self=shift; |
146
|
0
|
|
|
|
|
|
my $trackno=shift; |
147
|
0
|
|
|
|
|
|
my $track=shift; |
148
|
|
|
|
|
|
|
|
149
|
0
|
|
|
|
|
|
$track =~ s/\r|\n//gs; |
150
|
0
|
|
|
|
|
|
$self->{"track$trackno"}=$track; |
151
|
|
|
|
|
|
|
} |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
my %jids=( |
154
|
|
|
|
|
|
|
636033=>'Alabama', |
155
|
|
|
|
|
|
|
636059=>'Alaska', |
156
|
|
|
|
|
|
|
604427=>'American Samoa', |
157
|
|
|
|
|
|
|
636026=>'Arizona', |
158
|
|
|
|
|
|
|
636021=>'Arkansas', |
159
|
|
|
|
|
|
|
636014=>'California', |
160
|
|
|
|
|
|
|
636020=>'Colorado', |
161
|
|
|
|
|
|
|
636006=>'Connecticut', |
162
|
|
|
|
|
|
|
636011=>'Delaware', |
163
|
|
|
|
|
|
|
636043=>'District of Columbia', |
164
|
|
|
|
|
|
|
636010=>'Florida', |
165
|
|
|
|
|
|
|
636055=>'Georgia', |
166
|
|
|
|
|
|
|
636019=>'Guam', |
167
|
|
|
|
|
|
|
636047=>'Hawaii', |
168
|
|
|
|
|
|
|
636050=>'Idaho', |
169
|
|
|
|
|
|
|
636035=>'Illinois', |
170
|
|
|
|
|
|
|
636037=>'Indiana', |
171
|
|
|
|
|
|
|
636018=>'Iowa', |
172
|
|
|
|
|
|
|
636022=>'Kansas', |
173
|
|
|
|
|
|
|
636046=>'Kentucky', |
174
|
|
|
|
|
|
|
636007=>'Louisiana', |
175
|
|
|
|
|
|
|
636041=>'Maine', |
176
|
|
|
|
|
|
|
636003=>'Maryland', |
177
|
|
|
|
|
|
|
636002=>'Massachusetts', |
178
|
|
|
|
|
|
|
636032=>'Michigan', |
179
|
|
|
|
|
|
|
636038=>'Minnesota', |
180
|
|
|
|
|
|
|
636051=>'Mississippi', |
181
|
|
|
|
|
|
|
636030=>'Missouri', |
182
|
|
|
|
|
|
|
636008=>'Montana', |
183
|
|
|
|
|
|
|
636054=>'Nebraska', |
184
|
|
|
|
|
|
|
636049=>'Nevada', |
185
|
|
|
|
|
|
|
636039=>'New Hampshire', |
186
|
|
|
|
|
|
|
636036=>'New Jersey', |
187
|
|
|
|
|
|
|
636009=>'New Mexico', |
188
|
|
|
|
|
|
|
636001=>'New York', |
189
|
|
|
|
|
|
|
636004=>'North Carolina', |
190
|
|
|
|
|
|
|
636034=>'North Dakota', |
191
|
|
|
|
|
|
|
636023=>'Ohio', |
192
|
|
|
|
|
|
|
636058=>'Oklahoma', |
193
|
|
|
|
|
|
|
636029=>'Oregon', |
194
|
|
|
|
|
|
|
636025=>'Pennsylvania', |
195
|
|
|
|
|
|
|
636052=>'Rhode Island', |
196
|
|
|
|
|
|
|
636005=>'South Carolina', |
197
|
|
|
|
|
|
|
636042=>'South Dakota', |
198
|
|
|
|
|
|
|
636027=>'State Dept(USA)', |
199
|
|
|
|
|
|
|
636053=>'Tennessee', |
200
|
|
|
|
|
|
|
636015=>'Texas', |
201
|
|
|
|
|
|
|
636062=>'US Virgin Islands', |
202
|
|
|
|
|
|
|
636040=>'Utah', |
203
|
|
|
|
|
|
|
636024=>'Vermont', |
204
|
|
|
|
|
|
|
636000=>'Virginia', |
205
|
|
|
|
|
|
|
636045=>'Washington', |
206
|
|
|
|
|
|
|
636061=>'West Virginia', |
207
|
|
|
|
|
|
|
636031=>'Wisconsin', |
208
|
|
|
|
|
|
|
636060=>'Wyoming', |
209
|
|
|
|
|
|
|
636028=>'British Columbia', |
210
|
|
|
|
|
|
|
636048=>'Manitoba', |
211
|
|
|
|
|
|
|
636012=>'Ontario', |
212
|
|
|
|
|
|
|
636017=>'New Brunswick', |
213
|
|
|
|
|
|
|
636016=>'Newfoundland', |
214
|
|
|
|
|
|
|
636013=>'Nova Scotia', |
215
|
|
|
|
|
|
|
604426=>'Prince Edward Island', |
216
|
|
|
|
|
|
|
604428=>'Quebec', |
217
|
|
|
|
|
|
|
636044=>'Saskatchewan', |
218
|
|
|
|
|
|
|
604429=>'Yukon', |
219
|
|
|
|
|
|
|
636056=>'Coahuila', |
220
|
|
|
|
|
|
|
636057=>'Hidalgo ' |
221
|
|
|
|
|
|
|
); |
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
sub country |
224
|
|
|
|
|
|
|
{ |
225
|
0
|
|
|
0
|
1
|
|
my $self=shift; |
226
|
0
|
|
|
|
|
|
return $jids{$self->{'id'}}; |
227
|
|
|
|
|
|
|
} |
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
my %country=( |
230
|
|
|
|
|
|
|
636033=>'USA', |
231
|
|
|
|
|
|
|
636059=>'USA', |
232
|
|
|
|
|
|
|
604427=>'USA', |
233
|
|
|
|
|
|
|
636026=>'USA', |
234
|
|
|
|
|
|
|
636021=>'USA', |
235
|
|
|
|
|
|
|
636014=>'USA', |
236
|
|
|
|
|
|
|
636020=>'USA', |
237
|
|
|
|
|
|
|
636006=>'USA', |
238
|
|
|
|
|
|
|
636011=>'USA', |
239
|
|
|
|
|
|
|
636043=>'USA', |
240
|
|
|
|
|
|
|
636010=>'USA', |
241
|
|
|
|
|
|
|
636055=>'USA', |
242
|
|
|
|
|
|
|
636019=>'USA', |
243
|
|
|
|
|
|
|
636047=>'USA', |
244
|
|
|
|
|
|
|
636050=>'USA', |
245
|
|
|
|
|
|
|
636035=>'USA', |
246
|
|
|
|
|
|
|
636037=>'USA', |
247
|
|
|
|
|
|
|
636018=>'USA', |
248
|
|
|
|
|
|
|
636022=>'USA', |
249
|
|
|
|
|
|
|
636046=>'USA', |
250
|
|
|
|
|
|
|
636007=>'USA', |
251
|
|
|
|
|
|
|
636041=>'USA', |
252
|
|
|
|
|
|
|
636003=>'USA', |
253
|
|
|
|
|
|
|
636002=>'USA', |
254
|
|
|
|
|
|
|
636032=>'USA', |
255
|
|
|
|
|
|
|
636038=>'USA', |
256
|
|
|
|
|
|
|
636051=>'USA', |
257
|
|
|
|
|
|
|
636030=>'USA', |
258
|
|
|
|
|
|
|
636008=>'USA', |
259
|
|
|
|
|
|
|
636054=>'USA', |
260
|
|
|
|
|
|
|
636049=>'USA', |
261
|
|
|
|
|
|
|
636039=>'USA', |
262
|
|
|
|
|
|
|
636036=>'USA', |
263
|
|
|
|
|
|
|
636009=>'USA', |
264
|
|
|
|
|
|
|
636001=>'USA', |
265
|
|
|
|
|
|
|
636004=>'USA', |
266
|
|
|
|
|
|
|
636034=>'USA', |
267
|
|
|
|
|
|
|
636023=>'USA', |
268
|
|
|
|
|
|
|
636058=>'USA', |
269
|
|
|
|
|
|
|
636029=>'USA', |
270
|
|
|
|
|
|
|
636025=>'USA', |
271
|
|
|
|
|
|
|
636052=>'USA', |
272
|
|
|
|
|
|
|
636005=>'USA', |
273
|
|
|
|
|
|
|
636042=>'USA', |
274
|
|
|
|
|
|
|
636027=>'USA', |
275
|
|
|
|
|
|
|
636053=>'USA', |
276
|
|
|
|
|
|
|
636062=>'USA', |
277
|
|
|
|
|
|
|
636040=>'USA', |
278
|
|
|
|
|
|
|
636024=>'USA', |
279
|
|
|
|
|
|
|
636000=>'USA', |
280
|
|
|
|
|
|
|
636045=>'USA', |
281
|
|
|
|
|
|
|
636061=>'USA', |
282
|
|
|
|
|
|
|
636031=>'USA', |
283
|
|
|
|
|
|
|
636060=>'USA', |
284
|
|
|
|
|
|
|
636028=>'CAN', |
285
|
|
|
|
|
|
|
636048=>'CAN', |
286
|
|
|
|
|
|
|
636012=>'CAN', |
287
|
|
|
|
|
|
|
636017=>'CAN', |
288
|
|
|
|
|
|
|
636016=>'CAN', |
289
|
|
|
|
|
|
|
636013=>'CAN', |
290
|
|
|
|
|
|
|
604426=>'CAN', |
291
|
|
|
|
|
|
|
604428=>'CAN', |
292
|
|
|
|
|
|
|
636044=>'CAN', |
293
|
|
|
|
|
|
|
604429=>'CAN', |
294
|
|
|
|
|
|
|
636056=>'MEX', |
295
|
|
|
|
|
|
|
636057=>'MEX' |
296
|
|
|
|
|
|
|
); |
297
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
sub new |
299
|
|
|
|
|
|
|
{ |
300
|
0
|
|
|
0
|
0
|
|
my $that = shift; |
301
|
0
|
|
0
|
|
|
|
my $class = ref($that) || $that; |
302
|
0
|
|
|
|
|
|
my $self = { |
303
|
|
|
|
|
|
|
track1=>undef, |
304
|
|
|
|
|
|
|
track2=>undef, |
305
|
|
|
|
|
|
|
track3=>undef |
306
|
|
|
|
|
|
|
}; |
307
|
0
|
|
|
|
|
|
bless $self, $class; |
308
|
0
|
|
|
|
|
|
return $self; |
309
|
|
|
|
|
|
|
}; |
310
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
1; |
312
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
=head1 DESCRIPTION |
314
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
License is a parser/decoder for the American Association of Motor Vehicle Administrators(AAMVA) format that is used to encode the magnetic stripe found on Driver's Licenses in the US and Canada. Most data is available both in its raw and decoded form. You should refer to the latest specification at |
316
|
|
|
|
|
|
|
www.aamva.org for details on the field contents. Starting and ending sentinals in the track data are optional. |
317
|
|
|
|
|
|
|
|
318
|
|
|
|
|
|
|
Load the tracks you have available, only track 1 is mandatory. Not all magnetic stripe readers can read track 3. |
319
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
=head1 SYNOPSIS |
321
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
$track1='%ORSPRINGFIELD ^ SIMPSON $HOMER$J ^ 742 EVERGREEN TERR ^?'; # % and ? are sentinals. |
323
|
|
|
|
|
|
|
$track2 =';6360291234567890123=180119550512=?'; # ; and ? are sentinals. |
324
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
$p = new Parse::AAMVA::License; |
326
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
$p->loadtrack( 1, $track1 ); |
328
|
|
|
|
|
|
|
$p->loadtrack( 2, $track2 ); |
329
|
|
|
|
|
|
|
$p->loadtrack( 3, $track3 ); |
330
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
$p->parse_magstripe; |
332
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
=head1 FIELDS |
334
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
Field Name AAMVA Field # Track |
336
|
|
|
|
|
|
|
|
337
|
|
|
|
|
|
|
state State/Province 2 1 |
338
|
|
|
|
|
|
|
city City Name 3 1 |
339
|
|
|
|
|
|
|
fname First Name 4 1 |
340
|
|
|
|
|
|
|
lname Last Name 4 1 |
341
|
|
|
|
|
|
|
middle Middle Name 4 1 |
342
|
|
|
|
|
|
|
address1 Address Line 1 5 1 |
343
|
|
|
|
|
|
|
address2 Address Line 2 5 1 |
344
|
|
|
|
|
|
|
id ISO Id 2 2 |
345
|
|
|
|
|
|
|
license License Number 3/7 2 Includes overflow from field 7 |
346
|
|
|
|
|
|
|
expdate Expiration 5 2 YYYY-MM-DD (1) |
347
|
|
|
|
|
|
|
birthdate Birth Date 6 2 YYYY-MM-DD |
348
|
|
|
|
|
|
|
cdsversion CDS Version 2 3 |
349
|
|
|
|
|
|
|
jdversion Juris. Version 3 3 |
350
|
|
|
|
|
|
|
postalcode Postal/Zip Code 4 3 |
351
|
|
|
|
|
|
|
dlclass License Class 5 3 |
352
|
|
|
|
|
|
|
restrictions Lic. Restrictions 6 3 |
353
|
|
|
|
|
|
|
endorsements Lic. Endorsements 7 3 |
354
|
|
|
|
|
|
|
sex Sex 1=Male, 2=Female 8 3 |
355
|
|
|
|
|
|
|
height Height in in. or cm. 9 3 (2) |
356
|
|
|
|
|
|
|
weight Weight in lbs or kg. 10 3 (2) |
357
|
|
|
|
|
|
|
haircolor Hair Color 11 3 (3) |
358
|
|
|
|
|
|
|
eyecolor Eye Color 12 3 |
359
|
|
|
|
|
|
|
did Optionally defined by |
360
|
|
|
|
|
|
|
jurisdiction 13,14,15 3 |
361
|
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
(1). If expiration date year is 2077, license never expires. |
363
|
|
|
|
|
|
|
Otherwise, this field represents the last valid date. |
364
|
|
|
|
|
|
|
|
365
|
|
|
|
|
|
|
(2). Height is in inches or cm depending on country. |
366
|
|
|
|
|
|
|
Weight is in pounds or kg. Call the country method |
367
|
|
|
|
|
|
|
to determine country of origin: USA, MEX or CAN. |
368
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
(3). This the raw hair color, e.g. BRO. For a description, |
370
|
|
|
|
|
|
|
call the haircolor method. |
371
|
|
|
|
|
|
|
|
372
|
|
|
|
|
|
|
=head1 METHODS |
373
|
|
|
|
|
|
|
|
374
|
|
|
|
|
|
|
=over 12 |
375
|
|
|
|
|
|
|
|
376
|
|
|
|
|
|
|
=item $p->loadtrack(tracknumber,string); |
377
|
|
|
|
|
|
|
|
378
|
|
|
|
|
|
|
Load the magnetic stripe track |
379
|
|
|
|
|
|
|
|
380
|
|
|
|
|
|
|
=item $p->parse_magstripe |
381
|
|
|
|
|
|
|
|
382
|
|
|
|
|
|
|
Parse loaded magstripe data. Returns null. |
383
|
|
|
|
|
|
|
|
384
|
|
|
|
|
|
|
=item $p->country |
385
|
|
|
|
|
|
|
|
386
|
|
|
|
|
|
|
Attempts to determine country of origin from the ISO ID. Returns CAN, MEX or USA. |
387
|
|
|
|
|
|
|
|
388
|
|
|
|
|
|
|
=item $p->haircolor |
389
|
|
|
|
|
|
|
|
390
|
|
|
|
|
|
|
Returns the ANSI D20 hair color definition |
391
|
|
|
|
|
|
|
BAL Bald |
392
|
|
|
|
|
|
|
BLK Black |
393
|
|
|
|
|
|
|
BLN Blond |
394
|
|
|
|
|
|
|
BRO Brown |
395
|
|
|
|
|
|
|
GRY Grey |
396
|
|
|
|
|
|
|
RED Red/Auburn |
397
|
|
|
|
|
|
|
SDY Sandy |
398
|
|
|
|
|
|
|
WHI White |
399
|
|
|
|
|
|
|
UNK Unknown |
400
|
|
|
|
|
|
|
|
401
|
|
|
|
|
|
|
=back |
402
|
|
|
|
|
|
|
|
403
|
|
|
|
|
|
|
=head1 ACCESSING FIELDS |
404
|
|
|
|
|
|
|
|
405
|
|
|
|
|
|
|
Decoded fields are accessed directly via an anonymous hash: |
406
|
|
|
|
|
|
|
Ex. print $p->{license}; |
407
|
|
|
|
|
|
|
|
408
|
|
|
|
|
|
|
=head1 EXAMPLE |
409
|
|
|
|
|
|
|
|
410
|
|
|
|
|
|
|
$p=new Parse:AAMVA:License; |
411
|
|
|
|
|
|
|
$p->loadtrack(1,$track1); |
412
|
|
|
|
|
|
|
$p->loadtrack(2,$track2); |
413
|
|
|
|
|
|
|
$p->loadtrack(3,$track3); |
414
|
|
|
|
|
|
|
$p->parse_magstripe; |
415
|
|
|
|
|
|
|
|
416
|
|
|
|
|
|
|
print "Name: ".$p->{fname}.' '.$p->{lname}; |
417
|
|
|
|
|
|
|
print "Birth Date: ".$p->{birthdate}; |
418
|
|
|
|
|
|
|
|
419
|
|
|
|
|
|
|
=head1 AUTHOR |
420
|
|
|
|
|
|
|
Curt Evans, C<< >> |
421
|
|
|
|
|
|
|
|
422
|
|
|
|
|
|
|
=head1 COPYRIGHT |
423
|
|
|
|
|
|
|
|
424
|
|
|
|
|
|
|
Copyright Curt Evans, 2014. |
425
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or |
426
|
|
|
|
|
|
|
modify it under the terms of either: |
427
|
|
|
|
|
|
|
a) the GNU General Public License; |
428
|
|
|
|
|
|
|
either version 2 of the License, or (at your option) any later |
429
|
|
|
|
|
|
|
version. You should have received a copy of the GNU General |
430
|
|
|
|
|
|
|
Public License along with this program; see the file COPYING. |
431
|
|
|
|
|
|
|
If not, write to the Free Software Foundation, Inc., 59 |
432
|
|
|
|
|
|
|
Temple Place, Suite 330, Boston, MA 02111-1307 USA |
433
|
|
|
|
|
|
|
b) the Perl Artistic License. |
434
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful, |
435
|
|
|
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
436
|
|
|
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
437
|
|
|
|
|
|
|
=cut |