Jump to content

Looking for a relatively simple method to create regex patterns to detect a number range


 Share

Go to solution Solved by Morthawt,

Recommended Posts

Example. Here is how the basic function would work

RegexRange(0, 9)

Return: ([0-9])

RegexRange(0, 99)

Return: ([0-9]|[1-9][0-9])

RegexRange(107, 217)

Return: (10[7-9]|1[1-9][0-9]|20[0-9]|21[0-7])

I can then take all the returns and built it up for my IP purposes. I really cannot describe or demonstrate it any simpler than that. I hope that clarifies everything.

Edited by Morthawt
Link to comment
Share on other sites

  • Replies 41
  • Created
  • Last Reply

Top Posters In This Topic

Top Posters In This Topic

Re-read my post.  

 I want to generate a regular expression which encapsulates a number range.

 

This is what I'm asking.  To generate the SRE you need to feed it a pattern of sorts, for example, 192.168.0.0/16 (from your first post) means generate the following SRE - '192.168.0.[01]6$'.  Is this not correct?  You seem to be using the '/' as range.

Forum Rules         Procedure for posting code

"I like pigs.  Dogs look up to us.  Cats look down on us.  Pigs treat us as equals."

- Sir Winston Churchill

Link to comment
Share on other sites

I have no idea what that means. Ignore the fact that I am dealing with IP addresses, just as I showed in my last example. I am trying to take a two numbers which can be between 1 and 3 digits and make a regular expression which will find any number in that range, in it's rawest form. The fact I am using small numbers first will not hinder my eventual usage of the patterns because there will be 4 different patterns combined with a definite starting point and ending point so that a whole pattern will emerge to ensure that a complete match is achieved.

Link to comment
Share on other sites

Because I am generating regular expression ban entries for TeamSpeak and they need to be in regular expression. Someone comes into my server, disrupts my members ( I have a large community server so I need to protect my people) and some people know how the ban system works and they keep coming back with new IP addresses by using VPN's. Well when this happens I have to check their IP, research the company it belongs to, research all the IP ranges they have purchased, make a list of all the CIDR networks, convert to IP ranges, look at the ranges and combine duplicate/consecutive ranges to provide a larger range that absorbs multiple "networks" they have, then once I have condensed everything down to pure ranges they have I need to take forever to create regex patterns for each block, which by it's self takes me a while to go through 1 IP range. Then consider that I may have 30 ranges to go through, it takes me forever. So I want to cut the time down by making a program to do the bulk of the hard and time consuming part by creating the actual regex patterns. Once I get that done, I may be able to investigate the possibility of writing a separate program or combining one into this where it could do the consecutive ranges into one larger range. But my goal is to just first make something which can take a list of CIDR networks (or raw IP ranges depending on how I use the function) and automatically create the regex patterns. That would be one massive time saver.

So far the new script I am working on can generate the basic regex blocks for numbers between 1 and 2 digits. I am about to try and implement 3 digits, which is proving more difficult. But that is why I came here to see if someone had an elegant idea/process/technique/principle that I could use to more easily produce the basic regex pattern blocks for the individual octet ranges. But so far no such luck, so I am having to continue with my second attempt which is proving to be much better than my first but I bet there is a far quicker, nicer method that is possible.

Edited by Morthawt
Link to comment
Share on other sites

RegEx and IP addresses are usually a bad match. Creating one that works with valid IP addresses isn't hard, it's creating one that works with invalid IP addresses that it becomes a problem. You'd be better off just using a stringsplit and comparing the octets with whatever it is you're looking to do with them.

If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Link to comment
Share on other sites

RegEx and IP addresses are usually a bad match. Creating one that works with valid IP addresses isn't hard, it's creating one that works with invalid IP addresses that it becomes a problem. You'd be better off just using a stringsplit and comparing the octets with whatever it is you're looking to do with them.

As I have said, I need to generate a whole regular expression that encompasses an entire IP range for use in a VOIP system which requires a regular espression pattern. I cannot just to some checking in AutoIt for something. It has to be a whole regular expression pattern which gets put into the VOIP program. I have been manually making IP regex ban entries for months, but I have to do it by hand. So I decided that I would really give it my best shot at making one, breaking down what I am thinking when I start, what am I looking for, how do I proceed from there. So I know the process works, I am just trying to automate the process. So far I have it working with numbers between 1 and 2 digits, and so far I have also (I think) 3 digits working as long as the first digit is the same for both numbers. I am now working on making it work if the first digits are different between the two numbers (octets).

If I pull this off and it is as good as I expect it to be, I may share it on here for anyone who cares to be able to do such things. I have looked all over the internet and the best I can do is find somewhere that turns CIDR networks into IP ranges, then find a different place which can turn 1 IP range into a (properly formatted and gigantic) regular expression pattern. My manual method produces much smaller patterns and when I am done with this program, if I succeed, it will produce patterns which are almost as small as my manual ones. Plus I might even be able to shrink and optimize the resulting patterns.

Link to comment
Share on other sites

Morthawt,

Thank You for the explanation.  I know that this Web site blocks IP's.  Have you asked M23 or Jon for advice/technique on this?

Not specifically, typically moderators on forums prefer to give support via forums, because then it helps anyone else who may have the same question. So I made a thread about it. But I was surprised I managed to "lose" people with my explanation. I am close to completing this phase, but it is tricky at this point.

Link to comment
Share on other sites

