#!/usr/bin/perl -w ######################################################################### # # A perl CGI program to display a number in various base formats. # # v1.0, Sep 14 2002 # v1.1, Sep 16 2002 added CIDR subnet stuff # v1.2, Sep 21 2002 partial IP addresses like 10. expand to 10.0.0.0 # v1.3, Sep 21 2002 in CIDR, added Broadcast, removed 0 and 255 from hosts # v1.4, sep 27 2002 added 255.255.xx style display for Mask. # v1.5, oct 12 put 0 and 255 back in. # # Copyright (c) 2002 Jim Mahoney (mahoney@marlboro.edu), Marlboro College. # All rights reserved. This program is free software; you can # redistribute and/or modify it under the same terms as perl itself. # ########################################################################## use strict; use CGI qw(:standard); my $number = param("number"); # inputs from cgi form or URL my $explain = param("explain"); print header, start_html(-title => 'Base Conversion and Subnet Tool'), start_form, "
\n" . " Base 10: " . " " . underBars(sprintf("%u",$input),3) ."\n" . " Octal: " . "0___" . sprintf( "%o",$input) ."\n" . " Hex: " . "0x__" . underBars(sprintf("%x",$input),2) ."\n" . " IP: " . " " . asIP($input) ."\n" . " Binary: " . "0b__" . underBars( asBinary($input), 8) ."\n" . $maskHtml . "\n"; } } # ---------------------------------------------------------- # Input: $maskOnes = number of subnet mask ones, i.e. 22 # $input = IP address # Output: html formatted description of CIDR subnet and addresses. sub getMaskHtml { my ($maskOnes, $input) = @_; return "" unless $maskOnes; $maskOnes = int($maskOnes + 0.49); if ($maskOnes>32) { return "\nOops: Subnet mask '\\$maskOnes' is larger than 32. \n"; } my $numAddr = 2**(32-$maskOnes); my $mask = 2**32 - $numAddr; my $network = $mask & $input; # bitwise "and" return "\n" . " Mask: " . " " . asIP($mask) . "\n" . " = " . "0b__" . underBars( asBinary($mask), 8) . "\n" . " Subnet: " . " " . asIP($network) . "\n" . " = " . "0b__" . underBars( asBinary($network), 8) . "\n\n" . " The number of addresses is 2**(32-$maskOnes) = ".$numAddr . "\n" . " which go from " . asIP($network) . " up to " . asIP($network+$numAddr-1) . " .\n" . " (The lowest is the network address, \n" . " and the highest is the broadcast address.)\n"; } # ---------------------------------------------------------- # Convert a number like 201778690 # to a string like 1100000001101110011000000010 sub asBinary { my ($number) = @_; my $result = ""; my $count = 32; while ($number or ($count>0)) { my $nextBit = $number % 2; $number = ($number - $nextBit) / 2; $result = ($nextBit or "0") . $result; $count--; } return $result; } # --------------------------------------------------------- # Convert a number like 201778690 to a string like 12.6.230.2 sub asIP { my ($number) = @_; my $result = ""; my $count = 4; while ($number or ($count>0)) { my $nextByte = $number % 2**8; $number = ($number - $nextByte) / 2**8; $result = ($nextByte or "0") . '.' . $result; $count--; } $result =~ s/.$//; # Remove trailing ".", since the while loop # constructs the result as "xxx.xxx.xxx.xxx.". return $result; } # --------------------------------------------------------- # Convert a string like 12345678 to a string like 12_345_678 for readability. # The number of digits to group together is passed as the parameter $n. sub underBars { my ($string, $n) = @_; return $string unless $n; my @digits = split //, $string; my @underbars; while (@digits) { unshift( @underbars, pop(@digits)) for 1..$n; unshift( @underbars, "_") if @digits; } return join("", @underbars); } # --------------------------------------------------------- # Return as html an explanation of what this script does. sub explanation_html { return qq{ Enter a number in any of the following formats, then hit return to see that number displayed in all the others.
Base 10 201_778_690 Octal (Base 8) 0__1401563002 (leading zero) Hex (Base 16) 0x_0C_06_E6_02 (leading 0x) IP 12.6.230.2 (periods) Binary (Base 2) 0b_00001100_00000110_11100110_00000010 (leading 0b)The underbar character ("_") in all of these is entirely optional and included for legibility only.
To see a CIDR subnet mask applied to your number, append a slash and a number between 1 and 32, i.e. 12.6.230.2/22 .
Numbers in IP format (i.e. 12.6.230.2) must begin with a digit
and contain either one, two, or three periods.
Partial IP addresses like 10. or 10.2 will be expanded by appending zeros
and periods at the right end as needed.
The number may be passed in the scipt URL as ?number= , i.e. baseConvert.cgi?number=10.2.1/22 .
So there you are. }; } # --------------------------------------------------------- sub footer_html { return qq{