fork download
  1. #!/usr/bin/perl
  2. # your code goes here
  3. sub findCreditCardNumbers {
  4. my %params = @_;
  5. my $text = $params{text};
  6.  
  7. my $ccList = [];
  8.  
  9. my $patternDetectRE = '(?:\D|^){0,4}((?:\d[\- ( )]*){14,19})(?:\D|$)';
  10. my $cardRE = '(?:\D|^)((?:\d[\- ( )]*){14,19})(?:\D|$)';
  11. my $orderIdRE = '(?:\D|^)(?:[A-Z0-9]{3}-\d{7}-\d{7})(?:\D|$)';
  12.  
  13. while ($text =~ /$patternDetectRE/g) {
  14. my $ccnumOri = $&;
  15.  
  16. # Discard stuff that looks like an order
  17. next if ( $ccnumOri =~ /$orderIdRE/ );
  18. $ccnumOri =~ /$cardRE/;
  19. $ccnumOri = $&;
  20.  
  21. my $ccnum = join("", split(/[- ]/, $1));
  22.  
  23. # Discard shipment tracking IDs. In DE, some of them start
  24. # with 0 and match luhn's check. tt/0024102494
  25. next if ( $ccnum =~ /^0/ );
  26.  
  27. # Checksum ("Mod 10")
  28. # Add even digits in even length strings or odd digits in odd length strings.
  29. my $checksum = 0;
  30. for (my $i=(2-(length($ccnum) % 2)); $i <= length($ccnum); $i+=2) {
  31. $checksum += substr($ccnum, $i-1, 1);
  32. }
  33.  
  34. # Analyze odd digits in even length strings or even digits in odd length strings.
  35. for (my $x=((length($ccnum) % 2)+1); $x < length($ccnum); $x+=2) {
  36. my $digit = substr($ccnum, $x-1, 1) * 2;
  37. if ($digit < 10) {
  38. $checksum += $digit;
  39. }
  40. else {
  41. $checksum += ($digit-9);
  42. }
  43. }
  44.  
  45. if (($checksum % 10) == 0) {
  46. # Aggressively trim
  47. $ccnumOri =~ s/^\D*//g;
  48. $ccnumOri =~ s/\D*$//g;
  49. push (@$ccList, $ccnumOri);
  50. }
  51. }
  52.  
  53. return $ccList;
  54. }
  55.  
  56. sub filterCCFromText {
  57. my $text = shift;
  58. my $ccList = findCreditCardNumbers( text => $text );
  59. if (ref $ccList eq 'ARRAY' && scalar(@$ccList)) {
  60. foreach my $cc ( @$ccList ) {
  61. $text =~ s/\Q$cc\E/[CC REMOVED]/g;
  62. }
  63. }
  64.  
  65. return $text;
  66. }
  67.  
  68. while(<>){
  69. print filterCCFromText($_);
  70. }
  71.  
Success #stdin #stdout 0.01s 5272KB
stdin
Test Credit Card Account Numbers

While testing, use only the credit card numbers listed here. Other numbers produce an error.

Expiration Date must be a valid date in the future (use the mmyy format).
Test Credit Card Account Numbers

Credit Card Type
	

Credit Card Number

American Express
	

378282246310005

American Express
	

371449635398431

American Express Corporate
	

378734493671000

Australian BankCard
	

5610591081018250

Diners Club
	

30569309025904

Diners Club
	

38520000023237

Discover
	

6011111111111117

Discover
	

6011000990139424

JCB
	

3530111333300000

JCB
	

3566002020360505

MasterCard
	

5555555555554444

MasterCard
	

5105105105105100

Visa
	

4111111111111111

Visa
	

4012888888881881

Visa
	

4222222222222

Note : Even though this number has a different character count than the other test numbers, it is the correct and functional number.

Processor-specific Cards

Dankort (PBS)
	

76009244561

Dankort (PBS)
	

5019717010103742

Switch/Solo (Paymentech)
	

6331101999990016
stdout
Test Credit Card Account Numbers

While testing, use only the credit card numbers listed here. Other numbers produce an error.

Expiration Date must be a valid date in the future (use the mmyy format).
Test Credit Card Account Numbers

Credit Card Type
	

Credit Card Number

American Express
	

[CC REMOVED]

American Express
	

[CC REMOVED]

American Express Corporate
	

[CC REMOVED]

Australian BankCard
	

[CC REMOVED]

Diners Club
	

[CC REMOVED]

Diners Club
	

[CC REMOVED]

Discover
	

[CC REMOVED]

Discover
	

[CC REMOVED]

JCB
	

[CC REMOVED]

JCB
	

[CC REMOVED]

MasterCard
	

[CC REMOVED]

MasterCard
	

[CC REMOVED]

Visa
	

[CC REMOVED]

Visa
	

[CC REMOVED]

Visa
	

4222222222222

Note : Even though this number has a different character count than the other test numbers, it is the correct and functional number.

Processor-specific Cards

Dankort (PBS)
	

76009244561

Dankort (PBS)
	

[CC REMOVED]

Switch/Solo (Paymentech)
	

[CC REMOVED]