From 8ae76db7435b037ba94af69023adc7f795f51691 Mon Sep 17 00:00:00 2001 From: Roman Bazalevskiy Date: Wed, 10 Oct 2018 12:42:42 +0300 Subject: [PATCH] =?utf8?q?=D0=9F=D1=80=D0=B8=D0=B2=D0=B5=D0=B4=D0=B5=D0=BD?= =?utf8?q?=D0=B8=D0=B5=20=D0=B2=20=D0=B1=D0=BE=D0=BB=D0=B5=D0=B5=20=D0=BF?= =?utf8?q?=D1=80=D0=B8=D0=BB=D0=B8=D1=87=D0=BD=D1=8B=D0=B9=20=D0=B2=D0=B8?= =?utf8?q?=D0=B4=20=D1=81=20=D0=B2=D1=8B=D0=BD=D0=BE=D1=81=D0=BE=D0=BC=20?= =?utf8?q?=D0=B8=D1=81=D0=BF=D0=BE=D0=BB=D1=8C=D0=B7=D1=83=D0=B5=D0=BC?= =?utf8?q?=D1=8B=D1=85=20=D0=B1=D0=B0=D0=B7=D0=BE=D0=B2=D1=8B=D1=85=20?= =?utf8?q?=D1=84=D1=83=D0=BD=D0=BA=D1=86=D0=B8=D0=B9=20=D0=B2=20=D0=BE?= =?utf8?q?=D1=82=D0=B4=D0=B5=D0=BB=D1=8C=D0=BD=D1=83=D1=8E=20=D0=B1=D0=B8?= =?utf8?q?=D0=B1=D0=BB=D0=B8=D0=BE=D1=82=D0=B5=D0=BA=D1=83.?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- etc/config/filemanager | 3 +- usr/lib/lua/cgi.lua | 8 +- usr/lib/lua/luafm.lua | 102 ++++++++++++++++++++ www/cgi-bin/fs | 206 ++++++++++++++++++++-------------------- www/cgi-bin/fs-download | 17 +--- www/cgi-bin/fs-upload | 22 +---- 6 files changed, 219 insertions(+), 139 deletions(-) create mode 100644 usr/lib/lua/luafm.lua diff --git a/etc/config/filemanager b/etc/config/filemanager index daffa4f..1154ecc 100644 --- a/etc/config/filemanager +++ b/etc/config/filemanager @@ -1,3 +1,4 @@ config filemanager 'config' - option basedir '/mnt/' + option basedir '/mnt' + option tmpdir '/tmp' diff --git a/usr/lib/lua/cgi.lua b/usr/lib/lua/cgi.lua index f5108ee..e9068e5 100644 --- a/usr/lib/lua/cgi.lua +++ b/usr/lib/lua/cgi.lua @@ -1,5 +1,9 @@ -- cgi util module +local uci = require("uci") +local u_c = uci.cursor() +local tmppath = u_c.get("filemanager","config","tmpdir") + local prevbuf = "" local blocksize = 4096 local _M = {} @@ -31,7 +35,7 @@ function _M.new(req) req.boundary = "--" .. req.boundary end -- this is useful only if you have /tmp on tmpfs like in openwrt. otherwise can be set to "" - req.tempdir = "/tmp" + req.tempdir = tmppath req.post = {} end @@ -113,4 +117,4 @@ function _M.parse_request_body (req) return 400, "Malformed POST. Boundary not properly ended with CRLF or --." end -return _M \ No newline at end of file +return _M diff --git a/usr/lib/lua/luafm.lua b/usr/lib/lua/luafm.lua new file mode 100644 index 0000000..2de767a --- /dev/null +++ b/usr/lib/lua/luafm.lua @@ -0,0 +1,102 @@ +#!/usr/bin/lua + +local uci = require "uci" +local fs = require "nixio.fs" +local u_c = uci.cursor() +local basepath = u_c.get("filemanager","config","basedir") + +local _M = {} + +local bp = basepath:match("(.*)/") +if bp and bp ~= "" then + basepath = bp +end +_M.basepath = basepath; + +function _M.is_in_dir(file, dir) + if file == dir then + return true + else + return file:sub(1, #dir) == dir + end +end + +function _M.path_valid(path) + return _M.is_in_dir(path,_M.basepath) and fs.access(path,"r") +end + +function _M.dir_path_valid(path) + return _M.is_in_dir(path,_M.basepath) and fs.stat(path,"type")=="dir" and fs.access(path,"w") +end + +function _M.new_path_valid(path) + local dirpath = fs.dirname(path) + return _M.is_in_dir(dirpath,_M.basepath) and fs.access(dirpath,"w") +end + +function _M.make_path(path) + local realpath = fs.realpath(_M.basepath..'/'..path) + if _M.path_valid(realpath) then + return realpath + else + return nil + end +end + +function _M.make_new_path(path) + local realpath = fs.realpath(fs.dirname(_M.basepath..'/'..path))..'/'..fs.basename(path) + if _M.new_path_valid(realpath) then + return realpath + else + return nil + end +end + +function _M.make_dir_path(path) + local realpath = fs.realpath(_M.basepath..'/'..path) + if _M.dir_path_valid(realpath) then + return realpath + else + return nil + end +end + +function _M.rm(item) + local ftype = fs.stat(item,"type") + if ftype == "reg" then + return fs.remove(item) + elseif ftype == "dir" then + local dir = fs.dir(item) + for file in dir do + if not _M.rm(item..'/'..file) then + return false + end + end + return fs.rmdir(item) + else + return false + end +end + +function _M.chmod(item,mode,recursive) + local result = fs.chmod(item,mode) + if result and recursive then + local dir = fs.dir(item) + if dir then + for file in dir do + local ftype = fs.stat(item..'/'..file,"type") + if ftype == "dir" then + result = _M.chmod(item..'/'..file,mode,recursive) + elseif ftype == "reg" then + result = _M.chmod(item..'/'..file,string.gsub(mode,"x","-"),false) + end + if not result then + break + end + end + end + end + return result +end + +return _M diff --git a/www/cgi-bin/fs b/www/cgi-bin/fs index cee5f0f..81282d7 100755 --- a/www/cgi-bin/fs +++ b/www/cgi-bin/fs @@ -3,51 +3,7 @@ local os = require "os" local fs = require "nixio.fs" local json = require "json" -local uci = require("uci") - -local function is_in_dir(file, dir) - if file == dir then - return true - else - return file:sub(1, #dir) == dir - end -end - -local function rm(item) - local ftype = fs.stat(item,"type") - if ftype == "reg" then - return fs.remove(item) - elseif ftype == "dir" then - local dir = fs.dir(item) - for file in dir do - if not rm(item..'/'..file) then - return false - end - end - return fs.rmdir(item) - end -end - -local function chmod(item,mode,recursive) - local result = fs.chmod(item,mode) - if result and recursive then - local dir = fs.dir(item) - if dir then - for file in dir do - local ftype = fs.stat(item..'/'..file,"type") - if ftype == "dir" then - result = chmod(item..'/'..file,mode,recursive) - elseif ftype == "reg" then - result = chmod(item..'/'..file,string.gsub(mode,"x","-"),false) - end - if not result then - break - end - end - end - end - return result -end +local luafm = require("luafm") print("Content-type: text/html; charset=utf-8") print("Cache-control: no-cache") @@ -64,9 +20,6 @@ local request=io.read("*all") local params=json.decode(request) local action=params["action"] -local u_c = uci.cursor() -local basepath = u_c.get("filemanager","config","basedir") - local path local items local item @@ -89,15 +42,15 @@ local command if action == "list" then - path = fs.realpath(basepath..'/'..params["path"]) - - if path and is_in_dir(path,basepath) and fs.access(path,"r") then + path = luafm.make_path(params["path"]) + + if path then files = {} local rec for name in fs.dir(path) do basename=fs.realpath(path..'/'..name) if basename then - fstat=fs.stat(fs.realpath(path..'/'..name)) + fstat=fs.stat(basename) if fstat["type"]=="reg" then ftype="file" elseif fstat["type"]=="dir" then @@ -118,11 +71,16 @@ if action == "list" then elseif action == "rename" then - item = fs.realpath(basepath..'/'..params["item"]) - newItemPath = fs.realpath(basepath..'/'..fs.dirname(params["newItemPath"]))..'/'..fs.basename(params["newItemPath"]) + item = luafm.make_path(params["item"]) + newItemPath = luafm.make_new_path(params["newItemPath"]) - if is_in_dir(item,basepath) and is_in_dir(newItemPath,basepath) and item ~= basepath and newItemPath ~= basepath then - result = { result = { success=fs.rename(item,newItemPath), error="" } } + if item and newItemPath and item ~= luafm.basepath and newItemPath ~= luafm.basepath then + result = fs.rename(item,newItemPath) + if result then + result = { result = { success=true, error="" } } + else + result = { result = { success=false, error="Cannot rename requested file/directory" } } + end else result = { result = { success=false, error="Invalid path request" } } end @@ -130,18 +88,18 @@ elseif action == "rename" then elseif action == "move" then items = params["items"] - newPath = fs.realpath(basepath..'/'..params["newPath"]) + newPath = luafm.make_dir_path(params["newPath"]) - if is_in_dir(newPath,basepath) then + if newPath then result = true for key,item in pairs(items) do - item = fs.realpath(basepath..'/'..item) - basename = fs.basename(item) + item = luafm.make_path(item) - if is_in_dir(item,basepath) and item ~= basepath then + if item and item ~= luafm.basepath then + basename = fs.basename(item) result = fs.move(item,newPath.."/"..basename) if not result then break @@ -153,7 +111,11 @@ elseif action == "move" then end - result = { result = { success=result, error="" } } + if result then + result = { result = { success=true, error="" } } + else + result = { result = { success=false, error="Cannot move requested file/directory" } } + end else @@ -164,26 +126,27 @@ elseif action == "move" then elseif action == "copy" then items = params["items"] - newPath = fs.realpath(basepath..'/'..params["newPath"]) - singleFilename = params["singleFilename"] - if singleFilename then - singleFilename = fs.basename(singleFilename) - end + newPath = luafm.make_dir_path(params["newPath"]) + + if newPath then - if is_in_dir(newPath,basepath) then + singleFilename = params["singleFilename"] + if singleFilename then + singleFilename = fs.basename(singleFilename) + end result = true for key,item in pairs(items) do - item = fs.realpath(basepath..'/'..item) - if singleFilename then - basename = singleFilename - else - basename = fs.basename(item) - end + item = luafm.make_path(item) - if is_in_dir(item,basepath) and item ~= basepath then + if item and item ~= luafm.basepath then + if singleFilename then + basename = singleFilename + else + basename = fs.basename(item) + end result = fs.copy(item,newPath.."/"..basename) if not result then break @@ -195,7 +158,11 @@ elseif action == "copy" then end - result = { result = { success=result, error="" } } + if result then + result = { result = { success=true, error="" } } + else + result = { result = { success=false, error="Cannot copy requested file/directory" } } + end else @@ -211,10 +178,10 @@ elseif action == "remove" then for key,item in pairs(items) do - item = fs.realpath(basepath..'/'..item) + item = luafm.make_path(item) - if is_in_dir(item,basepath) and item ~= basepath then - result = rm(item) + if item and item ~= luafm.basepath then + result = luafm.rm(item) if not result then break end @@ -225,13 +192,17 @@ elseif action == "remove" then end - result = { result = { success=result, error="" } } + if result then + result = { result = { success=true, error="" } } + else + result = { result = { success=false, error="Cannot remove requested file/directory" } } + end elseif action == "getContent" then - item = fs.realpath(basepath..'/'..params["item"]) + item = luafm.make_path(params["item"]) - if is_in_dir(item,basepath) and item ~= basepath then + if item and item ~= luafm.basepath then content = fs.readfile(item) result = { result = content } else @@ -240,21 +211,31 @@ elseif action == "getContent" then elseif action == "edit" then - item = fs.realpath(basepath..'/'..params["item"]) + item = luafm.make_path(params["item"]) content = params["content"] - if is_in_dir(item,basepath) and item ~= basepath then - result = { result = { success=fs.writefile(item,content), error="" } } + if item and item ~= luafm.basepath then + result = fs.writefile(item,content) + if result then + result = { result = { success=true, error="" } } + else + result = { result = { success=false, error="Cannot write requested file content" } } + end else result = { result = { success=false, error="Invalid path request" } } end elseif action == "createFolder" then - newPath = fs.realpath(basepath..'/'..fs.dirname(params["newPath"]))..'/'..fs.basename(params["newPath"]) + newPath = luafm.make_new_path(params["newPath"]) - if is_in_dir(newPath,basepath) and newPath ~= basepath then - result = { result = { success=fs.mkdir(newPath), error="" } } + if newPath and newPath ~= luafm.basepath then + result = fs.mkdir(newPath) + if result then + result = { result = { success=true, error="" } } + else + result = { result = { success=false, error="Cannot create folder" } } + end else result = { result = { success=false, error="Invalid path request" } } end @@ -262,6 +243,7 @@ elseif action == "createFolder" then elseif action == "changePermissions" then items = params["items"] + if params["perms"] then mode = params["perms"] else @@ -276,10 +258,10 @@ elseif action == "changePermissions" then for key,item in pairs(items) do - item = fs.realpath(basepath..'/'..item) + item = luafm.make_path(item) - if is_in_dir(item,basepath) and item ~= basepath then - result = chmod(item,mode,recursive) + if item and item ~= luafm.basepath then + result = luafm.chmod(item,mode,recursive) if not result then break end @@ -290,7 +272,11 @@ elseif action == "changePermissions" then end - result = { result = { success=result, error="" } } + if result then + result = { result = { success=true, error="" } } + else + result = { result = { success=false, error="Cannot change permissions" } } + end else @@ -304,16 +290,16 @@ elseif action == "compress" then destination = params["destination"] compressedFilename = params["compressedFilename"] - newPath = fs.realpath(basepath..'/'..destination)..'/'..fs.basename(params["compressedFilename"]) + newPath = luafm.make_new_path(destination..'/'..fs.basename(params["compressedFilename"])) result = true files = "" for key,item in pairs(items) do - realitem = fs.realpath(basepath..'/'..item) + realitem = luafm.make_path(item) - if is_in_dir(realitem,basepath) and realitem ~= basepath then + if realitem and realitem ~= luafm.basepath then item = item:match("/(.*)") files = files.." "..item else @@ -325,28 +311,40 @@ elseif action == "compress" then if files then - command = "cd "..basepath.."; zip -r "..newPath..files - os.execute(command) + command = "cd "..luafm.basepath.."; zip -r "..newPath..files + result = os.execute(command) + + if result then + result = { result = { success=true, error="" } } + else + result = { result = { success=false, error="Archiver returned error" } } + end + + else + + result = { result = { success=false, error="No files selected" } } end - result = { result = { success=result, error="" } } - elseif action == "extract" then - item = fs.realpath(basepath..'/'..params["item"]) + item = luafm.make_path(params["item"]) destination = params["destination"] folderName = params["folderName"] - newPath = fs.realpath(basepath..'/'..destination)..'/'..fs.basename(params["folderName"]) + newPath = luafm.make_new_path(destination..'/'..fs.basename(params["folderName"])) result = true files = "" - if is_in_dir(item,basepath) and is_in_dir(newPath,basepath) and item ~= basepath then + if item and newPath and item ~= luafm.basepath then command = "unzip "..item.." -d "..newPath - os.execute(command) - result = { result = { success=true, error="" } } + result = os.execute(command) + if result then + result = { result = { success=true, error="" } } + else + result = { result = { success=false, error="Archiver returned error" } } + end else result = { result = { success=false, error="Invalid path request" } } end diff --git a/www/cgi-bin/fs-download b/www/cgi-bin/fs-download index 5ae634a..d33ec96 100755 --- a/www/cgi-bin/fs-download +++ b/www/cgi-bin/fs-download @@ -2,17 +2,9 @@ nixio = require "nixio" fs = require "nixio.fs" -uci = require("uci") util = require "luci.util" ltn12 = require "ltn12" - -local function is_in_dir(file, dir) - if file == dir then - return true - else - return file:sub(1, #dir) == dir - end -end +luafm = require "luafm" args = {} @@ -21,17 +13,14 @@ for dummy,param in pairs(util.split(nixio.getenv('QUERY_STRING'),'&')) do args[val[1]] = util.urldecode(val[2],true) end -local u_c = uci.cursor() -local basepath = u_c.get("filemanager","config","basedir") - -path = fs.realpath(basepath..'/'..args["path"]) +path = luafm.make_path(args["path"]) if path then file = io.open(path,"rb") else file = nil end -if file and is_in_dir(path,basepath) then +if file then print("Content-Type: application/octet-stream") print('Content-Disposition: attachment; filename="'..fs.basename(args["path"])..'"') print("\r") diff --git a/www/cgi-bin/fs-upload b/www/cgi-bin/fs-upload index 46d047e..101c841 100755 --- a/www/cgi-bin/fs-upload +++ b/www/cgi-bin/fs-upload @@ -1,21 +1,11 @@ #!/usr/bin/lua local cgi = require "cgi" -local uci = require("uci") -local fs = require("nixio.fs") -local os = require("os") -local json = require("json") +local fs = require "nixio.fs" +local luafm = require "luafm" local req = {} -local function is_in_dir(file, dir) - if file == dir then - return true - else - return file:sub(1, #dir) == dir - end -end - print("\r") cgi.new(req) @@ -27,15 +17,11 @@ end destfile=io.open(req.post["destination"][1]["tempname"],"r") destination=destfile:read("*all") -local u_c = uci.cursor() -local basepath = u_c.get("filemanager","config","basedir") - for k, v in pairs(req.post) do for j, v in pairs(req.post[k]) do if v["filename"] then - path = basepath..destination..'/'..v.filename - dir = fs.realpath(fs.dirname(path)) - if dir and is_in_dir(dir,basepath) then + path = luafm.make_new_path(destination..'/'..v.filename) + if path then fs.copy(req.post[k][j].tempname, path) end end -- 2.34.1