#!/usr/bin/env lua
local json = require "luci.jsonc"
local fs   = require "nixio.fs"
local sys = require "luci.sys"
local ut = require "luci.util"

local methods = {
	run_command = {
		args = { cmd = "none", args = "none" },
		call = function(args)
			local exec_cmd = tostring(args.cmd) .. " " .. tostring(args.args)
			local handle = io.popen(exec_cmd .. " 2>/dev/null")
			local res = {}
			res = handle:read("*a")
			handle:close()
			return { result = res }
		end
	},
	get_ssh_server_users = {
		call = function()
			local res = {}
			local ssh_authorized_users = sys.exec("ltrx_cli enable \\\\ ssh \\\\ server \\\\ show | grep 'Username' | awk -F ':' '{print$2}' | tr -d ' '")
			for str in string.gmatch(ssh_authorized_users, "[^\r\n]+") do
				local data = {}
				data["username"] = str
				local ssh_user_info = luci.sys.exec("ltrx_cli enable \\\\ ssh \\\\ server \\\\ show authorized user " .. str )
				if ssh_user_info then
					for new_line in string.gmatch(ssh_user_info, "([^\r\n]+)") do
						if(string.find(new_line, "RSA Key")) then
							if(string.find(new_line, "rsa")) then
								local public_key=luci.sys.exec('/usr/sbin/ltrx-sshserverusers-viewkey.sh "ltrx-sshserverusers-viewkey" "rsa" '.. str ..'')
								local rsa_keys = {}
								for key in string.gmatch(public_key, "[^\r\n]+") do
									table.insert(rsa_keys, key)
								end
								data["rsa"] = rsa_keys
							else
								data["rsa"] = new_line
							end
						elseif(string.find(new_line, "DSA Key")) then
							if(string.find(new_line, "dss")) then
								local public_key=luci.sys.exec('/usr/sbin/ltrx-sshserverusers-viewkey.sh "ltrx-sshserverusers-viewkey" "dsa" '.. str ..'')
								local dsa_keys = {}
								for key in string.gmatch(public_key, "[^\r\n]+") do
									table.insert(dsa_keys, key)
								end
								data["dsa"] = dsa_keys
							else
								data["dsa"] = new_line
							end
						else
							data["password"] = new_line
						end
					end
				end
				table.insert(res, data)

			end
			return { result = res }
		end
	},
	get_ssh_client_known_hosts = {
		call = function()
			local res = {}
			local ssh_authorized_users = sys.exec("ltrx_cli enable \\\\ ssh \\\\ client \\\\ show | grep 'Server' | awk -F ':' '{print$2}' | tr -d ' '")
			for server in string.gmatch(ssh_authorized_users, "[^\r\n]+") do
				local data = {}
				data["servername"] = server
				local knownhost_server_info = luci.sys.exec("ltrx_cli enable \\\\ ssh \\\\ client \\\\ show | sed -n '/Known Hosts:/,/Users:/p' | grep -v 'Known Hosts:' | grep -v 'Users:' | grep -v 'Server'")
				if knownhost_server_info then
					for new_line in string.gmatch(knownhost_server_info, "([^\r\n]+)") do
						if(string.find(new_line, "RSA Key")) then
							if(string.find(new_line, "rsa")) then
								local public_key=luci.sys.exec('/usr/sbin/ltrx-sshclientknownhosts-viewkey.sh "ltrx-sshclientknownhosts-viewkey" "rsa" '.. server ..'')
								local rsa_keys = {}
								for key in string.gmatch(public_key, "[^\r\n]+") do
									table.insert(rsa_keys, key)
								end
								data["rsa"] = rsa_keys
							else
								data["rsa"] = new_line
							end
						elseif(string.find(new_line, "DSA Key")) then
							if(string.find(new_line, "dss")) then
								local public_key=luci.sys.exec('/usr/sbin/ltrx-sshclientknownhosts-viewkey.sh "ltrx-sshclientknownhosts-viewkey" "dsa" '.. server ..'')
								local dsa_keys = {}
								for key in string.gmatch(public_key, "[^\r\n]+") do
									table.insert(dsa_keys, key)
								end
								data["dsa"] = dsa_keys
							else
								data["dsa"] = new_line
							end
						else
							data["password"] = new_line
						end
					end
				end
				table.insert(res, data)
			end
			return { result = res }
		end
	},
	get_ssh_client_users = {
		call = function()
			local res = {}
			local ssh_users = sys.exec("ltrx_cli enable \\\\ ssh \\\\ client \\\\ show | grep 'Username' | awk -F ':' '{print$2}' | tr -d ' '")
			for user in string.gmatch(ssh_users, "[^\r\n]+") do
				local data = {}
				data["username"] = user
				local ssh_user_info = luci.sys.exec("ltrx_cli enable \\\\ ssh \\\\ client \\\\ show user " .. user )
				if ssh_user_info then
					for new_line in string.gmatch(ssh_user_info, "([^\r\n]+)") do
						if((string.find(new_line, "RSA Private Key")) or (string.find(new_line, "DSA Private Key"))) then
							--  Skip Private key
						elseif(string.find(new_line, "Command")) then
							data["command"] = new_line
						elseif(string.find(new_line, "RSA Public Key")) then
							if(string.find(new_line, "rsa")) then
								local public_key = luci.sys.exec('/usr/sbin/ltrx-sshclientusers-viewkey.sh "ltrx-sshclientusers-viewkey" "rsa" '.. user ..'')
								local rsa_keys = {}
								for key in string.gmatch(public_key, "[^\r\n]+") do
									table.insert(rsa_keys, key)
								end
								data["rsa"] = rsa_keys
							else
								data["rsa"] = new_line
							end
						elseif(string.find(new_line, "DSA Public Key")) then
							if(string.find(new_line, "dss")) then
								local public_key=luci.sys.exec('/usr/sbin/ltrx-sshclientusers-viewkey.sh "ltrx-sshclientusers-viewkey" "dsa" '.. user ..'')
								local dsa_keys = {}
								for key in string.gmatch(public_key, "[^\r\n]+") do
									table.insert(dsa_keys, key)
								end
								data["dsa"] = dsa_keys
							else
								data["dsa"] = new_line
							end
						else
							data["password"] = new_line
						end
					end
				end
				table.insert(res, data)
			end
			return { result = res }
		end
	}
}

