Unix style "tail -f" written in VBS. *APPLIED*

This section contains scripts that hMailServer has contributed with. hMailServer 5 is needed to use these.
Post Reply
User avatar
SorenR
Senior user
Senior user
Posts: 4201
Joined: 2006-08-21 15:38
Location: Denmark

Unix style "tail -f" written in VBS. *APPLIED*

Post by SorenR » 2019-06-26 13:19

Proof-of-Concept code here:
https://www.hmailserver.com/forum/viewt ... 67#p212967

Practical use and further adaptation of code in this thread. Thanks.
SørenR.

Algorithm (noun.)
Word used by programmers when they do not want to explain what they did.

User avatar
SorenR
Senior user
Senior user
Posts: 4201
Joined: 2006-08-21 15:38
Location: Denmark

Re: Unix style "tail -f" written in VBS. *APPLIED*

Post by SorenR » 2019-06-27 00:16

Minor changes.

Code: Select all

Option Explicit

'******************************************************************************************************************************
'********** Configuration                                                                                            **********
'******************************************************************************************************************************
'
'   COM authentication
'
Private Const ADMIN = "Administrator"
Private Const PASSWORD = "VerySecretPassword"
'
'   Misc. settings
'
Private Const intInterval = "2" '   Event trigger interval in seconds.
Private Const strComputer = "." '   Nodename/Computer name
Private Const FOR_READING = 1

'******************************************************************************************************************************
'********** Functions                                                                                                **********
'******************************************************************************************************************************

Function tailFile(strFileName)
    Dim intCurrLine, intNewNumLines, strReadLine, strRegEx, arrReadLine
    Dim oFSO, oFile
    Set oFSO = CreateObject("Scripting.FileSystemObject")
    Set oFile = oFSO.OpenTextFile(strFileName, FOR_READING)
    intNewNumLines = 0
    intCurrLine = 0
    Do Until oFile.AtEndOfStream
        intCurrLine = intCurrLine + 1
        If intCurrLine <= intLastRunLineinFile Then
            oFile.skipline
        Else
            strReadLine = oFile.ReadLine
            '
            '    THIS IS WHERE THE FUN BEGINS ==>
            '
            WScript.echo strReadLine
            strRegEx = "(Unknown user)|(Origin Banned)|(mechanism not supported)|(Authentication failed)"
            If Lookup(strRegEx, strReadLine) Then
                With CreateObject("hMailServer.Message")
                    .AddRecipient "Postmaster", "postmaster@acme.inc"
                    .FromAddress = "postmaster@acme.inc"
                    .HeaderValue("To") = Chr(34) & "Postmaster" & Chr(34) & " <postmaster@acme.inc>"
                    .HeaderValue("From") = Chr(34) & "Postmaster" & Chr(34) & " <postmaster@acme.inc>"
                    .Subject = "log_tail.vbs found something"
                    .Body = strReadLine
                    .Save
                End With
            End If
            '
            '    ==> THIS IS WHERE THE FUN ENDS
            '
            intNewNumLines = intNewNumLines + 1
        End If
    Loop
    If intCurrLine < intLastRunLineinFile Then
        '   The number of lines on this scan was less than the last run so resetting the num lines in file
        intLastRunLineinFile = intCurrLine
    Else
        intLastRunLineinFile = intLastRunLineinFile + intNewNumLines
    End If
    oFile.close
    Set oFile = Nothing
    Set oFSO = Nothing
End Function

Function get_NumLinesInFile(strFileName)
    Dim intTotalNumLines
    Dim oFSO, oFile
    Set oFSO = CreateObject("Scripting.FileSystemObject")
    Set oFile = oFSO.OpenTextFile(strFileName, FOR_READING)
    intTotalNumLines = 0
    Do Until oFile.AtEndOfStream
        oFile.skipline
        intTotalNumLines = intTotalNumLines + 1
    Loop
    oFile.close
    Set oFile = Nothing
    Set oFSO = Nothing
    get_NumLinesInFile = intTotalNumLines
End Function

