Pulling my hair out.. simple stringlen counter breaks script

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Message
Author
MKANET
Posts: 160
Joined: 31 Mar 2012 21:31

Re: Pulling my hair out.. simple stringlen counter breaks sc

#16 Post by MKANET » 02 Aug 2013 15:02

Penpen, the getstringlength subroutine takes relatively long; especially when the batch file runs against a very large log file. Is there any way to avoid having to call :getStringLength twice? Also, I tried my best to use the high performance macros stringlength method (that I posted in the first post); but, couldn't get it to work with the full script; problems with local delayed expansion/non-local variables; especially in the full script.

Here's the code without the typos :)

Code: Select all

@echo off
setlocal EnableDelayedExpansion


set "padding=                                                                                                                                                                          "
set "info=07/23/13 10:17:53am Service [stunnel-sslh] connected remote server from: c-24-12-152-129.hsd1.il.comcast.net [24.12.152.129]"
set "location= - United States of America"
set "info.length="
set "location.length="

call :getStringLength "info.length" "info"
call :getStringLength "location.length" "location"

set /A "min=%location.length%+%info.length%"

if %min% GEQ 170 goto :noPadding
set "print=%padding%%location%"
set "print=%print:~-170%"
call set "print=%info%%%print:~%info.length%%%"
goto :out

:noPadding
set "print=%info%%location%"

:out
echo "%print%"



goto :eof

:getStringLength
(   
    setlocal EnableDelayedExpansion
    set "s=!%~2!#"
    set "len=0"
    for %%P in (4096 2048 1024 512 256 128 64 32 16 8 4 2 1) do (
        if "!s:~%%P,1!" NEQ "" (
            set /a "len+=%%P"
            set "s=!s:~%%P!"
        )
    )
)
(
    endlocal
    set "%~1=%len%"
    exit /b
)


penpen
Expert
Posts: 2009
Joined: 23 Jun 2013 06:15
Location: Germany

Re: Pulling my hair out.. simple stringlen counter breaks sc

#17 Post by penpen » 02 Aug 2013 15:13

You may use a macro for :getStringLength like in the Thread:
http://www.dostips.com/forum/viewtopic.php?f=3&t=4452&p=25302&hilit=strLen+macro#p25302
See the post from jeb with timedtamp: 03 Apr 2013 10:54.
(Should be the third post there.)

Then you should also avoid:

Code: Select all

call set "print=%info%%%print:~%info.length%%%"


You can use delayed expansion for this, so it results in:

Code: Select all

set "print=!info!!print:~%info.length%!"



penpen

Magialisk
Posts: 104
Joined: 25 Jul 2013 19:00

Re: Pulling my hair out.. simple stringlen counter breaks sc

#18 Post by Magialisk » 02 Aug 2013 16:08

pen pen just wanted to say thanks for the tip about the for being in ( )'s thus not overwriting the file contents, as well as the info about that approach being faster than >>.

In the version of code I posted to correct his problem I removed the "extra" ( )'s around the FOR block, because I didn't think they were serving a purpose. Removing them of course necessitated the >>. Great tip as I'm always looking for ways to do things faster/better!

MKANET
Posts: 160
Joined: 31 Mar 2012 21:31

Re: Pulling my hair out.. simple stringlen counter breaks sc

#19 Post by MKANET » 02 Aug 2013 16:33

I have bad news and good news:

Bad News: We're back to the same issue I had when I started this thread. Although, I have much better padding code now (that works great by itself), it still breaks my main batch file. I get the same exact error that had me pulling my hair out before I started this thread. :(

The syntax of the command is incorrect. If I put echo ON, I still can't tell what's causing the problem. *sigh*

Code: Select all

