268 lines
6.1 KiB
Lua
Executable File
268 lines
6.1 KiB
Lua
Executable File
#!/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)
|
|
if not yn("Do you want to remove the field '" ..field.attrs.name.. "'?") then return end
|
|
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
|
|
|
|
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,
|
|
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
|
|
|
|
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
|
|
}
|
|
)
|
|
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)
|
|
table.insert(entriesMenu,entry.attrs.name)
|
|
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)
|