This may not be practical depending on the number of players you have, but have you considered doing a whitelist of approved users rather than fighting to keep a working blacklist of unwanted users?  Of course that would take a lot of work too and if people join and quit a lot, and folks with dynamic IPs on their ISP modems.....  Just thinking out loud I guess...

Ian

My projects:

  • IP Scanner - Multi-threaded ping tool to scan your available networks for used and available IP addresses, shows ping times, resolves IPs in to host names, and allows individual IPs to be pinged.
  • INFSniff - Great technicians tool - a tool which scans DriverPacks archives for INF files and parses out the HWIDs to a database file, and rapidly scans the local machine's HWIDs, searches the database for matches, and installs them.
  • PPK3 (Persistent Process Killer V3) - Another for the techs - suppress running processes that you need to keep away, helpful when fighting spyware/viruses.
  • Sync Tool - Folder sync tool with lots of real time information and several checking methods.
  • USMT Front End - Front End for Microsoft's User State Migration Tool, including all files needed for USMT 3.01 and 4.01, 32 bit and 64 bit versions.
  • Audit Tool - Computer audit tool to gather vital hardware, Windows, and Office information for IT managers and field techs. Capabilities include creating a customized site agent.
  • CSV Viewer - Displays CSV files with automatic column sizing and font selection. Lines can also be copied to the clipboard for data extraction.
  • MyDirStat - Lists number and size of files on a drive or specified path, allows for deletion within the app.
  • 2048 Game - My version of 2048, fun tile game.
  • Juice Lab - Ecigarette liquid making calculator.
  • Data Protector - Secure notes to save sensitive information.
  • VHD Footer - Add a footer to a forensic hard drive image to allow it to be mounted or used as a virtual machine hard drive.
  • Find in File - Searches files containing a specified phrase.
Link to comment
Share on other sites

This may not be practical depending on the number of players you have, but have you considered doing a whitelist of approved users rather than fighting to keep a working blacklist of unwanted users?  Of course that would take a lot of work too and if people join and quit a lot, and folks with dynamic IPs on their ISP modems.....  Just thinking out loud I guess...

Ian

 

I only ban VPN and VPS companies that trolls use to keep getting new IP addresses that don't tie to their ISP. Banning typical ISP blocks is just going to end up banning your user-base lol. If anyone is interested, here is my source code with two example uses of the function at the top. I welcome feedback.

$range = CIDRtoRegex('23.27.0.0/20', 1) ; This fetches an array containing two elements. One with the start of the network, the other the end of the network.
ConsoleWrite($range[0] & ' - ' & $range[1] & @CRLF) ; Displays the range in the console

ConsoleWrite(CIDRtoRegex('23.27.0.0/20') & @CRLF) ; This displays the Regular Expression ban entry that is compatible with TeamSpeak 3 server/client.

Func CIDRtoRegex($_CIDRNet, $rangeonly = False)
    $slashPos = StringInStr($_CIDRNet, '/')
    $networkNumber = StringMid($_CIDRNet, $slashPos + 1, StringLen($_CIDRNet) - $slashPos)
    $networkRemainder = 32 - $networkNumber
    Local $LastIP[4]
    $FirstIP = StringSplit($_CIDRNet, '.', 3)
    $FirstIP[3] = StringReplace($FirstIP[3], '/' & $networkNumber, '')

    $binpos = 128
    $bintotal = 0
    $currentOctet = 0
    $deductamount = 0
    For $a = 1 To 32
        If $a > $networkNumber Then
            $deductamount += $binpos
        EndIf

        $binpos /= 2
        If IsInt($a / 8) Then
            $LastIP[$currentOctet] = $FirstIP[$currentOctet] + $deductamount
            If $LastIP[$currentOctet] > 255 Then
                Return SetError(1, 0, 0)
            EndIf
            $deductamount = 0
            $binpos = 128
            $currentOctet += 1
        EndIf
    Next

    If $rangeonly Then
        Local $range[2]
        For $go = 0 To 3
            $range[0] &= $FirstIP[$go] & (($go = 3) ? ('') : ('.'))
            $range[1] &= $LastIP[$go] & (($go = 3) ? ('') : ('.'))
        Next
        Return $range
    EndIf


    $finalregex = '^'
    For $go = 0 To 3
        If $FirstIP[$go] <> $LastIP[$go] Then
            $finalregex &= IPRegex($FirstIP[$go], $LastIP[$go])
        Else
            $finalregex &= $FirstIP[$go]
        EndIf
        $finalregex &= (($go = 3) ? ('$') : ('\.'))
    Next
    Return $finalregex
EndFunc   ;==>CIDRtoRegex