Function get_DefaultLogFileName(stdDrive, strFolder)
    Dim oLog, i, arrArgsLine
    Set oLog = CreateObject("hMailServer.Logging")
    get_DefaultLogFileName = oLog.CurrentDefaultLog
    Set oLog = Nothing
    arrArgsLine = Split(get_DefaultLogFileName, "\")
    strDrive = arrArgsLine(0)
    If UBound(arrArgsLine) > 1 Then
        For i = 1 To UBound(arrArgsLine)-1
            strFolder = strFolder & "\\" & arrArgsLine(i)
        Next
        strFolder = strFolder & "\\"
    End If
End Function

Function Lookup(strRegEx, strMatch) : Lookup = False
   If strRegEx = "" Then Exit Function
   With CreateObject("VBScript.RegExp")
      .Pattern = strRegEx
      .Global = False
      .MultiLine = True
      .IgnoreCase = True
      If .Test(strMatch) Then Lookup = True
   End With
End Function

Function oLookup(strRegEx, strMatch, bGlobal)
   If strRegEx = "" Then strRegEx = StrReverse(strMatch)
   With CreateObject("VBScript.RegExp")
      .Pattern = strRegEx
      .Global = bGlobal
      .MultiLine = True
      .IgnoreCase = True
      Set oLookup = .Execute(strMatch)
   End With
End Function

'******************************************************************************************************************************
'********** Main Code                                                                                                **********
'******************************************************************************************************************************

Dim oApp : Set oApp = CreateObject("hMailServer.Application")
Call oApp.Authenticate(ADMIN, PASSWORD)
Dim EventLog : Set EventLog = CreateObject("hMailServer.EventLog")

Dim strLongFileName, strDrive, strFolder, strQuery, intLastRunLineinFile, colEvents
Dim oWMIService, oEvent, oTargetInst
'
'   Read logfile
'
strLongFileName = get_DefaultLogFileName(strDrive, strFolder)
intLastRunLineinFile = get_NumLinesInFile(strLongFileName)
'
'   Build interface to WMI
'
strQuery = "Select * From __InstanceOperationEvent Within " & intInterval & _
           " Where Targetinstance Isa 'CIM_DataFile' And TargetInstance.Drive='" & strDrive & _
           "' And TargetInstance.Path='" & strFolder & "'"
Set oWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colEvents = oWMIService.ExecNotificationQuery(strQuery)
'
'   Event management
'
Do
    Set oEvent = colEvents.NextEvent()
    Set oTargetInst = oEvent.TargetInstance
    Select Case oEvent.Path_.Class
        Case "__InstanceDeletionEvent"
            If 0 = StrComp(oTargetInst.Name, strLongFileName, 1) Then
                WScript.echo oTargetInst.Name & " has been deleted. Exiting."
                WScript.quit
            End If
        Case "__InstanceModificationEvent"
            If 0 = StrComp(oTargetInst.Name, strLongFileName, 1) Then
                tailFile(oTargetInst.Name)
            End If
        Case "__InstanceCreationEvent"
            If 0 = StrComp(Left(oTargetInst.Name, 12), Left(strLongFileName, 12), 1) Then
                WScript.echo oTargetInst.Name & " has been created. Loading new logfile."
                strLongFileName = oTargetInst.Name
                intLastRunLineinFile = 0
            End If
    End Select
Loop
WScript.quit
SørenR.

Algorithm (noun.)
Word used by programmers when they do not want to explain what they did.

User avatar
SorenR
Senior user
Senior user
Posts: 4201
Joined: 2006-08-21 15:38
Location: Denmark

Re: Unix style "tail -f" written in VBS. *APPLIED*

Post by SorenR » 2019-06-27 17:46

Fixed problem motoring logfiles. If an error log was created the code would follow the error log and not the regular log.

Code: Select all

Option Explicit

'******************************************************************************************************************************
'********** Configuration                                                                                            **********
'******************************************************************************************************************************
'
'   COM authentication
'
Private Const ADMIN = "Administrator"
Private Const PASSWORD = "VerySecretPassword"
'
'   Misc. settings
'
Private Const intInterval = "2" '   Event trigger interval in seconds.
Private Const strComputer = "." '   Nodename/Computer name
Private Const FOR_READING = 1

'******************************************************************************************************************************
'********** Functions                                                                                                **********
'******************************************************************************************************************************

Function tailFile(strFileName)
    Dim intCurrLine, intNewNumLines, strReadLine, strRegEx, arrReadLine
    Dim oFSO, oFile
    Set oFSO = CreateObject("Scripting.FileSystemObject")
    Set oFile = oFSO.OpenTextFile(strFileName, FOR_READING)
    intNewNumLines = 0
    intCurrLine = 0
    Do Until oFile.AtEndOfStream
        intCurrLine = intCurrLine + 1
        If intCurrLine <= intLastRunLineinFile Then
            oFile.skipline
        Else
            strReadLine = oFile.ReadLine
            '
            '    THIS IS WHERE THE FUN BEGINS ==>
            '
            WScript.echo strReadLine
            strRegEx = "(Unknown user)|(Origin Banned)|(mechanism not supported)|(Authentication failed)"
            If Lookup(strRegEx, strReadLine) Then
                With CreateObject("hMailServer.Message")
                    .AddRecipient "Postmaster", "postmaster@acme.inc"
                    .FromAddress = "postmaster@acme.inc"
                    .HeaderValue("To") = Chr(34) & "Postmaster" & Chr(34) & " <postmaster@acme.inc>"
                    .HeaderValue("From") = Chr(34) & "Postmaster" & Chr(34) & " <postmaster@acme.inc>"
                    .Subject = "hm_tail.vbs found something"
                    .Body = strReadLine
                    .Save
                End With
            End If
            '
            '    ==> THIS IS WHERE THE FUN ENDS
            '
            intNewNumLines = intNewNumLines + 1
        End If
    Loop
    If intCurrLine < intLastRunLineinFile Then
        '   The number of lines on this scan was less than the last run so resetting the num lines in file
        intLastRunLineinFile = intCurrLine
    Else
        intLastRunLineinFile = intLastRunLineinFile + intNewNumLines
    End If
    oFile.close
    Set oFile = Nothing
    Set oFSO = Nothing
End Function

Function get_NumLinesInFile(strFileName)
    Dim intTotalNumLines
    Dim oFSO, oFile
    Set oFSO = CreateObject("Scripting.FileSystemObject")
    Set oFile = oFSO.OpenTextFile(strFileName, FOR_READING)
    intTotalNumLines = 0
    Do Until oFile.AtEndOfStream
        oFile.skipline
        intTotalNumLines = intTotalNumLines + 1
    Loop
    oFile.close
    Set oFile = Nothing
    Set oFSO = Nothing
    get_NumLinesInFile = intTotalNumLines
End Function

Function get_DefaultLogFileName(stdDrive, strFolder)
    Dim oLog, i, arrArgsLine
    Set oLog = CreateObject("hMailServer.Logging")
    get_DefaultLogFileName = oLog.CurrentDefaultLog
    Set oLog = Nothing
    arrArgsLine = Split(get_DefaultLogFileName, "\")
    strDrive = arrArgsLine(0)
    If UBound(arrArgsLine) > 1 Then
        For i = 1 To UBound(arrArgsLine)-1
            strFolder = strFolder & "\\" & arrArgsLine(i)
        Next
        strFolder = strFolder & "\\"
    End If
End Function

Function get_FileName(strFileName)
    Dim oFSO, oFile
    Set oFSO = CreateObject("Scripting.FileSystemObject")
    Set oFile = oFSO.GetFile(strFileName)
    get_FileName = oFSO.GetFileName(oFile)
    Set oFile = Nothing
    Set oFSO = Nothing
End Function

Function Lookup(strRegEx, strMatch) : Lookup = False
   If strRegEx = "" Then Exit Function
   With CreateObject("VBScript.RegExp")
      .Pattern = strRegEx
      .Global = False
      .MultiLine = True
      .IgnoreCase = True
      If .Test(strMatch) Then Lookup = True
   End With
End Function

Function oLookup(strRegEx, strMatch, bGlobal)
   If strRegEx = "" Then strRegEx = StrReverse(strMatch)
   With CreateObject("VBScript.RegExp")
      .Pattern = strRegEx
      .Global = bGlobal
      .MultiLine = True
      .IgnoreCase = True
      Set oLookup = .Execute(strMatch)
   End With
End Function

'******************************************************************************************************************************
'********** Main Code                                                                                                **********
'******************************************************************************************************************************

Dim oApp : Set oApp = CreateObject("hMailServer.Application")
Call oApp.Authenticate(ADMIN, PASSWORD)
Dim EventLog : Set EventLog = CreateObject("hMailServer.EventLog")

Dim strLongFileName, strDrive, strFolder, strQuery, intLastRunLineinFile, colEvents
Dim oWMIService, oEvent, oTargetInst
'
'   Read logfile
'
strLongFileName = get_DefaultLogFileName(strDrive, strFolder)
intLastRunLineinFile = get_NumLinesInFile(strLongFileName)
'
'   Build interface to WMI
'
strQuery = "Select * From __InstanceOperationEvent Within " & intInterval & _
           " Where Targetinstance Isa 'CIM_DataFile' And TargetInstance.Drive='" & strDrive & _
           "' And TargetInstance.Path='" & strFolder & "'"
Set oWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colEvents = oWMIService.ExecNotificationQuery(strQuery)
'
'   Event management
'
Do
    Set oEvent = colEvents.NextEvent()
    Set oTargetInst = oEvent.TargetInstance
    Select Case oEvent.Path_.Class
        Case "__InstanceDeletionEvent"
            If 0 = StrComp(oTargetInst.Name, strLongFileName, 1) Then
                WScript.echo oTargetInst.Name & " has been deleted. Exiting."
                WScript.quit
            End If
        Case "__InstanceModificationEvent"
            If 0 = StrComp(oTargetInst.Name, strLongFileName, 1) Then
                tailFile(oTargetInst.Name)
            End If
        Case "__InstanceCreationEvent"
            If 0 = StrComp(Left(get_FileName(oTargetInst.Name), 12), Left(get_FileName(strLongFileName), 12), 1) Then
                WScript.echo oTargetInst.Name & " has been created. Loading new logfile."
                strLongFileName = oTargetInst.Name
                intLastRunLineinFile = 0
            End If
    End Select
Loop
WScript.quit
SørenR.

Algorithm (noun.)
Word used by programmers when they do not want to explain what they did.

palinka
Senior user
Senior user
Posts: 2475
Joined: 2017-09-12 17:57

Re: Unix style "tail -f" written in VBS. *APPLIED*

Post by palinka » 2019-06-27 18:08

Trying to understand how this works. What passes "strFileName"? A trigger? Loads at startup? Scheduled task? I don't get that part. :?:

palinka
Senior user
Senior user
Posts: 2475
Joined: 2017-09-12 17:57

Re: Unix style "tail -f" written in VBS. *APPLIED*

Post by palinka » 2019-06-27 18:49

I just came up with a clever use case for this. I just noticed my mom autobanned herself from too many password tries. I'd like to be notified when that happens again, which will definitely happen again soon. :mrgreen:

User avatar
SorenR
Senior user
Senior user
Posts: 4201
Joined: 2006-08-21 15:38
Location: Denmark

Re: Unix style "tail -f" written in VBS. *APPLIED*

Post by SorenR » 2019-06-27 21:16

palinka wrote:
2019-06-27 18:08
Trying to understand how this works. What passes "strFileName"? A trigger? Loads at startup? Scheduled task? I don't get that part. :?:
It's quite simple. It's sort of like creating a "stored procedure" on a database table. If you change, add or delete data in the table you trigger the procedure. 8)

This will tell WMI to monitor a specific folder:

Code: Select all

Select * From __InstanceOperationEvent Within 2
   Where Targetinstance Isa 'CIM_DataFile' And TargetInstance.Drive='C:'
   And TargetInstance.Path='\hmailserver\logs'
This will configure WMI:

Code: Select all

Set oWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
Set colEvents = oWMIService.ExecNotificationQuery(strQuery)
This is the trigger that WMI activate in case of an event:

Code: Select all

Set oEvent = colEvents.NextEvent()
This is simply to decode which event occured:

Code: Select all

Set oTargetInst = oEvent.TargetInstance
Select Case oEvent.Path_.Class
oTargetInst.Name is the name (full path) of the file triggering the event:

Left column on this page lists the events that can be monitored..
https://docs.microsoft.com/en-us/window ... etionevent

And... strFileName is not really used :mrgreen:

I'm currently testing a version where SnowShoe, LashBack and Out-of-Area logins are banned. All based on hmailserver_<date>.log with TCPIP logging activated. The option in hMailServer to keep logfiles open have no affect on the functionality.

I found that I need a function in Eventhandlers.vbs to check IF an IPAddress has been banned somewhere between TCPIP Connect and the event OnClientConnect/OnHELO. Banning an ongoing connection will NOT disconnect it automatically.
Attachments
tail.jpg
SørenR.

Algorithm (noun.)
Word used by programmers when they do not want to explain what they did.

User avatar
RvdH
Senior user
Senior user
Posts: 1218
Joined: 2008-06-27 14:42
Location: Netherlands

Re: Unix style "tail -f" written in VBS. *APPLIED*

Post by RvdH » 2019-06-28 14:42

I have ran this for some time...got e few mails, would be nice to have the previous line (or previous few lines) included in the mail as well, now i still have to lookup that line in the logfile myself :)
CIDR to RegEx: d-fault.nl/CIDRtoRegEx
DNS Lookup: d-fault.nl/DNSTools
DNSBL Lookup: d-fault.nl/DNSBLLookup
GEOIP Lookup: d-fault.nl/GeoipLookup

