local paths = require('muwiki.paths') local M = {} function M.file_exists(path) local stat = vim.uv.fs_stat(path) return stat and stat.type == 'file' end function M.dir_exists(path) local stat = vim.uv.fs_stat(path) return stat and stat.type == 'directory' end function M.create_dir_safely(dirpath, wiki_root) if not paths.is_within_wiki(dirpath, wiki_root) then return false, 'Directory is outside wiki root' end if M.dir_exists(dirpath) then return true, nil end if vim.fn.mkdir(dirpath, 'p') ~= 1 then return false, 'Failed to create directory' end if not paths.is_within_wiki(dirpath, wiki_root) then vim.fn.delete(dirpath, 'd') return false, 'Symlink attack detected' end return true, nil end function M.ensure_parent_dirs(filepath, wiki_root, mode, callback) local dirpath = vim.fs.dirname(filepath) if M.dir_exists(dirpath) then if callback then callback(true) end return true end local function do_create() local success, err = M.create_dir_safely(dirpath, wiki_root) if not success then vim.notify(string.format('Cannot create directory: %s', err), vim.log.levels.ERROR) if callback then callback(false) end return false end if mode == 'notify' then vim.notify(string.format('Created directory: %s', dirpath), vim.log.levels.INFO) end if callback then callback(true) end return true end if mode == 'prompt' then vim.ui.select({ 'Yes', 'No' }, { prompt = string.format('Directory does not exist. Create %s?', dirpath), }, function(choice) if choice == 'Yes' then do_create() else vim.notify('Directory creation cancelled', vim.log.levels.INFO) if callback then callback(false) end end end) return nil end return do_create() end return M