Check Installed Plugins Against the Store.fh_lua--[[
@Title: Check Installed Plugins Against The Store
@Author: Calico Pie
@Version: 3.3
@LastUpdated: 05 Oct 2022
@Description: Checks currently installed plugins against those currently in the store and optionally downloads and installs later versions.
V2.0 Added Author Column and updated to show the status of all plugins in the main plug directory.
V2.1 Add Superseded support
V2.2 Improve version checking where the component numbers are greater than 9
V2.3/2.4 trim line endings.
V2.7/8 Improve Reporting for plugins not in store.
V2.9 Support HTTPS as now used at Family Historian when used with FH 7
V3.0 Lua 5.3 compatibility
V3.1 Support http for V6
V3.2 Strip hex(0) if returned in Status string
V3.3 Add Window handling for FH7 and above
@Licence: This plugin is copyright (c) 2022 Calico Pie & contributors and is licensed under the MIT License
which is hereby incorporated by reference (see https://pluginstore.family-historian.co.uk/fh-plugin-licence)
]]
require('luacom')
require('lfs')
require('iuplua')
iup.SetGlobal("CUSTOMQUITMESSAGE","YES")
local sFHVer = fhGetAppVersion()
local sHandle
siteurl = "https://www.family-historian.co.uk/lnk/"
if _VERSION == 'Lua 5.1' then
siteurl = "http://www.family-historian.co.uk/lnk/"
end
bforcecheck = false
function main()
local tblPlugin = {}
local tblCurVer = {}
local tblStoreVer = {}
local tblStatusDesc = {}
local tblAuthor = {}
local tblMsg = {}
local tblCount = {0,0,0,0,0,0,0}
local tblStatus = {'A. Newer Than Store','B. Upgraded', 'C. New Version Available',
'D. Up To Date','E. Not In Store','F. No Version','G. Superseded'}
pluginDir = fhGetContextInfo('CI_APP_DATA_FOLDER')..'\\plugins\\'
local count = 0
for filename,attr in dirtree(pluginDir) do
path,name,ext = splitfilename(filename)
if ext == 'fh_lua' and path == pluginDir then -- Only Look at plugin files which are in the main plugin directory
count = count + 1
end
end
local step = 100 / count
ProgressBar.Start("Check Installed Plugins",count)
for filename,attr in dirtree(pluginDir) do
path,name,ext = splitfilename(filename)
if ext == 'fh_lua' and path == pluginDir then -- Only Look at plugin files which are in the main plugin directory
iStatus = 6
ProgressBar.Step(step)
if ProgressBar.Stop() then break end
-- Get version information from script
local script = StrLoadFromFile(filename)
local _,_,version = string.find(script:lower(), '@version[:%s]%W+([%d%.]*)')
local author= script:match('@[Aa]uthor:%s+([^\n]+)')
local versionStore,id = nil,nil
if bforcecheck then version = version or '0' end
if version then
versionStore,id,msg = checkVersionInStore('file',name)
if version ~= versionStore then
if versionStore ~= nil and cvtVer(version) < cvtVer(versionStore) then
local res
if sFHVer >= 7 then
res = fhMessageBox('Newer version of '..name:gsub('%.fh_lua','')..' found, would you like to upgrade','MB_YESNO','MB_ICONQUESTION',sHandle)
else
res = fhMessageBox('Newer version of '..name:gsub('%.fh_lua','')..' found, would you like to upgrade','MB_YESNO','MB_ICONQUESTION')
end
if res == 'Yes' then
updatePlugin(id)
iStatus = 2
else
iStatus = 3
end
end
end
if iStatus == 6 then
if versionStore and version == versionStore then
iStatus = 4
else
if versionStore and cvtVer(version) > cvtVer(versionStore) then
iStatus = 1
else
iStatus = 5
end
end
end
end
if msg then
-- fhMessageBox(name:gsub('%.fh_lua','')..' '..msg)
if msg:find('not found') then
iStatus = 5
else
fhMessageBox(name:gsub('%.fh_lua','')..' '..msg)
iStatus = 7
end
end
table.insert(tblPlugin,name:match('(.+)%.fh_lua'))
table.insert(tblCurVer,version or ' ')
table.insert(tblStoreVer,versionStore or ' ')
table.insert(tblStatusDesc,tblStatus[iStatus] or ' ')
table.insert(tblAuthor,author or ' ')
table.insert(tblMsg,msg or ' ')
tblCount[iStatus] = tblCount[iStatus] + 1
end
end
ProgressBar.Close()
if #tblPlugin > 0 then
local strMsg = string.format('%u Plugins have been checked with the following Results:\n',sumtbl(tblCount))
for i,v in ipairs(tblCount) do
if v > 0 then
strMsg = string.format('%s%s: %u \n',strMsg,tblStatus[i],v)
end
end
strMsg = string.format('%s\nDisplay detailed results?\n',strMsg)
local res = fhMessageBox(strMsg,'MB_YESNO','MB_ICONQUESTION')
if res == 'Yes' then
fhOutputResultSetTitles("Plug Status Summary", "Plug Status Summary", "Printed Date: %#x")
-- Output Result Set
fhOutputResultSetColumn("Status", "text", tblStatusDesc, #tblPlugin, 80, "align_left",1,true)
fhOutputResultSetColumn("Current", "text", tblCurVer, #tblPlugin, 30, "align_right")
fhOutputResultSetColumn("Store", "text", tblStoreVer, #tblPlugin, 25, "align_right")
fhOutputResultSetColumn("Plugin", "text", tblPlugin, #tblPlugin, 250, "align_left",2,true)
fhOutputResultSetColumn("Author", "text", tblAuthor, #tblPlugin, 150, "align_left",2,true)
fhOutputResultSetColumn("Message", "text", tblMsg, #tblPlugin, 250, "align_left",2,true)
end
else
fhMessageBox('No Plugins Found')
end
end
-------------------------------------------------- Functions
function updatePlugin(id)
-- Get Plugin down and upgrade it
local http = luacom.CreateObject("winhttp.winhttprequest.5.1")
local url = siteurl.."fetchlatestpluginversion.php?id="..id
http:Open("GET",url,false)
http:Send()
http:WaitForResponse(30)
local status = stripz(http.StatusText)
print('Status = '..status)
print(http:getAllResponseHeaders())
if status == 'Moved Temporarily' then
url = http:GetResponseHeader('Location')
print(url)
http:Open("GET",url,false)
http:Send()
http:WaitForResponse(30)
status = stripz(http.StatusText)
print('Status = '..status)
end
if status == 'OK' then
-- length = http:GetResponseHeader('Content-Length')
print(http:GetResponseHeader('Content-Disposition'))
filename = string.match(http:GetResponseHeader('Content-Disposition'),'="(.*)"')
print(filename)
data = http.ResponseBody
data = data:gsub("\r\n","\n") -- Remove CR characters at end of line
SaveStringToFile(data,pluginDir..'\\'..filename)
print('Data Size :'..#data)
-- print('Content-Length:'..length)
print(http:getAllResponseHeaders())
else
fhMessageBox('An error occurred in Download please try later')
end
end
function checkVersionInStore(type,value)
--[[
@description: Checks the version in the plugin store by name or id
@Parms:
1: String, must be either 'id' or 'name' or file
2: String where name search or number where id search
@Returns:
1: nil where value not found or parameter 1 is invalid, or the value of the plugins version field
2: the reference
3: where an error was returned the message following the "Error:"
]]
if type ~= 'id' and type ~= 'name' and type ~= 'file' then
return nil
end
if value then
local http = luacom.CreateObject("winhttp.winhttprequest.5.1")
fhVer = table.concat({fhGetAppVersion()},'.')
strRequest =siteurl..'checkpluginversion.php?'..type..'='..value..'&fhver='..fhVer
http:Open("GET",strRequest,false)
http:Send()
local strReturn = http.Responsebody
print(strReturn)
local ver,ref,msg
if strReturn ~= nil then
ver,ref = strReturn:match('(%d.*),(%d*)')
if strReturn:sub(1,5) == 'Error' then
msg = strReturn:sub(7)
end
end
print(msg)
return ver,ref,msg
else
return nil
end
end
function cvtVer(s)
if s:lower() == 'fh' then
s = table.concat({fhGetAppVersion()},'.')
end
local ver,factor,max = 0,10000,3
local t = {}
for word in s:gmatch("%d+") do
table.insert(t,tonumber(word))
end
for j = 1,max do
t[j] = t[j] or 0
ver = ver + (t[j] * factor^(max-j))
end
return ver
end
function dirtree(dir)
assert(dir and dir ~= "", "directory parameter is missing or empty")
if string.sub(dir, -1) == "\\" then
dir=string.sub(dir, 1, -2)
end
local function yieldtree(dir)
for entry in lfs.dir(dir) do
if entry ~= "." and entry ~= ".." then
entry=dir.."\\"..entry
local attr=lfs.attributes(entry)
coroutine.yield(entry,attr)
if attr ~= nil and attr.mode == "directory" then
yieldtree(entry)
print(entry)
end
end
end
end
return coroutine.wrap(function() yieldtree(dir) end)
end
function splitfilename(strfilename)
-- Returns the Path Filename and extension as 3 values
return string.match(strfilename, "(.-)([^\\]-([^%.]+))$")
end
-- Open File and return Handle --
function OpenFile(strFileName,strMode)
local fileHandle, strError = io.open(strFileName,strMode)
if not fileHandle then
error("\n Unable to open file in \""..strMode.."\" mode. \n "..strFileName.." \n "..tostring(strError).." \n")
end
return fileHandle
end -- OpenFile
-- Load string from file --
function StrLoadFromFile(strFileName)
local fileHandle = OpenFile(strFileName,"r")
local strString = fileHandle:read("*all")
assert(fileHandle:close())
return strString
end
-- StrLoadFromFile
function SaveStringToFile(strString,strFileName)
local fileHandle = OpenFile(strFileName,"w")
fileHandle:write(strString)
assert(fileHandle:close())
end -- SaveStringToFile
-- Progress Bar
ProgressBar = {
Start = function(strTitle,intMax) -- Create & start Progress Bar window
if not DlgGauge then
IsBarStop = false
IntStart = os.time()
IntDelta = 0
StrClock = "00:00:00"
local btnStop = iup.button { title="Stop "..strTitle, rastersize="200x30", action=function() IsBarStop = true end, } -- Signal Stop button pressed return iup.CLOSE -- Often caused main GUI to close !!!
BarGauge = iup.progressbar { rastersize="400x30", value=0, max=intMax, } -- Progress bar maximum range
LblText = iup.label { title=" ", expand="YES", alignment="ACENTER", tip="Percentage and Time Elapsed", }
DlgGauge = iup.dialog { title=strTitle.." Progress", dialogframe="YES", -- Remove Windows minimize/maximize menu
iup.vbox{ alignment="ACENTER", gap="10",
LblText,
BarGauge,
btnStop,
},
move_cb = function(self,x,y) IntDataX=x IntDataY=y end,
close_cb = btnStop.action, -- Windows Close button = Stop button
}
if sFHVer >= 7 then
iup.SetAttribute(DlgGauge, "NATIVEPARENT", fhGetContextInfo("CI_PARENT_HWND"));
end
DlgGauge:showxy(IntDataX,IntDataY) -- Show the Progress Bar window
sHandle = DlgGauge.HWND
end
end,
SetText = function(strText) -- Show the Progress text message
if DlgGauge then LblText.title = strText end
end,
Step = function(intStep) -- Step the Progress Bar forward
if DlgGauge then
local intVal = tonumber(BarGauge.value)
local intMax = tonumber(BarGauge.max)
intVal = intVal + intStep
if intVal > intMax then intVal = intMax end -- Ensure value does not exceed maximum
BarGauge.value = intVal
local intDelta = os.difftime(os.time(),IntStart)
if IntDelta < intDelta then -- Update clock of elapsed time
IntDelta = intDelta
local intHour = math.floor( intDelta / 3600 )
local intMins = math.floor( intDelta / 60 - intHour * 60 )
local intSecs = intDelta - intMins * 60 - intHour * 3600
StrClock = string.format("%02d : %02d : %02d",intHour,intMins,intSecs)
end
LblText.title = string.format("%4d %% %s ", math.floor( intVal / intMax * 100 ), StrClock) -- Display % and clock progress
DlgGauge.bringfront = "YES"
iup.LoopStep()
end
end,
Reset = function() -- Reset the Progress Bar
if DlgGauge then BarGauge.value = 0 end
end,
Stop = function() -- Check if Stop button pressed
return IsBarStop
end,
Close = function() -- Close the Progress Bar window
IsBarStop = false
if DlgGauge then DlgGauge:destroy() DlgGauge = nil end
end,
} -- ProgressBar
function sumtbl(tbl)
local tot = 0
for _,v in ipairs(tbl) do
tot = tot + (tonumber(v) or 0)
end
return tot
end
function stripz(s)
return (s:gsub( "%z", "" ))
end
-- Execute Main Function
main()
--[[
@Title: Check Installed Plugins Against The Store
@Author: Calico Pie
@Version: 3.3
@LastUpdated: 05 Oct 2022
@Description: Checks currently installed plugins against those currently in the store and optionally downloads and installs later versions.
V2.0 Added Author Column and updated to show the status of all plugins in the main plug directory.
V2.1 Add Superseded support
V2.2 Improve version checking where the component numbers are greater than 9
V2.3/2.4 trim line endings.
V2.7/8 Improve Reporting for plugins not in store.
V2.9 Support HTTPS as now used at Family Historian when used with FH 7
V3.0 Lua 5.3 compatibility
V3.1 Support http for V6
V3.2 Strip hex(0) if returned in Status string
V3.3 Add Window handling for FH7 and above
@Licence: This plugin is copyright (c) 2022 Calico Pie & contributors and is licensed under the MIT License
which is hereby incorporated by reference (see https://pluginstore.family-historian.co.uk/fh-plugin-licence)
]]
require('luacom')
require('lfs')
require('iuplua')
iup.SetGlobal("CUSTOMQUITMESSAGE","YES")
local sFHVer = fhGetAppVersion()
local sHandle
siteurl = "https://www.family-historian.co.uk/lnk/"
if _VERSION == 'Lua 5.1' then
siteurl = "http://www.family-historian.co.uk/lnk/"
end
bforcecheck = false
function main()
local tblPlugin = {}
local tblCurVer = {}
local tblStoreVer = {}
local tblStatusDesc = {}
local tblAuthor = {}
local tblMsg = {}
local tblCount = {0,0,0,0,0,0,0}
local tblStatus = {'A. Newer Than Store','B. Upgraded', 'C. New Version Available',
'D. Up To Date','E. Not In Store','F. No Version','G. Superseded'}
pluginDir = fhGetContextInfo('CI_APP_DATA_FOLDER')..'\\plugins\\'
local count = 0
for filename,attr in dirtree(pluginDir) do
path,name,ext = splitfilename(filename)
if ext == 'fh_lua' and path == pluginDir then -- Only Look at plugin files which are in the main plugin directory
count = count + 1
end
end
local step = 100 / count
ProgressBar.Start("Check Installed Plugins",count)
for filename,attr in dirtree(pluginDir) do
path,name,ext = splitfilename(filename)
if ext == 'fh_lua' and path == pluginDir then -- Only Look at plugin files which are in the main plugin directory
iStatus = 6
ProgressBar.Step(step)
if ProgressBar.Stop() then break end
-- Get version information from script
local script = StrLoadFromFile(filename)
local _,_,version = string.find(script:lower(), '@version[:%s]%W+([%d%.]*)')
local author= script:match('@[Aa]uthor:%s+([^\n]+)')
local versionStore,id = nil,nil
if bforcecheck then version = version or '0' end
if version then
versionStore,id,msg = checkVersionInStore('file',name)
if version ~= versionStore then
if versionStore ~= nil and cvtVer(version) < cvtVer(versionStore) then
local res
if sFHVer >= 7 then
res = fhMessageBox('Newer version of '..name:gsub('%.fh_lua','')..' found, would you like to upgrade','MB_YESNO','MB_ICONQUESTION',sHandle)
else
res = fhMessageBox('Newer version of '..name:gsub('%.fh_lua','')..' found, would you like to upgrade','MB_YESNO','MB_ICONQUESTION')
end
if res == 'Yes' then
updatePlugin(id)
iStatus = 2
else
iStatus = 3
end
end
end
if iStatus == 6 then
if versionStore and version == versionStore then
iStatus = 4
else
if versionStore and cvtVer(version) > cvtVer(versionStore) then
iStatus = 1
else
iStatus = 5
end
end
end
end
if msg then
-- fhMessageBox(name:gsub('%.fh_lua','')..' '..msg)
if msg:find('not found') then
iStatus = 5
else
fhMessageBox(name:gsub('%.fh_lua','')..' '..msg)
iStatus = 7
end
end
table.insert(tblPlugin,name:match('(.+)%.fh_lua'))
table.insert(tblCurVer,version or ' ')
table.insert(tblStoreVer,versionStore or ' ')
table.insert(tblStatusDesc,tblStatus[iStatus] or ' ')
table.insert(tblAuthor,author or ' ')
table.insert(tblMsg,msg or ' ')
tblCount[iStatus] = tblCount[iStatus] + 1
end
end
ProgressBar.Close()
if #tblPlugin > 0 then
local strMsg = string.format('%u Plugins have been checked with the following Results:\n',sumtbl(tblCount))
for i,v in ipairs(tblCount) do
if v > 0 then
strMsg = string.format('%s%s: %u \n',strMsg,tblStatus[i],v)
end
end
strMsg = string.format('%s\nDisplay detailed results?\n',strMsg)
local res = fhMessageBox(strMsg,'MB_YESNO','MB_ICONQUESTION')
if res == 'Yes' then
fhOutputResultSetTitles("Plug Status Summary", "Plug Status Summary", "Printed Date: %#x")
-- Output Result Set
fhOutputResultSetColumn("Status", "text", tblStatusDesc, #tblPlugin, 80, "align_left",1,true)
fhOutputResultSetColumn("Current", "text", tblCurVer, #tblPlugin, 30, "align_right")
fhOutputResultSetColumn("Store", "text", tblStoreVer, #tblPlugin, 25, "align_right")
fhOutputResultSetColumn("Plugin", "text", tblPlugin, #tblPlugin, 250, "align_left",2,true)
fhOutputResultSetColumn("Author", "text", tblAuthor, #tblPlugin, 150, "align_left",2,true)
fhOutputResultSetColumn("Message", "text", tblMsg, #tblPlugin, 250, "align_left",2,true)
end
else
fhMessageBox('No Plugins Found')
end
end
-------------------------------------------------- Functions
function updatePlugin(id)
-- Get Plugin down and upgrade it
local http = luacom.CreateObject("winhttp.winhttprequest.5.1")
local url = siteurl.."fetchlatestpluginversion.php?id="..id
http:Open("GET",url,false)
http:Send()
http:WaitForResponse(30)
local status = stripz(http.StatusText)
print('Status = '..status)
print(http:getAllResponseHeaders())
if status == 'Moved Temporarily' then
url = http:GetResponseHeader('Location')
print(url)
http:Open("GET",url,false)
http:Send()
http:WaitForResponse(30)
status = stripz(http.StatusText)
print('Status = '..status)
end
if status == 'OK' then
-- length = http:GetResponseHeader('Content-Length')
print(http:GetResponseHeader('Content-Disposition'))
filename = string.match(http:GetResponseHeader('Content-Disposition'),'="(.*)"')
print(filename)
data = http.ResponseBody
data = data:gsub("\r\n","\n") -- Remove CR characters at end of line
SaveStringToFile(data,pluginDir..'\\'..filename)
print('Data Size :'..#data)
-- print('Content-Length:'..length)
print(http:getAllResponseHeaders())
else
fhMessageBox('An error occurred in Download please try later')
end
end
function checkVersionInStore(type,value)
--[[
@description: Checks the version in the plugin store by name or id
@Parms:
1: String, must be either 'id' or 'name' or file
2: String where name search or number where id search
@Returns:
1: nil where value not found or parameter 1 is invalid, or the value of the plugins version field
2: the reference
3: where an error was returned the message following the "Error:"
]]
if type ~= 'id' and type ~= 'name' and type ~= 'file' then
return nil
end
if value then
local http = luacom.CreateObject("winhttp.winhttprequest.5.1")
fhVer = table.concat({fhGetAppVersion()},'.')
strRequest =siteurl..'checkpluginversion.php?'..type..'='..value..'&fhver='..fhVer
http:Open("GET",strRequest,false)
http:Send()
local strReturn = http.Responsebody
print(strReturn)
local ver,ref,msg
if strReturn ~= nil then
ver,ref = strReturn:match('(%d.*),(%d*)')
if strReturn:sub(1,5) == 'Error' then
msg = strReturn:sub(7)
end
end
print(msg)
return ver,ref,msg
else
return nil
end
end
function cvtVer(s)
if s:lower() == 'fh' then
s = table.concat({fhGetAppVersion()},'.')
end
local ver,factor,max = 0,10000,3
local t = {}
for word in s:gmatch("%d+") do
table.insert(t,tonumber(word))
end
for j = 1,max do
t[j] = t[j] or 0
ver = ver + (t[j] * factor^(max-j))
end
return ver
end
function dirtree(dir)
assert(dir and dir ~= "", "directory parameter is missing or empty")
if string.sub(dir, -1) == "\\" then
dir=string.sub(dir, 1, -2)
end
local function yieldtree(dir)
for entry in lfs.dir(dir) do
if entry ~= "." and entry ~= ".." then
entry=dir.."\\"..entry
local attr=lfs.attributes(entry)
coroutine.yield(entry,attr)
if attr ~= nil and attr.mode == "directory" then
yieldtree(entry)
print(entry)
end
end
end
end
return coroutine.wrap(function() yieldtree(dir) end)
end
function splitfilename(strfilename)
-- Returns the Path Filename and extension as 3 values
return string.match(strfilename, "(.-)([^\\]-([^%.]+))$")
end
-- Open File and return Handle --
function OpenFile(strFileName,strMode)
local fileHandle, strError = io.open(strFileName,strMode)
if not fileHandle then
error("\n Unable to open file in \""..strMode.."\" mode. \n "..strFileName.." \n "..tostring(strError).." \n")
end
return fileHandle
end -- OpenFile
-- Load string from file --
function StrLoadFromFile(strFileName)
local fileHandle = OpenFile(strFileName,"r")
local strString = fileHandle:read("*all")
assert(fileHandle:close())
return strString
end
-- StrLoadFromFile
function SaveStringToFile(strString,strFileName)
local fileHandle = OpenFile(strFileName,"w")
fileHandle:write(strString)
assert(fileHandle:close())
end -- SaveStringToFile
-- Progress Bar
ProgressBar = {
Start = function(strTitle,intMax) -- Create & start Progress Bar window
if not DlgGauge then
IsBarStop = false
IntStart = os.time()
IntDelta = 0
StrClock = "00:00:00"
local btnStop = iup.button { title="Stop "..strTitle, rastersize="200x30", action=function() IsBarStop = true end, } -- Signal Stop button pressed return iup.CLOSE -- Often caused main GUI to close !!!
BarGauge = iup.progressbar { rastersize="400x30", value=0, max=intMax, } -- Progress bar maximum range
LblText = iup.label { title=" ", expand="YES", alignment="ACENTER", tip="Percentage and Time Elapsed", }
DlgGauge = iup.dialog { title=strTitle.." Progress", dialogframe="YES", -- Remove Windows minimize/maximize menu
iup.vbox{ alignment="ACENTER", gap="10",
LblText,
BarGauge,
btnStop,
},
move_cb = function(self,x,y) IntDataX=x IntDataY=y end,
close_cb = btnStop.action, -- Windows Close button = Stop button
}
if sFHVer >= 7 then
iup.SetAttribute(DlgGauge, "NATIVEPARENT", fhGetContextInfo("CI_PARENT_HWND"));
end
DlgGauge:showxy(IntDataX,IntDataY) -- Show the Progress Bar window
sHandle = DlgGauge.HWND
end
end,
SetText = function(strText) -- Show the Progress text message
if DlgGauge then LblText.title = strText end
end,
Step = function(intStep) -- Step the Progress Bar forward
if DlgGauge then
local intVal = tonumber(BarGauge.value)
local intMax = tonumber(BarGauge.max)
intVal = intVal + intStep
if intVal > intMax then intVal = intMax end -- Ensure value does not exceed maximum
BarGauge.value = intVal
local intDelta = os.difftime(os.time(),IntStart)
if IntDelta < intDelta then -- Update clock of elapsed time
IntDelta = intDelta
local intHour = math.floor( intDelta / 3600 )
local intMins = math.floor( intDelta / 60 - intHour * 60 )
local intSecs = intDelta - intMins * 60 - intHour * 3600
StrClock = string.format("%02d : %02d : %02d",intHour,intMins,intSecs)
end
LblText.title = string.format("%4d %% %s ", math.floor( intVal / intMax * 100 ), StrClock) -- Display % and clock progress
DlgGauge.bringfront = "YES"
iup.LoopStep()
end
end,
Reset = function() -- Reset the Progress Bar
if DlgGauge then BarGauge.value = 0 end
end,
Stop = function() -- Check if Stop button pressed
return IsBarStop
end,
Close = function() -- Close the Progress Bar window
IsBarStop = false
if DlgGauge then DlgGauge:destroy() DlgGauge = nil end
end,
} -- ProgressBar
function sumtbl(tbl)
local tot = 0
for _,v in ipairs(tbl) do
tot = tot + (tonumber(v) or 0)
end
return tot
end
function stripz(s)
return (s:gsub( "%z", "" ))
end
-- Execute Main Function
main()Source:Check-Installed-Plugins-Against-the-Store-5.fh_lua