prpw/prpw-tui

277 lines
6.3 KiB
Plaintext
Raw Normal View History

2024-08-20 11:58:55 +00:00
#!/usr/bin/env lua
basepath = (debug.getinfo(1, "S").source:sub(2):match("(.*[/\\])") or "./"):sub(1,-2)
local entryBackups = {}
local function makeEntryBackup(id)
if entryBackups[id] ~= nil then return end
env.run({"entry_backup",id})
entryBackups[id] = true
end
local function eprint(text)
io.stderr:write(text .. "\n")
end
local function input(text)
if text == nil then text = "" end
io.stderr:write(text)
return io.read()
end
local function yn(question)
io.stderr:write(question .. " - y/n: ")
local inp = false
while true do
inp = string.lower(input())
if (
inp == "y" or
inp == "n"
) then break end
end
return (inp == "y")
end
local function menu(choices)
for i,v in ipairs(choices) do
eprint(tostring(i).. ": " ..tostring(v))
end
local choice = false
while true do
choice = tonumber(input("Choice: "))
if not (
choice == nil or
choice < 1 or
choice > #choices or
math.floor(choice) ~= choice
) then
break
end
end
return choice
end
local function emenu(title,choices,functions,lastSelection)
if lastSelection == nil then lastSelection = "<- BACK" end
table.insert(choices,lastSelection)
while true do
eprint(title)
local i = menu(choices)
if i == #choices then
return
end
eprint("")
functions[i]()
eprint("")
end
end
local function printPassword(entry)
print(env.run({"field_get",entry.attrs.id,"password"}))
end
local function fieldPrint(entry,field)
print(env.run({"field_get",entry.attrs.id,field.attrs.name}))
end
local function fieldPrintType(entry,field)
print(env.run({"field_get_type",entry.attrs.id,field.attrs.name}))
end
local function fieldSetText(entry,field)
local text = input("Text: ")
makeEntryBackup(entry.attrs.id)
env.run({"field_set",entry.attrs.id,field.attrs.name,text})
env.run({"save"})
end
local function fieldSetType(entry,field)
local tp = input("Type: ")
makeEntryBackup(entry.attrs.id)
env.run({"field_set_type",entry.attrs.id,field.attrs.name,tp})
env.run({"save"})
end
local function fieldRemove(entry,field)
2024-08-30 14:03:40 +00:00
if not yn("Do you want to remove the field '" ..field.attrs.name.. "'?") then return end
2024-08-20 11:58:55 +00:00
makeEntryBackup(entry.attrs.id)
env.run({"field_remove",entry.attrs.id,field.attrs.name})
env.run({"save"})
end
local function fieldImportFile(entry,field)
local fpath = input("File path: ")
local fh = io.open(fpath,"r")
if fh == nil then
eprint("Error opening file, make sure to remove any \" or '.")
return
end
local bytes = fh:read("*a")
fh:close()
local base64 = require("base64")
bytes = base64.encode(bytes)
makeEntryBackup(entry.attrs.id)
env.run({"field_set",entry.attrs.id,field.attrs.name,bytes})
bytes = nil
collectgarbage("collect")
env.run({"save"})
end
local function fieldExportFile(entry,field)
local fpath = input("File path: ")
local fh = io.open(fpath,"r")
if fh ~= nil then
fh:close()
eprint("Error: file already exists.")
return
end
fh = io.open(fpath,"w")
if fh == nil then
eprint("Error opening file, make sure to remove any \" or '.")
return
end
local bytes = env.run({"field_get",entry.attrs.id,field.attrs.name})
local base64 = require("base64")
bytes = base64.decode(bytes)
fh:write(bytes)
fh:close()
bytes = nil
collectgarbage("collect")
end
local function fieldRename(entry,field)
local fieldName = input("New field name: ")
makeEntryBackup(entry.attrs.id)
env.run({"field_rename",entry.attrs.id,field.attrs.name,fieldName})
env.run({"save"})
end
2024-08-20 11:58:55 +00:00
local function fieldActions(entry,field)
emenu(
"Field '" ..field.attrs.name.. "':",
{
"Print value + exit",
"Print value",
"Print type",
"Set value",
"Set type",
"Import file",
"Export file",
"Rename",
"Remove"
},
{
function() fieldPrint(entry,field); os.exit(0) end,
function() fieldPrint(entry,field) end,
function() fieldPrintType(entry,field) end,
function() fieldSetText(entry,field) end,
function() fieldSetType(entry,field) end,
function() fieldImportFile(entry,field) end,
function() fieldExportFile(entry,field) end,
function() fieldRename(entry,field) end,
2024-08-20 11:58:55 +00:00
function() fieldRemove(entry,field) end
}
)
end
local function fieldsActions(entry)
local fields = env.run({"field_list",entry.attrs.id})
local funcs = {}
for i,field in pairs(fields) do
fields[i] = field.attrs.name;
table.insert(funcs,function() fieldActions(entry,field) end)
end
emenu("Fields:",fields,funcs)
end
local function fieldAdd(entry)
local fieldName = input("Field name: ")
makeEntryBackup(entry.attrs.id)
env.run({"field_set",entry.attrs.id,fieldName,""})
env.run({"save"})
end
local function entryRename(entry)
local entryName = input("New entry name: ")
makeEntryBackup(entry.attrs.id)
env.run({"entry_rename",entry.attrs.id,entryName})
env.run({"save"})
end
local function entryRemove(entry)
if not yn("Do you want to remove the entry '" ..entry.attrs.name.. "'?") then return end
env.run({"entry_remove",entry.attrs.id})
env.run({"save"})
end
2024-08-20 11:58:55 +00:00
local function manageEntry(entry)
emenu(
"Entry - " ..entry.attrs.name.. ":",
{
"Print password + exit",
"Field add",
"Fields",
"Entry rename",
"Entry remove"
},
{
function() printPassword(entry); os.exit(0) end,
function() fieldAdd(entry) end,
function() fieldsActions(entry) end,
function() entryRename(entry) end,
function() entryRemove(entry) end
2024-08-20 11:58:55 +00:00
}
)
end
local function searchByName()
local entries = {}
local entriesMenu = {}
local name = string.lower(input("Name: "))
for i,entry in pairs(env.xmlFindTags(env.db,"entries")[1].children) do
if string.find(string.lower(entry.attrs.name),name) ~= nil then
table.insert(entries,function() manageEntry(entry) end)
2024-08-30 14:04:50 +00:00
local username = nil
pcall(function()
username = env.run({"field_get",entry.attrs.id,"username"})
end)
local output = entry.attrs.name
if username ~= nil then
output = output .. " (" .. username .. ")"
end
table.insert(entriesMenu,output)
2024-08-20 11:58:55 +00:00
end
end
emenu("Found entries:",entriesMenu,entries)
end
local function main(arg)
package.path = basepath .. "/lib/?.lua;" .. basepath .. "/lib/?/main.lua;" .. package.path
require("prpw")
env.cli = false
env.run({"open",arg[1]})
emenu(
"Search entry by ...",
{
"Name",
"All non-secret field contents",
"Field content",
"List all"
},
{
searchByName,
searchByFields, -- todo
searchByField, -- todo
listAll -- todo
},
"<- EXIT"
)
end
main(arg)