@ECHO OFF
setlocal enableDelayedExpansion
set "log=stunnel.log"
set "logx=stunnelx.log"
for /f "tokens=1-3* delims= " %%a in ('findstr /V /I /C:"127.0.0" /C:"192.168" /C:"byte" /C:"WSAECONNRESET" /C:"Peer suddenly disconnected" "%log%"') do (
   set "dateValue=%%a"
   set "dateValue=!dateValue:~5,2!/!dateValue:~8,2!/!dateValue:~2,2!"
      for /F "tokens=1* delims=:" %%e in ("%%b") do (
         set /A "timeValue=%%e"
         if !timeValue! == 0 (
            set "timeValue=12:%%fam"
         ) else if !timeValue! Lss 12 (
            set "timeValue=%%e:%%fam"
         ) else if !timeValue! == 12 (
            set "timeValue=12:%%fpm"
         ) else (
            set /A "timeValue-=12"
            set "timeValue=0!timeValue!"
            set "timeValue=!timeValue:~-2!:%%fpm"
         )
      )
      set "info=%%d"   
      set "ipPort="
      for %%e in (!info!) do set "ipPort=%%e"
      for /F "tokens=1,2 delims=:" %%f in ("!ipPort!") do (
         if not defined IP[%%f] for /f "tokens=2 delims= " %%h in ('nslookup %%f 2^> nul ^| findstr /I /C:"Name" ') do set "IP[%%f]= %%h"
         if not defined IP[%%f] set "IP[%%f]= "
         set "host=!IP[%%f]:~1!"
         if defined host (
            set "info=!info: %%f:%%g=!: !host! [%%f]"
         ) else (
            set "info=!info: %%f:%%g=!: [%%f]"
         )
      )
   set "location=- United States of America"

   ::::::::::::::::::::: Padding Code :::::::::::::::::::::
   set "padding=                                                                                                                                                                          "
   set "info=!dateValue! !timeValue! !info!"
   set "info.length="
   set "location.length="
   setlocal disableDelayedExpansion
   call :getStringLength
   %$strlen%  "info.length" "info"

   call :getStringLength
   %$strlen%  "location.length" "location"
   setlocal EnableDelayedExpansion

   set /A "min=%location.length%+%info.length%"

   if %min% GEQ 170 goto :noPadding
   set "print=%padding%%location%"
   set "print=%print:~-170%"
   call set "print=!info!!print:~%info.length%!"
   goto :output

   :noPadding
   set "print=%info%%location%"
   :::::::::::::::::: End Padding Code ::::::::::::::::::::

   :output
   echo("%print%" >> "%logx%"
)

GOTO:EOF

:getStringLength
set LF=^


::Above 2 blank lines are required - do not remove
set ^"\n=^^^%LF%%LF%^%LF%%LF%^^"
:::: StrLen pResult pString
set $strLen=for /L %%n in (1 1 2) do if %%n==2 (%\n%
      for /F "tokens=1,2 delims=, " %%1 in ("!argv!") do (%\n%
         set "str=A!%%~2!"%\n%
           set "len=0"%\n%
           for /l %%A in (12,-1,0) do (%\n%
            set /a "len|=1<<%%A"%\n%
            for %%B in (!len!) do if "!str:~%%B,1!"=="" set /a "len&=~1<<%%A"%\n%
           )%\n%
           for %%v in (!len!) do endlocal^&if "%%~b" neq "" (set "%%~1=%%v") else echo %%v%\n%
      ) %\n%
) ELSE setlocal enableDelayedExpansion ^& set argv=,
exit /b


The good news: At least I have a much more efficient way to do padding. Below:

Code: Select all

@echo off
setlocal EnableDelayedExpansion


set "timeValue=11:44:32pm "
set "dateValue=07/23/13 "
set "info=Service [stunnel-sslh] accepted connection from: r74-194-126-35.jsbrcmta02.jnboar.lr.dh.suddenlink.net [74.194.126.35]"
set "location= - Mountain Home, Arkansas |United  States|"

::::::::::::::::::::: Padding Code :::::::::::::::::::::
set "padding=                                                                                                                                                                          "
set "info=!dateValue! !timeValue! !info!"
set "info.length="
set "location.length="
setlocal disableDelayedExpansion
call :getStringLength
%$strlen%  "info.length" "info"

call :getStringLength
%$strlen%  "location.length" "location"
setlocal EnableDelayedExpansion

set /A "min=%location.length%+%info.length%"

if %min% GEQ 170 goto :noPadding
set "print=%padding%%location%"
set "print=%print:~-170%"
call set "print=!info!!print:~%info.length%!"
goto :output

:noPadding
set "print=%info%%location%"
:::::::::::::::::: End Padding Code ::::::::::::::::::::

:output
echo("%print%"
)

goto :eof

:getStringLength
set LF=^


::Above 2 blank lines are required - do not remove
set ^"\n=^^^%LF%%LF%^%LF%%LF%^^"
:::: StrLen pResult pString
set $strLen=for /L %%n in (1 1 2) do if %%n==2 (%\n%
      for /F "tokens=1,2 delims=, " %%1 in ("!argv!") do (%\n%
         set "str=A!%%~2!"%\n%
           set "len=0"%\n%
           for /l %%A in (12,-1,0) do (%\n%
            set /a "len|=1<<%%A"%\n%
            for %%B in (!len!) do if "!str:~%%B,1!"=="" set /a "len&=~1<<%%A"%\n%
           )%\n%
           for %%v in (!len!) do endlocal^&if "%%~b" neq "" (set "%%~1=%%v") else echo %%v%\n%
      ) %\n%
) ELSE setlocal enableDelayedExpansion ^& set argv=,
exit /b

Magialisk
Posts: 104
Joined: 25 Jul 2013 19:00

Re: Pulling my hair out.. simple stringlen counter breaks sc

#20 Post by Magialisk » 02 Aug 2013 21:59

It looks to me like the exact same problem and solution as the last night. You are trying to GOTO :NoPadding inside of the big FOR loop. CALLs are OK because they return to inside the loop when they're done, but GOTO is no good. Last night I re-wrote the GOTOs as an IF SET <var> with an IF NOT DEFINED <var>, so that same technique should work here?

In addition, I noticed you're using a CALL inside the FOR to jump out and run the string length macro. Macros are fast, but CALLs are pathetically slow, so using a CALL to run a macro somewhat defeats the purpose. You want to try to encapsulate the maco code into variable expansions, something like: "%call_macro% ("param1 param2 etc") %macroname%". That example uses dbenham's syntax which I've just been getting familiar with over the last week or so. I guess the hotter trend is Jeb's syntax with the parameters at the end, but either way the object should be to avoid the CALL altogether.

MKANET
Posts: 160
Joined: 31 Mar 2012 21:31

Re: Pulling my hair out.. simple stringlen counter breaks sc

#21 Post by MKANET » 02 Aug 2013 23:58

Magialisk, the solution you had posted didn't work correctly (padding didn't work at all); even after I corrected the delayed expansion variable issue. However, I think I understand what you're saying; and, tried my best to apply the IF DEFINED approach. Unfortunately, my attempt to do that introduced all sorts of errors. See below full batch file using IF DEFINED. Hopefully, it wouldnt be too much trouble to just post a revised version of what I have below; with it actually working correctly :)

As far the macros, I just copied the same method used by Jeb when demonstrating his macro in the below post. He seemed to think it was pretty fast as-is in his demonstration. Once we get the batch file working correctly, we can address a faster way to use the macro.
http://www.dostips.com/forum/viewtopic.php?f=3&t=4452&p=25302&hilit=strLen+macro#p25302

Code: Select all

