#!/usr/bin/perl -w use CGI qw / :standard /; use LWP::UserAgent; use strict; print header(); # use z to enter a zip and get the city and state # use cs to enter the city, state and get all available zip codes for the area my $query = 'z'; my $city = 'New York'; my $state = 'NY'; my $zip = '10001'; my $usps_form = 'http://www.usps.gov/cgi-bin/zip4/ctystzip2'; # prepare agent my $ua = LWP::UserAgent->new(); $ua->agent( 'AgentName/0.1 ' . $ua->agent ); # prepare request my $req = HTTP::Request->new( POST => $usps_form ); $req->content_type( 'application/x-www-form-urlencoded' ); $req->content( "ctystzip=$city $state&Submit=Process" ) if $query eq 'cs'; $req->content( "ctystzip=$zip&Submit=Process" ) if $query eq 'z'; # process request my $res = $ua->request( $req ); # process result if ( $res->is_success ) { # city/state to zip query if ( $query eq 'cs'){ my @zips = zip_from_city_state( $res->content ); my $count = @zips; print p( "$count zip codes for $city, $state" ), blockquote ( join ( ", ", @zips ) ); } # zip to city/state query elsif ( $query eq 'z' ){ my $cs_aref = city_state_from_zip( $res->content ); print p( "Cities listed for $zip:" ), '
'; print "$_->{'c'}, $_->{'s'}", br() foreach @$cs_aref; print '
'; } else { die 'Bad query.'; } } else { warn 'USPS down, bad request, or no results.'; } sub zip_from_city_state { my @zips; # there has to be a more efficient way to do this :) foreach ( split( /
/i, ( split( m||i, $_[0] ) )[1] ) ){ my $zip = substr( $_, 0, 5 ); push @zips, $zip if $zip =~ /^\d{5,5}/; } return @zips; } sub city_state_from_zip { my ( $res, $cs_aref ) = ( shift, () ); $res =~ s/
/\n/gi; # there has to be a more efficient way to do this :) my @lines = split( "\n", ( split( /--+/, ( split( m||i, $res ) )[1] ) )[1] ); for my $line ( @lines ){ my ( $city, $state ) = unpack( 'A27A2', $line ); push @$cs_aref, { 'c' => $city, 's' => $state } if $city and $state; } return $cs_aref; }