Func IPRegex($start, $ender)
    If $start = 0 And $ender = 255 Then Return '[0-9]+'

    Local $realender = $ender, $realstart = $start

    Local $regex, $previousprocessing = 0
    Local $currentnumreached = 0, $was1digit = 0, $was2digits = 0
    If StringLen($start) = 1 Then
        $regex &= '(' ; Now 1 digit
        $regex &= '[' & $start & ((StringLen($ender) = 1) ? ('-' & $ender & ']') : ('-9]'))
        If StringLen($ender) = 1 Then
            $regex &= ')'
            Return RegexCleanup($regex)
        EndIf
        $previousprocessing = 1
        $was1digit = 1
        If StringLen($start) = 1 Then $start = 10

    EndIf

    If StringLen($start) = 2 Or $previousprocessing = 1 Then
        $regex &= (($previousprocessing = 1) ? ('|') : ('(')) ; Now 2 digits
        If $was1digit Then $previousprocessing = 0

        If StringLen($ender) > 2 And $previousprocessing = 1 Or $ender >= 99 And StringMid($start, 2, 1) = 0 Then
            $regex &= '[' & (($previousprocessing = 1) ? (1) : (StringMid($start, 1, 1))) & '-9][0-9]'
        Else
            If StringLen($ender) = 2 And StringMid($ender, 1, 1) > StringMid($start, 1, 1) And $previousprocessing = 0 Then

                $regex &= StringMid($start, 1, 1) & '[' & StringMid($start, 2, 1) & '-9]|'
                If StringMid($ender, 1, 1) - StringMid($start, 1, 1) > 1 Then
                    $regex &= '[' & StringMid($start, 1, 1) + 1 & '-' & StringMid($ender, 1, 1) - 1 & ']' & '[0-9]|' & StringMid($ender, 1, 1) & '[0-' & StringMid($ender, 2, 1) & ']'
                Else
                    $regex &= '[' & StringMid($start, 1, 1) + 1 & '-' & StringMid($ender, 1, 1) & ']' & '[0-' & StringMid($ender, 2, 1) & ']'
                EndIf

            ElseIf StringLen($ender) > 2 Then

                $regex &= StringMid($start, 1, 1) & '[' & StringMid($start, 2, 1) & '-9]|'
                $regex &= '[' & StringMid($start, 1, 1) + 1 & '-' & 9 & ']' & '[0-9]'

            Else
                $regex &= StringMid($start, 1, 1) & '[' & StringMid($start, 2, 1) & '-' & StringMid($ender, 2, 1) & ']'
            EndIf


        EndIf


        If StringLen($ender) = 2 Then
            $regex &= ')'
            Return RegexCleanup($regex)
        EndIf
        $previousprocessing = 1
        $was2digits = 1
    EndIf

    If StringLen($start) = 3 Or $previousprocessing = 1 Then
        $regex &= (($previousprocessing = 1) ? ('|') : ('(')) ; Now 3 digits
        If $previousprocessing Then $start = 100 ; If we are building up from a smaller than 3 digit number but going up to 3 digits, we start at the 1st 3 digit number

        If StringMid($start, 1, 1) = StringMid($ender, 1, 1) Then ; If the 1st digits are the same
            $regex &= StringMid($start, 1, 1) & '('

            If StringMid($start, 2, 1) = StringMid($ender, 2, 1) Then ; If the second digits are the same

                $regex &= StringMid($start, 2, 1) & '[' & StringMid($start, 3, 1) & '-' & StringMid($ender, 3, 1) & '])'

            Else ; If the second digits are not the same
                If StringMid($start, 3, 1) = 0 Then ; If the starter third digit is a 0
                    $regex &= '[' & StringMid($start, 2, 1) & '-' & (StringMid($ender, 2, 1) - 1) & '][0-9]|'
                    $regex &= '' & StringMid($ender, 2, 1) & '[0-' & StringMid($ender, 3, 1) & '])'


                Else ; The third starter digit is not 0
                    $regex &= StringMid($start, 2, 1) & '[' & StringMid($start, 3, 1) & '-9]'
                    If StringMid($ender, 2, 1) - StringMid($start, 2, 1) > 1 Then ; There is a second digit gap of more than 1 digit
                        $regex &= '|[' & StringMid($start, 2, 1) + 1 & '-' & StringMid($ender, 2, 1) - 1 & ']' & '[0-9]'
                        $regex &= '|' & StringMid($ender, 2, 1) & '[0-' & StringMid($ender, 3, 1) & '])'
                    Else
                        $regex &= '|[' & StringMid($start, 2, 1) + 1 & '-' & StringMid($ender, 2, 1) & ']' & '[0-' & StringMid($ender, 3, 1) & '])'
                    EndIf

                EndIf

            EndIf


            $regex &= ')'
        Else ; The first digits are not the same

            If StringMid($start, 2, 1) = 0 And StringMid($start, 3, 1) = 0 Then ; If 100 start just run through all up to 199 ready for starting at 200
                $regex &= StringMid($start, 1, 1) & '[0-9]' & '[0-9]|'

            Else

                Local $realender = $ender, $realstart = $start
                $ender = 199
                $regex &= StringMid($start, 1, 1) & '('

                If StringMid($start, 2, 1) = StringMid($ender, 2, 1) Then ; If the second digits are the same

                    $regex &= StringMid($start, 2, 1) & '[' & StringMid($start, 3, 1) & '-' & StringMid($ender, 3, 1) & '])'

                Else ; If the second digits are not the same
                    If StringMid($start, 3, 1) = 0 Then ; If the starter third digit is a 0
                        $regex &= '[' & StringMid($start, 2, 1) & '-' & (StringMid($ender, 2, 1) - 1) & '][0-9]|'
                        $regex &= '' & StringMid($ender, 2, 1) & '[0-' & StringMid($ender, 3, 1) & '])'

                    Else ; The third starter digit is not 0
                        $regex &= StringMid($start, 2, 1) & '[' & StringMid($start, 3, 1) & '-9]'
                        If StringMid($ender, 2, 1) - StringMid($start, 2, 1) > 1 Then ; There is a second digit gap of more than 1 digit
                            $regex &= '|[' & StringMid($start, 2, 1) + 1 & '-' & StringMid($ender, 2, 1) - 1 & ']' & '[0-9]'
                            $regex &= '|' & StringMid($ender, 2, 1) & '[0-' & StringMid($ender, 3, 1) & '])|'
                        Else
                            $regex &= '|[' & StringMid($start, 2, 1) + 1 & '-' & StringMid($ender, 2, 1) & ']' & '[0-' & StringMid($ender, 3, 1) & '])|'
                        EndIf

                    EndIf

                EndIf

            EndIf
            $ender = $realender
            $start = 200
            $regex &= '|' & StringMid($ender, 1, 1) & '('

            If StringMid($start, 2, 1) = StringMid($ender, 2, 1) Then ; If the second digits are the same

                $regex &= StringMid($start, 2, 1) & '[' & StringMid($start, 3, 1) & '-' & StringMid($ender, 3, 1) & '])'

            Else ; If the second digits are not the same
                If StringMid($start, 3, 1) = 0 Then ; If the starter third digit is a 0
                    $regex &= '[' & StringMid($start, 2, 1) & '-' & (StringMid($ender, 2, 1) - 1) & '][0-9]|'
                    $regex &= '' & StringMid($ender, 2, 1) & '[0-' & StringMid($ender, 3, 1) & '])'

                Else ; The third starter digit is not 0
                    $regex &= StringMid($start, 2, 1) & '[' & StringMid($start, 3, 1) & '-9]'
                    If StringMid($ender, 2, 1) - StringMid($start, 2, 1) > 1 Then ; There is a second digit gap of more than 1 digit
                        $regex &= '|[' & StringMid($start, 2, 1) + 1 & '-' & StringMid($ender, 2, 1) - 1 & ']' & '[0-9]'
                        $regex &= '|' & StringMid($ender, 2, 1) & '[0-' & StringMid($ender, 3, 1) & '])'
                    Else
                        $regex &= '|[' & StringMid($start, 2, 1) + 1 & '-' & StringMid($ender, 2, 1) & ']' & '[0-' & StringMid($ender, 3, 1) & '])'
                    EndIf

                EndIf

            EndIf

            $regex &= ')'

        EndIf

        Return RegexCleanup($regex)

    EndIf