User avatar
SorenR
Senior user
Senior user
Posts: 4201
Joined: 2006-08-21 15:38
Location: Denmark

Re: Unix style "tail -f" written in VBS. *APPLIED*

Post by SorenR » 2019-06-28 15:21

RvdH wrote:
2019-06-28 14:42
I have ran this for some time...got e few mails, would be nice to have the previous line (or previous few lines) included in the mail as well, now i still have to lookup that line in the logfile myself :)
You'll just have to figure out how to make a 5 line floating buffer :mrgreen:

One application I can see for this is looking for SnowShoe/LashBack/GeoIP blocking to update a firewall in real-time - or perhaps for statistical purposes. The advantage is you can change it all you want, start/stop it all day long and even if it fails it will NOT affect hMailServer.

I've been playing with those three to AutoBan but TCPIP will register when a banned IP connect so it generates a lot of traffic :roll:
SørenR.

Algorithm (noun.)
Word used by programmers when they do not want to explain what they did.

User avatar
RvdH
Senior user
Senior user
Posts: 1218
Joined: 2008-06-27 14:42
Location: Netherlands

Re: Unix style "tail -f" written in VBS. *APPLIED*

Post by RvdH » 2019-06-28 20:38

SorenR wrote:
2019-06-28 15:21
You'll just have to figure out how to make a 5 line floating buffer :mrgreen:
Something like this? :wink:
https://stackoverflow.com/questions/341 ... 6#34187866
CIDR to RegEx: d-fault.nl/CIDRtoRegEx
DNS Lookup: d-fault.nl/DNSTools
DNSBL Lookup: d-fault.nl/DNSBLLookup
GEOIP Lookup: d-fault.nl/GeoipLookup