@ECHO OFF
setlocal enableDelayedExpansion
set "log=stunnel.log"
set "logx=stunnelx.log"
for /f "tokens=1-3* delims= " %%a in ('findstr /V /I /C:"127.0.0" /C:"192.168" /C:"byte" /C:"WSAECONNRESET" /C:"Peer suddenly disconnected" "%log%"') do (
   set "dateValue=%%a"
   set "dateValue=!dateValue:~5,2!/!dateValue:~8,2!/!dateValue:~2,2!"
      for /F "tokens=1* delims=:" %%e in ("%%b") do (
         set /A "timeValue=%%e"
         if !timeValue! == 0 (
            set "timeValue=12:%%fam"
         ) else if !timeValue! Lss 12 (
            set "timeValue=%%e:%%fam"
         ) else if !timeValue! == 12 (
            set "timeValue=12:%%fpm"
         ) else (
            set /A "timeValue-=12"
            set "timeValue=0!timeValue!"
            set "timeValue=!timeValue:~-2!:%%fpm"
         )
      )
      set "info=%%d"   
      set "ipPort="
      for %%e in (!info!) do set "ipPort=%%e"
      for /F "tokens=1,2 delims=:" %%f in ("!ipPort!") do (
         if not defined IP[%%f] for /f "tokens=2 delims= " %%h in ('nslookup %%f 2^> nul ^| findstr /I /C:"Name" ') do set "IP[%%f]= %%h"
         if not defined IP[%%f] set "IP[%%f]= "
         set "host=!IP[%%f]:~1!"
         if defined host (
            set "info=!info: %%f:%%g=!: !host! [%%f]"
         ) else (
            set "info=!info: %%f:%%g=!: [%%f]"
         )
      )
   set "location=- United States of America"

   ::::::::::::::::::::: Padding Code :::::::::::::::::::::
   set "padding=                                                                                                                                                                          "
   set "info=!dateValue! !timeValue! !info!"
   set "info.length="
   set "location.length="
   setlocal disableDelayedExpansion
   call :getStringLength
   %$strlen%  "info.length" "info"

   call :getStringLength
   %$strlen%  "location.length" "location"
   setlocal EnableDelayedExpansion

   set /A "min=%location.length%+%info.length%"

   if !min! GEQ 170 set skippadding=1
   IF NOT DEFINED skippadding (
   set "print=%padding%%location%"
   set "print=%print:~-170%"
   call set "print=!info!!print:~%info.length%!"
   )

   IF DEFINED skippadding (
   set "print=%info%%location%"
   ) ELSE (
   echo("%print%" >> "%logx%"
   )
)



GOTO:EOF

:getStringLength
set LF=^


::Above 2 blank lines are required - do not remove
set ^"\n=^^^%LF%%LF%^%LF%%LF%^^"
:::: StrLen pResult pString
set $strLen=for /L %%n in (1 1 2) do if %%n==2 (%\n%
      for /F "tokens=1,2 delims=, " %%1 in ("!argv!") do (%\n%
         set "str=A!%%~2!"%\n%
           set "len=0"%\n%
           for /l %%A in (12,-1,0) do (%\n%
            set /a "len|=1<<%%A"%\n%
            for %%B in (!len!) do if "!str:~%%B,1!"=="" set /a "len&=~1<<%%A"%\n%
           )%\n%
           for %%v in (!len!) do endlocal^&if "%%~b" neq "" (set "%%~1=%%v") else echo %%v%\n%
      ) %\n%
) ELSE setlocal enableDelayedExpansion ^& set argv=,
exit /b

Magialisk wrote:It looks to me like the exact same problem and solution as the last night. You are trying to GOTO :NoPadding inside of the big FOR loop. CALLs are OK because they return to inside the loop when they're done, but GOTO is no good. Last night I re-wrote the GOTOs as an IF SET <var> with an IF NOT DEFINED <var>, so that same technique should work here?

In addition, I noticed you're using a CALL inside the FOR to jump out and run the string length macro. Macros are fast, but CALLs are pathetically slow, so using a CALL to run a macro somewhat defeats the purpose. You want to try to encapsulate the maco code into variable expansions, something like: "%call_macro% ("param1 param2 etc") %macroname%". That example uses dbenham's syntax which I've just been getting familiar with over the last week or so. I guess the hotter trend is Jeb's syntax with the parameters at the end, but either way the object should be to avoid the CALL altogether.

Magialisk
Posts: 104
Joined: 25 Jul 2013 19:00

Re: Pulling my hair out.. simple stringlen counter breaks sc

#22 Post by Magialisk » 03 Aug 2013 06:06

Here's what I did:

1.) Move the CALL :get Stringlength out of the FOR loop. I put it just under the @echo off. It only needs to run once to define the macro, not every time you want to call the macro. That was my point last night, though I admit I didn't make it clear. Just make sure it's always before you enable delayed expansion and you'll be fine.
2.) Because of #1, not only do we get rid of two CALLs per FOR iteration, but we don't need the setlocal/endlocal inside the FOR either, so I deleted those. These changes should greatly improve the speed.
* At this point the program "ran" fine, but gave "missing operand" errors and output only ""s *
3.) Missing operaand is a dead giveaway for a set /A statement problem, so I changed the %%'s to !!'s and that error went away.
4.) Outputting ""s leads me to believe your print statements were outputting null, so again I changed the %%'s to !!'s and that seems to have fixed it. I now get an output log that looks like what you want, with padding before the location.

Code: Select all

"07/23/13 10:16:00am Service [stunnel-sslh] connected remote server from: c-24-12-152-129.hsd1.il.comcast.net [24.12.152.129]                    - United States of America" 
"07/23/13 10:17:53am Service [stunnel-sslh] accepted connection from: c-71-194-51-232.hsd1.il.comcast.net [71.194.51.232]                        - United States of America"
"07/23/13 10:17:53am connect_blocking: connected: c-24-12-152-129.hsd1.il.comcast.net [24.12.152.129]                                            - United States of America"
"07/23/13 10:17:53am Service [stunnel-sslh] connected remote server from: c-24-12-152-129.hsd1.il.comcast.net [24.12.152.129]                    - United States of America"
"07/23/13 10:17:53am Service [stunnel-sslh] accepted connection from: c-71-194-51-232.hsd1.il.comcast.net [71.194.51.232]                        - United States of America"
"07/23/13 10:17:53am Service [stunnel-sslh] accepted connection from: c-71-194-51-232.hsd1.il.comcast.net [71.194.51.232]                        - United States of America"
"07/23/13 10:17:53am Service [stunnel-sslh] accepted connection from: c-71-194-51-232.hsd1.il.comcast.net [71.194.51.232]                        - United States of America"

A few other minor changes I wanted to point out:
5.) In the IF DEFINED skippadding block I added a 'set skippadding=' to "reset" the flag. So you check the length, set the flag if it's longer than 170, run whichever code block based on the flag, but then reset the flag if it's set, so it doesn't stay set forever. BTW this use of a flag to determine code path vs. labels and GOTOs is just something I've been doing for years so it's old habit. I don't know if it's the best, or even a good way, but it does work for me. I just don't want to be accused of teaching you bad coding habits :)
6.) Another old habit I don't know whether it's good or bad: I changed your 'CALL set' to a FOR loop in the NOT DEFINED skippadding block. This is just a method I came up with when I need something like !VAR[!index!]! inside a FOR loop, I let a second FOR expand the index as %%b and then get !VAR[%%b]!. I believe this will be faster than a 'CALL set', but it accomplishes the same thing. If I'm off base in my belief, or if there's an even better way, I'd love to learn it. (penpen?)
7.) I wasn't sure what you were trying to do with the ELSE before the 'echo print >>log'. The way I was reading the logic it was saying If skippadding is defined do this, otherwise print to the log. I assume you wanted all lines printed, whether you padded them or not, so I removed the ELSE. I looked above to see if it belonged to an earlier code block, but found nothing to tie it to...

Here's the final code:

Code: Select all

@ECHO OFF
call :getStringLength
setlocal enableDelayedExpansion
set "log=stunnel.log"
set "logx=stunnelx.log"


