diff --git a/contrib/autostyle.lua b/contrib/autostyle.lua index a12cd0a..319b8f3 100644 --- a/contrib/autostyle.lua +++ b/contrib/autostyle.lua @@ -39,6 +39,7 @@ GPLv2 local darktable = require "darktable" local du = require "lib/dtutils" local filelib = require "lib/dtutils.file" +local syslib = require "lib/dtutils.system" du.check_min_api_version("7.0.0", "autostyle") @@ -68,7 +69,7 @@ script_data.show = nil -- only required for libs since the destroy_method only h -- run command and retrieve stdout local function get_stdout(cmd) -- Open the command, for reading - local fd = assert(io.popen(cmd, 'r')) + local fd = assert(syslib.io_popen(cmd, 'r')) darktable.control.read(fd) -- slurp the whole file local data = assert(fd:read('*a')) diff --git a/contrib/color_profile_manager.lua b/contrib/color_profile_manager.lua index ed08317..d87d9a6 100644 --- a/contrib/color_profile_manager.lua +++ b/contrib/color_profile_manager.lua @@ -45,6 +45,7 @@ local dt = require "darktable" local du = require "lib/dtutils" local df = require "lib/dtutils.file" +local dtsys = require "lib/dtutils.system" du.check_min_api_version("7.0.0", "color_profile_manager") @@ -106,7 +107,7 @@ end local function list_profiles(dir) local files = {} - local p = io.popen(DIR_CMD .. " " .. dir) + local p = dtsys.io_popen(DIR_CMD .. " " .. dir) if p then for line in p:lines() do table.insert(files, line) diff --git a/contrib/fujifilm_dynamic_range.lua b/contrib/fujifilm_dynamic_range.lua index d373d13..1034411 100644 --- a/contrib/fujifilm_dynamic_range.lua +++ b/contrib/fujifilm_dynamic_range.lua @@ -60,6 +60,7 @@ cameras may behave in other ways. local dt = require "darktable" local du = require "lib/dtutils" local df = require "lib/dtutils.file" +local dtsys = require "lib/dtutils.system" local gettext = dt.gettext.gettext du.check_min_api_version("7.0.0", "fujifilm_dynamic_range") @@ -105,7 +106,7 @@ local function detect_dynamic_range(event, image) -- without -n flag, exiftool will round to the nearest tenth command = command .. " -RawExposureBias -n -t " .. RAF_filename dt.print_log(command) - output = io.popen(command) + output = dtsys.io_popen(command) local raf_result = output:read("*all") output:close() if #raf_result == 0 then diff --git a/contrib/fujifilm_ratings.lua b/contrib/fujifilm_ratings.lua index f9bb1c8..ef93513 100644 --- a/contrib/fujifilm_ratings.lua +++ b/contrib/fujifilm_ratings.lua @@ -26,6 +26,7 @@ Dependencies: local dt = require "darktable" local du = require "lib/dtutils" local df = require "lib/dtutils.file" +local dtsys = require "lib/dtutils.system" local gettext = dt.gettext.gettext du.check_min_api_version("7.0.0", "fujifilm_ratings") @@ -61,7 +62,7 @@ local function detect_rating(event, image) local JPEG_filename = string.gsub(RAF_filename, "%.RAF$", ".JPG") local command = "exiftool -Rating " .. JPEG_filename dt.print_error(command) - local output = io.popen(command) + local output = dtsys.io_popen(command) local jpeg_result = output:read("*all") output:close() if string.len(jpeg_result) > 0 then @@ -72,7 +73,7 @@ local function detect_rating(event, image) end command = "exiftool -Rating " .. RAF_filename dt.print_error(command) - output = io.popen(command) + output = dtsys.io_popen(command) local raf_result = output:read("*all") output:close() if string.len(raf_result) > 0 then diff --git a/contrib/geoJSON_export.lua b/contrib/geoJSON_export.lua index 695976a..406c37c 100644 --- a/contrib/geoJSON_export.lua +++ b/contrib/geoJSON_export.lua @@ -35,6 +35,7 @@ USAGE local dt = require "darktable" local du = require "lib/dtutils" local df = require "lib/dtutils.file" +local dtsys = require "lib/dtutils.system" local gettext = dt.gettext.gettext du.check_min_api_version("7.0.0", "geoJSON_export") @@ -330,7 +331,7 @@ dt.preferences.register("geoJSON_export", _("opens the geoJSON file after the export with the standard program for geoJSON files"), false ) -local handle = io.popen("xdg-user-dir DESKTOP") +local handle = dtsys.io_popen("xdg-user-dir DESKTOP") local result = handle:read() handle:close() if (result == nil) then diff --git a/contrib/geoToolbox.lua b/contrib/geoToolbox.lua index 83caa13..d654eeb 100644 --- a/contrib/geoToolbox.lua +++ b/contrib/geoToolbox.lua @@ -28,6 +28,7 @@ require "geoToolbox" local dt = require "darktable" local du = require "lib/dtutils" local df = require "lib/dtutils.file" +local dtsys = require "lib/dtutils.system" local gettext = dt.gettext.gettext du.check_min_api_version("7.0.0", "geoToolbox") @@ -411,7 +412,7 @@ local function reverse_geocode() -- jq could be replaced with a Lua JSON parser startCommand = string.format("curl --silent \"https://api.mapbox.com/geocoding/v5/mapbox.places/%s,%s.json?types=%s&access_token=%s\" | jq '.features | .[0] | '.text''", lon1, lat1, types, tokan) - local handle = io.popen(startCommand) + local handle = dtsys.io_popen(startCommand) local result = trim12(handle:read("*a")) handle:close() diff --git a/contrib/image_stack.lua b/contrib/image_stack.lua index c63ff16..ba0909b 100644 --- a/contrib/image_stack.lua +++ b/contrib/image_stack.lua @@ -348,7 +348,7 @@ local function list_files(search_string) search_string = string.gsub(search_string, "/", "\\\\") end - local f = io.popen(ls .. search_string) + local f = dtsys.io_popen(ls .. search_string) if f then local found_file = f:read() while found_file do diff --git a/contrib/image_time.lua b/contrib/image_time.lua index f20e500..fa00b57 100644 --- a/contrib/image_time.lua +++ b/contrib/image_time.lua @@ -107,6 +107,7 @@ local dt = require "darktable" local du = require "lib/dtutils" local df = require "lib/dtutils.file" local ds = require "lib/dtutils.string" +local dtsys = require "lib/dtutils.system" local gettext = dt.gettext.gettext local img_time = {} @@ -225,7 +226,7 @@ local function get_image_taken_time(image) local exiv2 = df.check_if_bin_exists("exiv2") if exiv2 then - p = io.popen(exiv2 .. " -K Exif.Image.DateTime " .. image.path .. PS .. image.filename) + p = dtsys.io_popen(exiv2 .. " -K Exif.Image.DateTime " .. image.path .. PS .. image.filename) if p then for line in p:lines() do if string.match(line, "Exif.Image.DateTime") then @@ -243,7 +244,7 @@ end local function _get_windows_image_file_creation_time(image) local datetime = nil - local p = io.popen("dir " .. image.path .. PS .. image.filename) + local p = dtsys.io_popen("dir " .. image.path .. PS .. image.filename) if p then for line in p:lines() do if string.match(line, ds.sanitize_lua(image.filename)) then @@ -264,7 +265,7 @@ end local function _get_nix_image_file_creation_time(image) local datetime = nil - local p = io.popen("ls -lL --time-style=full-iso " .. image.path .. PS .. image.filename) + local p = dtsys.io_popen("ls -lL --time-style=full-iso " .. image.path .. PS .. image.filename) if p then for line in p:lines() do if string.match(line, ds.sanitize_lua(image.filename)) then diff --git a/contrib/kml_export.lua b/contrib/kml_export.lua index ec1aa04..ec7218c 100644 --- a/contrib/kml_export.lua +++ b/contrib/kml_export.lua @@ -343,7 +343,7 @@ if dt.configuration.running_os == "windows" then elseif dt.configuration.running_os == "macos" then defaultDir = os.getenv("HOME") else - local handle = io.popen("xdg-user-dir DESKTOP") + local handle = dsys.io_popen("xdg-user-dir DESKTOP") defaultDir = handle:read() handle:close() end diff --git a/lib/dtutils.lua b/lib/dtutils.lua index c17ce33..c8331cb 100644 --- a/lib/dtutils.lua +++ b/lib/dtutils.lua @@ -82,8 +82,7 @@ dtutils.libdoc.functions["check_max_api_version"] = { run against the current api version. This function is used when a part of the Lua API that the script relies on is removed. If the maximum api version is not met, then an error message is printed saying the script_name failed to load, then an error is thrown causing the - program to stop executing. - + program to stop executing.]], Return_Value = [[result - true if the maximum api version is available, false if not.]], Limitations = [[When using the default handler on a script being executed from the luarc file, the error thrown will stop the luarc file from executing any remaining statements. This limitation does not apply to script_manger.]], diff --git a/lib/dtutils/file.lua b/lib/dtutils/file.lua index cd898e7..b871711 100644 --- a/lib/dtutils/file.lua +++ b/lib/dtutils/file.lua @@ -42,7 +42,7 @@ end local function _win_os_execute(cmd) local result = nil - local p = io.popen(cmd) + local p = dsys.io_popen(cmd) local output = p:read("*a") p:close() if string.match(output, "true") then @@ -94,7 +94,7 @@ dtutils_file.libdoc.functions["test_file"] = { function dtutils_file.test_file(path, test) local cmd = "test -" - local engine = os.execute + local engine = dsys.os_execute local cmdstring = "" if dt.configuration.running_os == "windows" then @@ -167,7 +167,7 @@ local function _search_for_bin_windows(bin) for _,arg in ipairs(args) do local cmd = "where " .. arg .. " " .. ds.sanitize(bin) - local p = io.popen(cmd) + local p = dsys.io_popen(cmd) local output = p:read("*a") p:close() local lines = du.split(output, "\n") @@ -191,7 +191,7 @@ end local function _search_for_bin_nix(bin) local result = false - local p = io.popen("command -v " .. bin) + local p = dsys.io_popen("command -v " .. bin) local output = p:read("*a") p:close() if string.len(output) > 0 then @@ -220,7 +220,7 @@ local function _search_for_bin_macos(bin) search_start = "/Applications/" .. bin .. ".app" end - local p = io.popen("find " .. search_start .. " -type f -name " .. bin .. " -print") + local p = dsys.io_popen("find " .. search_start .. " -type f -name " .. bin .. " -print") local output = p:read("*a") p:close() local lines = du.split(output, "\n") @@ -445,7 +445,7 @@ function dtutils_file.check_if_file_exists(filepath) local result = false if (dt.configuration.running_os == 'windows') then filepath = string.gsub(filepath, '[\\/]+', '\\') - local p = io.popen("if exist " .. dtutils_file.sanitize_filename(filepath) .. " (echo 'yes') else (echo 'no')") + local p = dsys.io_popen("if exist " .. dtutils_file.sanitize_filename(filepath) .. " (echo 'yes') else (echo 'no')") local ans = p:read("*all") p:close() if string.match(ans, "yes") then @@ -456,7 +456,7 @@ function dtutils_file.check_if_file_exists(filepath) -- result = false -- end elseif (dt.configuration.running_os == "linux") then - result = os.execute('test -e ' .. dtutils_file.sanitize_filename(filepath)) + result = dsys.os_execute('test -e ' .. dtutils_file.sanitize_filename(filepath)) if not result then result = false end @@ -522,9 +522,9 @@ function dtutils_file.file_copy(fromFile, toFile) local result = nil -- if cp exists, use it if dt.configuration.running_os == "windows" then - result = os.execute('copy "' .. fromFile .. '" "' .. toFile .. '"') + result = dsys.os_execute('copy "' .. fromFile .. '" "' .. toFile .. '"') elseif dtutils_file.check_if_bin_exists("cp") then - result = os.execute("cp '" .. fromFile .. "' '" .. toFile .. "'") + result = dsys.os_execute("cp '" .. fromFile .. "' '" .. toFile .. "'") end -- if cp was not present, or if cp failed, then a pure lua solution @@ -575,7 +575,7 @@ function dtutils_file.file_move(fromFile, toFile) if not success then -- an error occurred, so let's try using the operating system function if dtutils_file.check_if_bin_exists("mv") then - success = os.execute("mv '" .. fromFile .. "' '" .. toFile .. "'") + success = dsys.os_execute("mv '" .. fromFile .. "' '" .. toFile .. "'") end -- if the mv didn't exist or succeed, then... if not success then diff --git a/lib/dtutils/system.lua b/lib/dtutils/system.lua index f41f821..e8ce9af 100644 --- a/lib/dtutils/system.lua +++ b/lib/dtutils/system.lua @@ -1,6 +1,7 @@ local dtutils_system = {} local dt = require "darktable" +local ds = require "lib/dtutils.string" dtutils_system.libdoc = { Name = [[dtutils.system]], @@ -50,9 +51,9 @@ function dtutils_system.external_command(command) local result = nil if dt.configuration.running_os == "windows" then - result = dtutils_system.windows_command(command) + result = dtutils_system.windows_command(ds.sanitize(command)) else - result = dt.control.execute(command) + result = dt.control.execute(ds.sanitize(command)) end return result @@ -77,15 +78,20 @@ dtutils_system.libdoc.functions["windows_command"] = { Copyright = [[]], } +local function quote_windows_command(command) + return "\"" .. command .. "\"" +end + function dtutils_system.windows_command(command) local result = 1 - local fname = dt.configuration.tmp_dir .. "/run_command.bat" + local fname = ds.sanitize(dt.configuration.tmp_dir .. "/run_command.bat") local file = io.open(fname, "w") if file then dt.print_log("opened file") command = string.gsub(command, "%%", "%%%%") -- escape % from windows shell + command = quote_windows-command(command) file:write(command) file:close() @@ -129,4 +135,55 @@ function dtutils_system.launch_default_app(path) end +dtutils_system.libdoc.functions["os_execute"] = { + Name = [[os_execute]], + Synopsis = [[wrapper around the lua os.execute function]], + Usage = [[local dsys = require "lib/dtutils.file" + + result = dsys.os_execute(cmd) + cmd - string - a command to execute on the operating system]], + Description = [[os_execute wraps the lua os.execute system call to provide + correct sanitization of windows commands]], + Return_Value = [[see the lua os.execute documentation]], + Limitations = [[]], + Example = [[]], + See_Also = [[]], + Reference = [[]], + License = [[]], + Copyright = [[]], +} + +function dtutils_system.os_execute(cmd) + if dt.configuration.running_os == "windows" then + cmd = quote_windows_command(cmd) + end + return os.execute(cmd) +end + +dtutils_system.libdoc.functions["io_popen"] = { + Name = [[io_popen]], + Synopsis = [[wrapper around the lua io.popen function]], + Usage = [[local dsys = require "lib/dtutils.file" + + result = dsys.io_popen(cmd) + cmd - string - a command to execute and attach to]], + Description = [[io_popen wraps the lua io.popen system call to provide + correct sanitization of windows commands]], + Return_Value = [[see the lua io.popen documentation]], + Limitations = [[]], + Example = [[]], + See_Also = [[]], + Reference = [[]], + License = [[]], + Copyright = [[]], +} + +function dtutils_system.io_popen(cmd) + if dt.configuration.running_os == "windows" then + cmd = quote_windows_command(cmd) + end + return io.popen(cmd) +end + + return dtutils_system diff --git a/official/enfuse.lua b/official/enfuse.lua index c8df51b..c193c35 100644 --- a/official/enfuse.lua +++ b/official/enfuse.lua @@ -116,7 +116,7 @@ if enfuse_installed then local version = nil - local p = io.popen(enfuse_installed .. " --version") + local p = dtsys.io_popen(enfuse_installed .. " --version") local f = p:read("all") p:close() version = string.match(f, "enfuse (%d.%d)") diff --git a/tools/executable_manager.lua b/tools/executable_manager.lua index cc98cd9..0e28668 100644 --- a/tools/executable_manager.lua +++ b/tools/executable_manager.lua @@ -31,6 +31,7 @@ local dt = require "darktable" local du = require "lib/dtutils" local df = require "lib/dtutils.file" +local dtsys = require "lib/dtutils.system" du.check_min_api_version("7.0.0", "executable_manager") @@ -75,7 +76,7 @@ local function grep(file, pattern) if dt.configuration.running_os == "windows" then -- use find to get the matches local command = "\\windows\\system32\\find.exe " .. "\"" .. pattern .. "\"" .. " " .. file - local f = io.popen(command) + local f = dtsys.io_popen(command) local output = f:read("all") f:close() -- strip out the first line @@ -84,7 +85,7 @@ local function grep(file, pattern) else -- use grep and just return the answers local command = "grep " .. pattern .. " " .. file - local f = io.popen(command) + local f = dtsys.io_popen(command) local output = f:read("all") f:close() result = du.split(output, "\n") diff --git a/tools/get_lib_manpages.lua b/tools/get_lib_manpages.lua index a3c3915..91d5dbb 100644 --- a/tools/get_lib_manpages.lua +++ b/tools/get_lib_manpages.lua @@ -7,6 +7,7 @@ local dt = require "darktable" local du = require "lib/dtutils" local df = require "lib/dtutils.file" +local dtsys = require "lib/dtutils.system" local log = require "lib/dtutils.log" local libname = nil @@ -45,7 +46,7 @@ local function output_man(d) mf:close() if df.check_if_bin_exists("groff") then if df.check_if_bin_exists("ps2pdf") then - os.execute("groff -man " .. fname .. " | ps2pdf - " .. fname .. ".pdf") + dtsys.os_execute("groff -man " .. fname .. " | ps2pdf - " .. fname .. ".pdf") else log.msg(log.error, "Missing ps2pdf. Can't generate pdf man pages.") end @@ -59,7 +60,7 @@ end -- find the libraries -local output = io.popen("cd "..dt.configuration.config_dir.."/lua/lib ;find . -name \\*.lua -print | sort") +local output = dtsys.io_popen("cd "..dt.configuration.config_dir.."/lua/lib ;find . -name \\*.lua -print | sort") -- loop through the libraries diff --git a/tools/get_libdoc.lua b/tools/get_libdoc.lua index 5cb0812..2328014 100644 --- a/tools/get_libdoc.lua +++ b/tools/get_libdoc.lua @@ -6,6 +6,7 @@ local dt = require "darktable" local du = require "lib/dtutils" +local dtsys = require "lib/dtutils.system" du.check_min_api_version("3.0.0", "get_libdoc") @@ -36,7 +37,7 @@ end -- find the libraries -local output = io.popen("cd "..dt.configuration.config_dir.."/lua/lib ;find . -name \\*.lua -print | sort") +local output = dtsys.io_popen("cd "..dt.configuration.config_dir.."/lua/lib ;find . -name \\*.lua -print | sort") -- loop through the libraries