User avatar
SorenR
Senior user
Senior user
Posts: 4201
Joined: 2006-08-21 15:38
Location: Denmark

Re: Unix style "tail -f" written in VBS. *APPLIED*

Post by SorenR » 2019-06-28 22:31

RvdH wrote:
2019-06-28 20:38
SorenR wrote:
2019-06-28 15:21
You'll just have to figure out how to make a 5 line floating buffer :mrgreen:
Something like this? :wink:
https://stackoverflow.com/questions/341 ... 6#34187866
or https://gallery.technet.microsoft.com/s ... 1749f42f21
SørenR.

Algorithm (noun.)
Word used by programmers when they do not want to explain what they did.

User avatar
SorenR
Senior user
Senior user
Posts: 4201
Joined: 2006-08-21 15:38
Location: Denmark

Re: Unix style "tail -f" written in VBS. *APPLIED*

Post by SorenR » 2019-06-29 00:02

Now with a 10 line Ring Buffer in case the last 10 lines are needed.

Code: Select all

Option Explicit

'******************************************************************************************************************************
'********** Configuration                                                                                            **********
'******************************************************************************************************************************
'
'   COM authentication
'
Private Const ADMIN = "Administrator"
Private Const PASSWORD = "Secret-Secret-Secret"
'
'   Misc. settings
'
Private Const intInterval = "2" '   Event trigger interval in seconds.
Private Const strComputer = "." '   Nodename/Computer name
Private Const FOR_READING = 1
Private Const RING_COUNT  = 10

