The MasterLibrary is now current with this version of IPCalc. It also has a adaption of the Alejando Tejada's thumbnail extraction routine.

https://www.dropbox.com/s/3wpwn3hfbmpl7sk/MasterLibrary.livecode?dl=0

-= Mike


On 1/27/15 6:38 PM, Bob Sneidar wrote:
Hi Alex.

Thanks for testing this for me and your input. Here is an updated function that 
accounts for any non-numerical octets and expands the limits of the CIDR to 
0-32. Also, if the IP or the CIDR ends in any number of periods it returns an 
error. I have made the same check for subnet masks.

This reminds me of when I originally started programming. I would proudly show 
off my new creation to a friend of mine who was a school principle, and he 
would set about breaking it. :-) It was a good lesson.

function IPCalc theIPAddress, theSubnetMask
    /* IPCalc yyy
       Syntax:
       IPCalc theIPAddress, [theSubnetMask]
       Examples:
Description:
       Derive Internet values from either CIDR notation in the IPAddress
       or a standard IP and subnet mask
Input:
       .    theIPAddress -  the IP address in CIDR notation
        or
       .    theIPAddress - a standard IP address and
      .     theSubNetMask - a standard subNetMask
Returns an array of the following values:
       .   bcastaddr
       .   cidraddr
       .   cidrdepth
       .   firstaddr
       .   ipaddress
       .   lastaddr
       .   subnetaddr
       .   subnetmask
       .   usablecount
       Returns a string beginning with ERROR: if the parameters are out of range
       Check that the returned value is an array to see if there was an error
Source:
        Bob Sneidar,  [email protected]
    IPCalc */
set the itemdelimiter to "." -- check parameters
    -- the IP address must be 4 octets of numbers
    if the number of items of theIPAddress <>4 \
          or the last char of theIPAddress is "." \
          or ".." is in theIPAddress then
       return "ERROR: The IP Address must be in the form:" & cr & \
             "'nnn.nnn.nnn.nnn' or 'nnn.nnn.nnn.nnn/nn'. (ipaddress = '" & theIPAddress & 
"')"
    end if
-- initial setup
    set the numberFormat to "00000000"
-- detemine format
    if theIPAddress contains "/" then
       put offset("/", theIPAddress) into theCIDRDelim
       put char theCIDRDelim +1 to -1 of theIPAddress into theCIDRDepth
-- CIDR depth must be a WHOLE number
       put cleanString(theCIDRDepth) into theCIDRDepth
if theCIDRDepth is not a number then
          return "ERROR: The CIDR Depth must be a number between 0 and 32. " & \
                "(CIDRDepth = '" & theCIDRDepth & "')"
       end if
put charx("1", theCIDRDepth) & charx("0", 32-theCIDRDepth) into theBinSubnetMask
       put baseconvert(char 1 to 8 of theBinSubnetMask, 2, 10) into item 1 of 
theSubnetMask
       put baseconvert(char 9 to 16 of theBinSubnetMask, 2, 10) into item 2 of 
theSubnetMask
       put baseconvert(char 17 to 24 of theBinSubnetMask, 2, 10) into item 3 of 
theSubnetMask
       put baseconvert(char 25 to 32 of theBinSubnetMask, 2, 10) into item 4 of 
theSubnetMask
       put char 1 to theCIDRDelim -1 of theIPAddress into theIPAddress
    else
       -- subnet mask octets must be 4 numbers between 0 and 255
       -- and all octets after the first octet less than 255 must be 0
if the number of items of theSubnetMask <>4 \
             or the last char of theSubnetMask is "." \
             or ".." is in theSubnetMask then
          return "ERROR: The Subnet Mask must be in the form:" & cr & \
                "'nnn.nnn.nnn.nnn' (subnetmask = '" & theSubnetMask & "')"
       end if
put false into mustBeZero
       repeat for each item theOctet in theSubnetMask
if theOctet <0 or theOctet >255 then
             return "Each octet in the subnet mask must be a number between 0 and 255. 
" & \
                   "(subnetmask = '" & theSubnetMask & "')"
          end if
if mustBeZero and theOctet >0 then
             return "ERROR: All octets after an octet less than 255 must be 0. " 
& \
                   "(subnetmask = '" & theSubnetMask & "')"
          end if
if theOctet <255 then
             put true into mustBeZero
          end if
       end repeat
-- convert the subnet mask to binary
       put 0 into whichOctet
       repeat for each item theOctet in theSubnetMask
          add 1 to whichOctet
-- subnet mask must contain only 4 octets
          if whichOctet >4 then
             return "ERROR: The Subnet Mask must contain 4 numbers between 0 and 255 
