#!/usr/bin/perl # # Codez (c) March 1, 2003 # Written by Peter Beckman # Distributed under the GNU Public License # Some code adapted from ddclient Perl program without permission. # http://purplecow.com/ # require 5.004; use strict; use Getopt::Long; use Sys::Hostname; use IO::Socket; my $version = "0.1"; my $result = ""; my $programd = $0; $programd =~ s%^.*/%%; my $program = $programd; $program =~ s/d$//; sub _msg { my $log = shift; my $prefix = shift; my $format = shift; my $buffer = sprintf $format, @_; chomp($buffer); $prefix = sprintf "%-9s ", $prefix if $prefix; $buffer .= "\n"; print $prefix.$buffer; my $msgs .= $buffer if $log; } sub msg { _msg(0, '', @_); } sub verbose { _msg(1, @_) if opt('verbose'); } sub debug { _msg(0, 'DEBUG:', @_) if opt('debug'); } sub warning { _msg(1, 'WARNING:', @_); } sub opt { my $v = shift; if ($v eq "verbose") { return 0; } if ($v eq "debug") { return 1; } if ($v eq "exec") { return 1; } #return $opt{$v} if defined $opt{$v}; #return $globals{$v} if defined $globals{$v}; #return default($v) if defined default($v); #return undef; return 0; } ###################################################################### ## geturl ###################################################################### sub geturl { my $proxy = shift || ''; my $url = shift || ''; my $method = shift || 'GET'; my $vars = shift || ''; my $login = shift || ''; my $password = shift || ''; my ($peer, $server, $port); my ($sd, $rq, $request, $reply); ## canonify proxy and url $proxy =~ s%^http://%%i; $url =~ s%^http://%%i; $server = $url; $server =~ s%/.*%%; $url = "/" unless $url =~ m%/%; $url =~ s%^[^/]*/%%; ## determine peer and port to use. $peer = $proxy || $server; $peer =~ s%/.*%%; $port = $peer; $port =~ s%^.*:%%; $port = 80 unless $port =~ /^\d+$/; $peer =~ s%:.*$%%; my $to = sprintf "%s%s", $server, $proxy ? " via proxy $peer:$port" : ""; verbose("CONNECT:", "%s", $to); $request = $method." "; $request .= "http://$server" if $proxy; $request .= "/$url HTTP/1.0\n"; $request .= "Host: $server\n"; #my $auth = encode_base64("${login}:${password}"); #$request .= "Authorization: Basic $auth" if $login || $password; $vars =~ s/ /%20/g; # should expand this for all values that need massaging my $varsLength = length($vars); $request .= "User-Agent: ${program}/${version}\n"; $request .= "Connection: close\n"; if ($method =~ /^post$/i) { $request .= "Content-type: application/x-www-form-urlencoded\nContent-length: $varsLength\n"; $request .= "\n".$vars; } $request .= "\n"; ## make sure newlines are for some pedantic proxy servers ($rq = $request) =~ s/\n/\r\n/g; # local $^W = 0; if (! opt('exec')) { debug("skipped network connection"); verbose("SENDING:", $request); } elsif (! defined($sd = IO::Socket::INET->new(PeerAddr => $peer, PeerPort => $port, Proto => 'tcp'))) { warning("cannot connect to $peer:$port socket: $@"); } else { ## send the requet to the http server verbose("CONNECTED:", ""); verbose("SENDING:", $request); my $result = send $sd, $rq, 0; if ($result != length($rq)) { warning("cannot send to $peer:$port ($!)."); } else { my $timeout = 0; local $SIG{'ALRM'} = sub { $timeout = 1; }; alarm(opt('timeout')) if opt('timeout') > 0; while (!$timeout && ($_ = <$sd>)) { verbose("RECEIVE:", "%s", $_); $reply .= $_ if defined $_; } if (opt('timeout') > 0) { alarm(0); } close($sd); if ($timeout) { warning("TIMEOUT: %s after %s seconds", $to, opt('timeout')); $reply = ''; } $reply = '' if !defined $reply; } } ## during testing simulate reading the URL # if (opt('test')) { # my $filename = "$server/$url"; # $filename =~ s|/|%2F|g; # if (opt('exec')) { # $reply = save_file("${savedir}$filename", $reply, 'unique'); # } else { # $reply = load_file("${savedir}$filename"); # } # } $reply =~ s/\r//g if defined $reply; return $reply; } sub getzip { my $zip = shift || ''; my $url = "http://www.usps.com/zip4/zip_response.jsp"; my $reply = geturl('',$url,'POST','zipcode='.$zip); my @lines = split(/\n/,$reply); my $start = 0; my $line; my $row = ""; my $in = 0; my $num = 0; my @out = (); print "Cities that match Zip Code $zip\n"; print "-----------------------------------------------------------------------\n"; foreach $line (@lines) { if (opt('verbose')) { print $line."\n"; } if ($line =~ /ZIP Code Type/) { $start = 1; } if ($start) { if ($line =~ /^[A-Z]/) { $line =~ s/<.*>//g; $out[$num][$in] = $line; $in++; } if ($in == 4) { $in = 0; $num++; } } } $in = 0; foreach $row (@out) { printf("%-40s %-21s %-15s\n",$row->[0].", ".$row->[1], $row->[2], $row->[3]); } print "\nData Scraped from USPS.com without permission\nVisit http://www.usps.com/ and buy stuff\nfrom them so they don't mind.\n"; } sub getcitystate { my $zip = shift || ''; my $url = "http://56.0.134.24/zip4/citystate_response.jsp"; # process citystate stuff my @split = split(/,/,$zip); my $state = uc($split[1]); $state =~ s/\s+//g; my $city = ucfirst($split[0]); $city =~ s/^\s+//g; $city =~ s/\s+$//g; $zip = $city." ".$state; my $reply = geturl('',$url,'POST','citystate='.$zip.'&state='.$state.'&city='.$city.'&Selection=2&Submit_x=29&Submit_y=10'); my @lines = split(/\n/,$reply); my $start = 0; my $line; my $row = ""; my $in = 0; my $num = 0; my @out = (); print "Zip Codes that match $zip\n"; print "-----------------------------------------------------------------------\n"; foreach $line (@lines) { if ($line =~ /ZIP Codes/) { $start = 1; } if ($start) { if ($line =~ /^\s+\[\w \(\)]{5,}\<\/center\>/) { #print $in.": ".$line."\n"; $line =~ s/<[^>]*>|\s{2,}//g; $out[$num][$in] = $line; $in++; } if ($in == 3) { $in = 0; $num++; } } } $in = 0; foreach $row (@out) { printf("%-10s %-30s %-20s\n",$row->[0], $row->[1], $row->[2]); } print "\nData Scraped from USPS.com without permission\nVisit http://www.usps.com/ and buy stuff\nfrom them so they don't mind.\n"; } sub getarea { my $ac = shift || ''; my $url = "http://www.melissadata.com/lookups/phonelocation.asp?number=".$ac."&submit1=Process"; my $reply = geturl('',$url,'GET'); my @lines = split(/\n/,$reply); my $start = 0; my $line; my @row = ""; my $row = ""; my $in = 0; my $num = 0; my @out = (); my $hdrcnt; my $x; my @hdr; print "Info about $ac\n"; print "---------------------------------------------------------------------------\n"; foreach $line (@lines) { if ($line =~ /value="Process"/) { $start = 1; } if ($start) { if ($line =~ /\\]*>/,$line); for ($x=0;$x<=$#foo;$x++) { $foo[$x] =~ s/<[^>]*>|\s{2,}//g; $foo[$x] =~ s/ / /g; $out[$num][$x] = $foo[$x]; } $num++; } elsif ($line =~ /\]*>]*>/) { if ($hdrcnt == 0) { $hdrcnt++; } elsif ($hdrcnt == 1) { @hdr = split(/<\/th>]*>/i,$line); for ($x=0;$x<=$#hdr;$x++) { $hdr[$x] =~ s/<[^>]*>|\s{2,}//g; } } } #if ($line =~ /^<\/table>$/) { last; } } } $in = 0; printf("%-30s %-25s %-15s %-15s\n", $hdr[0], $hdr[1], $hdr[2], $hdr[3]); foreach $row (@out) { printf("%-30s %-25s %-15s %-15s\n",$row->[0],$row->[1], $row->[2], $row->[3]); #print $in++.": ".$row.":".$row->[0]."\n"; } print "\nData Scraped from MelissaData without permission\nVisit http://www.melissadata.com/ and buy stuff\nfrom them so they don't mind.\n"; } sub parseinput { my $input = shift || ''; print "Codez v".$version." (C)2003 by Peter Beckman\n"; if ($input eq "") { print "No input.\nExiting...\n"; exit(0); } if ($input =~ /^\d{5}(-?[\d]{4})?$/) { if ($input !~ /-/ and length($input)>5) { $input = substr($input,0,5)."-".substr($input,5,4); } getzip($input); debug("getzip 1"); } elsif ($input =~ /^[0-9]{3,10}$/) { getarea($input); debug("getarea 2"); } elsif ($input =~ /^[0-9]{3}-[0-9]{3,4}$/) { getarea($input); debug("getarea 3"); } elsif ($input =~ /^[0-9]{3}-[0-9]{3}-[0-9]{4}$/) { getarea($input); debug("getarea 4"); } elsif ($input =~ /^[a-zA-Z0-9 ]+,?\s*[a-zA-Z]{2}$/) { getcitystate($input); debug("getcitystate 5"); } else { print "Not a valid area code, zip code or city/state.\nExiting...\n"; exit(0); } } my $myinput = $ARGV[0]." ".$ARGV[1]." ".$ARGV[2]." ".$ARGV[3]; $myinput =~ s/^\s*//g; $myinput =~ s/\s*$//g; parseinput($myinput); __END__ =head1 NAME codez - return information about area codes or zip codes =head1 SYNOPSIS codez B =head1 DESCRIPTION codez gets all relevant information about a US Zip Code or telephone area code, exchanges and phone numbers themselves. The data is scraped from USPS.com (zip codes) and MelissaData.com (phone info). "B" is one of the following: - B - B - B - B - B - B =head1 EXAMPLES codez Falls Church, VA codez Falls Church VA codez 22042 codez 22042-1917 codez 703 codez 703-536 codez 536-3600 codez 703-536-3600 codez 7035363600 =head1 ACTUAL REGEXPS C< /^\d{5}(-?[\d]{4})?$/ > -> C< getzip($input); > C< /^[0-9]{3,10}$/ > -> C< getarea($input); > C< /^[0-9]{3}-[0-9]{3,4}$/ > -> C< getarea($input); > C< /^[0-9]{3}-[0-9]{3}-[0-9]{4}$/ > -> C< getarea($input); > C< /^[a-zA-Z0-9 ]+,?\s*[a-zA-Z]{2}$/ > -> C< getcitystate($input); > =head1 ACKNOWLEDGMENTS Peter Beckman wrote it. Yeah. Visit his website at I. =cut