File Coverage

blib/lib/HTML/CheckArgs/cc_number.pm
Criterion Covered Total %
statement 38 39 97.4
branch 10 12 83.3
condition 3 6 50.0
subroutine 5 5 100.0
pod 0 2 0.0
total 56 64 87.5


line stmt bran cond sub pod time code
1             package HTML::CheckArgs::cc_number;
2              
3 1     1   5 use strict;
  1         1  
  1         40  
4 1     1   5 use warnings;
  1         1  
  1         34  
5              
6 1     1   5 use base 'HTML::CheckArgs::Object';
  1         2  
  1         991  
7              
8             sub is_valid {
9 4     4 0 7 my $self = shift;
10            
11 4         16 my $value = $self->value;
12 4         18 my $config = $self->config;
13              
14 4         23 $self->check_params( required => [], optional => [], cleanable => 1 );
15              
16             # no value passed in
17 4 100 66     35 if ( $config->{required} && !$value ) {
    50 33        
18 1         9 $self->error_code( 'cc_number_00' ); # required
19 1         6 $self->error_message( 'Not given.' );
20 1         5 return;
21             } elsif ( !$config->{required} && !$value ) {
22 0         0 return 1;
23             }
24              
25             # clean it up for validation
26 3         7 $value =~ tr/0-9//cd;
27              
28 3 100       7 if ( !luhn_check( $value ) ) {
29 1         5 $self->error_code( 'cc_number_01' ); # not valid
30 1         4 $self->error_message( 'Not valid.' );
31 1         3 return;
32             }
33              
34             # send back cleaned up value?
35 2 100       7 unless ( $config->{noclean} ) {
36 1         5 $self->value( $value );
37             }
38            
39 2         8 return 1;
40             }
41              
42             sub luhn_check {
43              
44 3     3 0 5 my ($number, @in_digits, $number_digits, $sum, $odd, $count, $chunk);
45 3         5 $number = $_[0];
46              
47             # For a card with an even number of digits, double every odd numbered
48             # digit and subtract 9 if the product is greater than 9. Add up all the
49             # even digits as well as the doubled-odd digits, and the result must be
50             # a multiple of 10 or it's not a valid card. If the card has an odd
51             # number of digits, perform the same addition doubling the even numbered
52             # digits instead.
53             # -- Phrack, issue 47, section 8
54             # http://www.lglobal.com/TAO/Zines/Phrack/47/P47-08
55              
56 3         18 @in_digits = split( '', $number );
57 3         6 $number_digits = @in_digits;
58 3         6 $odd = $number_digits & 1;
59 3         4 $sum = 0;
60              
61 3         12 for ( $count= 0; $count < $number_digits; $count++ ) {
62 40         46 $chunk = $in_digits[$count];
63 40 100       100 unless ( $count & 1 ^ $odd ) {
64 20         27 $chunk = $chunk * 2;
65 20 50       32 $chunk -= 9 if $chunk > 9;
66             }
67 40         79 $sum += $chunk;
68             }
69            
70 3         17 return ( $sum % 10 == 0 );
71             }
72              
73             1;