use Net::IDN::Encode; use constant REGEXP_HOSTNAME => qr!^[\w\-.]+$!; use constant REGEXP_IPADDR   => qr!^((?:(?:25[0-5]|2[0-4]\d|[0-1]??\d{1,2})[.](?:25[0-5]|2[0-4]\d|[0-1]??\d{1,2})[.](?:25[0-5]|2[0-4]\d|[0-1]??\d{1,2})[.](?:25[0-5]|2[0-4]\d|[0-1]??\d{1,2})))$!; sub host_toidn {   return domain_to_ascii(shift); } sub host_fromidn {   return domain_to_unicode(shift); } sub valid_hostname {   my $value = host_toidn(shift);   return 0 unless $value =~ REGEXP_HOSTNAME;   return 0 unless index($value, ".") > 0;   my @parts = split /\./, $value;   my $valid = scalar @parts;   foreach my $label (@parts)   {      $valid = 0 if (length $label > 63) or ($label =~ qr!^\-!) or ($label =~ qr!\-$!);      last unless $valid;   }   $valid = 0 if $parts[-1] =~ qr!^\d.*!;   return $valid; } sub valid_ipaddr {   my $value = shift;   return $value =~ REGEXP_IPADDR; } sub valid_host {   my $value = shift;   return valid_hostname($value) || valid_ipaddr($value); }