local function parseInput()
	local parse = json.new()
	local done, err

	while true do
		local chunk = io.read(4096)
		if not chunk then
			break
		elseif not done and not err then
			done, err = parse:parse(chunk)
		end
	end

	if not done then
		print(json.stringify({ error = err or "Incomplete input" }))
		os.exit(1)
	end

	return parse:get()
end

local function validateArgs(func, uargs)
	local method = methods[func]
	if not method then
		print(json.stringify({ error = "Method not found" }))
		os.exit(1)
	end

	if type(uargs) ~= "table" then
		print(json.stringify({ error = "Invalid arguments" }))
		os.exit(1)
	end

	uargs.ubus_rpc_session = nil

	local k, v
	local margs = method.args or {}
	for k, v in pairs(uargs) do
		if margs[k] == nil or
			(v ~= nil and type(v) ~= type(margs[k]))
		then
			print(json.stringify({ error = "Invalid arguments" }))
			os.exit(1)
		end
	end

	return method
end

if arg[1] == "list" then
	local _, method, rv = nil, nil, {}
	for _, method in pairs(methods) do rv[_] = method.args or {} end
	print((json.stringify(rv):gsub(":%[%]", ":{}")))
elseif arg[1] == "call" then
	local args = parseInput()
	local method = validateArgs(arg[2], args)
	local result, code = method.call(args)
	print((json.stringify(result):gsub("^%[%]$", "{}")))
	os.exit(code or 0)
end
