Jump to content

Updater for the CLI (using CryptoNG)


 Share

Recommended Posts

I know there are other Updater scripts out there. Mine uses the file-hashing function in @TheXman's CryptoNG UDF to compare the user's (local) version with the current (remote) version of the subject file. First set the User Variables, then compile it with Change2CUI = y. Command-line options /Q and /QQ suppress console output. Option /? gives help.

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_UseUpx=y
#AutoIt3Wrapper_UseX64=n
#AutoIt3Wrapper_Change2CUI=y
#AutoIt3Wrapper_Run_Au3Stripper=y
#AutoIt3Wrapper_AU3Check_Parameters=-w 3 -w 4 -w 5 -w 6 -d
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****

#cs
--------------------------
Updater.au3 -- C.L.Distefano rev. 2024-08-13
Template for Command-Line File Updater
Compare local file to remote file; if not identical,
  (1) Back up local file; and
  (2) Update local file (overwrite with remote file)

Credit: TheXMan, author of CryptoNG
https://www.autoitscript.com/forum/files/file/490-cryptong-udf-cryptography-api-next-generation/
------------------------------
#ce

Global $sRevDate = "[C.L.Distefano rev. 2024-08-13]"

#include ".\CryptoNG\CryptoNG.au3"
#include <File.au3>
#include <FileConstants.au3>
#include <InetConstants.au3>
#include <Process.au3>
#include <StringConstants.au3>

Global $sArgs = "", $sTmp
Global $sLocalFn, $sRemoteFn, $sRemoteFnTmp, $sRemFname
Global $sIniFile, $sLogFile, $d, $p, $f, $e, $h0
_PathSplit(@ScriptFullPath, $d, $p, $f, $e)
$sIniFile = $d & $p & $f & ".ini"
$sLogFile = $d & $p & $f & ".log"
Global $bLogIt = 0, $bQuiet = 0
Global $sSection = "Default"

If Not FileExists($sIniFile) Then
    $h0 = FileOpen($sIniFile, $FO_OVERWRITE)
    If $h0 > -1 Then
        FileWrite($h0, "; " & @ScriptName & " -- Settings" & @CRLF & @CRLF & "; How to Edit This File:" & @CRLF & "; Each [Section] lists the fully-qualified path to a local file to be" & @CRLF & "; updated (""LocalFile"") and a URL for the remote file (""RemoteFile"")," & @CRLF & "; i.e., the current version of the file. Name and populate your own sections" & @CRLF & "; accordingly. (See ""[Demo]"" below for an example.) To check the availability" & @CRLF & "; of updates for a given file, command """ & @ScriptName & " <SectionName>""." & @CRLF & "; For further help, command """ & @ScriptName & " /?""" & @CRLF & "; ------------------------------------------------------------------------" & @CRLF & @CRLF & "[Default]" & @CRLF & "LocalFile=" & @CRLF & "RemoteFile=" & @CRLF & @CRLF & "[Demo]" & @CRLF & "LocalFile=" & @ScriptDir & "\AAMilne6.txt" & @CRLF & "RemoteFile=https://www.gutenberg.org/cache/epub/70516/pg70516.txt" & @CRLF & @CRLF & "[File1]" & @CRLF & "LocalFile=" & @CRLF & "RemoteFile=" & @CRLF & @CRLF & "[File2]" & @CRLF & "LocalFile=" & @CRLF & "RemoteFile=" & @CRLF & @CRLF)
        FileClose($h0)
        Exit Run("notepad.exe " & $sIniFile)
    Else
        Exit _ExitErr("Error opening " & $sIniFile)
    EndIf
EndIf

If $CmdLine[0] > 0 Then $sArgs = _ArgGetRawArgs()
If $sArgs Then
    If StringInStr($sArgs, "/?") Or StringInStr($sArgs, "-?") Or _
        StringinStr($sArgs, "/h") Or StringInStr($sArgs, "-h") Or _
        StringInStr($sArgs, "--help") Then Exit _ShowHelp()
    If StringInStr($sArgs, "/L") Then
        $bLogIt = 1
        $sTmp = StringTrimLeft($sArgs, StringInStr($sArgs, "/L") + 1)
        If StringInStr($sTmp, '"') = 1 Then
            $sTmp = StringTrimLeft($sTmp, 1)
            If StringInStr($sTmp, '"') Then $sTmp = StringLeft($sTmp, StringInStr($sTmp, '"') - 1)
        ElseIf StringInStr($sTmp, " ") Then
            $sTmp = StringLeft($sTmp, StringInStr($sTmp, " ") - 1)
        EndIf
        If StringInStr($sTmp, ":") = 1 Then $sTmp = StringTrimLeft($sTmp, 1)
        If $sTmp Then $sLogFile = $sTmp
