diff --git a/build/safemin.py b/build/safemin.py index 2576159..1567b5f 100644 --- a/build/safemin.py +++ b/build/safemin.py @@ -28,7 +28,7 @@ def minify(path: str): contents = f.read() f.close() - if re.search(r'--+\[+', contents) != None: + if re.search(r'--+\[(?!\[@as)+', contents) != None: # absolutely not dealing with lua multiline comments # - there are more important things to do # - this minification is intended to be 100% safe, so working with multiline comments is asking for trouble diff --git a/ccmsi.lua b/ccmsi.lua index a7f7eb8..e1ec80c 100644 --- a/ccmsi.lua +++ b/ccmsi.lua @@ -15,7 +15,7 @@ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ]]-- -local CCMSI_VERSION = "v1.17" +local CCMSI_VERSION = "v1.19" local install_dir = "/.install-cache" local manifest_path = "https://mikaylafischler.github.io/cc-mek-scada/manifests/" @@ -169,6 +169,7 @@ local function write_install_manifest(manifest, dependencies) end -- try at most 3 times to download a file from the repository and write into w_path base directory +---@return 0|1|2|3 success 0: ok, 1: download fail, 2: file open fail, 3: out of space local function http_get_file(file, w_path) local dl, err for i = 1, 3 do @@ -176,17 +177,28 @@ local function http_get_file(file, w_path) if dl then if i > 1 then green();println("success!");lgray() end local f = fs.open(w_path..file, "w") - f.write(dl.readAll()) + if not f then return 2 end + local ok, msg = pcall(function() f.write(dl.readAll()) end) f.close() + if not ok then + if string.find(msg or "", "Out of space") ~= nil then + red();println("[out of space]");lgray() + return 3 + else return 2 end + end break else red();println("HTTP Error: "..err) - if i < 3 then lgray();print("> retrying...") end ----@diagnostic disable-next-line: undefined-field - os.sleep(i/3.0) + if i < 3 then + lgray();print("> retrying...") + ---@diagnostic disable-next-line: undefined-field + os.sleep(i/3.0) + else + return 1 + end end end - return dl ~= nil + return 0 end -- recursively build a tree out of the file manifest @@ -407,7 +419,7 @@ elseif mode == "install" or mode == "update" then if manifest.versions.installer ~= CCMSI_VERSION then if not update_installer then yellow();println("A different version of the installer is available, it is recommended to update to it.");white() end - if update_installer or ask_y_n("Would you like to update now") then + if update_installer or ask_y_n("Would you like to update now", true) then lgray();println("GET ccmsi.lua") local dl, err = http.get(repo_path.."ccmsi.lua") @@ -492,19 +504,119 @@ elseif mode == "install" or mode == "update" then -- check space constraints if space_available < space_required then single_file_mode = true - yellow();println("NOTICE: Insufficient space available for a full cached download!");white() - lgray();println("Files can instead be downloaded one by one. If you are replacing a current install this may corrupt your install ONLY if it fails (such as a sudden network issue). If that occurs, you can still try again.") - if mode == "update" then println("If installation still fails, delete this device's log file and/or any unrelated files you have on this computer then try again.") end - white(); - if not ask_y_n("Do you wish to continue", false) then - println("Operation cancelled.") - return - end end local success = true - if not single_file_mode then + -- delete a file if the capitalization changes so that things work on Windows + ---@param path string + local function mitigate_case(path) + local dir, file = fs.getDir(path), fs.getName(path) + if not fs.isDir(dir) then return end + for _, p in ipairs(fs.list(dir)) do + if string.lower(p) == string.lower(file) then + if p ~= file then fs.delete(path) end + return + end + end + end + + ---@param dl_stat 1|2|3 download status + ---@param file string file name + ---@param attempt integer recursive attempt # + ---@param sf_install function installer function for recursion + local function handle_dl_fail(dl_stat, file, attempt, sf_install) + red() + if dl_stat == 1 then + println("failed to download "..file) + elseif dl_stat > 1 then + if dl_stat == 2 then println("filesystem error with "..file) else println("no space for "..file) end + if attempt == 1 then + orange();println("re-attempting operation...");white() + sf_install(2) + elseif attempt == 2 then + yellow() + if dl_stat == 2 then println("There was an error writing to a file.") else println("Insufficient space available.") end + lgray() + if dl_stat == 2 then + println("This may be due to insufficent space available or file permission issues. The installer can now attempt to delete files not used by the SCADA system.") + else + println("The installer can now attempt to delete files not used by the SCADA system.") + end + white() + if not ask_y_n("Continue", false) then + success = false + return + end + clean(manifest) + sf_install(3) + elseif attempt == 3 then + yellow() + if dl_stat == 2 then println("There again was an error writing to a file.") else println("Insufficient space available.") end + lgray() + if dl_stat == 2 then + println("This may be due to insufficent space available or file permission issues. Please delete any unused files you have on this computer then try again. Do not delete the "..app..".settings file unless you want to re-configure.") + else + println("Please delete any unused files you have on this computer then try again. Do not delete the "..app..".settings file unless you want to re-configure.") + end + white() + success = false + end + end + end + + -- single file update routine: go through all files and replace one by one + ---@param attempt integer recursive attempt # + local function sf_install(attempt) +---@diagnostic disable-next-line: undefined-field + if attempt > 1 then os.sleep(2.0) end + + local abort_attempt = false + success = true + + for _, dependency in pairs(dependencies) do + if mode == "update" and unchanged(dependency) then + pkg_message("skipping install of unchanged package", dependency) + else + pkg_message("installing package", dependency) + lgray() + + -- beginning on the second try, delete the directory before starting + if attempt >= 2 then + if dependency == "system" then + elseif dependency == "common" then + if fs.exists("/scada-common") then + fs.delete("/scada-common") + println("deleted /scada-common") + end + else + if fs.exists("/"..dependency) then + fs.delete("/"..dependency) + println("deleted /"..dependency) + end + end + end + + local files = file_list[dependency] + for _, file in pairs(files) do + println("GET "..file) + mitigate_case(file) + local dl_stat = http_get_file(file, "/") + if dl_stat ~= 0 then + abort_attempt = true +---@diagnostic disable-next-line: param-type-mismatch + handle_dl_fail(dl_stat, file, attempt, sf_install) + break + end + end + end + if abort_attempt or not success then break end + end + end + + -- handle update/install + if single_file_mode then sf_install(1) + else if fs.exists(install_dir) then fs.delete(install_dir);fs.makeDir(install_dir) end -- download all dependencies @@ -518,9 +630,17 @@ elseif mode == "install" or mode == "update" then local files = file_list[dependency] for _, file in pairs(files) do println("GET "..file) - if not http_get_file(file, install_dir.."/") then + local dl_stat = http_get_file(file, install_dir.."/") + success = dl_stat == 0 + if dl_stat == 1 then red();println("failed to download "..file) - success = false + break + elseif dl_stat == 2 then + red();println("filesystem error with "..file) + break + elseif dl_stat == 3 then + -- this shouldn't occur in this mode + red();println("no space for "..file) break end end @@ -548,57 +668,27 @@ elseif mode == "install" or mode == "update" then end fs.delete(install_dir) + end - if success then - write_install_manifest(manifest, dependencies) - green() - if mode == "install" then - println("Installation completed successfully.") - else println("Update completed successfully.") end - white();println("Ready to clean up unused files, press any key to continue...") - any_key();clean(manifest) - white();println("Done.") - else - if mode == "install" then - red();println("Installation failed.") - else orange();println("Update failed, existing files unmodified.") end - end + if success then + write_install_manifest(manifest, dependencies) + green() + if mode == "install" then + println("Installation completed successfully.") + else println("Update completed successfully.") end + white();println("Ready to clean up unused files, press any key to continue...") + any_key();clean(manifest) + white();println("Done.") else - -- go through all files and replace one by one - for _, dependency in pairs(dependencies) do - if mode == "update" and unchanged(dependency) then - pkg_message("skipping install of unchanged package", dependency) - else - pkg_message("installing package", dependency) - lgray() - - local files = file_list[dependency] - for _, file in pairs(files) do - println("GET "..file) - if not http_get_file(file, "/") then - red();println("failed to download "..file) - success = false - break - end - end - end - if not success then break end - end - - if success then - write_install_manifest(manifest, dependencies) - green() - if mode == "install" then - println("Installation completed successfully.") - else println("Update completed successfully.") end - white();println("Ready to clean up unused files, press any key to continue...") - any_key();clean(manifest) - white();println("Done.") - else - red() + red() + if single_file_mode then if mode == "install" then println("Installation failed, files may have been skipped.") else println("Update failed, files may have been skipped.") end + else + if mode == "install" then + println("Installation failed.") + else orange();println("Update failed, existing files unmodified.") end end end elseif mode == "uninstall" then diff --git a/coordinator/config/system.lua b/coordinator/config/system.lua index 7e37f3b..3925114 100644 --- a/coordinator/config/system.lua +++ b/coordinator/config/system.lua @@ -144,7 +144,7 @@ function system.create(tool_ctl, main_pane, cfg_sys, divs, ext, style) PushButton{parent=net_c_3,x=44,y=14,text="Next \x1a",callback=submit_tr,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} TextBox{parent=net_c_4,x=1,y=1,height=2,text="Optionally, set the facility authentication key below. Do NOT use one of your passwords."} - TextBox{parent=net_c_4,x=1,y=4,height=6,text="This enables verifying that messages are authentic, so it is intended for security on multiplayer servers. All devices on the same network MUST use the same key if any device has a key. This does result in some extra compution (can slow things down).",fg_bg=g_lg_fg_bg} + TextBox{parent=net_c_4,x=1,y=4,height=6,text="This enables verifying that messages are authentic, so it is intended for security on multiplayer servers. All devices on the same network MUST use the same key if any device has a key. This does result in some extra computation (can slow things down).",fg_bg=g_lg_fg_bg} TextBox{parent=net_c_4,x=1,y=11,text="Facility Auth Key"} local key, _ = TextField{parent=net_c_4,x=1,y=12,max_len=64,value=ini_cfg.AuthKey,width=32,height=1,fg_bg=bw_fg_bg} diff --git a/reactor-plc/config/system.lua b/reactor-plc/config/system.lua index 478d677..d6bd734 100644 --- a/reactor-plc/config/system.lua +++ b/reactor-plc/config/system.lua @@ -237,7 +237,7 @@ function system.create(tool_ctl, main_pane, cfg_sys, divs, style, exit) PushButton{parent=net_c_2,x=44,y=14,text="Next \x1a",callback=submit_ct_tr,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} TextBox{parent=net_c_3,x=1,y=1,height=2,text="Optionally, set the facility authentication key below. Do NOT use one of your passwords."} - TextBox{parent=net_c_3,x=1,y=4,height=6,text="This enables verifying that messages are authentic, so it is intended for security on multiplayer servers. All devices on the same network MUST use the same key if any device has a key. This does result in some extra compution (can slow things down).",fg_bg=g_lg_fg_bg} + TextBox{parent=net_c_3,x=1,y=4,height=6,text="This enables verifying that messages are authentic, so it is intended for security on multiplayer servers. All devices on the same network MUST use the same key if any device has a key. This does result in some extra computation (can slow things down).",fg_bg=g_lg_fg_bg} TextBox{parent=net_c_3,x=1,y=11,text="Facility Auth Key"} local key, _ = TextField{parent=net_c_3,x=1,y=12,max_len=64,value=ini_cfg.AuthKey,width=32,height=1,fg_bg=bw_fg_bg} diff --git a/reactor-plc/startup.lua b/reactor-plc/startup.lua index c918d4d..67dc290 100644 --- a/reactor-plc/startup.lua +++ b/reactor-plc/startup.lua @@ -18,7 +18,7 @@ local plc = require("reactor-plc.plc") local renderer = require("reactor-plc.renderer") local threads = require("reactor-plc.threads") -local R_PLC_VERSION = "v1.8.11" +local R_PLC_VERSION = "v1.8.12" local println = util.println local println_ts = util.println_ts diff --git a/rtu/config/system.lua b/rtu/config/system.lua index 956ff7a..5b572e4 100644 --- a/rtu/config/system.lua +++ b/rtu/config/system.lua @@ -159,7 +159,7 @@ function system.create(tool_ctl, main_pane, cfg_sys, divs, ext, style) PushButton{parent=net_c_2,x=44,y=14,text="Next \x1a",callback=submit_ct_tr,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} TextBox{parent=net_c_3,x=1,y=1,height=2,text="Optionally, set the facility authentication key below. Do NOT use one of your passwords."} - TextBox{parent=net_c_3,x=1,y=4,height=6,text="This enables verifying that messages are authentic, so it is intended for security on multiplayer servers. All devices on the same network MUST use the same key if any device has a key. This does result in some extra compution (can slow things down).",fg_bg=g_lg_fg_bg} + TextBox{parent=net_c_3,x=1,y=4,height=6,text="This enables verifying that messages are authentic, so it is intended for security on multiplayer servers. All devices on the same network MUST use the same key if any device has a key. This does result in some extra computation (can slow things down).",fg_bg=g_lg_fg_bg} TextBox{parent=net_c_3,x=1,y=11,text="Facility Auth Key"} local key, _ = TextField{parent=net_c_3,x=1,y=12,max_len=64,value=ini_cfg.AuthKey,width=32,height=1,fg_bg=bw_fg_bg} diff --git a/rtu/startup.lua b/rtu/startup.lua index 03353f4..f5ec27f 100644 --- a/rtu/startup.lua +++ b/rtu/startup.lua @@ -31,7 +31,7 @@ local sna_rtu = require("rtu.dev.sna_rtu") local sps_rtu = require("rtu.dev.sps_rtu") local turbinev_rtu = require("rtu.dev.turbinev_rtu") -local RTU_VERSION = "v1.10.13" +local RTU_VERSION = "v1.10.14" local RTU_UNIT_TYPE = types.RTU_UNIT_TYPE local RTU_HW_STATE = databus.RTU_HW_STATE diff --git a/scada-common/comms.lua b/scada-common/comms.lua index 037ce5e..1775248 100644 --- a/scada-common/comms.lua +++ b/scada-common/comms.lua @@ -17,7 +17,7 @@ local max_distance = nil local comms = {} -- protocol/data versions (protocol/data independent changes tracked by util.lua version) -comms.version = "3.0.0" +comms.version = "3.0.1" comms.api_version = "0.0.6" ---@enum PROTOCOL diff --git a/supervisor/config/system.lua b/supervisor/config/system.lua index 56ff6a5..9e0b0c7 100644 --- a/supervisor/config/system.lua +++ b/supervisor/config/system.lua @@ -155,7 +155,7 @@ function system.create(tool_ctl, main_pane, cfg_sys, divs, fac_pane, style, exit PushButton{parent=net_c_3,x=44,y=14,text="Next \x1a",callback=submit_tr,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} TextBox{parent=net_c_4,x=1,y=1,height=2,text="Optionally, set the facility authentication key below. Do NOT use one of your passwords."} - TextBox{parent=net_c_4,x=1,y=4,height=6,text="This enables verifying that messages are authentic, so it is intended for security on multiplayer servers. All devices on the same network MUST use the same key if any device has a key. This does result in some extra compution (can slow things down).",fg_bg=g_lg_fg_bg} + TextBox{parent=net_c_4,x=1,y=4,height=6,text="This enables verifying that messages are authentic, so it is intended for security on multiplayer servers. All devices on the same network MUST use the same key if any device has a key. This does result in some extra computation (can slow things down).",fg_bg=g_lg_fg_bg} TextBox{parent=net_c_4,x=1,y=11,text="Facility Auth Key"} local key, _ = TextField{parent=net_c_4,x=1,y=12,max_len=64,value=ini_cfg.AuthKey,width=32,height=1,fg_bg=bw_fg_bg} diff --git a/supervisor/startup.lua b/supervisor/startup.lua index bf702b7..537b263 100644 --- a/supervisor/startup.lua +++ b/supervisor/startup.lua @@ -22,7 +22,7 @@ local supervisor = require("supervisor.supervisor") local svsessions = require("supervisor.session.svsessions") -local SUPERVISOR_VERSION = "v1.5.9" +local SUPERVISOR_VERSION = "v1.5.10" local println = util.println local println_ts = util.println_ts