for /f "tokens=1-3* delims= " %%a in ('findstr /V /I /C:"127.0.0" /C:"192.168" /C:"byte"

/C:"WSAECONNRESET" /C:"Peer suddenly disconnected" "%log%"') do (
   set "dateValue=%%a"
   set "dateValue=!dateValue:~5,2!/!dateValue:~8,2!/!dateValue:~2,2!"
      for /F "tokens=1* delims=:" %%e in ("%%b") do (
         set /A "timeValue=%%e"
         if !timeValue! == 0 (
            set "timeValue=12:%%fam"
         ) else if !timeValue! Lss 12 (
            set "timeValue=%%e:%%fam"
         ) else if !timeValue! == 12 (
            set "timeValue=12:%%fpm"
         ) else (
            set /A "timeValue-=12"
            set "timeValue=0!timeValue!"
            set "timeValue=!timeValue:~-2!:%%fpm"
         )
      )
      set "info=%%d"   
      set "ipPort="
      for %%e in (!info!) do set "ipPort=%%e"
      for /F "tokens=1,2 delims=:" %%f in ("!ipPort!") do (
         if not defined IP[%%f] for /f "tokens=2 delims= " %%h in ('nslookup %%f 2^> nul ^| findstr

/I /C:"Name" ') do set "IP[%%f]= %%h"
         if not defined IP[%%f] set "IP[%%f]= "
         set "host=!IP[%%f]:~1!"
         if defined host (
            set "info=!info: %%f:%%g=!: !host! [%%f]"
         ) else (
            set "info=!info: %%f:%%g=!: [%%f]"
         )
      )

   set "location=- United States of America"

   ::::::::::::::::::::: Padding Code :::::::::::::::::::::
   set "padding=                                                                                     

                                                                                    "
   set "info=!dateValue! !timeValue! !info!"
   set "info.length="
   set "location.length="
   %$strlen%  "info.length" "info"
   %$strlen%  "location.length" "location"
   set /A "min=!location.length!+!info.length!"
   if !min! GEQ 170 set skippadding=1
   IF NOT DEFINED skippadding (
      set "print=!padding!!location!"
      set "print=!print:~-170!"
      FOR %%b IN (!info.length!) DO (
         set "print=!info!!print:~%%b!"
      )
   )
   IF DEFINED skippadding (
      set "print=!info!!location!"
      set skippadding=
   )
   echo("!print!" >> "%logx%"
)
GOTO:EOF

:getStringLength
set LF=^


::Above 2 blank lines are required - do not remove
set ^"\n=^^^%LF%%LF%^%LF%%LF%^^"
:::: StrLen pResult pString
set $strLen=for /L %%n in (1 1 2) do if %%n==2 (%\n%
      for /F "tokens=1,2 delims=, " %%1 in ("!argv!") do (%\n%
         set "str=A!%%~2!"%\n%
           set "len=0"%\n%
           for /l %%A in (12,-1,0) do (%\n%
            set /a "len|=1<<%%A"%\n%
            for %%B in (!len!) do if "!str:~%%B,1!"=="" set /a "len&=~1<<%%A"%\n%
           )%\n%
           for %%v in (!len!) do endlocal^&if "%%~b" neq "" (set "%%~1=%%v") else echo %%v%\n%
      ) %\n%
) ELSE setlocal enableDelayedExpansion ^& set argv=,
exit /b

penpen
Expert
Posts: 2009
Joined: 23 Jun 2013 06:15
Location: Germany

Re: Pulling my hair out.. simple stringlen counter breaks sc

#23 Post by penpen » 03 Aug 2013 18:34

I have revised the code to make it faster.
It is not much i fear:

Code: Select all

@echo off
setlocal
call :getStringLength

setlocal enableDelayedExpansion
set "log=stunnel log\stunnel.log"
set "logx=stunnel log\stunnelx.log"
set "location= - United States of America"
set "location.length="
set "padding=                                                                                                                                                                          "

for /L %%a in ( 0, 1, 9) do set "meridiemness[0%%a]=am"
for /L %%a in ( 0, 1,11) do set "meridiemness[%%a]=am"
for /L %%a in (12, 1,23) do set "meridiemness[%%a]=pm"
for /L %%a in (0, 1, 23) do (
   set /A "num=((11 + %%a)%%12)+101"
   set "hour[!num:~-2!]=!num:~-2!"
   set "hour[%%a]=!num:~-2!"
)
set "hour[00]=12"

(
   for /f "tokens=1-3* delims= " %%a in ('findstr /V /I /C:"127.0.0" /C:"192.168" /C:"byte" /C:"WSAECONNRESET" /C:"Peer suddenly disconnected" "%log%"') do (
      set "dateValue=%%a"
      set "dateValue=!dateValue:~5,2!/!dateValue:~8,2!/!dateValue:~2,2!"

      for /F "tokens=1* delims=:" %%A in ("%%b") do set "timeValue=!hour[%%A]!:%%B!meridiemness[%%A]!"

      set "info=%%d"

      set "ipPort="
      for %%A in (!info:-24!) do set "ipPort=%%A"
      for /F "tokens=1 delims=0123456789.:" %%e in ("!ipPort!") do set "ipPort="
      for /F "tokens=1,2 delims=:" %%A in ("!ipPort!") do (
         if not defined DN[%%A] (
            for /f "tokens=2 delims= " %%0 in ('nslookup %%A 2^> nul ^| findstr /I /C:"Name" ') do set "DN[%%A]= %%0 "
            if not defined DN[%%A] set "DN[%%A]= "
         )
         set "info=!info: %%A:%%B=!:!DN[%%A]![%%A]"
      )
      set "info=!dateValue! !timeValue! !info!"

      ::::::::::::::::::::: Padding Code :::::::::::::::::::::
      set "print=!info!!location!"
      %$strlen% "print.length" "print"
      set /A "availablePaddingChars=170-!print.length!"
      if 0 LSS !availablePaddingChars! for %%A in (!availablePaddingChars!) do set "print=!info!!padding:~-%%A!!location!"

      echo(!print!
   )
) > "%logx%"

endlocal
endlocal
goto :eof


:getStringLength
set LF=^


::Above 2 blank lines are required - do not remove
set ^"\n=^^^%LF%%LF%^%LF%%LF%^^"

:::: StrLen pResult pString
set $strLen=for /L %%n in (1 1 2) do if %%n==2 (%\n%
   for /F "tokens=1,2 delims=, " %%1 in ("!argv!") do (%\n%
      set "str=A!%%~2!"%\n%
      set "len=0"%\n%
      for /l %%A in (12,-1,0) do (%\n%
         set /a "len|=1<<%%A"%\n%
         for %%B in (!len!) do if "!str:~%%B,1!"=="" set /a "len&=~1<<%%A"%\n%
      )%\n%
      for %%v in (!len!) do endlocal^&if "%%~b" neq "" (set "%%~1=%%v") else echo %%v%\n%
   ) %\n%
) ELSE setlocal enableDelayedExpansion ^& set argv=,
exit /b

penpen

Edit:
added set "hour[00]=12" to correct the code,
added for /F "tokens=1 delims=0123456789.:" %%e in ("!ipPort!") do set "ipPort=" to ignore lines without names at end
Edit2:
added :~-24 in the line above to speed up ip:port detection
Last edited by penpen on 04 Aug 2013 03:50, edited 2 times in total.

MKANET
Posts: 160
Joined: 31 Mar 2012 21:31

Re: Pulling my hair out.. simple stringlen counter breaks sc

#24 Post by MKANET » 03 Aug 2013 22:24

@Magialisk the second time you explained how to access the macro, it made much more sense. I was able to follow each change you made; and, comprehend it! I still need to feel comfortable with the full code in it's entirety; so, I can use similar technique in other batch files. I'll always remember you for showing me the IF NOT DEFINED technique; and, when seeing a "Missing operand" to know it's related to "set /A" statement problems; and, change any %%'s to !!'s.

@Penpen I really appreciate your final performance enhancements. I actually preferred your method of surrounding the whole batch file with parentheses to redirect output to stunnelx.log. I needed to squeeze as much performance as I could get in the batch file; in order to accommodate my GeoIP subroutine (which plugged in very easily) to define the !location! variable. :) With a couple of minor changes to the batch file, I get the final stunnelx.log output below. The log file looks very nice on a high-resolution/wide screen display; just maximize your web browser! 8)

Just a couple of minor issues... If my original stunnel.log has a line such as:

Code: Select all

2013.07.23 15:48:05 LOG3[10152:7688]: SSL_accept: 1408F10B: error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number

... it confuses the batch file into thinking the last word is an IP; and, unnecessarily adds, ": [number]"

Code: Select all

07/23/13 03:48:05pm - SSL_accept: 1408F10B: error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number: [number]


Also when the time stamp is supposed to show 12:38:58am, it shows :38:58am instead.

Example output:

Code: Select all

07/23/13 11:17:05am - Service [stunnel-sslh] accepted connection from: pool-100-4-182-108.albyny.fios.verizon.net [100.4.182.108]
07/23/13 11:17:05am - Service [stunnel-sslh] accepted connection from: pool-100-4-182-108.albyny.fios.verizon.net [100.4.182.108]
07/23/13 11:17:05am - Service [stunnel-sslh] accepted connection from: pool-100-4-182-108.albyny.fios.verizon.net [100.4.182.108]
07/23/13 11:17:23am - Service [stunnel-sslh] accepted connection from: 5.10.83.87-static.reverse.softlayer.com [5.10.83.87]        ◄ Netherlands ►
07/23/13 11:18:14am - Service [stunnel-sslh] accepted connection from: 178-134-122-88.dsl.utg.ge [178.134.122.88]                  ◄ Georgia ►
07/23/13 11:18:37am - Service [stunnel-sslh] accepted connection from: 5.10.83.87-static.reverse.softlayer.com [5.10.83.87]        ◄ Netherlands ►
07/23/13 11:19:43am - Service [stunnel-sslh] accepted connection from: 5.10.83.87-static.reverse.softlayer.com [5.10.83.87]        ◄ Netherlands ►
07/23/13 11:24:07am - Service [stunnel-sslh] accepted connection from: dyn-86.106.34.164.tm.upcnet.ro [86.106.34.164]              ◄ Romania ► Timisoara, Timiş
07/23/13 11:24:27am - Service [stunnel-sslh] accepted connection from: 5.10.83.87-static.reverse.softlayer.com [5.10.83.87]        ◄ Netherlands ►
07/23/13 11:30:39am - Service [stunnel-sslh] accepted connection from: 5.10.83.87-static.reverse.softlayer.com [5.10.83.87]        ◄ Netherlands ►
07/23/13 11:32:25am - Service [stunnel-sslh] accepted connection from: 5.10.83.87-static.reverse.softlayer.com [5.10.83.87]        ◄ Netherlands ►
07/23/13 11:35:36am - Service [stunnel-sslh] accepted connection from: 5.10.83.87-static.reverse.softlayer.com [5.10.83.87]        ◄ Netherlands ►
07/23/13 11:37:33am - Service [stunnel-sslh] accepted connection from: 5.10.83.87-static.reverse.softlayer.com [5.10.83.87]        ◄ Netherlands ►
07/23/13 11:37:38am - Service [stunnel-sslh] accepted connection from: 5.10.83.87-static.reverse.softlayer.com [5.10.83.87]        ◄ Netherlands ►
07/23/13 11:39:26am - Service [stunnel-sslh] accepted connection from: 5.10.83.87-static.reverse.softlayer.com [5.10.83.87]        ◄ Netherlands ►
07/23/13 11:39:55am - Service [stunnel-sslh] accepted connection from: [180.76.4.57]                                               ◄ China ► Beijing, Beijing
07/23/13 11:39:56am - Service [stunnel-sslh] accepted connection from: [180.76.4.248]                                              ◄ China ► Beijing, Beijing
07/23/13 11:45:00am - Service [stunnel-sslh] accepted connection from: 5.10.83.87-static.reverse.softlayer.com [5.10.83.87]        ◄ Netherlands ►
07/23/13 11:47:50am - Service [stunnel-sslh] accepted connection from: 5.10.83.87-static.reverse.softlayer.com [5.10.83.87]        ◄ Netherlands ►
07/23/13 11:50:45am - Service [stunnel-sslh] accepted connection from: 5.10.83.87-static.reverse.softlayer.com [5.10.83.87]        ◄ Netherlands ►
07/23/13 11:50:54am - Service [stunnel-sslh] accepted connection from: 5.10.83.87-static.reverse.softlayer.com [5.10.83.87]        ◄ Netherlands ►
07/23/13 11:51:15am - Service [stunnel-sslh] accepted connection from: 5.10.83.87-static.reverse.softlayer.com [5.10.83.87]        ◄ Netherlands ►
07/23/13 12:01:53pm - Service [stunnel-sslh] accepted connection from: crawl-66-249-74-201.googlebot.com [66.249.74.201]           ◄ United States ► Mountain View, California
07/23/13 12:03:20pm - Service [stunnel-sslh] accepted connection from: 5.10.83.87-static.reverse.softlayer.com [5.10.83.87]        ◄ Netherlands ►
07/23/13 12:04:08pm - Service [stunnel-sslh] accepted connection from: 5.10.83.87-static.reverse.softlayer.com [5.10.83.87]        ◄ Netherlands ►
07/23/13 12:07:30pm - Service [stunnel-sslh] accepted connection from: 5.10.83.87-static.reverse.softlayer.com [5.10.83.87]        ◄ Netherlands ►
07/23/13 12:14:20pm - Service [stunnel-sslh] accepted connection from: [220.181.89.150]                                            ◄ China ► Beijing, Beijing
07/23/13 12:14:28pm - Service [stunnel-sslh] accepted connection from: [121.54.54.54]                                              ◄ Philippines ► Quezon City, Quezon City
07/23/13 12:14:28pm - Service [stunnel-sslh] accepted connection from: [121.54.54.54]                                              ◄ Philippines ► Quezon City, Quezon City
07/23/13 12:16:51pm - Service [stunnel-sslh] accepted connection from: 5.10.83.87-static.reverse.softlayer.com [5.10.83.87]        ◄ Netherlands ►
07/23/13 12:17:43pm - Service [stunnel-sslh] accepted connection from: [121.54.54.54]                                              ◄ Philippines ► Quezon City, Quezon City
07/23/13 12:17:43pm - Service [stunnel-sslh] accepted connection from: [121.54.54.54]                                              ◄ Philippines ► Quezon City, Quezon City
07/23/13 12:18:15pm - Service [stunnel-sslh] accepted connection from: 178-134-122-88.dsl.utg.ge [178.134.122.88]                  ◄ Georgia ►
07/23/13 12:18:20pm - Service [stunnel-sslh] accepted connection from: [121.54.54.54]                                              ◄ Philippines ► Quezon City, Quezon City
07/23/13 12:18:21pm - Service [stunnel-sslh] accepted connection from: [121.54.54.54]                                              ◄ Philippines ► Quezon City, Quezon City
07/23/13 12:18:21pm - Service [stunnel-sslh] accepted connection from: [121.54.54.54]                                              ◄ Philippines ► Quezon City, Quezon City
07/23/13 12:21:04pm - Service [stunnel-sslh] accepted connection from: 139.sub-70-197-3.myvzw.com [70.197.3.139]                   ◄ United States ► Dublin, California
07/23/13 12:21:05pm - Service [stunnel-sslh] accepted connection from: 139.sub-70-197-3.myvzw.com [70.197.3.139]                   ◄ United States ► Dublin, California
07/23/13 03:48:05pm - Service [stunnel-sslh] accepted connection from: 75-131-120-23.dhcp.jcsn.tn.charter.com [75.131.120.23]      ◄ United States ► Clarksville, Tennessee
07/23/13 03:48:05pm - SSL_accept: 1408F10B: error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number: [number]         
07/23/13 06:11:02pm - SSL_accept: 1408F10B: error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number: [number]         
07/23/13 06:17:20pm - SSL_accept: 1408F10B: error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number: [number]         
07/24/13 :14:29am - Service [stunnel-sslh] accepted connection from: crawl-66-249-74-201.googlebot.com [66.249.74.201]            ◄ United States ►  Mountain View, California
07/24/13 :18:23am - Service [stunnel-sslh] accepted connection from: 178-134-122-88.dsl.utg.ge [178.134.122.88]                   ◄ Georgia ►
07/24/13 :19:53am - Service [stunnel-sslh] accepted connection from: msnbot-157-55-33-27.search.msn.com [157.55.33.27]            ◄ United States ►
07/24/13 :28:30am - Service [stunnel-sslh] accepted connection from: msnbot-157-55-33-27.search.msn.com [157.55.33.27]            ◄ United States ►
07/24/13 :38:57am - Service [stunnel-sslh] accepted connection from: baiduspider-180-76-5-141.crawl.baidu.com [180.76.5.141]      ◄ China ►  Beijing, Beijing
07/24/13 :38:58am - Service [stunnel-sslh] accepted connection from: baiduspider-180-76-5-170.crawl.baidu.com [180.76.5.170]      ◄ China ►  Beijing, Beijing

penpen
Expert
Posts: 2009
Joined: 23 Jun 2013 06:15
Location: Germany

Re: Pulling my hair out.. simple stringlen counter breaks sc

#25 Post by penpen » 04 Aug 2013 04:03

MKANET wrote:Just a couple of minor issues... If my original stunnel.log has a line such as:

Code: Select all

2013.07.23 15:48:05 LOG3[10152:7688]: SSL_accept: 1408F10B: error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number
... it confuses the batch file into thinking the last word is an IP; and, unnecessarily adds, ": [number]"

Code: Select all

07/23/13 03:48:05pm - SSL_accept: 1408F10B: error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number: [number]

This is because you have deleted one line that avoids this in the last thread. I thought you don't need it anymore:

Code: Select all

for /F "tokens=1 delims=0123456789.:" %%e in ("!ipPort!") do set "ipPort="
I have reimplemented it in the code above.

MKANET wrote:Also when the time stamp is supposed to show 12:38:58am, it shows :38:58am instead.
Ups :oops: , i have corrected the code in my last post, so it shows the 12.

And i've found a minor speed up, that i have added to this code, too.

penpen

Magialisk
Posts: 104
Joined: 25 Jul 2013 19:00

Re: Pulling my hair out.. simple stringlen counter breaks sc

#26 Post by Magialisk » 04 Aug 2013 05:57

I'm glad it's working well for you now MKANET. I have a portrait eyefinity setup so I pulled my browser across two of the screens and you're right, that's a nice clean log output! Thanks to penpen I even got to learn a couple things along the way.

MKANET
Posts: 160
Joined: 31 Mar 2012 21:31

Re: Pulling my hair out.. simple stringlen counter breaks sc

#27 Post by MKANET » 05 Aug 2013 19:34

This was a great learning experience for me guys. One thing I realized...

I will be running this batch file regularly against a constantly updating/growing stunnel.log file. It wouldn't make sense to run it against part of the log that has already been processed. So, I added a few more lines of code so the batch file will "remember" the last place it stopped (saving date/time stamp to a temp file). I'm not sure how ugly the code is that I added. Maybe there's a much better way to do it? I also included the GeoIP code as well.

...just one thing that REALLY puzzled me! For some weird reason, I had to do:

Code: Select all

if exist "!lastrun.tmp!" (
   for /f "delims=" %%a in ('type "!lastrun.tmp!"') do set "lastrun.tmp.contents=%%a"
   ) else (
   set PROCESS=yes
)

instead of this:

Code: Select all

if exist "!lastrun.tmp!" (
   for /f "delims=" %%a in ("!lastrun.tmp!") do set "lastrun.tmp.contents=%%a"
   ) else (
   set PROCESS=yes
)

I tried all sorts of things; no matter what I tried, I couldn't use only "!lastrun.tmp!" or "%lastrun.tmp%" surrounded by quotes by itself. I had to turn it into a command and type the contents. I'm sure its a "novice" mistake. But, it would be good to know if there's a simpler way to ultimately achieve what I wanted.

Here's the full/final code I have:

Code: Select all

@echo off
setlocal
call :getStringLength

setlocal enableDelayedExpansion
set "log=\stunnel.log"
set "logx=\stunnelx.log"
set "lastrun.tmp=D:\Multimedia Files\lastrun.tmp"
set "location.length="
set "padding=                                                                                                                                 "
set "PROCESS="
set "CurrentRawTimeStamp="

if exist "!lastrun.tmp!" (
   for /f "delims=" %%a in ('type "!lastrun.tmp!"') do set "lastrun.tmp.contents=%%a"
   ) else (
   set PROCESS=yes
)

for /L %%a in ( 0, 1, 9) do set "meridiemness[0%%a]=am"
for /L %%a in ( 0, 1,11) do set "meridiemness[%%a]=am"
for /L %%a in (12, 1,23) do set "meridiemness[%%a]=pm"
for /L %%a in (0, 1, 23) do (
   set /A "num=((11 + %%a)%%12)+101"
   set "hour[!num:~-2!]=!num:~-2!"
   set "hour[%%a]=!num:~-2!"
)
set "hour[00]=12"

(
   for /f "tokens=1-3* delims= " %%a in ('findstr /V /I /C:"127.0.0" /C:"192.168" /C:"byte" /C:"WSAECONNRESET" /C:"Peer suddenly disconnected" "%log%"') do (
     set "CurrentRawTimeStamp=%%a %%b"
     if defined PROCESS (
        set "dateValue=%%a"
        set "dateValue=!dateValue:~5,2!/!dateValue:~8,2!/!dateValue:~2,2!"

        for /F "tokens=1* delims=:" %%A in ("%%b") do set "timeValue=!hour[%%A]!:%%B!meridiemness[%%A]!"

        set "info=%%d"

        set "ipPort="
        for %%A in (!info:~24!) do set "ipPort=%%A"
        for /F "tokens=1 delims=0123456789.:" %%e in ("!ipPort!") do set "ipPort="
        for /F "tokens=1,2 delims=:" %%A in ("!ipPort!") do (
          if not defined DN[%%A] (
            for /f "tokens=2 delims= " %%0 in ('nslookup %%A 2^> nul ^| findstr /I /C:"Name" ') do set "DN[%%A]= %%0 "
            if not defined DN[%%A] set "DN[%%A]= "
          )
          set "info=!info: %%A:%%B=!:!DN[%%A]![%%A]"
        call :GeoIP %%A
        )
        set "info=!dateValue! !timeValue! - !info!"

        ::::::::::::::::::::: Padding Code :::::::::::::::::::::
        set "print=!info!"
        %$strlen% "print.length" "print"
        set /A "availablePaddingChars=129-!print.length!"
        if 0 LSS !availablePaddingChars! for %%A in (!availablePaddingChars!) do set "print=!info!!padding:~-%%A!!location!"

        echo(!print!
     )
     if [!CurrentRawTimeStamp!] == [!lastrun.tmp.contents!] set PROCESS=yes
   )
) >> "%logx%"
echo(!CurrentRawTimeStamp!>"!lastrun.tmp!"

endlocal
endlocal


goto :eof
:GeoIP
set "location="
set "country="
set "state="
set "city="
for /F "tokens=*" %%a in ('curl -s freegeoip.net/json/%1') do set geoIP=%%a
for /F "tokens=1-6 delims=," %%a in ("!geoIP!") do (
   set "country=%%c"
   set "state=%%e"
   set "city=%%f"
   )
for /F "tokens=1-2 delims=:" %%a in ("!country!") do set "country= ◄ %%~b ►"
for /F "tokens=1-2 delims=:" %%a in ("!state!") do set "state= %%~b"
for /F "tokens=1-2 delims=:" %%a in ("!city!") do set "city= %%~b,"
if "!city!" == " ," set "city="
if "!state!" == " " set "state="
if "!country!" == " ||" set "country="
if not [!city!!state!!country!] == [] set "location=!country! !city!!state!"
exit /b

:getStringLength
set LF=^


::Above 2 blank lines are required - do not remove
set ^"\n=^^^%LF%%LF%^%LF%%LF%^^"

:::: StrLen pResult pString
set $strLen=for /L %%n in (1 1 2) do if %%n==2 (%\n%
   for /F "tokens=1,2 delims=, " %%1 in ("!argv!") do (%\n%
      set "str=A!%%~2!"%\n%
      set "len=0"%\n%
      for /l %%A in (12,-1,0) do (%\n%
         set /a "len|=1<<%%A"%\n%
         for %%B in (!len!) do if "!str:~%%B,1!"=="" set /a "len&=~1<<%%A"%\n%
      )%\n%
      for %%v in (!len!) do endlocal^&if "%%~b" neq "" (set "%%~1=%%v") else echo %%v%\n%
   ) %\n%
) ELSE setlocal enableDelayedExpansion ^& set argv=,
exit /b

Magialisk
Posts: 104
Joined: 25 Jul 2013 19:00

Re: Pulling my hair out.. simple stringlen counter breaks sc

#28 Post by Magialisk » 05 Aug 2013 20:53

I only took a quick glance, so forgive me if I'm wrong, but I believe you just need to add usebackq in the FOR statement. So it would look something like: FOR /F "usebackq tokens= delims= " %%a IN ("%filename%") DO (.

filename can be %%'s or !!'s as necessary of course, but it's the lack of backquotes that I believe is hanging you up.

Editing to add: Another thing you might want to consider is the "skip=" option in the FOR loop. It tells it to skip some number of lines at the top of the file. So maybe instead of having a second file with a timestamp and Geo-ID, you could just count how many lines you processed in the log file each run, and use that (cumulatively) as the number of lines to skip for the next time? I guess you'd still need a place to store that number... maybe the registry instead of a second file? One other technique I have yet to experiment with is Alternate Data Streams (ADS). You could actually store the line count (or your timestamp/Geo-ID) as a hidden ADS within the batch file itself. As long as you don't move the batch file off an NTFS filesystem (ie: onto a USB drive) that hidden data will stay with the file. Something I learned in a recent cyber security course as a way to hide malicious data on a victim machine, and I've been itching to try out for a legitimate purpose :)

penpen
Expert
Posts: 2009
Joined: 23 Jun 2013 06:15
Location: Germany

Re: Pulling my hair out.. simple stringlen counter breaks sc

#29 Post by penpen » 06 Aug 2013 02:08

If the log file grows always without losing data on the first lines,
then using the line number should be easier and faster i think.
But if the log file size is limited to 64 MB (for example) then the first
lines will be deleted, if the limit is reached.
If that happens the timestamp solution will be more robust.

Another thing is, that your padding actually is not working anymore, as you changed the code to:

Code: Select all

:: as you changed this code
::::::::::::::::::::: Padding Code :::::::::::::::::::::
        set "print=!info!!location!"

:: to
::::::::::::::::::::: Padding Code :::::::::::::::::::::
        set "print=!info!"


And the last thing is, that you should avoid calls (call :GeoIP %%A
) for speedup, so you should make a macro of it.

penpen

MKANET
Posts: 160
Joined: 31 Mar 2012 21:31

Re: Pulling my hair out.. simple stringlen counter breaks sc

#30 Post by MKANET » 06 Aug 2013 22:57

Penpen/Magialisk:

I did what you suggested with taking advantage of for /f "skip=" feature (see code below). Although, this method should be faster, the code didn't appear any more simpler than what I had before. There was an unexpected weird limitation with for /f "skip=0" failing if 0 is a variable (which I learned the hard way). See http://stackoverflow.com/questions/6452323/why-does-for-f-skip-0-fail

I did play with alternate data streams. Unfortunately, it wasn't very practical in this case. There are only two native Windows commands that even know about ADS: "echo" and "more". So, my options on how to use it were very limited. For example, I couldn't use it with an if exist %adsfilename% command or a for /f %%a in (%adsfilename%) do. I didn't want to rely on any more on external non-native Windows command-line commands; which could further make the code unnecessarily complex. Plus, it's easier to delete the temp file via Windows Explorer (in case I need to reset the log files).

@Penpen: The change I made to the padding code was actually on purpose (due to a recent formatting re-arrangement I made to the location variable formatting. I actually think it looks much better than before (see difference below)

Before padding change:

Code: Select all

07/23/13 11:17:05am Service [stunnel-sslh] accepted connection from: pool-100-4-182-108.albyny.fios.verizon.net [100.4.182.108]                           -  ◄ United States ►
07/23/13 11:17:23am Service [stunnel-sslh] accepted connection from: 5.10.83.87-static.reverse.softlayer.com [5.10.83.87]                                   -  ◄ Netherlands ►
07/23/13 11:18:14am Service [stunnel-sslh] accepted connection from: 178-134-122-88.dsl.utg.ge [178.134.122.88]                                                 -  ◄ Georgia ►
07/23/13 11:19:43am Service [stunnel-sslh] accepted connection from: 5.10.83.87-static.reverse.softlayer.com [5.10.83.87]                                   -  ◄ Netherlands ►
07/23/13 11:39:55am Service [stunnel-sslh] accepted connection from: [180.76.4.57]                                                               -  Beijing, Beijing ◄ China ►
07/23/13 11:39:56am Service [stunnel-sslh] accepted connection from: [180.76.4.248]                                                              -  Beijing, Beijing ◄ China ►


After padding change:

Code: Select all

07/23/13 02:58:46pm - Service [stunnel-sslh] accepted connection from: 139.sub-70-197-3.myvzw.com [70.197.3.139]                  ◄ United States ►  Dublin, California
07/23/13 02:58:48pm - Service [stunnel-sslh] accepted connection from: 5.10.83.96-static.reverse.softlayer.com [5.10.83.96]       ◄ Netherlands ►
07/23/13 03:01:52pm - Service [stunnel-sslh] accepted connection from: baiduspider-180-76-5-64.crawl.baidu.com [180.76.5.64]      ◄ China ►  Beijing, Beijing
07/23/13 03:17:02pm - Service [stunnel-sslh] accepted connection from: 5.10.83.96-static.reverse.softlayer.com [5.10.83.96]       ◄ Netherlands ►
07/23/13 03:18:19pm - Service [stunnel-sslh] accepted connection from: 178-134-122-88.dsl.utg.ge [178.134.122.88]                 ◄ Georgia ►
07/23/13 03:22:16pm - Service [stunnel-sslh] accepted connection from: 5.10.83.96-static.reverse.softlayer.com [5.10.83.96]       ◄ Netherlands ►


I have no idea how to setup a macro for the geo-IP lookup (I'm currently using a CALL to the subroutine; which is slow). I will slowly learn how to do that. The good news is I have something that works pretty good all thanks to you guys!

Here's the latest working code:

Code: Select all

@echo off
setlocal
call :getStringLength

setlocal enableDelayedExpansion
set "log=\stunnel.log"
set "logx=\stunnelx.log"
set "linecount.tmp=\linecount.tmp"
set "location.length="
set "padding=                                                                                                                                 "
set "linecounter="
set "SKIP="

if not exist "!linecount.tmp!" echo 0 >"!linecount.tmp!"

for /f "usebackq delims=" %%a in ("!linecount.tmp!") do set /a N=%%a

if %N% GTR 0 (
   set SKIP="skip=%N% tokens=1-3* delims= "
   ) else (
   set SKIP="tokens=1-3* delims= "
)

for /L %%a in ( 0, 1, 9) do set "meridiemness[0%%a]=am"
for /L %%a in ( 0, 1,11) do set "meridiemness[%%a]=am"
for /L %%a in (12, 1,23) do set "meridiemness[%%a]=pm"
for /L %%a in (0, 1, 23) do (
   set /A "num=((11 + %%a)%%12)+101"
   set "hour[!num:~-2!]=!num:~-2!"
   set "hour[%%a]=!num:~-2!"
)
set "hour[00]=12"

(
   for /f %SKIP% %%a in ('findstr /V /I /C:"127.0.0" /C:"192.168" /C:"byte" /C:"WSAECONNRESET" /C:"Peer suddenly disconnected" "%log%"') do (
      set "dateValue=%%a"
      set "dateValue=!dateValue:~5,2!/!dateValue:~8,2!/!dateValue:~2,2!"

      for /F "tokens=1* delims=:" %%A in ("%%b") do set "timeValue=!hour[%%A]!:%%B!meridiemness[%%A]!"

      set "info=%%d"

      set "ipPort="
      for %%A in (!info:~24!) do set "ipPort=%%A"
      for /F "tokens=1 delims=0123456789.:" %%e in ("!ipPort!") do set "ipPort="
      for /F "tokens=1,2 delims=:" %%A in ("!ipPort!") do (
         if not defined DN[%%A] (
            for /f "tokens=2 delims= " %%0 in ('nslookup %%A 2^> nul ^| findstr /I /C:"Name" ') do set "DN[%%A]= %%0 "
            if not defined DN[%%A] set "DN[%%A]= "
         )
         set "info=!info: %%A:%%B=!:!DN[%%A]![%%A]"
      call :GeoIP %%A
      )
      set "info=!dateValue! !timeValue! - !info!"

      ::::::::::::::::::::: Padding Code :::::::::::::::::::::
      set "print=!info!"
      %$strlen% "print.length" "print"
      set /A "availablePaddingChars=129-!print.length!"
      if 0 LSS !availablePaddingChars! for %%A in (!availablePaddingChars!) do set "print=!info!!padding:~-%%A!!location!"

      echo(!print!
     set /a linecounter=linecounter+1
   )
) >> "%logx%"
set /a N=N+linecounter
echo(!N!>"!linecount.tmp!"

endlocal
endlocal


goto :eof
:GeoIP
set "location="
set "country="
set "state="
set "city="
for /F "tokens=*" %%a in ('curl -s freegeoip.net/json/%1') do set geoIP=%%a
for /F "tokens=1-6 delims=," %%a in ("!geoIP!") do (
   set "country=%%c"
   set "state=%%e"
   set "city=%%f"
   )
for /F "tokens=1-2 delims=:" %%a in ("!country!") do set "country= ◄ %%~b ►"
for /F "tokens=1-2 delims=:" %%a in ("!state!") do set "state= %%~b"
for /F "tokens=1-2 delims=:" %%a in ("!city!") do set "city= %%~b,"
if "!city!" == " ," set "city="
if "!state!" == " " set "state="
if "!country!" == " ||" set "country="
if not [!city!!state!!country!] == [] set "location=!country! !city!!state!"
exit /b

:getStringLength
set LF=^


::Above 2 blank lines are required - do not remove
set ^"\n=^^^%LF%%LF%^%LF%%LF%^^"

:::: StrLen pResult pString
set $strLen=for /L %%n in (1 1 2) do if %%n==2 (%\n%
   for /F "tokens=1,2 delims=, " %%1 in ("!argv!") do (%\n%
      set "str=A!%%~2!"%\n%
      set "len=0"%\n%
      for /l %%A in (12,-1,0) do (%\n%
         set /a "len|=1<<%%A"%\n%
         for %%B in (!len!) do if "!str:~%%B,1!"=="" set /a "len&=~1<<%%A"%\n%
      )%\n%
      for %%v in (!len!) do endlocal^&if "%%~b" neq "" (set "%%~1=%%v") else echo %%v%\n%
   ) %\n%
) ELSE setlocal enableDelayedExpansion ^& set argv=,
exit /b

Post Reply