ConsoleWrite($sLogFile & @CRLF)
    EndIf
    If StringInStr($sArgs, "/Q") Then
        $bQuiet = 1
        If StringInStr($sArgs, "/QQ") Then $bQuiet = 2
    EndIf
    If StringInStr($CmdLine[$CmdLine[0]], "/") <> 1 Then _
        $sSection = $CmdLine[$CmdLine[0]]
EndIf

$sLocalFn = IniRead($sIniFile, $sSection, "LocalFile", "")
$sRemoteFn = IniRead($sIniFile, $sSection, "RemoteFile", "")
If Not ($sLocalFn And $sRemoteFn) Then Exit Run("notepad.exe " & $sIniFile)
_PathSplit($sRemoteFn, $d, $p, $sRemFname, $e)
Global $hI = -1
Global $xHashLocal, $xHashRemote
Global $sTmpBaseDir = @TempDir
If Not FileExists($sTmpBaseDir) Then $sTmpBaseDir = @ScriptDir
Global $sTempDir = _TempFile($sTmpBaseDir)
_CreateDir($sTempDir)
If StringRight($sTempDir, 1) = "\" Then $sTempDir = StringTrimRight($sTempDir, 1)
$sRemoteFnTmp = $sTempDir & "\" & $sRemFname
If $bQuiet < 1 Then ConsoleWrite("Checking for updates...")
$hI = InetGet($sRemoteFn, $sRemoteFnTmp, $INET_FORCERELOAD)
If Not $hI Then
    _ConsoleEraseLine("Checking for updates...")
    If StringInStr($sArgs, "/L") Then _LogEntry("Download failed")
    If $bQuiet < 1 Then ConsoleWrite("Cleaning up...")
    _CleanUp()
    _ConsoleEraseLine("Cleaning up...")
    If $bQuiet < 2 Then ConsoleWrite(@CRLF & "Download failed!" & @CRLF)
    Exit 1
EndIf
InetClose($hI)
Sleep(1500)

$xHashLocal = _CryptoNG_HashFile($CNG_BCRYPT_SHA256_ALGORITHM, $sLocalFn)
$xHashRemote = _CryptoNG_HashFile($CNG_BCRYPT_SHA256_ALGORITHM, $sRemoteFnTmp)
_ConsoleEraseLine("Checking for updates...")
If $xHashRemote = $xHashLocal Then
    If StringInStr($sLocalFn, " ") Then $sLocalFn = """" & $sLocalFn & """"
    If $bQuiet < 1 Then
        _ConsoleWriteANSI($sLocalFn)
        If $sSection = "Default" Then _ConsoleWriteANSI(" (the default file)")
        _ConsoleWriteANSI(" is up to date!" & @CRLF)
        If $bLogIt Then _LogEntry("Up to date")
    EndIf
Else
    If $bQuiet > 0 Then
        _DoUpdate()
    Else
        _ConsoleWriteANSI("Update available", 37, 41)
        ConsoleWrite(" for " & $sLocalFn)
        If $sSection = "Default" Then ConsoleWrite(" (the default file)")
        ConsoleWrite(@CRLF & "Get it now? (Y|N)" & @CRLF)
        While 1
            Switch StringLeft(StringUpper(ConsoleRead()), 1)
                Case "Y"
                    _DoUpdate()
                    ExitLoop
                Case "N"
                    If $bLogIt Then _LogEntry("Update available")
                    ExitLoop
                Case Else
                    Sleep(25)
            EndSwitch
        WEnd
    EndIf
EndIf
_CleanUp()
Exit 0

