You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@spamassassin.apache.org by jm...@apache.org on 2004/05/01 04:11:41 UTC
svn commit: rev 10468 - in incubator/spamassassin/trunk: . lib/Mail/SpamAssassin lib/Mail/SpamAssassin/Plugin lib/Mail/SpamAssassin/Util t
Author: jm
Date: Fri Apr 30 19:11:41 2004
New Revision: 10468
Added:
incubator/spamassassin/trunk/lib/Mail/SpamAssassin/Util/
incubator/spamassassin/trunk/lib/Mail/SpamAssassin/Util/RegistrarBoundaries.pm
Modified:
incubator/spamassassin/trunk/MANIFEST
incubator/spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/SPF.pm
incubator/spamassassin/trunk/lib/Mail/SpamAssassin/Received.pm
incubator/spamassassin/trunk/lib/Mail/SpamAssassin/Util.pm
incubator/spamassassin/trunk/t/ip_addrs.t
Log:
more comprehensive handling of the (sick, sick, sick) rules for TLD delegation -- now deals with 3 and 4 level TLDs correctly
Modified: incubator/spamassassin/trunk/MANIFEST
==============================================================================
--- incubator/spamassassin/trunk/MANIFEST (original)
+++ incubator/spamassassin/trunk/MANIFEST Fri Apr 30 19:11:41 2004
@@ -343,3 +343,4 @@
t/body_mod.t
t/bayesdbm_flock.t
t/spamc_E.t
+lib/Mail/SpamAssassin/Util/RegistrarBoundaries.pm
Modified: incubator/spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/SPF.pm
==============================================================================
--- incubator/spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/SPF.pm (original)
+++ incubator/spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/SPF.pm Fri Apr 30 19:11:41 2004
@@ -143,7 +143,12 @@
if ($ishelo) {
dbg ("SPF: checking HELO (helo=$helo, ip=$ip)");
- $helo = Mail::SpamAssassin::Util::trim_domain_to_registrar_boundary ($helo);
+
+ if ($helo !~ /^\d+\.\d+\.\d+\.\d+$/) {
+ # get rid of hostname part of domain, understanding delegation
+ $helo = Mail::SpamAssassin::Util::RegistrarBoundaries::trim_domain ($helo);
+ }
+
dbg ("SPF: trimmed HELO down to '$helo'");
} else {
Modified: incubator/spamassassin/trunk/lib/Mail/SpamAssassin/Received.pm
==============================================================================
--- incubator/spamassassin/trunk/lib/Mail/SpamAssassin/Received.pm (original)
+++ incubator/spamassassin/trunk/lib/Mail/SpamAssassin/Received.pm Fri Apr 30 19:11:41 2004
@@ -47,6 +47,7 @@
use Mail::SpamAssassin::Dns;
use Mail::SpamAssassin::PerMsgStatus;
+use Mail::SpamAssassin::Util::RegistrarBoundaries;
use Mail::SpamAssassin::Constants qw(:ip);
use vars qw{
@@ -325,22 +326,17 @@
sub mx_of_helo_near_ip {
my ($self, $helo, $ip) = @_;
- my $helodomain = $helo;
+ my $helodom = $helo;
# TODO: should we just traverse down the chain instead of this;
# e.g. "foo.bar.baz.co.uk" would be "bar.baz.co.uk", "baz.co.uk",
# instead of just "baz.co.uk" straight away?
- if (Mail::SpamAssassin::Util::is_in_subdelegated_cctld ($helo)) {
- if ($helo =~ /\.([^\.]+\.[^\.]+\.[^\.]+)$/) {
- $helodomain = $1;
- }
- } else {
- if ($helo =~ /\.([^\.]+\.[^\.]+)$/) {
- $helodomain = $1;
- }
+
+ if ($helo !~ /^\d+\.\d+\.\d+\.\d+$/) {
+ $helodom = Mail::SpamAssassin::Util::RegistrarBoundaries::trim_domain ($helo);
}
- my $mxes = $self->lookup_mx ($helodomain);
+ my $mxes = $self->lookup_mx ($helodom);
my @mxips = ();
foreach my $mx (@$mxes) {
push (@mxips, $self->lookup_all_ips ($mx));
@@ -348,7 +344,7 @@
if ($mxes && Mail::SpamAssassin::Util::ips_match_in_24_mask ([ $ip ], [ @mxips ]))
{
dbg ("IP address $ip is near to an MX (".join (', ', @mxips).
- ") for ".$helodomain);
+ ") for ".$helodom);
return 1;
}
return 0;
Modified: incubator/spamassassin/trunk/lib/Mail/SpamAssassin/Util.pm
==============================================================================
--- incubator/spamassassin/trunk/lib/Mail/SpamAssassin/Util.pm (original)
+++ incubator/spamassassin/trunk/lib/Mail/SpamAssassin/Util.pm Fri Apr 30 19:11:41 2004
@@ -34,6 +34,7 @@
@EXPORT = qw(local_tz base64_decode);
use Mail::SpamAssassin;
+use Mail::SpamAssassin::Util::RegistrarBoundaries;
use Config;
use File::Spec;
@@ -749,31 +750,13 @@
# keep IPs intact
if ($uri !~ /^\d+\.\d+\.\d+\.\d+$/) {
# get rid of hostname part of domain, understanding delegation
- if (Mail::SpamAssassin::Util::is_in_subdelegated_cctld($uri)) {
- $uri = $1 if $uri =~ /\.([^\.]+\.[^\.]+\.[^\.]+)$/;
- }
- else {
- $uri = $1 if $uri =~ /\.([^\.]+\.[^\.]+)$/;
- }
+ $uri = Mail::SpamAssassin::Util::RegistrarBoundaries::trim_domain ($uri);
}
# $uri is now the domain only
return $uri;
}
-sub is_in_subdelegated_cctld {
- my ($domain) = @_;
-
- # http://www.bestregistrar.com/help/ccTLD.htm lists these
- return ($domain =~ /\.
- (?:ac| ae| ar| at| au| az| bb| bm| br| bs| ca| cn| co|
- cr| cu| cy| do| ec| eg| fj| ge| gg| gu| hk| hu| id| il| im|
- in| je| jo| jp| kh| kr| la| lb| lc| lv| ly| mm| mo| mt| mx| my|
- na| nc| ni| np| nz| pa| pe| ph| pl| py| ru| sg| sh| sv| sy| th|
- tn| tr| tw| ua| ug| uk| uy| ve| vi| yu| za)
- $/ixo);
-}
-
sub uri_list_canonify {
my(@uris) = @_;
@@ -817,41 +800,6 @@
my %uris = map { $_ => 1 } @uris, @nuris;
return keys %uris;
-}
-
-###########################################################################
-
-sub trim_domain_to_registrar_boundary {
- my ($domain) = @_;
-
- # drop any hostname parts, if we can.
- my @domparts = split (/\./, $domain);
- my $numparts = scalar @domparts;
-
- # for the HELO variant, drop the first bit of the HELO (ie. turn
- # "host.dom.ain" into "dom.ain".)
- if ($numparts > 0) {
- my $partsreqd = 2;
-
- # the "Demon case"; Demon Internet registers domains for
- # its customers, ie. "foo.demon.co.uk".
- if ($domain =~ /\. (?:
- demon\.co\.uk
- )$/ix)
- {
- $partsreqd = 4;
- }
- # Subdelegated CCTLD
- elsif (is_in_subdelegated_cctld ($domain)) {
- $partsreqd = 3;
- }
-
- while ($numparts > $partsreqd) {
- $domain =~ s/^[^\.]+\.//;
- $numparts--;
- }
- }
- $domain;
}
###########################################################################
Added: incubator/spamassassin/trunk/lib/Mail/SpamAssassin/Util/RegistrarBoundaries.pm
==============================================================================
--- (empty file)
+++ incubator/spamassassin/trunk/lib/Mail/SpamAssassin/Util/RegistrarBoundaries.pm Fri Apr 30 19:11:41 2004
@@ -0,0 +1,631 @@
+# The (extremely complex) rules for domain delegation.
+
+# <@LICENSE>
+# Copyright 2004 Apache Software Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# </...@LICENSE>
+
+package Mail::SpamAssassin::Util::RegistrarBoundaries;
+
+use strict;
+use bytes;
+
+use vars qw (
+ @ISA $TWO_LEVEL_DOMAINS $THREE_LEVEL_DOMAINS $US_STATES $FOUR_LEVEL_DOMAINS
+);
+
+# This is required because the .us domain is nuts. See $THREE_LEVEL_DOMAINS
+# and $FOUR_LEVEL_DOMAINS below.
+#
+$US_STATES = qr{ (?:
+ ak|al|ar|az|ca|co|ct|dc|de|fl|ga|gu|hi|ia|id|il|in|ks|ky|la|ma|md|me|mi|
+ mn|mo|ms|mt|nc|nd|ne|nh|nj|nm|nv|ny|oh|ok|or|pa|pr|ri|sc|sd|tn|tx|ut|va|vi|
+ vt|wa|wi|wv|wy )
+}ix;
+
+# updated: 2004-04-30: first rev
+#
+$THREE_LEVEL_DOMAINS = qr( (?:
+ demon\.co\.uk |
+
+ # http://www.neustar.us/policies/docs/rfc_1480.txt
+ [^\.]+\.${US_STATES}\.us )
+)ix;
+
+$FOUR_LEVEL_DOMAINS = qr( (?:
+ # http://www.neustar.us/policies/docs/rfc_1480.txt
+ # "Fire-Dept.CI.Los-Angeles.CA.US"
+ # "<school-name>.PVT.K12.<state>.US"
+
+ pvt\.k12\.${US_STATES}\.us
+ c[io]\.[^\.]+\.${US_STATES}\.us
+)
+)ix;
+
+# updated: 2004-04-30: first rev
+$TWO_LEVEL_DOMAINS = qr{ (?:
+
+ # http://www.neustar.us/policies/docs/rfc_1480.txt
+
+ fed\.us |
+ dni\.us |
+
+ # data from http://spamcheck.freeapp.net/two-level-tlds , in turn from
+ # http://www.bestregistrar.com/help/ccTLD.htm
+
+ com\.ac |
+ edu\.ac |
+ gov\.ac |
+ net\.ac |
+ mil\.ac |
+ org\.ac |
+ com\.ae |
+ net\.ae |
+ org\.ae |
+ com\.ar |
+ net\.ar |
+ org\.ar |
+ co\.at |
+ ac\.at |
+ com\.au |
+ org\.au |
+ gov\.au |
+ org\.au |
+ edu\.au |
+ id\.au |
+ oz\.au |
+ info\.au |
+ net\.au |
+ asn\.au |
+ csiro\.au |
+ telememo\.au |
+ conf\.au |
+ com\.az |
+ net\.az |
+ org\.az |
+ com\.bb |
+ net\.bb |
+ org\.bb |
+ ac\.be |
+ belgie\.be |
+ dns\.be |
+ fgov\.be |
+ com\.bm |
+ edu\.bm |
+ gov\.bm |
+ org\.bm |
+ net\.bm |
+ art\.br |
+ sp\.br |
+ com\.br |
+ etc\.br |
+ g12\.br |
+ gov\.br |
+ ind\.br |
+ inf\.br |
+ mil\.br |
+ net\.br |
+ org\.br |
+ psi\.br |
+ rec\.br |
+ tmp\.br |
+ com\.bs |
+ net\.bs |
+ org\.bs |
+ ab\.ca |
+ bc\.ca |
+ mb\.ca |
+ nb\.ca |
+ nf\.ca |
+ ns\.ca |
+ nt\.ca |
+ nu\.ca |
+ on\.ca |
+ pe\.ca |
+ qc\.ca |
+ sk\.ca |
+ yk\.ca |
+ co\.ck |
+ com\.cn |
+ edu\.cn |
+ gov\.cn |
+ net\.cn |
+ org\.cn |
+ ac\.cn |
+ ah\.cn |
+ bj\.cn |
+ cq\.cn |
+ gd\.cn |
+ gs\.cn |
+ gx\.cn |
+ gz\.cn |
+ hb\.cn |
+ he\.cn |
+ hi\.cn |
+ hk\.cn |
+ hl\.cn |
+ hn\.cn |
+ jl\.cn |
+ js\.cn |
+ ln\.cn |
+ mo\.cn |
+ nm\.cn |
+ nx\.cn |
+ qh\.cn |
+ sc\.cn |
+ sn\.cn |
+ sh\.cn |
+ sx\.cn |
+ tj\.cn |
+ tw\.cn |
+ xj\.cn |
+ xz\.cn |
+ yn\.cn |
+ zj\.cn |
+ arts\.co |
+ com\.co |
+ edu\.co |
+ firm\.co |
+ gov\.co |
+ info\.co |
+ int\.co |
+ nom\.co |
+ mil\.co |
+ org\.co |
+ rec\.co |
+ store\.co |
+ web\.co |
+ ac\.cr |
+ co\.cr |
+ ed\.cr |
+ fi\.cr |
+ go\.cr |
+ or\.cr |
+ sa\.cr |
+ com\.cu |
+ net\.cu |
+ org\.cu |
+ ac\.cy |
+ com\.cy |
+ gov\.cy |
+ net\.cy |
+ org\.cy |
+ art\.do |
+ com\.do |
+ edu\.do |
+ gov\.do |
+ org\.do |
+ mil\.do |
+ net\.do |
+ web\.do |
+ com\.ec |
+ k12\.ec |
+ edu\.ec |
+ fin\.ec |
+ med\.ec |
+ gov\.ec |
+ mil\.ec |
+ org\.ec |
+ net\.ec |
+ com\.eg |
+ edu\.eg |
+ eun\.eg |
+ gov\.eg |
+ net\.eg |
+ org\.eg |
+ sci\.eg |
+ ac\.fj |
+ com\.fj |
+ gov\.fj |
+ id\.fj |
+ org\.fj |
+ school\.fj |
+ asso\.fr |
+ nom\.fr |
+ barreau\.fr |
+ com\.fr |
+ prd\.fr |
+ presse\.fr |
+ tm\.fr |
+ aeroport\.fr |
+ assedic\.fr |
+ avocat\.fr |
+ avoues\.fr |
+ cci\.fr |
+ chambagri\.fr |
+ chirurgiens-dentistes\.fr |
+ experts-comptables\.fr |
+ geometre-expert\.fr |
+ gouv\.fr |
+ greta\.fr |
+ huissier-justice\.fr |
+ medecin\.fr |
+ notaires\.fr |
+ pharmacien\.fr |
+ port\.fr |
+ veterinaire\.fr |
+ notaires\.fr |
+ com\.ge |
+ edu\.ge |
+ gov\.ge |
+ mil\.ge |
+ net\.ge |
+ org\.ge |
+ pvt\.ge |
+ co\.gg |
+ org\.gg |
+ sch\.gg |
+ ac\.gg |
+ gov\.gg |
+ ltd\.gg |
+ ind\.gg |
+ net\.gg |
+ alderney\.gg |
+ guernsey\.gg |
+ sark\.gg |
+ com\.gu |
+ edu\.gu |
+ net\.gu |
+ org\.gu |
+ gov\.gu |
+ mil\.gu |
+ com\.hk |
+ net\.hk |
+ org\.hk |
+ co\.hu |
+ org\.hu |
+ info\.hu |
+ nui\.hu |
+ priv\.hu |
+ tm\.hu |
+ ac\.id |
+ co\.id |
+ go\.id |
+ mil\.id |
+ net\.id |
+ or\.id |
+ co\.il |
+ net\.il |
+ org\.il |
+ ac\.il |
+ gov\.il |
+ k12\.il |
+ muni\.il |
+ co\.im |
+ net\.im |
+ org\.im |
+ ac\.im |
+ lkd\.co\.im |
+ gov\.im |
+ nic\.im |
+ plc\.co\.im |
+ co\.in |
+ net\.in |
+ ac\.in |
+ ernet\.in |
+ gov\.in |
+ nic\.in |
+ res\.in |
+ co\.je |
+ net\.je |
+ org\.je |
+ ac\.je |
+ gov\.je |
+ ind\.je |
+ jersey\.je |
+ ltd\.je |
+ sch\.je |
+ com\.jo |
+ net\.jo |
+ gov\.jo |
+ edu\.jo |
+ ad\.jp |
+ ac\.jp |
+ co\.jp |
+ net\.jp |
+ org\.jp |
+ gov\.jp |
+ com\.kh |
+ net\.kh |
+ org\.kh |
+ ac\.kr |
+ co\.kr |
+ go\.kr |
+ nm\.kr |
+ or\.kr |
+ pe\.kr |
+ re\.kr |
+ com\.la |
+ net\.la |
+ org\.la |
+ com\.lb |
+ org\.lb |
+ net\.lb |
+ gov\.lb |
+ mil\.lb |
+ com\.lc |
+ edu\.lc |
+ gov\.lc |
+ net\.lc |
+ org\.lc |
+ com\.lv |
+ net\.lv |
+ org\.lv |
+ edu\.lv |
+ gov\.lv |
+ mil\.lv |
+ id\.lv |
+ asn\.lv |
+ conf\.lv |
+ com\.ly |
+ net\.ly |
+ org\.ly |
+ com\.mm |
+ net\.mm |
+ org\.mm |
+ edu\.mm |
+ gov\.mm |
+ com\.mo |
+ net\.mo |
+ org\.mo |
+ edu\.mo |
+ gov\.mo |
+ com\.mt |
+ net\.mt |
+ org\.mt |
+ com\.mx |
+ net\.mx |
+ org\.mx |
+ com\.my |
+ org\.my |
+ gov\.my |
+ edu\.my |
+ net\.my |
+ com\.na |
+ org\.na |
+ net\.na |
+ com\.nc |
+ net\.nc |
+ org\.nc |
+ gov\.ng |
+ com\.ni |
+ com\.np |
+ net\.np |
+ org\.np |
+ gov\.np |
+ ac\.nz |
+ co\.nz |
+ cri\.nz |
+ gen\.nz |
+ geek\.nz |
+ govt\.nz |
+ iwi\.nz |
+ maori\.nz |
+ mil\.nz |
+ net\.nz |
+ org\.nz |
+ school\.nz |
+ com\.pa |
+ net\.pa |
+ org\.pa |
+ edu\.pa |
+ ac\.pa |
+ gob\.pa |
+ sld\.pa |
+ com\.pe |
+ net\.pe |
+ org\.pe |
+ ac\.pa |
+ com\.ph |
+ net\.ph |
+ org\.ph |
+ mil\.ph |
+ ngo\.ph |
+ com\.pl |
+ net\.pl |
+ org\.pl |
+ com\.py |
+ net\.py |
+ org\.py |
+ edu\.py |
+ asso\.re |
+ com\.re |
+ nom\.re |
+ com\.ru |
+ net\.ru |
+ org\.ru |
+ pp\.ru |
+ com\.sg |
+ net\.sg |
+ org\.sg |
+ edu\.sg |
+ gov\.sg |
+ com\.sh |
+ net\.sh |
+ org\.sh |
+ edu\.sh |
+ gov\.sh |
+ mil\.sh |
+ co\.sv |
+ com\.sy |
+ net\.sy |
+ org\.sy |
+ ac\.th |
+ co\.th |
+ go\.th |
+ net\.th |
+ or\.th |
+ com\.tn |
+ net\.tn |
+ org\.tn |
+ edunet\.tn |
+ gov\.tn |
+ ens\.tn |
+ fin\.tn |
+ nat\.tn |
+ ind\.tn |
+ info\.tn |
+ intl\.tn |
+ rnrt\.tn |
+ rnu\.tn |
+ rns\.tn |
+ tourism\.tn |
+ com\.tr |
+ net\.tr |
+ org\.tr |
+ edu\.tr |
+ gov\.tr |
+ mil\.tr |
+ bbs\.tr |
+ k12\.tr |
+ co\.tv |
+ com\.tw |
+ net\.tw |
+ org\.tw |
+ edu\.tw |
+ idv\.tw |
+ gove\.tw |
+ com\.ua |
+ net\.ua |
+ gov\.ua |
+ ac\.ug |
+ co\.ug |
+ or\.ug |
+ go\.ug |
+ co\.uk |
+ net\.uk |
+ org\.uk |
+ ltd\.uk |
+ plc\.uk |
+ sch\.uk |
+ ac\.uk |
+ gov\.uk |
+ nhs\.uk |
+ police\.uk |
+ mod\.uk |
+ com\.uy |
+ edu\.uy |
+ net\.uy |
+ org\.uy |
+ com\.ve |
+ net\.ve |
+ org\.ve |
+ co\.ve |
+ edu\.ve |
+ gov\.ve |
+ mil\.ve |
+ arts\.ve |
+ bib\.ve |
+ firm\.ve |
+ info\.ve |
+ int\.ve |
+ nom\.ve |
+ rec\.ve |
+ store\.ve |
+ tec\.ve |
+ web\.ve |
+ co\.vi |
+ net\.vi |
+ org\.vi |
+ ac\.yu |
+ co\.yu |
+ edu\.yu |
+ org\.yu |
+ ac\.za |
+ alt\.za |
+ bourse\.za |
+ city\.za |
+ co\.za |
+ edu\.za |
+ gov\.za |
+ law\.za |
+ mil\.za |
+ net\.za |
+ ngo\.za |
+ nom\.za |
+ org\.za |
+ school\.za |
+ tm\.za |
+ web\.za |
+ gov\.zw |
+ eu\.org |
+ au\.com |
+ e164\.arpa )
+}ix;
+
+###########################################################################
+
+=item ($hostname, $domain) = split_domain ($fqdn)
+
+Cut a fully-qualified hostname into the hostname part and the domain
+part, splitting at the DNS registrar boundary.
+
+Examples:
+
+ "www.foo.com" => ( "www", "foo.com" )
+ "www.foo.co.uk" => ( "www", "foo.co.uk" )
+
+=cut
+
+sub split_domain {
+ my ($domain) = @_;
+
+ # drop any hostname parts, if we can.
+ my @domparts = split (/\./, $domain);
+ my $numparts = scalar @domparts;
+
+ # turn "host.dom.ain" into "dom.ain".
+ my $chopped = '';
+ if ($numparts > 0) {
+ my $partsreqd;
+
+ if ($domain =~ /${FOUR_LEVEL_DOMAINS}/io) # Fire-Dept.CI.Los-Angeles.CA.US
+ { $partsreqd = 5; }
+ elsif ($domain =~ /${THREE_LEVEL_DOMAINS}/io) # demon.co.uk
+ { $partsreqd = 4; }
+ elsif ($domain =~ /${TWO_LEVEL_DOMAINS}/io) # co.uk
+ { $partsreqd = 3; }
+ else # com
+ { $partsreqd = 2; }
+
+ while ($numparts > $partsreqd) {
+ $domain =~ s/^([^\.]+\.)//;
+ $chopped .= $1;
+ $numparts--;
+ }
+ }
+
+ $chopped =~ s/\.$//;
+ ($chopped, $domain);
+}
+
+=item $domain = trim_domain ($fqdn)
+
+Cut a fully-qualified hostname into the hostname part and the domain
+part, returning just the domain.
+
+Examples:
+
+ "www.foo.com" => "foo.com"
+ "www.foo.co.uk" => "foo.co.uk"
+
+=cut
+
+sub trim_domain {
+ my ($domain) = @_;
+ my ($host, $dom) = split_domain ($domain);
+ return $dom;
+}
+
+1;
Modified: incubator/spamassassin/trunk/t/ip_addrs.t
==============================================================================
--- incubator/spamassassin/trunk/t/ip_addrs.t (original)
+++ incubator/spamassassin/trunk/t/ip_addrs.t Fri Apr 30 19:11:41 2004
@@ -26,7 +26,7 @@
rules_filename => "$prefix/rules",
});
-plan tests => 66;
+plan tests => 67;
sub tryone {
my ($pat, $testip) = @_;
@@ -95,7 +95,7 @@
sub tsttrim {
my $dom = shift;
my $want = shift;
- my $got = Mail::SpamAssassin::Util::trim_domain_to_registrar_boundary ($dom);
+ my $got = Mail::SpamAssassin::Util::RegistrarBoundaries::trim_domain ($dom);
if ($got eq $want) {
return 1;
} else {
@@ -111,5 +111,6 @@
ok (tsttrim ("jmason.org", "jmason.org"));
ok (tsttrim ("localhost.jmason.org", "jmason.org"));
ok (tsttrim ("localhost.jmason.edu.au", "jmason.edu.au"));
+ok (tsttrim ("localhost.jmason.hacked.au", "hacked.au"));
ok (tsttrim ("localhost.jmason.edu.net", "edu.net"));