'******************************************************************************************************************************
'********** Classes                                                                                                  **********
'******************************************************************************************************************************

Class ringBuffer
    Private buffer
    Private indexNext
    Private size

    Public Sub Class_Initialize
        resize 1   
    End Sub
    '
    'RESIZE THE BUFFER, OLD DATA IS LOST
    '
    Public Sub resize(numElements)
        size = Int(numElements)
        If size < 1 Then size = 1
        ReDim buffer(size-1)
        indexNext = 0
    End Sub
    '
    'ADD AN ELEMENT TO RING BUFFER OVERWRITING OLD DATA
    '
    Public Function add(element)
        buffer(indexNext) = element
        indexNext = wrapIndex(indexNext + 1)
    End Function
    '
    'GET PREVIOUS ELEMENT WITH DISTANCE i FROM NEWEST ELEMENT
    '
    Public Function getPrev(i)
        getPrev = buffer( wrapIndex(indexNext-1-i) )
    End Function
    '
    'MAKES AN INDEX TO RING BUFFER FROM 0 TO BUFFER SIZE-1
    'if index is outside the ring buffer,
    'then it will wrap it around so it goes inside the buffer
    '
    Public Function wrapIndex(i)
        If i >= size Then
            wrapIndex = i Mod size
        ElseIf i < 0 Then
            wrapIndex = (i + size * (Int(1 + Abs(i/size)))) Mod size
        Else
            wrapIndex = i
        End If
    End Function
    '
    'BECAUSE...
    '
    Public Sub testWrapIndex(indexLow, indexHigh)
        Dim s, i
        s = "size" & vbTab & Size & vbCrLf & "i" & vbTab & "wrapped" & vbCrLf
        For i = indexLow To indexHigh
            s = s & i & vbTab & wrapIndex(i) & vbCrLf
        Next
        WScript.echo s
    End Sub
