File Coverage

blib/lib/Business/IBAN/Database.pm
Criterion Covered Total %
statement 25 25 100.0
branch n/a
condition n/a
subroutine 7 7 100.0
pod 3 3 100.0
total 35 35 100.0


line stmt bran cond sub pod time code
1             package Business::IBAN::Database;
2 3     3   12 use warnings;
  3         3  
  3         87  
3 3     3   10 use strict;
  3         3  
  3         75  
4              
5 3     3   10 use Hash::Util 'lock_hash';
  3         3  
  3         12  
6 3     3   126 use Exporter 'import';
  3         5  
  3         2761  
7             our @EXPORT = qw/iban_db numify_iban mod97/;
8              
9             my %iban_db = (
10             'AD' => {
11             'country' => 'Andorra',
12             'iban_length' => '24',
13             'iban_structure' => 'AD[0-9]{2}[0-9]{4}[0-9]{4}[A-Za-z0-9]{12}',
14             'is_sepa' => 0,
15             'pattern' => 'AD2!n4!n4!n12!c'
16             },
17             'AE' => {
18             'country' => 'United Arab Emirates',
19             'iban_length' => '23',
20             'iban_structure' => 'AE[0-9]{2}[0-9]{3}[0-9]{16}',
21             'is_sepa' => 0,
22             'pattern' => 'AE2!n3!n16!n'
23             },
24             'AL' => {
25             'country' => 'Albania',
26             'iban_length' => '28',
27             'iban_structure' => 'AL[0-9]{2}[0-9]{8}[A-Za-z0-9]{16}',
28             'is_sepa' => 0,
29             'pattern' => 'AL2!n8!n16!c'
30             },
31             'AT' => {
32             'country' => 'Austria',
33             'iban_length' => '20',
34             'iban_structure' => 'AT[0-9]{2}[0-9]{5}[0-9]{11}',
35             'is_sepa' => 1,
36             'pattern' => 'AT2!n5!n11!n'
37             },
38             'AZ' => {
39             'country' => 'Republic of Azerbaijan',
40             'iban_length' => '28',
41             'iban_structure' => 'AZ[0-9]{2}[A-Z]{4}[A-Za-z0-9]{20}',
42             'is_sepa' => 0,
43             'pattern' => 'AZ2!n4!a20!c'
44             },
45             'BA' => {
46             'country' => 'Bosnia and Herzegovina',
47             'iban_length' => '20',
48             'iban_structure' => 'BA[0-9]{2}[0-9]{3}[0-9]{3}[0-9]{8}[0-9]{2}',
49             'is_sepa' => 0,
50             'pattern' => 'BA2!n3!n3!n8!n2!n'
51             },
52             'BE' => {
53             'country' => 'Belgium',
54             'iban_length' => '16',
55             'iban_structure' => 'BE[0-9]{2}[0-9]{3}[0-9]{7}[0-9]{2}',
56             'is_sepa' => 1,
57             'pattern' => 'BE2!n3!n7!n2!n'
58             },
59             'BG' => {
60             'country' => 'Bulgaria',
61             'iban_length' => '22',
62             'iban_structure' => 'BG[0-9]{2}[A-Z]{4}[0-9]{4}[0-9]{2}[A-Za-z0-9]{8}',
63             'is_sepa' => 1,
64             'pattern' => 'BG2!n4!a4!n2!n8!c'
65             },
66             'BH' => {
67             'country' => 'Kingdom of Bahrain',
68             'iban_length' => '22',
69             'iban_structure' => 'BH[0-9]{2}[A-Z]{4}[A-Za-z0-9]{14}',
70             'is_sepa' => 0,
71             'pattern' => 'BH2!n4!a14!c'
72             },
73             'BR' => {
74             'country' => 'Brazil',
75             'iban_length' => '29',
76             'iban_structure' => 'BR[0-9]{2}[0-9]{8}[0-9]{5}[0-9]{10}[A-Z]{1}[A-Za-z0-9]{1}',
77             'is_sepa' => 0,
78             'pattern' => 'BR2!n8!n5!n10!n1!a1!c'
79             },
80             'CH' => {
81             'country' => 'Switzerland',
82             'iban_length' => '21',
83             'iban_structure' => 'CH[0-9]{2}[0-9]{5}[A-Za-z0-9]{12}',
84             'is_sepa' => 1,
85             'pattern' => 'CH2!n5!n12!c'
86             },
87             'CR' => {
88             'country' => 'Costa Rica',
89             'iban_length' => '21',
90             'iban_structure' => 'CR[0-9]{2}[0-9]{3}[0-9]{14}',
91             'is_sepa' => 0,
92             'pattern' => 'CR2!n3!n14!n'
93             },
94             'CY' => {
95             'country' => 'Cyprus',
96             'iban_length' => '28',
97             'iban_structure' => 'CY[0-9]{2}[0-9]{3}[0-9]{5}[A-Za-z0-9]{16}',
98             'is_sepa' => 1,
99             'pattern' => 'CY2!n3!n5!n16!c'
100             },
101             'CZ' => {
102             'country' => 'Czech Republic',
103             'iban_length' => '24',
104             'iban_structure' => 'CZ[0-9]{2}[0-9]{4}[0-9]{6}[0-9]{10}',
105             'is_sepa' => 1,
106             'pattern' => 'CZ2!n4!n6!n10!n'
107             },
108             'DE' => {
109             'country' => 'Germany',
110             'iban_length' => '22',
111             'iban_structure' => 'DE[0-9]{2}[0-9]{8}[0-9]{10}',
112             'is_sepa' => 1,
113             'pattern' => 'DE2!n8!n10!n'
114             },
115             'DK' => {
116             'country' => 'Denmark',
117             'iban_length' => '18',
118             'iban_structure' => 'DK[0-9]{2}[0-9]{4}[0-9]{9}[0-9]{1}',
119             'is_sepa' => 1,
120             'pattern' => 'DK2!n4!n9!n1!n FO2!n4!n9!n1!n GL2!n4!n9!n1!n'
121             },
122             'DO' => {
123             'country' => 'Dominican Republic',
124             'iban_length' => '28',
125             'iban_structure' => 'DO[0-9]{2}[A-Za-z0-9]{4}[0-9]{20}',
126             'is_sepa' => 0,
127             'pattern' => 'DO2!n4!c20!n'
128             },
129             'EE' => {
130             'country' => 'Estonia',
131             'iban_length' => '20',
132             'iban_structure' => 'EE[0-9]{2}[0-9]{2}[0-9]{2}[0-9]{11}[0-9]{1}',
133             'is_sepa' => 1,
134             'pattern' => 'EE2!n2!n2!n11!n1!n'
135             },
136             'ES' => {
137             'country' => 'Spain',
138             'iban_length' => '24',
139             'iban_structure' => 'ES[0-9]{2}[0-9]{4}[0-9]{4}[0-9]{1}[0-9]{1}[0-9]{10}',
140             'is_sepa' => 1,
141             'pattern' => 'ES2!n4!n4!n1!n1!n10!n'
142             },
143             'FI' => {
144             'country' => 'Finland',
145             'iban_length' => '18',
146             'iban_structure' => 'FI[0-9]{2}[0-9]{6}[0-9]{7}[0-9]{1}',
147             'is_sepa' => 1,
148             'pattern' => 'FI2!n6!n7!n1!n'
149             },
150             'FO' => {
151             'country' => 'Denmark',
152             'iban_length' => '18',
153             'iban_structure' => 'FO[0-9]{2}[0-9]{4}[0-9]{9}[0-9]{1}',
154             'is_sepa' => 1,
155             'pattern' => 'DK2!n4!n9!n1!n FO2!n4!n9!n1!n GL2!n4!n9!n1!n'
156             },
157             'FR' => {
158             'country' => 'France',
159             'iban_length' => '27',
160             'iban_structure' => 'FR[0-9]{2}[0-9]{5}[0-9]{5}[A-Za-z0-9]{11}[0-9]{2}',
161             'is_sepa' => 1,
162             'pattern' => 'FR2!n5!n5!n11!c2!n'
163             },
164             'GB' => {
165             'country' => 'United Kingdom',
166             'iban_length' => '22',
167             'iban_structure' => 'GB[0-9]{2}[A-Z]{4}[0-9]{6}[0-9]{8}',
168             'is_sepa' => 1,
169             'pattern' => 'GB2!n4!a6!n8!n'
170             },
171             'GE' => {
172             'country' => 'Georgia',
173             'iban_length' => '22',
174             'iban_structure' => 'GE[0-9]{2}[A-Z]{2}[0-9]{16}',
175             'is_sepa' => 0,
176             'pattern' => 'GE2!n2!a16!n'
177             },
178             'GI' => {
179             'country' => 'Gibraltar',
180             'iban_length' => '23',
181             'iban_structure' => 'GI[0-9]{2}[A-Z]{4}[A-Za-z0-9]{15}',
182             'is_sepa' => 1,
183             'pattern' => 'GI2!n4!a15!c'
184             },
185             'GL' => {
186             'country' => 'Denmark',
187             'iban_length' => '18',
188             'iban_structure' => 'GL[0-9]{2}[0-9]{4}[0-9]{9}[0-9]{1}',
189             'is_sepa' => 1,
190             'pattern' => 'DK2!n4!n9!n1!n FO2!n4!n9!n1!n GL2!n4!n9!n1!n'
191             },
192             'GR' => {
193             'country' => 'Greece',
194             'iban_length' => '27',
195             'iban_structure' => 'GR[0-9]{2}[0-9]{3}[0-9]{4}[A-Za-z0-9]{16}',
196             'is_sepa' => 1,
197             'pattern' => 'GR2!n3!n4!n16!c'
198             },
199             'GT' => {
200             'country' => 'Guatemala',
201             'iban_length' => '28',
202             'iban_structure' => 'GT[0-9]{2}[A-Za-z0-9]{4}[A-Za-z0-9]{20}',
203             'is_sepa' => 0,
204             'pattern' => 'GT2!n4!c20!c'
205             },
206             'HR' => {
207             'country' => 'Croatia',
208             'iban_length' => '21',
209             'iban_structure' => 'HR[0-9]{2}[0-9]{7}[0-9]{10}',
210             'is_sepa' => 0,
211             'pattern' => 'HR2!n7!n10!n'
212             },
213             'HU' => {
214             'country' => 'Hungary',
215             'iban_length' => '28',
216             'iban_structure' => 'HU[0-9]{2}[0-9]{3}[0-9]{4}[0-9]{1}[0-9]{15}[0-9]{1}',
217             'is_sepa' => 1,
218             'pattern' => 'HU2!n3!n4!n1!n15!n1!n'
219             },
220             'IE' => {
221             'country' => 'Ireland',
222             'iban_length' => '22',
223             'iban_structure' => 'IE[0-9]{2}[A-Z]{4}[0-9]{6}[0-9]{8}',
224             'is_sepa' => 1,
225             'pattern' => 'IE2!n4!a6!n8!n'
226             },
227             'IL' => {
228             'country' => 'Israel',
229             'iban_length' => '23',
230             'iban_structure' => 'IL[0-9]{2}[0-9]{3}[0-9]{3}[0-9]{13}',
231             'is_sepa' => 0,
232             'pattern' => 'IL2!n3!n3!n13!n'
233             },
234             'IS' => {
235             'country' => 'Iceland',
236             'iban_length' => '26',
237             'iban_structure' => 'IS[0-9]{2}[0-9]{4}[0-9]{2}[0-9]{6}[0-9]{10}',
238             'is_sepa' => 1,
239             'pattern' => 'IS2!n4!n2!n6!n10!n'
240             },
241             'IT' => {
242             'country' => 'Italy',
243             'iban_length' => '27',
244             'iban_structure' => 'IT[0-9]{2}[A-Z]{1}[0-9]{5}[0-9]{5}[A-Za-z0-9]{12}',
245             'is_sepa' => 1,
246             'pattern' => 'IT2!n1!a5!n5!n12!c'
247             },
248             'JO' => {
249             'country' => 'Jordan',
250             'iban_length' => '30',
251             'iban_structure' => 'JO[0-9]{2}[A-Z]{4}[0-9]{4}[0-9]{18}',
252             'is_sepa' => 0,
253             'pattern' => 'JO2!a2!n4!n18!c' # 'JO2!a2!n4!a4!n18!c' according to registry
254             },
255             'KW' => {
256             'country' => 'Kuwait',
257             'iban_length' => '30',
258             'iban_structure' => 'KW[0-9]{2}[A-Z]{4}[A-Za-z0-9]{22}',
259             'is_sepa' => 0,
260             'pattern' => 'KW2!n4!a22!c'
261             },
262             'KZ' => {
263             'country' => 'Kazakhstan',
264             'iban_length' => '20',
265             'iban_structure' => 'KZ[0-9]{2}[0-9]{3}[A-Za-z0-9]{13}',
266             'is_sepa' => 0,
267             'pattern' => 'KZ2!n3!n13!c'
268             },
269             'LB' => {
270             'country' => 'Lebanon',
271             'iban_length' => '28',
272             'iban_structure' => 'LB[0-9]{2}[0-9]{4}[A-Za-z0-9]{20}',
273             'is_sepa' => 0,
274             'pattern' => 'LB2!n4!n20!c'
275             },
276             'LI' => {
277             'country' => 'Liechtenstein (Principality of)',
278             'iban_length' => '21',
279             'iban_structure' => 'LI[0-9]{2}[0-9]{5}[A-Za-z0-9]{12}',
280             'is_sepa' => 1,
281             'pattern' => 'LI2!n5!n12!c'
282             },
283             'LT' => {
284             'country' => 'Lithuania',
285             'iban_length' => '20',
286             'iban_structure' => 'LT[0-9]{2}[0-9]{5}[0-9]{11}',
287             'is_sepa' => 1,
288             'pattern' => 'LT2!n5!n11!n'
289             },
290             'LU' => {
291             'country' => 'Luxembourg',
292             'iban_length' => '20',
293             'iban_structure' => 'LU[0-9]{2}[0-9]{3}[A-Za-z0-9]{13}',
294             'is_sepa' => 1,
295             'pattern' => 'LU2!n3!n13!c'
296             },
297             'LV' => {
298             'country' => 'Latvia',
299             'iban_length' => '21',
300             'iban_structure' => 'LV[0-9]{2}[A-Z]{4}[A-Za-z0-9]{13}',
301             'is_sepa' => 1,
302             'pattern' => 'LV2!n4!a13!c'
303             },
304             'MC' => {
305             'country' => 'Monaco',
306             'iban_length' => '27',
307             'iban_structure' => 'MC[0-9]{2}[0-9]{5}[0-9]{5}[A-Za-z0-9]{11}[0-9]{2}',
308             'is_sepa' => 1,
309             'pattern' => 'MC2!n5!n5!n11!c2!n'
310             },
311             'MD' => {
312             'country' => 'Republic of Moldova',
313             'iban_length' => '24',
314             'iban_structure' => 'MD[0-9]{2}[A-Za-z0-9]{20}',
315             'is_sepa' => 0,
316             'pattern' => 'MD2!n20!c'
317             },
318             'ME' => {
319             'country' => 'Montenegro',
320             'iban_length' => '22',
321             'iban_structure' => 'ME[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}',
322             'is_sepa' => 0,
323             'pattern' => 'ME2!n3!n13!n2!n'
324             },
325             'MK' => {
326             'country' => 'Macedonia',
327             'iban_length' => '19',
328             'iban_structure' => 'MK[0-9]{2}[0-9]{3}[A-Za-z0-9]{10}[0-9]{2}',
329             'is_sepa' => 0,
330             'pattern' => 'MK2!n3!n10!c2!n'
331             },
332             'MR' => {
333             'country' => 'Mauritania',
334             'iban_length' => '27',
335             'iban_structure' => 'MR13[0-9]{5}[0-9]{5}[0-9]{11}[0-9]{2}',
336             'is_sepa' => 0,
337             'pattern' => 'MR135!n5!n11!n2!n'
338             },
339             'MT' => {
340             'country' => 'Malta',
341             'iban_length' => '31',
342             'iban_structure' => 'MT[0-9]{2}[A-Z]{4}[0-9]{5}[A-Za-z0-9]{18}',
343             'is_sepa' => 1,
344             'pattern' => 'MT2!n4!a5!n18!c'
345             },
346             'MU' => {
347             'country' => 'Mauritius',
348             'iban_length' => '30',
349             'iban_structure' => 'MU[0-9]{2}[A-Z]{4}[0-9]{2}[0-9]{2}[0-9]{12}[0-9]{3}[A-Z]{3}',
350             'is_sepa' => 0,
351             'pattern' => 'MU2!n4!a2!n2!n12!n3!n3!a'
352             },
353             'NL' => {
354             'country' => 'The Netherlands',
355             'iban_length' => '18',
356             'iban_structure' => 'NL[0-9]{2}[A-Z]{4}[0-9]{10}',
357             'is_sepa' => 1,
358             'pattern' => 'NL2!n4!a10!n'
359             },
360             'NO' => {
361             'country' => 'Norway',
362             'iban_length' => '15',
363             'iban_structure' => 'NO[0-9]{2}[0-9]{4}[0-9]{6}[0-9]{1}',
364             'is_sepa' => 1,
365             'pattern' => 'NO2!n4!n6!n1!n'
366             },
367             'PK' => {
368             'country' => 'Pakistan',
369             'iban_length' => '24',
370             'iban_structure' => 'PK[0-9]{2}[A-Z]{4}[A-Za-z0-9]{16}',
371             'is_sepa' => 0,
372             'pattern' => 'PK2!n4!a16!c'
373             },
374             'PL' => {
375             'country' => 'Poland',
376             'iban_length' => '28',
377             'iban_structure' => 'PL[0-9]{2}[0-9]{8}[0-9]{16}',
378             'is_sepa' => 1,
379             'pattern' => 'PL2!n8!n16!n'
380             },
381             'PS' => {
382             'country' => 'Palestine, State of',
383             'iban_length' => '29',
384             'iban_structure' => 'PS[0-9]{2}[A-Z]{4}[A-Za-z0-9]{21}',
385             'is_sepa' => 0,
386             'pattern' => 'PS2!n4!a21!c'
387             },
388             'PT' => {
389             'country' => 'Portugal',
390             'iban_length' => '25',
391             'iban_structure' => 'PT[0-9]{2}[0-9]{4}[0-9]{4}[0-9]{11}[0-9]{2}',
392             'is_sepa' => 1,
393             'pattern' => 'PT2!n4!n4!n11!n2!n'
394             },
395             'QA' => {
396             'country' => 'Qatar',
397             'iban_length' => '29',
398             'iban_structure' => 'QA[0-9]{2}[A-Z]{4}[A-Za-z0-9]{21}',
399             'is_sepa' => 0,
400             'pattern' => 'QA2!n4!a21!c'
401             },
402             'RO' => {
403             'country' => 'Romania',
404             'iban_length' => '24',
405             'iban_structure' => 'RO[0-9]{2}[A-Z]{4}[A-Za-z0-9]{16}',
406             'is_sepa' => 1,
407             'pattern' => 'RO2!n4!a16!c'
408             },
409             'RS' => {
410             'country' => 'Serbia',
411             'iban_length' => '22',
412             'iban_structure' => 'RS[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}',
413             'is_sepa' => 0,
414             'pattern' => 'RS2!n3!n13!n2!n'
415             },
416             'SA' => {
417             'country' => 'Saudi Arabia',
418             'iban_length' => '24',
419             'iban_structure' => 'SA[0-9]{2}[0-9]{2}[A-Za-z0-9]{18}',
420             'is_sepa' => 0,
421             'pattern' => 'SA2!n2!n18!c'
422             },
423             'SE' => {
424             'country' => 'Sweden',
425             'iban_length' => '24',
426             'iban_structure' => 'SE[0-9]{2}[0-9]{3}[0-9]{16}[0-9]{1}',
427             'is_sepa' => 1,
428             'pattern' => 'SE2!n3!n16!n1!n'
429             },
430             'SI' => {
431             'country' => 'Slovenia',
432             'iban_length' => '19',
433             'iban_structure' => 'SI[0-9]{2}[0-9]{5}[0-9]{8}[0-9]{2}',
434             'is_sepa' => 1,
435             'pattern' => 'SI2!n5!n8!n2!n'
436             },
437             'SK' => {
438             'country' => 'Slovak Republic',
439             'iban_length' => '24',
440             'iban_structure' => 'SK[0-9]{2}[0-9]{4}[0-9]{6}[0-9]{10}',
441             'is_sepa' => 1,
442             'pattern' => 'SK2!n4!n6!n10!n'
443             },
444             'SM' => {
445             'country' => 'San Marino',
446             'iban_length' => '27',
447             'iban_structure' => 'SM[0-9]{2}[A-Z]{1}[0-9]{5}[0-9]{5}[A-Za-z0-9]{12}',
448             'is_sepa' => 0,
449             'pattern' => 'SM2!n1!a5!n5!n12!c'
450             },
451             'TN' => {
452             'country' => 'Tunisia',
453             'iban_length' => '24',
454             'iban_structure' => 'TN59[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}',
455             'is_sepa' => 0,
456             'pattern' => 'TN592!n3!n13!n2!n'
457             },
458             'TL' => {
459             'country' => 'Timor-Leste',
460             'iban_length' => '23',
461             'iban_structure' => 'TL38[0-9]{3}[0-9]{14}[0-9]{2}',
462             'is_sepa' => 0,
463             'pattern' => 'TL2!n3!n14!n2!n'
464             },
465             'TR' => {
466             'country' => 'Turkey',
467             'iban_length' => '26',
468             'iban_structure' => 'TR[0-9]{2}[0-9]{5}[A-Za-z0-9]{1}[A-Za-z0-9]{16}',
469             'is_sepa' => 0,
470             'pattern' => 'TR2!n5!n1!c16!c'
471             },
472             'VG' => {
473             'country' => 'Virgin Islands, British',
474             'iban_length' => '24',
475             'iban_structure' => 'VG[0-9]{2}[A-Z]{4}[0-9]{16}',
476             'is_sepa' => 0,
477             'pattern' => 'VG2!n4!a16!n'
478             },
479             'XK' => {
480             'country' => 'Republic of Kosovo',
481             'iban_length' => '20',
482             'iban_structure' => 'XK[0-9]{2}[0-9]{4}[0-9]{10}[0-9]{2}',
483             'is_sepa' => 0,
484             'pattern' => 'XK2!n4!n10!n2!n'
485             }
486             );
487              
488             sub iban_db {
489 2     2 1 13 lock_hash(%iban_db);
490 2         174 return \%iban_db;
491             }
492              
493             my %lettermap = do {
494             my $i = 10;
495             map +($_ => $i++), 'A'..'Z';
496             };
497              
498             sub numify_iban {
499 141     141 1 148 my ($iban) = @_;
500              
501 141         282 my $to_check = substr($iban, 4) . substr($iban, 0, 4);
502 141         1118 $to_check =~ s/([A-Za-z])/$lettermap{uc($1)}/g;
503              
504 141         359 return $to_check;
505             }
506              
507             sub mod97 {
508 141     141 1 152 my ($number) = @_;
509              
510             # Max 9 digits, safe for 32bit INT
511 141         146 my ($r, $l) = (0, 9);
512 141         2374 while ($number =~ s/^([0-9]{1,$l})//) {
513 558         853 $r = $r . $1;
514 558         678 $r %= 97;
515 558         4241 $l = 9 - length($r);
516             }
517 141         514 return $r;
518             }
519              
520             1;
521              
522             =head1 NAME
523              
524             Business::IBAN::Database - Simple database for checking IBANs
525              
526             =head1 SYNOPSIS
527              
528             use Business::IBAN::Database;
529              
530             my $iso3166a2 = uc substr $iban, 0, 2;
531             if (!exists iban_db->{$iso3166a2}) {
532             die "Countrycode '$iso3166a2' not in IBAN.\n";
533             }
534             if (length($iban) != iban_db->{$iso3166a2}{iban_length}) {
535             die "Invalid length for '$iban'.\n";
536             }
537             if ($iban !~ iban_db->{$iso3166a2}{iban_structure}) {
538             die "Invalid pattern for '$iban'.\n";
539             }
540             if (mod97(numify_iban($iban)) != 1) {
541             die "Invalid checksum for '$iban'.\n";
542             }
543              
544             =head1 DESCRIPTION
545              
546             This module was originally generated from the IBAN_Registry.pdf document
547             supplied by SWIFT version 45 (April 2013) and updated to version 54
548             (January 2015).
549              
550             All functions are exported by default.
551              
552             =head2 iban_db()
553              
554             Returns a reference to the "database" of known IBAN entities, keyed on the
555             two letter code for participating countries (See ISO 3166 alpha 2 codes).
556              
557             =head2 numify_iban($iban)
558              
559             Put the first four characters at the end of the string. Transform all letters
560             into numbers. This results in a string of digits [0-9] that can be used as a
561             number.
562              
563             =head2 mod97($number)
564              
565             Returns the remainder of division by 97.
566              
567             =head1 STUFF
568              
569             (c) MMXIII-MMXV - Abe Timmerman
570              
571             =cut