1package Parse::PhoneNumber; 2use strict; 3use warnings; 4 5use Carp; 6 7use vars qw[$VERSION $EXT $MINLEN $MIN_US_LENGTH @CCODES]; 8 9$VERSION = qw(1.9); 10$EXT = qr/\s*(?:(?:ext|ex|xt|x)[\s.:]*(\d+))/i; 11 12$MINLEN = 7; 13$MIN_US_LENGTH = 10; 14 15@CCODES = qw[ 16 1 7 20 27 30 31 32 33 34 17 36 39 40 41 43 44 45 46 47 18 48 49 51 52 53 54 55 56 57 19 58 60 61 62 63 64 65 66 81 20 82 84 86 90 91 92 93 94 95 21 98 212 213 216 218 220 221 222 223 22 224 225 226 227 228 229 230 231 232 23 233 234 235 236 237 238 239 240 241 24 242 243 244 245 246 247 248 249 250 25 251 252 253 254 255 256 257 258 260 26 261 262 263 264 265 266 267 268 269 27 290 291 297 298 299 350 351 352 353 28 354 355 356 357 358 359 370 371 372 29 373 374 375 376 377 378 380 381 385 30 386 387 388 389 420 421 423 500 501 31 502 503 504 505 506 507 508 509 590 32 591 592 593 594 595 596 597 598 599 33 670 672 673 674 675 676 677 678 679 34 680 681 682 683 684 685 686 687 688 35 689 690 691 692 800 808 850 852 853 36 655 856 870 871 872 873 874 878 880 37 881 882 886 960 961 962 963 964 965 38 966 967 968 970 971 972 973 974 975 39 976 977 979 991 992 993 994 995 996 40 998 41]; 42 43=head1 NAME 44 45Parse::PhoneNumber - Parse Phone Numbers 46 47=head1 SYNOPSIS 48 49 use Parse::PhoneNumber; 50 my $number = Parse::PhoneNumber->parse( number => $phone ); 51 52 print $number->human; 53 54=head1 ABSTRACT 55 56Parse phone numbers. Phone number have a defined syntax (to a point), 57so they can be parsed (to a point). 58 59=head1 DESCRIPTION 60 61=head2 Methods 62 63=head3 new 64 65Create a new Parse::PhoneNumber object. Useful if a lot of numbers 66have to be parsed. 67 68=cut 69 70sub new { 71 return bless {}, shift; 72} 73 74=head3 parse 75 76Accepts a list of arguments. C<number> is the phone number. This method 77will return C<undef> and set C<errstr> on failure. On success, a 78C<Parse::PhoneNumber::Number> object is returned. C<assume_us> will have 79the country code default to C<1> if none is given. This is due to the fact 80that most people in the US are clueless about such things. 81 82=cut 83 84sub parse { 85 my ($class, %data) = @_; 86 croak "No phone number" unless $data{number}; 87 88 local $_ = $data{number}; 89 s/^\s+//;s/\s+$//; 90 91 my %number = ( 92 orig => $data{number}, 93 cc => undef, 94 num => undef, 95 ext => undef, 96 opensrs => undef, 97 human => undef, 98 ); 99 100 101 102 if ( m/$EXT$/ ) { 103 if ( length $1 > 4 ) { 104 $class->errstr( "Extension '$1' longer than four digits" ); 105 return undef; 106 } else { 107 $number{ext} = $1; 108 s/$EXT$//; 109 } 110 } 111 112 s/\D//g; 113 s/^0+//; 114 115 if ($data{'assume_us'}) { 116 if (length $_ < $MIN_US_LENGTH) { 117 $class->errstr("Invalid US number: $data{number}" ); 118 return; 119 } else { 120 $number{'cc'} = 1; 121 s/^1//; 122 $number{'num'} = $_; 123 } 124 } else { 125 126 foreach my $len ( 1 .. 3 ) { 127 last if $number{cc}; 128 129 my $cc = substr $_, 0, $len; 130 131 if ( grep { $_ eq $cc } @CCODES ) { 132 $number{cc} = $cc; 133 s/^$cc//; 134 } 135 } 136 137 if ( $number{cc} && length "$number{cc}$_" >= $MINLEN ) { 138 $number{num} = "$_"; 139 } else { 140 $class->errstr("Invalid international number: $data{number}" ); 141 return undef; 142 } 143 } 144 145 $number{opensrs} = sprintf "+%d.%s", @number{qw[cc num]}; 146 $number{opensrs} .= sprintf "x%d", $number{ext} if $number{ext}; 147 148 $number{human} = sprintf "+%d %s", @number{qw[cc num]}; 149 $number{human} .= sprintf " x%d", $number{ext} if $number{ext}; 150 151 return Parse::PhoneNumber::Number->new( %number ); 152} 153 154=head3 errstr 155 156Returns the last error reported, or undef if no errors have occured yet. 157 158=cut 159 160{ 161 my $errstr = undef; 162 sub errstr { $errstr = $_[1] if $_[1]; $errstr } 163 sub clear_errstr { $errstr = undef; } 164} 165 166package Parse::PhoneNumber::Number; 167use strict; 168use warnings; 169 170=head2 Parse::PhoneNumber::Number Objects 171 172The objects returned on a successful parse. 173 174=cut 175 176sub new { 177 my ($class, %data) = @_; 178 return bless \%data, $class; 179} 180 181=head3 orig 182 183The original string passed to C<parse>. 184 185=head3 cc 186 187The Country Code 188 189=head3 num 190 191The phone number, including the trunk pointer, area code, and 192subscriber number. 193 194=head3 ext 195 196An extension, if one is present. 197 198=head3 opensrs 199 200The format an OpenSRS Registrar must make a phone number for some 201TLDs. 202 203=head3 human 204 205Human readable format. 206 207=cut 208 209sub orig { $_[0]->{orig} } 210sub cc { $_[0]->{cc} } 211sub num { $_[0]->{num} } 212sub ext { $_[0]->{ext} } 213sub opensrs { $_[0]->{opensrs} } 214sub human { $_[0]->{human} } 215 2161; 217 218__END__ 219 220=head1 BUGS 221 222Currently only accept phone numbers in International format. If a 223number isn't given in international format, a false positive could 224occur. 225 226Please report bugs to the CPAN RT instance at 227L<https://rt.cpan.org/Dist/Display.html?Queue=Parse-PhoneNumber> 228 229=head1 SEE ALSO 230 231L<Number::Phone> 232 233=head1 AUTHOR 234 235Casey West <F<casey@geeknest.com>> 236 237Maintained by Tim Wilde <F<cpan@krellis.org>> 238 239=head1 COPYRIGHT 240 241Copyright (c) 2003 Casey West <casey@geeknest.com>. 242 243Portions Copyright (c) 2005 Dynamic Network Services, Inc. 244 245Portions Copyright (c) 2011 Tim Wilde 246 247Portions Copyright (c) 2012 Google, Inc. 248 249All rights reserved. 250 251This program is free software; you can redistribute it 252and/or modify it under the same terms as Perl itself. 253