| [reply] [d/l] |
If I am being oblique then tadman is being pedantic. Yes an IP address is 32 bit unsigned int and yes thanks to the use of old BSD (inet_addr(3)) libraries you can pass a decimal equivilent for translation to uint32.
I of course presumed our friend wished to verify a dotted quad.
Note tadman's approach breaks in IPV6.(well maybe break is the wrong word, 'is impudent' is probably better).
mitd-Made in the Dark
'My favourite colour appears to be grey.'
| [reply] |
To preface this: in case this is mistaken for a personal
attack of some sort, I'm not trying to do anything of the
sort. All I want to do is promote a sensible, concise,
and correct way of doing something, though this is not to
say that I'm not open to new ideas.
There are a few things that set my hair on fire, not unlike
the way that people rolling their own "CGI" routines does
to others, and IP address and e-mail address parsing using
oversimplified and/or overcomplicated regexes is one of
them. It is often because the programmer is applying a
superficial understanding of some concept, which only
creates problems for users later.
An example is someone who writes a routine to verify
postal codes, the sort of thing you see on Web sites
all the time. For some reason, it is assumed
that no sensible postal code would have letters in it:
if ($zip !~ /^\d+(\-\d{4})?$/)
{
$error{zip} = "Invalid postal code.";
}
So I pound in something like 'M6K3J8' and I'm chastised,
even though I can choose both country and province from
a drop-down which lists them explicitly.
To bring this back to the task at hand, inet_aton is
tough to match in terms of both accuracy and ease-of-use.
Stuff goes in, and if it passes the mustard, a packed
number comes out. No messy stuff, and no magic.
Further, if inet_aton can't figure out what to do with the address,
it is virtually guaranteed that no other program will be
able to either
since the vast majority of Internet software uses that
very function, or a functionally similar equivalent. On
the other hand, even if something passes through a
user constructed regex, there is still opportunity
for that to fail later on when the inet_aton has a crack
at it, which it most surely will if the address is ever
used for a connection.
That being said, if, for whatever reason, you absolutely had to use a regex,
then I would submit that an improved version would be:
sub valid_ip
{
my $bit = '[01]?\d\d?|2[0-4]\d|25[0-5]';
return $_[0] =~ /^($bit)(\.($bit)){3}/;
}
However, it still suffers from the same problems as the
original.
Another method, though this is really not
an improvement on the regex method in terms of being
easier to understand, goes about it quite literally:
sub valid_ip
{
my $bits = 0;
foreach (split (/\./, $_[0]))
{
return unless /^\d+$/ && $_ >= 0 && $_ < 256;
$bits++;
}
return $bits == 4;
}
I'm not sure what your remark about IPv6 compatibility
implies. Obviously the standard inet_aton function will
not handle IPv6 addresses. Not that the regex proposed
could handle them either.
The IPv6 Address Specification
is even more "open to
interpretation" than IPv4, such that writing a regex
for that would be considerably more difficult, and
consequently, more likely to fall short of the mark.
It would, however, be easy to upgrade the inet_aton
approach to IPv6. When Perl adds native support for the
IPv6 equivalent method for inet_aton, or now by using a
simple module written by Tony Monroe available on CPAN:
use Net::IPv6Addr;
sub valid_ipv6
{
return Net::IPv6Addr::ipv6_parse($_[0]);
}
| [reply] [d/l] [select] |
Now this is much more informative and convincing.
My pedantic remark was aimed at decimal example which was a tiny bit obscure.
IPV6 issues were a plain old fashion tongue in cheek tease.
The last arguments are compelling and informative, much more so than the original. In the end the fault is mine for succumbing to the male hormonal urge to show off a big regex. At my age these urges come so infrequently I forget how to control them.
tadman I respect and encourage your vigilance. I learned some stuff here and hopefully so did some other folks.
yours truly,
Peter G. Marshall -- mitd
| [reply] |