Mercurial Hosting > luan
diff src/luan/host/main.luan @ 1135:707a5d874f3e
add luan.host
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Sun, 28 Jan 2018 21:36:58 -0700 |
parents | |
children | 1f9d34a6f308 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/host/main.luan Sun Jan 28 21:36:58 2018 -0700 @@ -0,0 +1,187 @@ +java() +local Luan = require "luan:Luan.luan" +local error = Luan.error +local assert_string = Luan.assert_string or error() +local ipairs = Luan.ipairs or error() +local try = Luan.try or error() +local Io = require "luan:Io.luan" +local print = Io.print or error() +local Rpc = require "luan:Rpc.luan" +local Thread = require "luan:Thread.luan" +local String = require "luan:String.luan" +local literal = String.literal or error() +local lower = String.lower or error() +local matches = String.matches or error() +local Hosting = require "luan:host/Hosting.luan" +local Logging = require "luan:logging/Logging.luan" +local logger = Logging.logger "main" +local WebHandler = require "java:luan.host.WebHandler" + + +local sites_dir = Io.schemes.file(Hosting.sites_dir) + +sites_dir.mkdir() + +local function delete_unused(file) + if file.is_directory() then + if file.name() == "local" then + return false + end + local all_deleted = true + for _,child in ipairs(file.children()) do + all_deleted = delete_unused(child) and all_deleted + end + if not all_deleted then + return false + end + end + file.delete() + return true +end + + +local fns = Rpc.functions + +local function get_dir(domain,password) + assert_string(domain) + assert_string(password) + domain = lower(domain) + local dir = sites_dir.child(domain) + if dir.exists() then + local pwd = dir.child("password").read_text() + if pwd ~= password then + error "wrong password" + end + return dir.child("site") + else + return nil + end +end + +function fns.get(domain,password) + local site_dir = get_dir(domain,password) + if site_dir == nil then + return nil + end + + local children, file_info + + function children(dir) + if dir.name() == "local" then + return {} + end + local rtn = {} + for _,child in ipairs(dir.children()) do + local info = file_info(child) + if info ~= nil then + rtn[info.name] = info + end + end + return rtn + end + + function file_info(file) + local info = { name = file.name(), path = file.to_string() } + if file.is_directory() then + info.children = children(file) + elseif file.is_file() then + info.checksum = file.checksum() + else + return nil + end + return info + end + + return file_info(site_dir) +end + +function fns.create(domain,password) + assert_string(domain) + assert_string(password) + domain = lower(domain) + local dir = sites_dir.child(domain) + dir.exists() and error "already exists" + dir.mkdir() + dir.child("password").write(password) + dir = dir.child("site") + dir.mkdir() + return { name = dir.name(), path = dir.to_string(), children = {} } +end + +local function security(site_dir,file) + matches( file.to_string(), "^"..literal(site_dir.to_string()) ) or error "security violation" +end + +function fns.copy_file(domain,password,dir,name,content) + local site_dir = get_dir(domain,password) + site_dir or error "domain not found" + local file = Io.schemes.file(dir).child(name) + security(site_dir,file) + file.delete() + file.write(content) +end + +function fns.mkdir(domain,password,dir,name) + local site_dir = get_dir(domain,password) + site_dir or error "domain not found" + local file = Io.schemes.file(dir).child(name) + security(site_dir,file) + file.mkdir() + return { name = file.name(), path = file.to_string(), children = {} } +end + +function fns.delete_unused(domain,password,path) + local site_dir = get_dir(domain,password) + site_dir or error "domain not found" + local file = Io.schemes.file(path) + security(site_dir,file) + return delete_unused(file) +end + +function fns.update_handler(domain,password) + local site_dir = get_dir(domain,password) + site_dir or error "domain not found" + domain = lower(domain) + WebHandler.removeHandler(domain) + WebHandler.loadHandler(domain) +end + +function fns.delete(domain,password) + local site_dir = get_dir(domain,password) + site_dir or error "domain not found" + site_dir.parent().delete() + domain = lower(domain) + WebHandler.removeHandler(domain) +end + +function fns.exists(domain) + assert_string(domain) + domain = lower(domain) + return sites_dir.child(domain).exists() +end + +function fns.change_domain(old_domain,new_domain,password) + local old_dir = get_dir(old_domain,password) + old_dir or error "domain not found" + old_dir = old_dir.parent() + assert_string(new_domain) + new_domain = lower(new_domain) + local new_dir = sites_dir.child(new_domain) + new_dir.exists() and error "new_domain already exists" + WebHandler.removeHandler(old_domain) + old_dir.rename_to(new_dir.to_string()) + WebHandler.removeHandler(old_domain) + WebHandler.loadHandler(new_domain) +end + +function fns.change_password(domain,old_password,new_password) + local site_dir = get_dir(domain,old_password) + site_dir or error "domain not found" + site_dir.parent().child("password").write(new_password) + WebHandler.removeHandler(domain) + WebHandler.loadHandler(domain) +end + +fns.call = WebHandler.callSite + +Thread.fork(Rpc.serve)