EndFunc   ;==>IPRegex


Func RegexCleanup($_input, $no = 0)
    If $no Then Return $_input

    For $a = 0 To 9
        $_input = StringReplace($_input, '[' & $a & '-' & $a & ']', $a)
        If $a < 9 Then
            $_input = StringReplace($_input, '[' & $a & '-' & $a + 1 & ']', '[' & $a & $a + 1 & ']')
        EndIf
    Next

    Return $_input
EndFunc   ;==>RegexCleanup

; Possible bracket cleanup by searching for  last ( and first ) and see if there is a pipe in there, if not remove those brackets
Link to comment
Share on other sites

Your desire to use an all-encompassing regex is a noble idea, but I'd say impractical. You are wanting to check a range of IP addresses, what's wrong with checking them in an If/Then statement from a stringsplit of the IP address you have already? You need to check one or more of the octets of the IP address against a range of banned octets, it's far easier to do it one octet at a time.

If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Link to comment
Share on other sites

Your desire to use an all-encompassing regex is a noble idea, but I'd say impractical. You are wanting to check a range of IP addresses, what's wrong with checking them in an If/Then statement from a stringsplit of the IP address you have already? You need to check one or more of the octets of the IP address against a range of banned octets, it's far easier to do it one octet at a time.

Again, this is for a VOIP system. I am not doing any checks on IP's myself. The VOIP system has a ban feature. You can ban various things including IP addresses via regex. So in order for me to ban an entire VPS company's IP blocks I need to add regex rules to the VOIP ban system. I am not using AutoIt to check anything to do with the bans. It is simply to create the ban rules that another software needs in order for bans to take effect.

Link to comment
Share on other sites

  • Solution