;-----
Func _ArgGetRawArgs()
; Returns CMline arguments only
    Local $sOut = "", $sTmp
    If $CmdLine[0] Then
        For $i = 1 To $CmdLine[0]
            $sTmp = $CmdLine[$i]
            If StringInStr($sTmp, " ") Then $sTmp = """" & $sTmp & """"
            $sOut &= $sTmp
            If $i < $CmdLine[0] Then $sOut &= " "
        Next
    EndIf
    Return $sOut
EndFunc  ;==>_ArgGetRawArgs()

Func _DoUpdate()
    If FileExists($sLocalFn) Then
        Local $sBackupFn
        _PathSplit($sLocalFn, $d, $p, $f, $e)
        $sBackupFn = $d & $p & $f & "-" & StringRight(@YEAR, 2) & _
            @MON & @MDAY & "T" & @HOUR & @MIN & @SEC
        If $e Then $sBackupFn &= $e
        If Not FileCopy($sLocalFn, $sBackupFn) Then
            If $bQuiet < 2 Then _ConsoleWriteANSI("Error backing up " & _
                $sLocalFn & "!" & @CRLF, 36, 1)
        EndIf
    EndIf
    If FileCopy($sRemoteFnTmp, $sLocalFn, $FC_OVERWRITE) Then
        If $bQuiet < 1 Then _ConsoleWriteANSI($sLocalFn & " was successfully updated!" & @CRLF)
    Else
        If $bQuiet < 2 Then _ConsoleWriteANSI("Error copying update to " & _
             $sLocalFn & "!" & @CRLF, 36, 1)
    EndIf
    If $bLogIt Then
        _LogEntry("Updated")
    EndIf
EndFunc  ;==>_DoUpdate

Func _CleanUp()
    Local $c = 0
    While FileExists($sTempDir)
        RunWait("cmd.exe /c cd/d " & @ScriptDir & " &del/f/q " & $sTempDir & "\* >nul 2>nul &rd/s/q " & $sTempDir & " >nul 2>nul", @ScriptDir, @SW_HIDE)
        If $c > 300 Then ExitLoop
        Sleep(200)
        $c += 1
    WEnd
EndFunc  ;==>CleanUp

Func _ConsoleEraseLine($vIn)
; Erase one line (only) from console output
; Line to be erased must not terminate with Cr|Lf!
    If StringRight(String($vIn), 1) = @LF Then Return
    Local $sOut = ""
    If Not IsInt($vIn) Then $vIn = StringLen(String($vIn))
    For $i = 1 To $vIn
        $sOut &= Chr(8) & " " & Chr(8)
    Next
    ConsoleWrite($sOut)
    Return
EndFunc  ;==>_ConsoleErase

Func _ConsoleWriteANSI($sTxt, $iFg1 = 33, $iBg1 = 1, $iFg0 = 22, $iBg0 = 0)
; Write colorful text to the console ("TYPE tmp_file" method)
; Default color - Bright Yellow on Black background
    Local $h, $sTmpFn = _TempFile(@ScriptDir)
    $h = FileOpen($sTmpFn, $FO_BINARY + $FO_OVERWRITE)
    If $h < 0 Then Return ConsoleWrite($sTxt)
    If Not FileWrite($h, Chr(27) & "[" & $iFg1 & "m" & Chr(27) & _
        "[" & $iBg1 & "m" & $sTxt & Chr(27) & "[" & $iFg0 & "m" & _
        Chr(27) & "[" & $iBg0 & "m") Then
        FileClose($h)
        Return ConsoleWrite($sTxt)
    EndIf
    FileClose($h)
    _RunDos("type " & $sTmpFn)
    FileDelete($sTmpFn)
EndFunc  ;==>_ConsoleWriteANSI

Func _CreateDir($sDirName, $sLabel = $sDirName)
    Local $sMsg = ""
    If Not FileExists($sDirName) Then
        If Not DirCreate($sDirName) Then
            _CleanUp()
            _ConsoleEraseLine(50)
            $sMsg = "Error creating " & $sLabel & "!"
            If $sDirName <> $sLabel Then $sMsg &= "[" & $sDirName & "]"
            _ConsoleWriteANSI($sMsg & @CRLF, 96, 40)
            Exit 2
        EndIf
    EndIf
    Return
EndFunc  ;==>_CreateDir

Func _ExitErr($sMg)
    Exit ConsoleWrite($sMg & @CRLF)