End Class 

'******************************************************************************************************************************
'********** Functions                                                                                                **********
'******************************************************************************************************************************

Function tailFile(strFileName)
    Dim i, intCurrLine, intNewNumLines, strBody, strRegEx, arrReadLine
    Dim oFSO, oFile
    Set oFSO = CreateObject("Scripting.FileSystemObject")
    Set oFile = oFSO.OpenTextFile(strFileName, FOR_READING)
    intNewNumLines = 0
    intCurrLine = 0
    Do Until oFile.AtEndOfStream
        intCurrLine = intCurrLine + 1
        If intCurrLine <= intLastRunLineinFile Then
            oFile.skipline
        Else
            oRing.add(oFile.ReadLine)
            '
            '    THIS IS WHERE THE FUN BEGINS ==>
            '
            WScript.echo oRing.getPrev(0)

            strRegEx = "(Unknown user)|(Origin Banned)|(mechanism not supported)|(Authentication failed)"
            If Lookup(strRegEx, oRing.getPrev(0)) Then

                strBody = ""
                For i = RING_COUNT-1 To 0 Step -1
                    strBody = strBody & vbCrLf & oRing.getPrev(i)
                Next

                With CreateObject("hMailServer.Message")
                    .AddRecipient "Postmaster", "postmaster@acme.inc"
                    .FromAddress = "postmaster@acme.inc"
                    .HeaderValue("To") = Chr(34) & "Postmaster" & Chr(34) & " <postmaster@acme.inc>"
                    .HeaderValue("From") = Chr(34) & "Postmaster" & Chr(34) & " <postmaster@acme.inc>"
                    .Subject = "hm_tail.vbs found something"
                    .Body = strBody
                    .Save
                End With

            End If
            '
            '    ==> THIS IS WHERE THE FUN ENDS
            '
            intNewNumLines = intNewNumLines + 1
        End If
    Loop
    If intCurrLine < intLastRunLineinFile Then
        '   The number of lines on this scan was less than the last run so resetting the num lines in file
        intLastRunLineinFile = intCurrLine
    Else
        intLastRunLineinFile = intLastRunLineinFile + intNewNumLines
    End If
    oFile.close
    Set oFile = Nothing
    Set oFSO = Nothing
End Function