Here is my code so far: (code may be messy, tons of ways someone else could do it better/cleaner/faster, but it works. (updated to deal with the text files correctly)

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Outfile=CIDR network to REGEX ban entry for TS.exe
#AutoIt3Wrapper_Compression=4
#AutoIt3Wrapper_UseUpx=y
#AutoIt3Wrapper_Run_Au3Stripper=y
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
#include <String.au3>
#include <Array.au3>

#cs

    First paste CIDR networks in the "CIDRList.txt" text file and process them, then manually combine (if needed/desired) the IP ranges in the "IPRangesList.txt" file
    Then process the IP ranges.

    Alternatively you can create just a list of IP ranges in the "IPRangesList.txt" file and process them directly.

#ce

Global $RangesList = @ScriptDir & '\IPRangesList.txt', $REGEXList = @ScriptDir & '\REGEXList.txt'
If Not FileExists(@ScriptDir & '\CIDRList.txt') Then FileWrite(@ScriptDir & '\CIDRList.txt', '')
If Not FileExists($RangesList) Then FileWrite($RangesList, '')

$user = MsgBox(4, 'Morthawt''s IP Block Regexizer', 'Process ranges? (Press no to process raw CIDR)')
If $user = 7 Then
    If FileRead(@ScriptDir & '\CIDRList.txt') = '' Then
        MsgBox(0, 'Error', 'You need to add some CIDR networks in the file, one per line.')
        Exit
    EndIf
    CIDRListToRanges()
    MsgBox(0, 'Morthawt''s IP Block Regexizer', 'Operation has bee completed... Please modify the range file (if needed) and process the ranges by running this program again.')
    Exit
EndIf

If FileRead($RangesList) = '' Then
    MsgBox(0, 'Error', 'You need to add some IP ranges eg 192.168.0.1 - 192.168.0.128 in the file, one per line.')
    Exit
EndIf

If FileExists($RangesList) Then
    $RangeArray = FileReadToArray($RangesList)
Else
    MsgBox(0, 'Error', 'Ranges file (IPRangesList.txt) does not exist. Process CIDR rules first or add ranges to the range file.')
    Exit
EndIf
If FileExists($REGEXList) Then FileDelete($REGEXList)

For $a In $RangeArray
    $split = StringSplit($a, ' - ', 3)
    FileWriteLine($REGEXList, CIDRtoRegex($split[0], $split[1]))
Next
MsgBox(0, 'Morthawt''s IP Block Regexizer', 'Operation has bee completed... Please check the regex file for your completed list of IP block rules.')

Func CIDRListToRanges()

    $CIDRlist = FileReadToArray(@ScriptDir & '\CIDRList.txt')

    _ArraySort($CIDRlist)

    Local $bestnetwork, $networkip, $trashlist[0]

    For $a = 0 To UBound($CIDRlist) - 1
        $netip = StringMid($CIDRlist[$a], 1, StringInStr($CIDRlist[$a], '/') - 1)
        $net = StringMid($CIDRlist[$a], StringInStr($CIDRlist[$a], '/') + 1, StringInStr($CIDRlist[$a], '/'))
        If $netip = $networkip Then
            ReDim $trashlist[UBound($trashlist) + 1]
            $trashlist[UBound($trashlist) - 1] = $a
        EndIf
        $networkip = $netip
    Next

    If UBound($trashlist) Then
        Local $trashing
        For $a = 0 To UBound($trashlist) - 1
            $trashing &= $trashlist[$a] & (($a = (UBound($trashlist) - 1)) ? ('') : (';'))
        Next
        _ArrayDelete($CIDRlist, $trashing)
    EndIf


    Local $ranges[UBound($CIDRlist)]
    $count = 0
    For $a In $CIDRlist
        $temp = CIDRtoRegex($a, 1)
        $ranges[$count] = $temp[0] & ' - ' & $temp[1]
        $count += 1
    Next

    _ArraySort($ranges)
    Local $allranges
    Local $FullStartRange[UBound($CIDRlist)][4], $FullEndRange[UBound($CIDRlist)][4]
    For $a = 0 To UBound($ranges) - 1
        ConsoleWrite($ranges[$a] & @CRLF)
        $allranges &= $ranges[$a] & (($a = UBound($ranges) - 1) ? ('') : (@CRLF))
        $currentFull = StringSplit($ranges[$a], ' - ', 3)
        $currentStart = StringSplit($currentFull[0], '.', 3)
        $currentEnd = StringSplit($currentFull[1], '.', 3)

        For $z = 0 To 3
            $FullStartRange[$a][$z] = $currentStart[$z]
            $FullEndRange[$a][$z] = $currentEnd[$z]
        Next
    Next

    Local $FinalList[0]

    FileDelete($RangesList)
    FileWrite($RangesList, $allranges)

EndFunc   ;==>CIDRListToRanges

Func CIDRtoRegex($_CIDRNet, $rangeonly = False)
    $slashPos = StringInStr($_CIDRNet, '/')
    Local $LastIP[4]

    $networkNumber = StringMid($_CIDRNet, $slashPos + 1, StringLen($_CIDRNet) - $slashPos)
    $networkRemainder = 32 - $networkNumber
    $FirstIP = StringSplit($_CIDRNet, '.', 3)
    If $slashPos Then
        $FirstIP[3] = StringReplace($FirstIP[3], '/' & $networkNumber, '')

        $binpos = 128
        $bintotal = 0
        $currentOctet = 0
        $deductamount = 0
        For $a = 1 To 32
            If $a > $networkNumber Then
                $deductamount += $binpos
            EndIf

            $binpos /= 2
            If IsInt($a / 8) Then
                $LastIP[$currentOctet] = $FirstIP[$currentOctet] + $deductamount
                If $LastIP[$currentOctet] > 255 Then
                    Return SetError(1, 0, 0)
                EndIf
                $deductamount = 0
                $binpos = 128
                $currentOctet += 1
            EndIf
        Next
    Else ; If the first param is not a CIDR network, then the first and second params will be a start and end IP address.
        $LastIP = StringSplit($rangeonly, '.', 3)
    EndIf

    If $rangeonly And $slashPos > 0 Then
        Local $range[2]
        For $go = 0 To 3
            $range[0] &= $FirstIP[$go] & (($go = 3) ? ('') : ('.'))
            $range[1] &= $LastIP[$go] & (($go = 3) ? ('') : ('.'))
        Next

        Return $range
    EndIf

    $finalregex = '^'
    For $go = 0 To 3
        If $FirstIP[$go] <> $LastIP[$go] Then
            $finalregex &= IPRegex($FirstIP[$go], $LastIP[$go])
        Else
            $finalregex &= $FirstIP[$go]
        EndIf
        $finalregex &= (($go = 3) ? ('$') : ('\.'))
    Next
    Return $finalregex
EndFunc   ;==>CIDRtoRegex

Func IPRegex($start, $ender)
    If $start = 0 And $ender = 255 Then Return '[0-9]+'

    Local $realender = $ender, $realstart = $start

    Local $regex, $previousprocessing = 0
    Local $currentnumreached = 0, $was1digit = 0, $was2digits = 0
    If StringLen($start) = 1 Then
        $regex &= '(' ; Now 1 digit
        $regex &= '[' & $start & ((StringLen($ender) = 1) ? ('-' & $ender & ']') : ('-9]'))
        If StringLen($ender) = 1 Then
            $regex &= ')'
            Return RegexCleanup($regex)
        EndIf
        $previousprocessing = 1
        $was1digit = 1
        If StringLen($start) = 1 Then $start = 10

    EndIf

    If StringLen($start) = 2 Or $previousprocessing = 1 Then
        $regex &= (($previousprocessing = 1) ? ('|') : ('(')) ; Now 2 digits
        If $was1digit Then $previousprocessing = 0

        If StringLen($ender) > 2 And $previousprocessing = 1 Or $ender >= 99 And StringMid($start, 2, 1) = 0 Then
            $regex &= '[' & (($previousprocessing = 1) ? (1) : (StringMid($start, 1, 1))) & '-9][0-9]'
        Else
            If StringLen($ender) = 2 And StringMid($ender, 1, 1) > StringMid($start, 1, 1) And $previousprocessing = 0 Then

                $regex &= StringMid($start, 1, 1) & '[' & StringMid($start, 2, 1) & '-9]|'
                If StringMid($ender, 1, 1) - StringMid($start, 1, 1) > 1 Then
                    $regex &= '[' & StringMid($start, 1, 1) + 1 & '-' & StringMid($ender, 1, 1) - 1 & ']' & '[0-9]|' & StringMid($ender, 1, 1) & '[0-' & StringMid($ender, 2, 1) & ']'
                Else
                    $regex &= '[' & StringMid($start, 1, 1) + 1 & '-' & StringMid($ender, 1, 1) & ']' & '[0-' & StringMid($ender, 2, 1) & ']'
                EndIf

            ElseIf StringLen($ender) > 2 Then

                $regex &= StringMid($start, 1, 1) & '[' & StringMid($start, 2, 1) & '-9]|'
                If StringMid($start, 1, 1) < 9 Then
                    $regex &= '[' & StringMid($start, 1, 1) + 1 & '-' & 9 & ']' & '[0-9]' ; I had to restrict this to initial digits under 9 to prevent problems
                EndIf

            Else
                $regex &= StringMid($start, 1, 1) & '[' & StringMid($start, 2, 1) & '-' & StringMid($ender, 2, 1) & ']'
            EndIf

        EndIf

        If StringLen($ender) = 2 Then
            $regex &= ')'
            Return RegexCleanup($regex)
        EndIf
        $previousprocessing = 1
        $was2digits = 1
    EndIf

    If StringLen($start) = 3 Or $previousprocessing = 1 Then
        $regex &= (($previousprocessing = 1) ? ('|') : ('(')) ; Now 3 digits
        If $previousprocessing Then $start = 100 ; If we are building up from a smaller than 3 digit number but going up to 3 digits, we start at the 1st 3 digit number

        If StringMid($start, 1, 1) = StringMid($ender, 1, 1) Then ; If the 1st digits are the same
            $regex &= StringMid($start, 1, 1) & '('

            If StringMid($start, 2, 1) = StringMid($ender, 2, 1) Then ; If the second digits are the same

                $regex &= StringMid($start, 2, 1) & '[' & StringMid($start, 3, 1) & '-' & StringMid($ender, 3, 1) & '])'

            Else ; If the second digits are not the same
                If StringMid($start, 3, 1) = 0 Then ; If the starter third digit is a 0
                    $regex &= '[' & StringMid($start, 2, 1) & '-' & (StringMid($ender, 2, 1) - 1) & '][0-9]|'
                    $regex &= '' & StringMid($ender, 2, 1) & '[0-' & StringMid($ender, 3, 1) & '])'

                Else ; The third starter digit is not 0
                    $regex &= StringMid($start, 2, 1) & '[' & StringMid($start, 3, 1) & '-9]'
                    If StringMid($ender, 2, 1) - StringMid($start, 2, 1) > 1 Then ; There is a second digit gap of more than 1 digit
                        $regex &= '|[' & StringMid($start, 2, 1) + 1 & '-' & StringMid($ender, 2, 1) - 1 & ']' & '[0-9]'
                        $regex &= '|' & StringMid($ender, 2, 1) & '[0-' & StringMid($ender, 3, 1) & '])'
                    Else
                        $regex &= '|[' & StringMid($start, 2, 1) + 1 & '-' & StringMid($ender, 2, 1) & ']' & '[0-' & StringMid($ender, 3, 1) & '])'
                    EndIf

                EndIf

            EndIf

            $regex &= ')'
        Else ; The first digits are not the same

            If StringMid($start, 2, 1) = 0 And StringMid($start, 3, 1) = 0 Then ; If 100 start just run through all up to 199 ready for starting at 200
                $regex &= StringMid($start, 1, 1) & '[0-9]' & '[0-9]|'

            Else

                Local $realender = $ender, $realstart = $start
                $ender = 199
                $regex &= StringMid($start, 1, 1) & '('

                If StringMid($start, 2, 1) = StringMid($ender, 2, 1) Then ; If the second digits are the same

                    $regex &= StringMid($start, 2, 1) & '[' & StringMid($start, 3, 1) & '-' & StringMid($ender, 3, 1) & '])'

                Else ; If the second digits are not the same
                    If StringMid($start, 3, 1) = 0 Then ; If the starter third digit is a 0
                        $regex &= '[' & StringMid($start, 2, 1) & '-' & (StringMid($ender, 2, 1) - 1) & '][0-9]|'
                        $regex &= '' & StringMid($ender, 2, 1) & '[0-' & StringMid($ender, 3, 1) & '])'

                    Else ; The third starter digit is not 0
                        $regex &= StringMid($start, 2, 1) & '[' & StringMid($start, 3, 1) & '-9]'
                        If StringMid($ender, 2, 1) - StringMid($start, 2, 1) > 1 Then ; There is a second digit gap of more than 1 digit
                            $regex &= '|[' & StringMid($start, 2, 1) + 1 & '-' & StringMid($ender, 2, 1) - 1 & ']' & '[0-9]'
                            $regex &= '|' & StringMid($ender, 2, 1) & '[0-' & StringMid($ender, 3, 1) & '])|'
                        Else
                            $regex &= '|[' & StringMid($start, 2, 1) + 1 & '-' & StringMid($ender, 2, 1) & ']' & '[0-' & StringMid($ender, 3, 1) & '])|'
                        EndIf

                    EndIf

                EndIf

            EndIf
            $ender = $realender
            $start = 200
            $regex &= '|' & StringMid($ender, 1, 1) & '('

            If StringMid($start, 2, 1) = StringMid($ender, 2, 1) Then ; If the second digits are the same

                $regex &= StringMid($start, 2, 1) & '[' & StringMid($start, 3, 1) & '-' & StringMid($ender, 3, 1) & '])'

            Else ; If the second digits are not the same
                If StringMid($start, 3, 1) = 0 Then ; If the starter third digit is a 0
                    $regex &= '[' & StringMid($start, 2, 1) & '-' & (StringMid($ender, 2, 1) - 1) & '][0-9]|'
                    $regex &= '' & StringMid($ender, 2, 1) & '[0-' & StringMid($ender, 3, 1) & '])'

                Else ; The third starter digit is not 0
                    $regex &= StringMid($start, 2, 1) & '[' & StringMid($start, 3, 1) & '-9]'
                    If StringMid($ender, 2, 1) - StringMid($start, 2, 1) > 1 Then ; There is a second digit gap of more than 1 digit
                        $regex &= '|[' & StringMid($start, 2, 1) + 1 & '-' & StringMid($ender, 2, 1) - 1 & ']' & '[0-9]'
                        $regex &= '|' & StringMid($ender, 2, 1) & '[0-' & StringMid($ender, 3, 1) & '])'
                    Else
                        $regex &= '|[' & StringMid($start, 2, 1) + 1 & '-' & StringMid($ender, 2, 1) & ']' & '[0-' & StringMid($ender, 3, 1) & '])'
                    EndIf

                EndIf

            EndIf

            $regex &= ')'

        EndIf

        Return RegexCleanup($regex)

    EndIf

EndFunc   ;==>IPRegex

Func RegexCleanup($_input, $no = 0)
    If $no Then Return $_input

    For $a = 0 To 9
        $_input = StringReplace($_input, '[' & $a & '-' & $a & ']', $a)
        If $a < 9 Then
            $_input = StringReplace($_input, '[' & $a & '-' & $a + 1 & ']', '[' & $a & $a + 1 & ']')
        EndIf
    Next

    For $a = 1 To 10
        $_input = StringReplace($_input, '||', '|')
    Next

    Local $temp_input = $_input

    $sections = StringRegExp($temp_input, '\(.*\)', 4)
    For $a In $sections
        ConsoleWrite($a & @CRLF)
    Next

    $_input = $temp_input

    Return $_input
EndFunc   ;==>RegexCleanup

So now I can make a list of either CIDR networks (which get converted to IP ranges so that I can spot consecutive ranges and combine them manually and then convert from IP ranges to the final regex. Or I can just work with IP ranges from the start if I want to.

Edited by Morthawt
Link to comment
Share on other sites

Wow  :o

Seeing your avatar and what you said was priceless lol. This is going to be great, because I search the IP of the person on http://bgp.he.net/ and find other ranges from the company, put the CIDR networks into one long text file and let my program rip a couple of times on it and it does all the hard work. At most all I have to do (and I don't have to) is combine running ranges into one entry vs multiple ones, which is easy to do since everything is in order and you can easily spot if the end of one range is continued at the start of the next one.

Link to comment
Share on other sites

Without extensive testing nor error handling routines, this appears to work on valid data.

;#include <Array.au3>
; http://www.watchguard.com/infocenter/editorial/135191.asp
Local $CIDR = '192.168.12.0/22'

ConsoleWrite(_CIDRToIpRange($CIDR) & @LF) ; For $CIDR = '192.168.12.0/22 Returns 192.168.12.1 - 192.168.15.254

ConsoleWrite(_IsIpWithinCIDRRange('192.168.12.0', $CIDR) & @LF)   ; Returns "0"  for False
ConsoleWrite(_IsIpWithinCIDRRange('192.168.12.1', $CIDR) & @LF)   ; Returns "1"  for True
ConsoleWrite(_IsIpWithinCIDRRange('192.168.15.254', $CIDR) & @LF) ; Returns "1"  for True
ConsoleWrite(_IsIpWithinCIDRRange('192.168.15.255', $CIDR) & @LF) ; Returns "0"  for False


Func _IsIpWithinCIDRRange($Ip, $CIDR)
    Local $aIpRnge = StringSplit($CIDR, "/", 2)
    Local $Num = _IpToBitNum($aIpRnge[0])
    Local $LowIp = ($Num + 1)
    Local $UpIp = (BitOR($Num, (2 ^ (32 - $aIpRnge[1]) - 1) - 1))
    Local $IpNum = _IpToBitNum($Ip)
    ;ConsoleWrite($IpNum & "  " & $LowIp & "  " & $UpIp & @LF)
    Return ($IpNum >= $LowIp And ($IpNum <= $UpIp)) ? 1 : 0
EndFunc   ;==>_IpWithinCIDRRange

Func _CIDRToIpRange($CIDR)
    Local $aIpRnge = StringSplit($CIDR, "/", 2)
    Local $Num = _IpToBitNum($aIpRnge[0])
    Local $LowIp = _BitNumToIp($Num + 1)
    Local $UpIp = _BitNumToIp(BitOR($Num, (2 ^ (32 - $aIpRnge[1]) - 1) - 1))

    Return $LowIp & " - " & $UpIp
EndFunc   ;==>_CIDRToIpRange

Func _BitNumToIp($Num)
    Local $Ret, $a = StringRegExp(Hex($Num, 8), "(..)", 3)
    ;_ArrayDisplay($a)
    For $i = 0 To UBound($a) - 1
        $Ret &= Execute("0x" & $a[$i]) & "."
    Next
    Return StringTrimRight($Ret, 1)
EndFunc   ;==>_BitNumToIp

Func _IpToBitNum($Ip)
    Local $Ret, $r = 0, $a = StringRegExp($Ip, "[^./]+", 3), $iBound = UBound($a)
    If StringInStr($Ip, "/") Then
        $iBound -= 1
        $r = $a[$iBound]
    EndIf
    For $i = 0 To $iBound - 1
        $Ret &= Hex($a[$i], 2)
    Next
    Return Execute("0x" & $Ret)
EndFunc   ;==>_IpToBitNum
Link to comment
Share on other sites

 

Without extensive testing nor error handling routines, this appears to work on valid data.

;#include <Array.au3>
; http://www.watchguard.com/infocenter/editorial/135191.asp
Local $CIDR = '192.168.12.0/22'

ConsoleWrite(_CIDRToIpRange($CIDR) & @LF) ; For $CIDR = '192.168.12.0/22 Returns 192.168.12.1 - 192.168.15.254

ConsoleWrite(_IsIpWithinCIDRRange('192.168.12.0', $CIDR) & @LF)   ; Returns "0"  for False
ConsoleWrite(_IsIpWithinCIDRRange('192.168.12.1', $CIDR) & @LF)   ; Returns "1"  for True
ConsoleWrite(_IsIpWithinCIDRRange('192.168.15.254', $CIDR) & @LF) ; Returns "1"  for True
ConsoleWrite(_IsIpWithinCIDRRange('192.168.15.255', $CIDR) & @LF) ; Returns "0"  for False


Func _IsIpWithinCIDRRange($Ip, $CIDR)
    Local $aIpRnge = StringSplit($CIDR, "/", 2)
    Local $Num = _IpToBitNum($aIpRnge[0])
    Local $LowIp = ($Num + 1)
    Local $UpIp = (BitOR($Num, (2 ^ (32 - $aIpRnge[1]) - 1) - 1))
    Local $IpNum = _IpToBitNum($Ip)
    ;ConsoleWrite($IpNum & "  " & $LowIp & "  " & $UpIp & @LF)
    Return ($IpNum >= $LowIp And ($IpNum <= $UpIp)) ? 1 : 0
EndFunc   ;==>_IpWithinCIDRRange

Func _CIDRToIpRange($CIDR)
    Local $aIpRnge = StringSplit($CIDR, "/", 2)
    Local $Num = _IpToBitNum($aIpRnge[0])
    Local $LowIp = _BitNumToIp($Num + 1)
    Local $UpIp = _BitNumToIp(BitOR($Num, (2 ^ (32 - $aIpRnge[1]) - 1) - 1))

    Return $LowIp & " - " & $UpIp
EndFunc   ;==>_CIDRToIpRange

Func _BitNumToIp($Num)
    Local $Ret, $a = StringRegExp(Hex($Num, 8), "(..)", 3)
    ;_ArrayDisplay($a)
    For $i = 0 To UBound($a) - 1
        $Ret &= Execute("0x" & $a[$i]) & "."
    Next
    Return StringTrimRight($Ret, 1)
EndFunc   ;==>_BitNumToIp

Func _IpToBitNum($Ip)
    Local $Ret, $r = 0, $a = StringRegExp($Ip, "[^./]+", 3), $iBound = UBound($a)
    If StringInStr($Ip, "/") Then
        $iBound -= 1
        $r = $a[$iBound]
    EndIf
    For $i = 0 To $iBound - 1
        $Ret &= Hex($a[$i], 2)
    Next
    Return Execute("0x" & $Ret)
EndFunc   ;==>_IpToBitNum

I ran your script but I see no regex being pumped out of it.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...