EndFunc  ;==>_ExitErr

Func _LogEntry($sStatus)
    If Not $sStatus Then Return
    Local $h1, $h2, $sFC = "", $bFN = 0
    Local $sEntry = @YEAR & "-" & @MON & "-" & @MDAY & " " & @HOUR & _
    ":" & @MIN & ":" & @SEC & @CRLF & "Remote file: " & $sRemoteFn & _
    @CRLF & "Local file: " & $sLocalFn & @CRLF & "Status: " & _
    $sStatus & @CRLF & @CRLF
    If Not FileExists($sLogFile) Then
        If Not _FileCreate($sLogFile) Then Return
        $bFN = 1
    EndIf
    If Not $bFN Then
        $h1 = FileOpen($sLogfile, $FO_READ)
        If $h1 > -1 Then
            $sFC = FileRead($h1)
            FileClose($h1)
        Else
            Return
        EndIf
    EndIf
    $sFC = $sEntry & $sFC
    $h2 = FileOpen($sLogfile, $FO_OVERWRITE)
    If $h2 > -1 Then
        FileWrite($h2, $sFC)
        FileClose($h2)
    Else
        Return
    EndIf
EndFunc  ;==>_LogEntry

Func _ShowHelp()
    _ConsoleWriteANSI(@ScriptName & " " & $sRevDate & @CRLF & "File Updater for the Windows Command Line" & @CRLF)
    ConsoleWrite(@ScriptName & " compares a local file to a remote file; if the" & @CRLF & "two files' contents are not identical, the local file is" & @CRLF & "first backed up (to <filename>-<YYMMDD>T<hhmmss>[.<ext>]) and" & @CRLF & "then overwritten (updated) with the contents of the remote file." & @CRLF & "How It Works: " & @ScriptName & " compares SHA256 hashes of the local and" & @CRLF & "remote files. If the hashes differ, or if the local file does" & @CRLF & "not exist, an update is triggered." & @CRLF & "---" & @CRLF)
    _ConsoleWriteANSI("The first time you run " & @ScriptName & ", it will create the text file" & @CRLF, 96, 40)
    _ConsoleWriteANSI("          >>> " & $sIniFile & " <<<" & @CRLF, 97, 40)
    _ConsoleWriteANSI( "and open it in Notepad. To use " & @ScriptName & ", you must add one or " & @CRLF & "more ", 96, 40)
    _ConsoleWriteANSI("[Sections]", 97, 40)
    _ConsoleWriteANSI(" to " & $sIniFile & ", supplying ""LocalFile""" & @CRLF & "and ""RemoteFile"" values for each file you wish to update." & @CRLF, 96, 40)
    ConsoleWrite("---" & @CRLF)
    _ConsoleWriteANSI("Command-Line Usage:" & @CRLF, 97, 40)
    ConsoleWrite("  Updater.exe [/L[[:]<LogFileName>]] [/Q[Q] [<IniSectionName>] | /?" & @CRLF & "Do NOT put square brackets ""[]"" around <IniSectionName>" & @CRLF & "If <IniSectionName> is omitted, the file identified in .ini" & @CRLF & "  section ""[Default]"" (if any) is checked for updates" & @CRLF & "Option /L[[:]<LogFileName>] logs update status;" & @CRLF & "  Default LogFileName = " & StringTrimRight(@ScriptName, 4) & ".log" & @CRLF & "  Newest entry is at top of file" & @CRLF & "Option /Q (""Quiet"") suppresses informational prompts" & @CRLF & "Option /QQ (""very Quiet"") also suppresses error messages" & @CRLF & "Option /? displays this help" & @CRLF & "Demo: Command ")
    _ConsoleWriteANSI(@ScriptName & " DEMO", 96, 40)
    ConsoleWrite(" to ""update"" a throwaway file" & @CRLF)
EndFunc  ;==>_ShowHelp

 

Edited by CarlD
Added "How It Works" to help (/?); use ver. 2024-08-13
Link to comment
Share on other sites

Latest revision features an .ini file which allows Updater to be used for multiple different file updates. The first time you run Updater.exe, it creates Updater.ini and opens it for editing in Notepad. User is prompted to add a new [Section] for each a local-remote file pair. The command-line usages is now Updater.exe section_name.

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...