File Coverage

blib/lib/Ham/Reference/QRZ.pm
Criterion Covered Total %
statement 18 175 10.2
branch 0 56 0.0
condition 0 12 0.0
subroutine 6 27 22.2
pod 16 16 100.0
total 40 286 13.9


line stmt bran cond sub pod time code
1             package Ham::Reference::QRZ;
2              
3             # --------------------------------------------------------------------------
4             # Ham::Reference::QRZ - An interface to the QRZ XML Database Service
5             #
6             # Copyright (c) 2008-2016 Brad McConahay N8QQ.
7             # Cincinnati, Ohio USA
8             # --------------------------------------------------------------------------
9              
10 1     1   13140 use strict;
  1         1  
  1         22  
11 1     1   3 use warnings;
  1         1  
  1         19  
12 1     1   683 use XML::Simple;
  1         5877  
  1         5  
13 1     1   685 use LWP::UserAgent;
  1         30659  
  1         31  
14 1     1   432 use HTML::Entities;
  1         3639  
  1         56  
15 1     1   5 use vars qw($VERSION);
  1         0  
  1         2081  
16              
17             our $VERSION = '0.04';
18              
19             my $site_name = 'QRZ XML Database Service';
20             my $default_api_url = "http://xmldata.qrz.com/xml";
21             my $default_timeout = 10;
22              
23             sub new
24             {
25 0     0 1   my $class = shift;
26 0           my %args = @_;
27 0           my $self = {};
28 0           bless $self, $class;
29 0           $self->_set_agent;
30 0           $self->set_timeout($args{timeout});
31 0           $self->set_api_url($args{api_url});
32 0 0         $self->set_callsign($args{callsign}) if $args{callsign};
33 0 0         $self->set_username($args{username}) if $args{username};
34 0 0         $self->set_password($args{password}) if $args{password};
35 0 0         $self->set_key($args{key}) if $args{key};
36 0           $self->_clear_errors;
37 0           return $self;
38             }
39              
40             sub login
41             {
42 0     0 1   my $self = shift;
43 0           $self->_clear_errors;
44 0 0         if (!$self->{_username}) { die "No QRZ subscription username given" }
  0            
45 0 0         if (!$self->{_password}) { die "No QRZ subscription password given" }
  0            
46 0           my $url = "$self->{_api_url}/bin/xml?username=$self->{_username}&password=$self->{_password}&agent=$self->{_agent}";
47 0           my $login = $self->_get_xml($url);
48 0 0         if ($login->{Session}->{Error}) {
    0          
49 0           die $login->{Session}->{Error};
50             } elsif (!$login->{Session}->{Key}) {
51 0           die "Unknown Error - Could not retrieve session key";
52             } else {
53 0           $self->set_key($login->{Session}->{Key});
54 0           $self->{_session} = $login->{Session};
55             }
56             }
57              
58             sub set_callsign
59             {
60 0     0 1   my $self = shift;
61 0           my $callsign = shift;
62 0           $callsign =~ tr/a-z/A-Z/;
63 0           $self->{_callsign} = $callsign;
64 0           $self->{_listing} = {};
65 0           $self->{_bio} = {};
66             }
67              
68             sub set_username
69             {
70 0     0 1   my $self = shift;
71 0           my $username = shift;
72 0           $self->{_username} = $username;
73             }
74              
75             sub set_password
76             {
77 0     0 1   my $self = shift;
78 0           my $password = shift;
79 0           $self->{_password} = $password;
80             }
81              
82             sub set_key
83             {
84 0     0 1   my $self = shift;
85 0           my $key = shift;
86 0           $self->{_key} = $key;
87             }
88              
89             sub set_timeout
90             {
91 0     0 1   my $self = shift;
92 0   0       my $timeout = shift || $default_timeout;
93 0           $self->{_timeout} = $timeout;
94             }
95              
96             sub set_api_url
97             {
98 0     0 1   my $self = shift;
99 0   0       my $api_url = shift || $default_api_url;
100 0           $api_url =~ s/\/$//;
101 0           $self->{_api_url} = $api_url;
102             }
103              
104             sub get_listing
105             {
106 0     0 1   my $self = shift;
107 0           $self->_clear_errors;
108 0 0         return $self->{_listing} if $self->{_listing}->{call};
109 0 0         if (!$self->{_callsign}) {
110 0           $self->{is_error} = 1;
111 0           $self->{error_message} = "Can not get data without a callsign";
112 0           return undef;
113             }
114 0 0         if (!$self->{_key}) {
115 0           $self->login;
116             }
117 0           my $url = "$self->{_api_url}/bin/xml?s=$self->{_key}&callsign=$self->{_callsign}";
118 0           my $listing = $self->_get_xml($url);
119 0 0         if ($listing->{Session}->{Error}) {
120 0           $self->{is_error} = 1;
121 0           $self->{error_message} = $listing->{Session}->{Error};
122 0           return undef;
123             }
124 0           $self->{_session} = $listing->{Session};
125 0           $self->{_listing} = $listing->{Callsign};
126             }
127              
128             sub get_bio
129             {
130 0     0 1   my $self = shift;
131 0           $self->_clear_errors;
132 0 0         return $self->{_bio} if $self->{_bio}->{call};
133 0 0         if (!$self->{_callsign}) {
134 0           $self->{is_error} = 1;
135 0           $self->{error_message} = "Can not get data without a callsign";
136 0           return undef;
137             }
138 0 0         if (!$self->{_key}) {
139 0           $self->login;
140             }
141 0           my $url = "$self->{_api_url}/bin/xml?s=$self->{_key}&bio=$self->{_callsign}";
142 0           my $bio = $self->_get_xml($url);
143 0 0         if ($bio->{Session}->{Error}) {
144 0           $self->{is_error} = 1;
145 0           $self->{error_message} = $bio->{Session}->{Error};
146 0           return undef;
147             }
148 0           $self->{_session} = $bio->{Session};
149 0           $self->{_bio} = $bio->{Bio};
150             }
151              
152             sub get_bio_file
153             {
154 0     0 1   my $self = shift;
155 0           $self->_clear_errors;
156 0 0         $self->get_bio if !$self->{_bio}->{call};
157 0 0         if (!$self->{_bio}->{bio}) {
158 0           $self->{is_error} = 1;
159 0           $self->{error_message} = 'No URL for bio file is available for this callsign';
160 0           return undef;
161             }
162 0           my $url = "$self->{_bio}->{bio}";
163 0           my $content = $self->_get_http($url);
164 0 0         return undef if $self->{is_error};
165 0           $content =~ s/ / /g; # convert nbsp entity to regular printable spaces
166 0           $content = decode_entities($content);
167 0           $content =~ s/<.*?>//g; # strip html
168 0           return $content;
169             }
170              
171             sub get_dxcc
172             {
173 0     0 1   my $self = shift;
174 0           $self->_clear_errors;
175 0 0         return $self->{_dxcc} if $self->{_dxcc}->{call};
176 0 0         if (!$self->{_callsign}) {
177 0           $self->{is_error} = 1;
178 0           $self->{error_message} = "Can not get data without a callsign";
179 0           return undef;
180             }
181 0 0         if (!$self->{_key}) {
182 0           $self->login;
183             }
184 0           my $url = "$self->{_api_url}/bin/xml?s=$self->{_key}&dxcc=$self->{_callsign}";
185 0           my $bio = $self->_get_xml($url);
186 0 0         if ($bio->{Session}->{Error}) {
187 0           $self->{is_error} = 1;
188 0           $self->{error_message} = $bio->{Session}->{Error};
189 0           return undef;
190             }
191 0           $self->{_session} = $bio->{Session};
192 0           $self->{_dxcc} = $bio->{DXCC};
193             }
194              
195             sub get_arrl_section
196             {
197 0     0 1   my $self = shift;
198 0           $self->_clear_errors;
199 0 0         $self->get_listing if !$self->{_listing}->{callsign};
200 0 0 0       if (!$self->{_listing}->{state} or (!$self->{_listing}->{county} and $self->{_listing}->{country} ne 'Canada')) {
      0        
201 0           $self->{is_error} = 1;
202 0           $self->{error_message} = "Unable to look up ARRL Section without state or county";
203 0           return undef;
204             }
205 0           my $sections = $self->_get_arrl_sections;
206 0 0         my $section = (ref($sections->{$self->{_listing}->{state}}) eq 'HASH') ? $sections->{$self->{_listing}->{state}}->{$self->{_listing}->{county}} : $sections->{$self->{_listing}->{state}};
207 0           return $section;
208             }
209              
210             sub get_session
211             {
212 0     0 1   my $self = shift;
213 0           return $self->{_session};
214             }
215              
216              
217 0     0 1   sub is_error { my $self = shift; $self->{is_error} }
  0            