" & \
                   "separated by periods. (subnetmask = '" & theSubnetMask & 
"')"
          end if
put value(baseConvert(theOctet, 10, 2)) after theBinSubnetMask
       end repeat
       put offset("0", theBinSubnetMask) -1 into theCIDRDepth
    end if
-- CIDR depth must be between 0 and 32
    if theCIDRDepth <0 or theCIDRDepth >32 then
       return "ERROR: The CIDR Depth must be between 0 and 32. " & \
             "(CIDRDepth = '" & theCIDRDepth & "')"
    end if
-- All octets of the IP address must be between 0 and 255
    repeat for each item theOctet in theIPAddress
       if theOctet is empty or theOctet < 0 or theOctet > 255 then
          return "ERROR: Each IP Address octet must be a number between 0 and 255. 
" & \
                "(ipaddress = '" & theIPAddress & "')"
       end if
    end repeat
-- convert the ip address to binary
    put 0 into whichOctet
    repeat for each item theOctet in theIPAddress
       add 1 to whichOctet
       put baseConvert(theOctet, 10, 2) into theBinValue
       add 0 to theBinValue
       put theBinValue after theBinIPAddress
    end repeat
-- calculate the binary subnet address
    put char 1 to theCIDRDepth of theBinIPAddress into theBinNetworkAddr
    put char theCIDRDepth +1 to -1 of theBinIPAddress into theBinNodeAddr
    put theBinNodeAddr into theBinSubnetNodeAddr
    set the numberFormat to "0"
    replace "1" with "0" in theBinSubnetNodeAddr
    put theBinNetworkAddr & theBinSubnetNodeAddr into theBinSubnetAddr
-- convert the binary subnet address to decimal
    put baseconvert(char 1 to 8 of theBinSubnetAddr, 2, 10)  into item 1 of 
theSubnetAddr
    put baseconvert(char 9 to 16 of theBinSubnetAddr, 2, 10)  into item 2 of 
theSubnetAddr
    put baseconvert(char 17 to 24 of theBinSubnetAddr, 2, 10)  into item 3 of 
theSubnetAddr
    put baseconvert(char 25 to 32 of theBinSubnetAddr, 2, 10)  into item 4 of 
theSubnetAddr
-- calculate the first usable IP address
    put theSubnetAddr into theFirstAddr
    add 1 to item 4 of theFirstAddr
-- calculate the binary broadcast address
    put theBinNodeAddr into theBinBcastNodeAddr
    replace "0" with "1" in theBinBcastNodeAddr
    put theBinNetworkAddr & theBinBcastNodeAddr into theBinBcastAddr
-- convert the binary broadcast address to decimal
    put baseconvert(char 1 to 8 of theBinBcastAddr, 2, 10) into item 1 of 
theBcastAddr
    put baseconvert(char 9 to 16 of theBinBcastAddr, 2, 10) into item 2 of 
theBcastAddr
    put baseconvert(char 17 to 24 of theBinBcastAddr, 2, 10) into item 3 of 
theBcastAddr
    put baseconvert(char 25 to 32 of theBinBcastAddr, 2, 10) into item 4 of 
theBcastAddr
-- calculate the last usable IP address
    put theBcastAddr into theLastAddr
    subtract 1 from item 4 of theLastAddr
-- calculate the number of usable addresses
    -- put item 4 of theLastAddr - item 4 of theFirstAddr +1 into theAddrCount
    put baseconvert(theBinBcastNodeAddr, 2, 10) -1 into theAddrCount
-- calculate the CIDR notation
    put theIPAddress & "/" & theCIDRDepth into theCIDRAddr
-- create array
    put theIPAddress into ipdata ["ipaddress"]
    put theSubnetMask into ipdata ["subnetmask"]
    put theSubnetAddr into ipdata ["subnetaddr"]
    put theFirstAddr into ipdata ["firstaddr"]
    put theBcastAddr into ipdata["bcastaddr"]
    put theLastAddr into ipdata ["lastaddr"]
    put theCIDRDepth into ipdata ["cidrdepth"]
    put theAddrCount into ipdata ["usablecount"]
    put theCIDRAddr into ipdata ["cidraddr"]
    return ipdata
end IPCalc

Bob S


On Jan 26, 2015, at 16:22 , Bob Sneidar <[email protected]> wrote:

On Jan 26, 2015, at 12:14 , Alex Tweedly <[email protected]> wrote:

A couple of error cases that aren't caught gracefully

192.168.1/24.1
192.168..1/24

One that is accepted and shouldn't be
192.168.1.1/24.    (note the trailing ".")

Also, not sure why you limit CIDRDepth to between 1 and 30. RFC 4632 
specifically says between 0 and 3 - and indeed host routes (/32s) are common 
enough, as is default route.

Thanks again for contributing this Bob.

-- Alex.

_______________________________________________
use-livecode mailing list
[email protected]
Please visit this url to subscribe, unsubscribe and manage your subscription 
preferences:
http://lists.runrev.com/mailman/listinfo/use-livecode



_______________________________________________
use-livecode mailing list
[email protected]
Please visit this url to subscribe, unsubscribe and manage your subscription 
preferences:
http://lists.runrev.com/mailman/listinfo/use-livecode

Reply via email to