Function get_NumLinesInFile(strFileName)
    Dim intTotalNumLines
    Dim oFSO, oFile
    Set oFSO = CreateObject("Scripting.FileSystemObject")
    Set oFile = oFSO.OpenTextFile(strFileName, FOR_READING)
    intTotalNumLines = 0
    Do Until oFile.AtEndOfStream
        oFile.skipline
        intTotalNumLines = intTotalNumLines + 1
    Loop
    oFile.close
    Set oFile = Nothing
    Set oFSO = Nothing
    get_NumLinesInFile = intTotalNumLines
End Function

'
'    ByRef is used to update the global variables.
'
Function get_DefaultLogFileName(ByRef stdDrive, ByRef strFolder)
    Dim oLog, i, arrArgsLine
    Set oLog = CreateObject("hMailServer.Logging")
    get_DefaultLogFileName = oLog.CurrentDefaultLog
    Set oLog = Nothing
    arrArgsLine = Split(get_DefaultLogFileName, "\")
    strDrive = arrArgsLine(0)
    If UBound(arrArgsLine) > 1 Then
        For i = 1 To UBound(arrArgsLine)-1
            strFolder = strFolder & "\\" & arrArgsLine(i)
        Next
        strFolder = strFolder & "\\"
    End If
End Function

Function get_FileName(strFileName)
    Dim oFSO, oFile
    Set oFSO = CreateObject("Scripting.FileSystemObject")
    Set oFile = oFSO.GetFile(strFileName)
    get_FileName = oFSO.GetFileName(oFile)
    Set oFile = Nothing
    Set oFSO = Nothing
End Function

Function Lookup(strRegEx, strMatch) : Lookup = False
   If strRegEx = "" Then Exit Function
   With CreateObject("VBScript.RegExp")
      .Pattern = strRegEx
      .Global = False
      .MultiLine = True
      .IgnoreCase = True
      If .Test(strMatch) Then Lookup = True
   End With
End Function

Function oLookup(strRegEx, strMatch, bGlobal)
   If strRegEx = "" Then strRegEx = StrReverse(strMatch)
   With CreateObject("VBScript.RegExp")
      .Pattern = strRegEx
      .Global = bGlobal
      .MultiLine = True
      .IgnoreCase = True
      Set oLookup = .Execute(strMatch)
   End With
End Function

'******************************************************************************************************************************
'********** Main Code                                                                                                **********
'******************************************************************************************************************************

Dim oApp : Set oApp = CreateObject("hMailServer.Application")
Call oApp.Authenticate(ADMIN, PASSWORD)
Dim EventLog : Set EventLog = CreateObject("hMailServer.EventLog")

Dim strLongFileName, strDrive, strFolder, strQuery, intLastRunLineinFile, colEvents
Dim oWMIService, oEvent, oTargetInst, oRing

strLongFileName = get_DefaultLogFileName(strDrive, strFolder)
intLastRunLineinFile = get_NumLinesInFile(strLongFileName)

strQuery = "Select * From __InstanceOperationEvent Within " & intInterval & _
           " Where Targetinstance Isa 'CIM_DataFile' And TargetInstance.Drive='" & strDrive & _
           "' And TargetInstance.Path='" & strFolder & "'"
Set oWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colEvents = oWMIService.ExecNotificationQuery(strQuery)

Set oRing = New ringBuffer
oRing.resize RING_COUNT

Do
    Set oEvent = colEvents.NextEvent()
    Set oTargetInst = oEvent.TargetInstance
    Select Case oEvent.Path_.Class
        Case "__InstanceDeletionEvent"
            If 0 = StrComp(oTargetInst.Name, strLongFileName, 1) Then
                WScript.echo oTargetInst.Name & " has been deleted. Exiting."
                WScript.quit
            End If
        Case "__InstanceModificationEvent"
            If 0 = StrComp(oTargetInst.Name, strLongFileName, 1) Then
                tailFile(oTargetInst.Name)
            End If
        Case "__InstanceCreationEvent"
            If 0 = StrComp(Left(get_FileName(oTargetInst.Name), 12), Left(get_FileName(strLongFileName), 12), 1) Then
                WScript.echo oTargetInst.Name & " has been created. Loading new logfile."
                strLongFileName = oTargetInst.Name
                intLastRunLineinFile = 0
            End If
    End Select
Loop

WScript.quit
SørenR.

Algorithm (noun.)
Word used by programmers when they do not want to explain what they did.

palinka
Senior user
Senior user
Posts: 2475
Joined: 2017-09-12 17:57

Re: Unix style "tail -f" written in VBS. *APPLIED*

Post by palinka » 2019-06-29 00:35

SorenR wrote:
2019-06-27 21:16
It's quite simple.
Uh huh... :roll:







:mrgreen:

User avatar
SorenR
Senior user
Senior user
Posts: 4201
Joined: 2006-08-21 15:38
Location: Denmark

Re: Unix style "tail -f" written in VBS. *APPLIED*

Post by SorenR » 2019-06-29 10:50

palinka wrote:
2019-06-29 00:35
SorenR wrote:
2019-06-27 21:16
It's quite simple.
Uh huh... :roll:







:mrgreen:
Image
SørenR.

Algorithm (noun.)
Word used by programmers when they do not want to explain what they did.

palinka
Senior user
Senior user
Posts: 2475
Joined: 2017-09-12 17:57

Re: Unix style "tail -f" written in VBS. *APPLIED*

Post by palinka » 2019-06-29 12:09

Exactly! :mrgreen:

LOL

User avatar
RvdH
Senior user
Senior user
Posts: 1218
Joined: 2008-06-27 14:42
Location: Netherlands

Re: Unix style "tail -f" written in VBS. *APPLIED*

Post by RvdH » 2019-06-29 13:55

I already implemented my found solution, it was off sometimes, eg: mails containing way more lines as the supposed 5
your seem to work much better, thx! :mrgreen:
CIDR to RegEx: d-fault.nl/CIDRtoRegEx
DNS Lookup: d-fault.nl/DNSTools
DNSBL Lookup: d-fault.nl/DNSBLLookup
GEOIP Lookup: d-fault.nl/GeoipLookup

User avatar
RvdH
Senior user
Senior user
Posts: 1218
Joined: 2008-06-27 14:42
Location: Netherlands

Re: Unix style "tail -f" written in VBS. *APPLIED*

Post by RvdH » 2019-07-11 10:01

I have added some auto-ban functions inside hm_tail.vbs, i'll like it! :mrgreen:

Make sure you replace {backup-mx-ip} and {domain-to-be-blocked} variables

Code: Select all

dim intUnique : intUnique = 0
' Find Unique Indentifier
strRegEx = "^(?:\S+\s){2}(\S+)"
Set Matches = oLookup(strRegEx, oRing.getPrev(1), true)
If Matches.Count > 0 Then intUnique = Matches(0).Submatches(0)
Set Matches = Nothing
' find domains to block 
strRegEx = "(\<.+\@.*(?:{domain-to-be-blocked}).+\>)"
If lookup(strRegEx, oRing.getPrev(1)) then
	Dim strIp : strIp = ""
	Dim strEmailAddress : strEmailAddress = ""
	Dim Matches
' Find ip
	strRegEx = "\b((?:(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\b"
	Set Matches = oLookup(strRegEx, oRing.getPrev(1), false)
	If Matches.Count > 0 Then strIp = Matches(0).Value
	Set Matches = Nothing
' Find Emailaddress
	strRegEx = "\b(\w+([\-\+\.\']\w+)*\@\w+([\-\.]\w+)*\.\w+([\-\.]\w+)*)\b"
	Set Matches = oLookup(strRegEx, oRing.getPrev(1), false)
	If Matches.Count > 0 Then strEmailAddress = Matches(0).Value
	Set Matches = Nothing
	If (strIp <> "" And strEmailAddress <> "" And lookup("\b(" & intUnique & ")\b", oRing.getPrev(0))) then
		strRegEx = "^({backup-mx-ip})$"
' Filter out backup MX's
		If Not Lookup(strRegEx, strIp) Then
			Call AutoBan(strIp, strEmailAddress, 1, "ww")
		End If
	End If
End If

If lookup("\b(" & intUnique & ")\b", oRing.getPrev(0)) then
	With CreateObject("hMailServer.Message")
		
		.....
		
		.Subject = "hm_tail.vbs found something (" & intUnique & ")"
		.Body = strBody
		.Save
	End With
End If
CIDR to RegEx: d-fault.nl/CIDRtoRegEx
DNS Lookup: d-fault.nl/DNSTools
DNSBL Lookup: d-fault.nl/DNSBLLookup
GEOIP Lookup: d-fault.nl/GeoipLookup

Post Reply