218 0     0 1   sub error_message { my $self = shift; $self->{error_message} }
  0            
219              
220              
221             # -----------------------
222             # PRIVATE
223             # -----------------------
224              
225             sub _set_agent
226             {
227 0     0     my $self = shift;
228 0           $self->{_agent} = "Ham-Reference-QRZ-$VERSION";
229             }
230              
231             sub _get_xml
232             {
233 0     0     my $self = shift;
234 0           my $url = shift;
235 0           my $content = $self->_get_http($url);
236 0 0         return undef if $self->{is_error};
237 0           chomp $content;
238 0           $content =~ s/(\r|\n)//g;
239              
240 0           $content =~ s/iso8859-1/iso-8859-1/; # added to account for what appears to be an
241             # incorrect encoding declearation string, 2009-10-31 bam
242 0           my $xs = XML::Simple->new( SuppressEmpty => 0 );
243 0           my $data = $xs->XMLin($content);
244 0           return $data;
245             }
246              
247             sub _get_http
248             {
249 0     0     my $self = shift;
250 0           my $url = shift;
251 0           $self->_clear_errors;
252 0           my $ua = LWP::UserAgent->new( timeout=>$self->{_timeout} );
253 0           $ua->agent( $self->{_agent} );
254 0           my $request = HTTP::Request->new('GET', $url);
255 0           my $response = $ua->request($request);
256 0 0         if (!$response->is_success) {
257 0           $self->{is_error} = 1;
258 0           $self->{error_message} = "Could not contact $site_name - ".HTTP::Status::status_message($response->code);
259 0           return undef;
260             }
261 0           return $response->content;
262             }
263              
264             sub _clear_errors
265             {
266 0     0     my $self = shift;
267 0           $self->{is_error} = 0;
268 0           $self->{error_message} = '';
269             }
270              
271             sub _get_arrl_sections {
272             return {
273 0     0     'AL' => 'AL',
274             'AK' => 'AK',
275             'AB' => 'AB',
276             'AZ' => 'AZ',
277             'AR' => 'AR',
278             'BC' => 'BC',
279             'CA' => {
280             'Alameda' => 'EB',
281             'Contra Costa' => 'EB',
282             'Napa' => 'EB',
283             'Solano' => 'EB',
284             'Los Angeles' => 'LAX',
285             'Inyo' => 'ORG',
286             'Orange' => 'ORG',
287             'Riverside' => 'ORG',
288             'San Bernardino' => 'ORG',
289             'San Luis Obispo' => 'SB',
290             'Santa Barbara' => 'SB',
291             'Ventura' => 'SB',
292             'Monterey' => 'SCV',
293             'San Benito' => 'SCV',
294             'San Mateo' => 'SCV',
295             'Santa Clara' => 'SCV',
296             'Santa Cruz' => 'SCV',
297             'Imperial' => 'SDG',
298             'San Diego' => 'SDG',
299             'Del Norte' => 'SF',
300             'Humboldt' => 'SF',
301             'Lake' => 'SF',
302             'Marin' => 'SF',
303             'Mendocino' => 'SF',
304             'San Francisco' => 'SF',
305             'Sonoma' => 'SF',
306             'Calaveras' => 'SJV',
307             'Fresno' => 'SJV',
308             'Kern' => 'SJV',
309             'Kings' => 'SJV',
310             'Madera' => 'SJV',
311             'Mariposa' => 'SJV',
312             'Merced' => 'SJV',
313             'Mono' => 'SJV',
314             'San Joaquin' => 'SJV',
315             'Stanislaus' => 'SJV',
316             'Tulare' => 'SJV',
317             'Tuolumne' => 'SJV',
318             'Alpine' => 'SV',
319             'Amador' => 'SV',
320             'Butte' => 'SV',
321             'Colusa' => 'SV',
322             'El Dorado' => 'SV',
323             'Glenn' => 'SV',
324             'Lassen' => 'SV',
325             'Modoc' => 'SV',
326             'Nevada' => 'SV',
327             'Placer' => 'SV',
328             'Plumas' => 'SV',
329             'Sacramento' => 'SV',
330             'Shasta' => 'SV',
331             'Sierra' => 'SV',
332             'Siskiyou' => 'SV',
333             'Sutter' => 'SV',
334             'Tehama' => 'SV',
335             'Trinity' => 'SV',
336             'Yolo' => 'SV',
337             'Yuba' => 'SV'
338             },
339             'CO' => 'CO',
340             'CT' => 'CT',
341             'DE' => 'DE',
342             'DC' => 'MDC',
343             'FL' => {
344             'Alachua' => "NFL",
345             'Lee' => "SFL",
346             'Baker' => "NFL",
347             'Leon' => "NFL",
348             'Bay' => "NFL",
349             'Levy' => "NFL",
350             'Bradford' => "NFL",
351             'Liberty' => "NFL",
352             'Brevard' => "SFL",
353             'Madison' => "NFL",
354             'Broward' => "SFL",
355             'Manatee' => "WCF",
356             'Calhoun' => "NFL",
357             'Marion' => "NFL",
358             'Charlotte' => "WCF",
359             'Martin' => "SFL",
360             'Citrus' => "NFL",
361             'Miami-Dade' => "SFL",
362             'Clay' => "NFL",
363             'Monroe' => "SFL",
364             'Collier' => "SFL",
365             'Nassau' => "NFL",
366             'Columbia' => "NFL",
367             'Okaloosa' => "NFL",
368             'Desoto' => "WCF",
369             'Okeechobee' => "SFL",
370             'Dixie' => "NFL",
371             'Orange' => "NFL",
372             'Duval' => "NFL",
373             'Osceola' => "SFL",
374             'Escambia' => "NFL",
375             'Palm Beach' => "SFL",
376             'Flagler' => "NFL",
377             'Pasco' => "WCF",
378             'Franklin' => "NFL",
379             'Pinellas' => "WCF",
380             'Gadsden' => "NFL",
381             'Polk' => "WCF",
382             'Gilchrist' => "NFL",
383             'Putnam' => "NFL",
384             'Glades' => "SFL",
385             'Santa Rosa' => "NFL",
386             'Gulf' => "NFL",
387             'Sarasota' => "WCF",
388             'Hamilton' => "NFL",
389             'Seminole' => "NFL",
390             'Hardee' => "WCF",
391             'St. Johns' => "NFL",
392             'Hendry' => "SFL",
393             'St. Lucie' => "SFL",
394             'Hernando' => "NFL",
395             'Sumter' => "NFL",
396             'Highlands' => "WCF",
397             'Suwannee' => "NFL",
398             'Hillsborough' => "WCF",
399             'Taylor' => "NFL",
400             'Holmes' => "NFL",
401             'Union' => "NFL",
402             'Indian River' => "SFL",
403             'Volusia' => "NFL",
404             'Jackson' => "NFL",
405             'Wakulla' => "NFL",
406             'Jefferson' => "NFL",
407             'Walton' => "NFL",
408             'Lafayette' => "NFL",
409             'Washington' => "NFL",
410             'Lake' => "NFL"
411             },
412             'GA' => 'GA',
413             'GU' => 'GU',
414             'HI' => 'PAC',
415             'ID' => 'ID',
416             'IL' => 'IL',
417             'IN' => 'IN',
418             'IA' => 'IA',
419             'KS' => 'KS',
420             'KY' => 'KY',
421             'LA' => 'LA',
422             'MA' => {
423             'Barnstable' => 'EMA',
424             'Bristol' => 'EMA',
425             'Dukes' => 'EMA',
426             'Essex' => 'EMA',
427             'Middlesex' => 'EMA',
428             'Nantucket' => 'EMA',
429             'Norfolk' => 'EMA',
430             'Plymouth' => 'EMA',
431             'Berkshire' => 'WMA',
432             'Franklin' => 'WMA',
433             'Hampden' => 'WMA',
434             'Hampshire' => 'WMA',
435             'Worcester' => 'WMA'
436             },
437             'ME' => 'ME',
438             'MB' => 'MB',
439             'MD' => 'MDC',
440             'MI' => 'MI',
441             'MN' => 'MN',
442             'MS' => 'MS',
443             'MO' => 'MO',
444             'MT' => 'MT',
445             'NB' => 'NB',
446             'NC' => 'NC',
447             'ND' => 'ND',
448             'NE' => 'NE',
449             'NH' => 'NH',
450             'NJ' => {
451             'Bergen' => 'NNJ',
452             'Essex' => 'NNJ',
453             'Hudson' => 'NNJ',
454             'Hunterdon' => 'NNJ',
455             'Middlesex' => 'NNJ',
456             'Monmouth' => 'NNJ',
457             'Morris' => 'NNJ',
458             'Passaic' => 'NNJ',
459             'Somerset' => 'NNJ',
460             'Sussex' => 'NNJ',
461             'Union' => 'NNJ',
462             'Warren' => 'NNJ',
463             'Atlantic' => 'SNJ',
464             'Burlington' => 'SNJ',
465             'Camden' => 'SNJ',
466             'Cape May' => 'SNJ',
467             'Cumberland' => 'SNJ',
468             'Gloucester' => 'SNJ',
469             'Mercer' => 'SNJ',
470             'Ocean' => 'SNJ',
471             'Salem' => 'SNJ'
472             },
473             'NL' => 'NL',
474             'NM' => 'NM',
475             'NS' => 'NS',
476             'NT' => 'NT',
477             'NU' => 'NU',
478             'NV' => 'NV',
479             'NY' => {
480             'Bronx' => 'NLI',
481             'New York' => 'NLI',
482             'Kings' => 'NLI',
483             'Queens' => 'NLI',
484             'Richmond' => 'NLI',
485             'Nassau' => 'NLI',
486             'Suffolk' => 'NLI',
487             'Albany' => 'ENY',
488             'Columbia' => 'ENY',
489             'Dutchess' => 'ENY',
490             'Greene' => 'ENY',
491             'Orange' => 'ENY',
492             'Putnam' => 'ENY',
493             'Rensselaer' => 'ENY',
494             'Rockland' => 'ENY',
495             'Saratoga' => 'ENY',
496             'Schenectady' => 'ENY',
497             'Sullivan' => 'ENY',
498             'Ulster' => 'ENY',
499             'Warren' => 'ENY',
500             'Washington' => 'ENY',
501             'Westchester' => 'ENY',
502             'Clinton' => 'NNY',
503             'Essex' => 'NNY',
504             'Franklin' => 'NNY',
505             'Fulton' => 'NNY',
506             'Hamilton' => 'NNY',
507             'Jefferson' => 'NNY',
508             'Lewis' => 'NNY',
509             'Montgomery' => 'NNY',
510             'St. Lawrence' => 'NNY',
511             'Schoharie' => 'NNY',
512             'Allegany' => 'WNY',
513             'Broome' => 'WNY',
514             'Cattaraugus' => 'WNY',
515             'Cayuga' => 'WNY',
516             'Chautauqua' => 'WNY',
517             'Chemung' => 'WNY',
518             'Chenango' => 'WNY',
519             'Cortland' => 'WNY',
520             'Delaware' => 'WNY',
521             'Erie' => 'WNY',
522             'Genesee' => 'WNY',
523             'Herkimer' => 'WNY',
524             'Livingston' => 'WNY',
525             'Madison' => 'WNY',
526             'Monroe' => 'WNY',
527             'Niagara' => 'WNY',
528             'Oneida' => 'WNY',
529             'Onondaga' => 'WNY',
530             'Ontario' => 'WNY',
531             'Orleans' => 'WNY',
532             'Oswego' => 'WNY',
533             'Otsego' => 'WNY',
534             'Schuyler' => 'WNY',
535             'Seneca' => 'WNY',
536             'Steuben' => 'WNY',
537             'Tioga' => 'WNY',
538             'Tompkins' => 'WNY',
539             'Wayne' => 'WNY',
540             'Wyoming' => 'WNY',
541             'Yates' => 'WNY'
542             },
543             'OH' => 'OH',
544             'OK' => 'OK',
545             'ON' => 'ON',
546             'OR' => 'OR',
547             'PA' => {
548             'Adams' => 'EPA',
549             'Berks' => 'EPA',
550             'Bradford' => 'EPA',
551             'Bucks' => 'EPA',
552             'Carbon' => 'EPA',
553             'Chester' => 'EPA',
554             'Columbia' => 'EPA',
555             'Cumberland' => 'EPA',
556             'Dauphin' => 'EPA',
557             'Delaware' => 'EPA',
558             'Juniata' => 'EPA',
559             'Lackawanna' => 'EPA',
560             'Lancaster' => 'EPA',
561             'Lebanon' => 'EPA',
562             'Lehigh' => 'EPA',
563             'Luzerne' => 'EPA',
564             'Lycoming' => 'EPA',
565             'Monroe' => 'EPA',
566             'Montgomery' => 'EPA',
567             'Montour' => 'EPA',
568             'Northhampton' => 'EPA',
569             'Northumberland' => 'EPA',
570             'Perry' => 'EPA',
571             'Philadelphia' => 'EPA',
572             'Pike' => 'EPA',
573             'Schuylkill' => 'EPA',
574             'Snyder' => 'EPA',
575             'Sullivan' => 'EPA',
576             'Susquehanna' => 'EPA',
577             'Tioga' => 'EPA',
578             'Union' => 'EPA',
579             'Wayne' => 'EPA',
580             'Wyoming' => 'EPA',
581             'York' => 'EPA',
582             'Allegheny' => 'WPA',
583             'Armstrong' => 'WPA',
584             'Beaver' => 'WPA',
585             'Bedford' => 'WPA',
586             'Blair' => 'WPA',
587             'Butler' => 'WPA',
588             'Cambria' => 'WPA',
589             'Cameron' => 'WPA',
590             'Centre' => 'WPA',
591             'Clarion' => 'WPA',
592             'Clearfield' => 'WPA',
593             'Clinton' => 'WPA',
594             'Crawford' => 'WPA',
595             'Elk' => 'WPA',
596             'Erie' => 'WPA',
597             'Fayette' => 'WPA',
598             'Franklin' => 'WPA',
599             'Fulton' => 'WPA',
600             'Greene' => 'WPA',
601             'Huntingdon' => 'WPA',
602             'Indiana' => 'WPA',
603             'Jefferson' => 'WPA',
604             'Lawrence' => 'WPA',
605             'McKean' => 'WPA',
606             'Mercer' => 'WPA',
607             'Mifflin' => 'WPA',
608             'Potter' => 'WPA',
609             'Somerset' => 'WPA',
610             'Venango' => 'WPA',
611             'Warren' => 'WPA',
612             'Washington' => 'WPA',
613             'Westmoreland' => 'WPA'
614             },
615             'PE' => 'MAR',
616             'PR' => 'PR',
617             'QC' => 'QC',
618             'RI' => 'RI',
619             'SK' => 'SK',
620             'SC' => 'SC',
621             'SD' => 'SD',
622             'TN' => 'TN',
623             'TX' => {
624             'Anderson' => 'WTX',
625             'Andrews' => 'WTX',
626             'Angelina' => 'STX',
627             'Aransas' => 'STX',
628             'Archer' => 'NTX',
629             'Armstrong' => 'WTX',
630             'Atascosa' => 'STX',
631             'Austin' => 'STX',
632             'Bailey' => 'WTX',
633             'Bandera' => 'STX',
634             'Bastrop' => 'WTX',
635             'Baylor' => 'NTX',
636             'Bee' => 'STX',
637             'Bell' => 'NTX',
638             'Bexar' => 'STX',
639             'Blanco' => 'STX',
640             'Borden' => 'WTX',
641             'Bosque' => 'NTX',
642             'Bowie' => 'NTX',
643             'Brazoria' => 'STX',
644             'Brazos' => 'STX',
645             'Brewster' => 'WTX',
646             'Briscoe' => 'WTX',
647             'Brooks' => 'STX',
648             'Brown' => 'NTX',
649             'Burleson' => 'STX',
650             'Burnet' => 'STX',
651             'Caldwell' => 'STX',
652             'Calhoun' => 'STX',
653             'Callahan' => 'WTX',
654             'Cameron' => 'STX',
655             'Camp' => 'NTX',
656             'Carson' => 'WTX',
657             'Cass' => 'NTX',
658             'Castro' => 'WTX',
659             'Chambers' => 'STX',
660             'Cherokee' => 'NTX',
661             'Childress' => 'WTX',
662             'Clay' => 'NTX',
663             'Cochran' => 'WTX',
664             'Coke' => 'WTX',
665             'Coleman' => 'WTX',
666             'Collin' => 'NTX',
667             'Collingsworth' => 'WTX',
668             'Colorado' => 'STX',
669             'Comal' => 'STX',
670             'Comanche' => 'NTX',
671             'Concho' => 'WTX',
672             'Cooke' => 'NTX',
673             'Coryell' => 'NTX',
674             'Cottle' => 'WTX',
675             'Crane' => 'WTX',
676             'Crockett' => 'WTX',
677             'Crosby' => 'WTX',
678             'Culberson' => 'WTX',
679             'Dallam' => 'WTX',
680             'Dallas' => 'NTX',
681             'Dawson' => 'WTX',
682             'Deaf Smith' => 'WTX',
683             'Delta' => 'NTX',
684             'Denton' => 'NTX',
685             'DeWitt' => 'STX',
686             'Dickens' => 'WTX',
687             'Dimmit' => 'STX',
688             'Donley' => 'WTX',
689             'Duval' => 'STX',
690             'Eastland' => 'NTX',
691             'Ector' => 'WTX',
692             'Edwards' => 'STX',
693             'El Paso' => 'WTX',
694             'Ellis' => 'NTX',
695             'Erath' => 'NTX',
696             'Falls' => 'NTX',
697             'Fannin' => 'NTX',
698             'Fayette' => 'STX',
699             'Fisher' => 'WTX',
700             'Floyd' => 'WTX',
701             'Foard' => 'WTX',
702             'Fort Bend' => 'STX',
703             'Franklin' => 'NTX',
704             'Freestone' => 'NTX',
705             'Frio' => 'STX',
706             'Gaines' => 'WTX',
707             'Galveston' => 'STX',
708             'Garza' => 'WTX',
709             'Gillespie' => 'STX',
710             'Glasscock' => 'WTX',
711             'Goliad' => 'STX',
712             'Gonzales' => 'STX',
713             'Gray' => 'WTX',
714             'Grayson' => 'NTX',
715             'Gregg' => 'NTX',
716             'Grimes' => 'STX',
717             'Guadalupe' => 'STX',
718             'Hale' => 'WTX',
719             'Hall' => 'WTX',
720             'Hamilton' => 'NTX',
721             'Hansford' => 'WTX',
722             'Hardeman' => 'WTX',
723             'Hardin' => 'STX',
724             'Harris' => 'STX',
725             'Harrison' => 'NTX',
726             'Hartley' => 'WTX',
727             'Haskell' => 'WTX',
728             'Hays' => 'STX',
729             'Hemphill' => 'WTX',
730             'Henderson' => 'NTX',
731             'Hidalgo' => 'STX',
732             'Hill' => 'NTX',
733             'Hockley' => 'WTX',
734             'Hood' => 'NTX',
735             'Hopkins' => 'NTX',
736             'Houston' => 'STX',
737             'Howard' => 'WTX',
738             'Hudspeth' => 'WTX',
739             'Hunt' => 'NTX',
740             'Hutchinson' => 'WTX',
741             'Irion' => 'WTX',
742             'Jack' => 'NTX',
743             'Jackson' => 'STX',
744             'Jasper' => 'STX',
745             'Jeff Davis' => 'WTX',
746             'Jefferson' => 'STX',
747             'Jim Hogg' => 'STX',
748             'Jim Wells' => 'STX',
749             'Johnson' => 'NTX',
750             'Jones' => 'WTX',
751             'Karnes' => 'STX',
752             'Kaufman' => 'NTX',
753             'Kendall' => 'STX',
754             'Kenedy' => 'STX',
755             'Kent' => 'WTX',
756             'Kerr' => 'STX',
757             'Kimble' => 'STX',
758             'King' => 'WTX',
759             'Kinney' => 'STX',
760             'Kleberg' => 'STX',
761             'Knox' => 'WTX',
762             'La Salle' => 'STX',
763             'Lamar' => 'NTX',
764             'Lamb' => 'WTX',
765             'Lampasas' => 'NTX',
766             'Lavaca' => 'STX',
767             'Lee' => 'STX',
768             'Leon' => 'STX',
769             'Liberty' => 'STX',
770             'Limestone' => 'NTX',
771             'Lipscomb' => 'WTX',
772             'Live Oak' => 'STX',
773             'Llano' => 'STX',
774             'Loving' => 'WTX',
775             'Lubbock' => 'WTX',
776             'Lynn' => 'WTX',
777             'Madison' => 'STX',
778             'Marion' => 'NTX',
779             'Martin' => 'WTX',
780             'Mason' => 'STX',
781             'Matagorda' => 'STX',
782             'Maverick' => 'STX',
783             'McCulloch' => 'STX',
784             'McLennan' => 'NTX',
785             'McMullen' => 'STX',
786             'Medina' => 'STX',
787             'Menard' => 'STX',
788             'Midland' => 'WTX',
789             'Milam' => 'STX',
790             'Mills' => 'NTX',
791             'Mitchell' => 'WTX',
792             'Montague' => 'NTX',
793             'Montgomery' => 'STX',
794             'Moore' => 'WTX',
795             'Morris' => 'NTX',
796             'Motley' => 'WTX',
797             'Nacogdoches' => 'NTX',
798             'Navarro' => 'NTX',
799             'Newton' => 'STX',
800             'Nolan' => 'WTX',
801             'Nueces' => 'STX',
802             'Ochiltree' => 'WTX',
803             'Oldham' => 'WTX',
804             'Orange' => 'STX',
805             'Palo Pinto' => 'NTX',
806             'Panola' => 'NTX',
807             'Parker' => 'NTX',
808             'Parmer' => 'WTX',
809             'Pecos' => 'WTX',
810             'Polk' => 'STX',
811             'Potter' => 'WTX',
812             'Presidio' => 'WTX',
813             'Rains' => 'NTX',
814             'Randall' => 'WTX',
815             'Reagan' => 'WTX',
816             'Real' => 'STX',
817             'Red River' => 'NTX',
818             'Reeves' => 'WTX',
819             'Refugio' => 'STX',
820             'Roberts' => 'WTX',
821             'Robertson' => 'STX',
822             'Rockwall' => 'NTX',
823             'Runnels' => 'WTX',
824             'Rusk' => 'NTX',
825             'Sabine' => 'STX',
826             'San Augustine' => 'STX',
827             'San Jacinto' => 'STX',
828             'San Patricio' => 'STX',
829             'San Saba' => 'STX',
830             'Schleicher' => 'WTX',
831             'Scurry' => 'WTX',
832             'Shackelford' => 'WTX',
833             'Shelby' => 'NTX',
834             'Sherman' => 'WTX',
835             'Smith' => 'NTX',
836             'Somervell' => 'NTX',
837             'Starr' => 'STX',
838             'Stephens' => 'NTX',
839             'Sterling' => 'WTX',
840             'Stonewall' => 'WTX',
841             'Sutton' => 'WTX',
842             'Swisher' => 'WTX',
843             'Tarrant' => 'NTX',
844             'Taylor' => 'WTX',
845             'Terrell' => 'WTX',
846             'Terry' => 'WTX',
847             'Throckmorton' => 'NTX',
848             'Titus' => 'NTX',
849             'Tom Green' => 'WTX',
850             'Travis' => 'STX',
851             'Trinity' => 'STX',
852             'Tyler' => 'STX',
853             'Upshur' => 'NTX',
854             'Upton' => 'WTX',
855             'Uvalde' => 'STX',
856             'Val Verde' => 'STX',
857             'Van Zandt' => 'NTX',
858             'Victoria' => 'STX',
859             'Walker' => 'STX',
860             'Waller' => 'STX',
861             'Ward' => 'WTX',
862             'Washington' => 'STX',
863             'Webb' => 'STX',
864             'Wharton' => 'STX',
865             'Wheeler' => 'WTX',
866             'Wichita' => 'NTX',
867             'Wilbarger' => 'NTX',
868             'Willacy' => 'STX',
869             'Williamson' => 'STX',
870             'Wilson' => 'STX',
871             'Winkler' => 'WTX',
872             'Wise' => 'NTX',
873             'Wood' => 'NTX',
874             'Yoakum' => 'WTX',
875             'Young' => 'NTX',
876             'Zapata' => 'STX',
877             'Zavala' => 'STX'
878             },
879             'UT' => 'UT',
880             'VT' => 'VT',
881             'VA' => 'VA',
882             'VI' => 'VI',
883             'WA' => {
884             'Adams' => 'EWA',
885             'Asotin' => 'EWA',
886             'Benton' => 'EWA',
887             'Chelan' => 'EWA',
888             'Columbia' => 'EWA',
889             'Douglas' => 'EWA',
890             'Ferry' => 'EWA',
891             'Franklin' => 'EWA',
892             'Garfield' => 'EWA',
893             'Grant' => 'EWA',
894             'Kittitas' => 'EWA',
895             'Klickitat' => 'EWA',
896             'Lincoln' => 'EWA',
897             'Okanogan' => 'EWA',
898             'Pend Oreille' => 'EWA',
899             'Spokane' => 'EWA',
900             'Stevens' => 'EWA',
901             'Walla Walla' => 'EWA',
902             'Whitman' => 'EWA',
903             'Yakima' => 'EWA',
904             'Clallam' => 'WWA',
905             'Clark' => 'WWA',
906             'Cowlitz' => 'WWA',
907             'Grays Harbor' => 'WWA',
908             'Island' => 'WWA',
909             'Jefferson' => 'WWA',
910             'King' => 'WWA',
911             'Kitsap' => 'WWA',
912             'Lewis' => 'WWA',
913             'Mason' => 'WWA',
914             'Pacific' => 'WWA',
915             'Pierce' => 'WWA',
916             'San Juan' => 'WWA',
917             'Skagit' => 'WWA',
918             'Skamania' => 'WWA',
919             'Snohomish' => 'WWA',
920             'Thurston' => 'WWA',
921             'Wahkiakum' => 'WWA',
922             'Whatcom' => 'WWA'
923             },
924             'WI' => 'WI',
925             'WV' => 'WV',
926             'WY' => 'WY',
927             'YT' => 'YT'
928             };
929             }
930              
931             1;
932             __END__