mirror of
				https://github.com/kenzok8/openwrt-packages.git
				synced 2025-10-30 07:50:37 +08:00 
			
		
		
		
	update 2024-10-14 08:36:44
This commit is contained in:
		| @ -1,6 +1,8 @@ | ||||
| # Copyright (C) 2018-2020 Lienol <lawlienol@gmail.com> | ||||
| # | ||||
| # This is free software, licensed under the Apache License, Version 2.0 . | ||||
| # Copyright (C) 2021 ImmortalWrt | ||||
| # <https://immortalwrt.org> | ||||
| # | ||||
| # This is free software, licensed under the GNU General Public License v3. | ||||
| # | ||||
|  | ||||
| include $(TOPDIR)/rules.mk | ||||
| @ -9,6 +11,11 @@ LUCI_TITLE:=LuCI Support for FileBrowser | ||||
| LUCI_DEPENDS:=+filebrowser | ||||
| LUCI_PKGARCH:=all | ||||
|  | ||||
| PKG_NAME:=luci-app-filebrowser | ||||
| PKG_VERSION:=snapshot | ||||
| PKG_RELEASE:=118071b | ||||
|  | ||||
| PKG_LICENSE:=GPLv3 | ||||
|  | ||||
| include $(TOPDIR)/feeds/luci/luci.mk | ||||
|  | ||||
|  | ||||
| @ -1,59 +1,19 @@ | ||||
| -- Copyright 2018-2020 Lienol <lawlienol@gmail.com> | ||||
| -- Improve by xiaozhuai <xiaozhuai7@gmail.com> | ||||
| module("luci.controller.filebrowser", package.seeall) | ||||
|  | ||||
| local http = require "luci.http" | ||||
| local api = require "luci.model.cbi.filebrowser.api" | ||||
|  | ||||
| function index() | ||||
|     if not nixio.fs.access("/etc/config/filebrowser") then return end | ||||
|  | ||||
|     entry({"admin", "services"}, firstchild(), "Services", 44).dependent = false | ||||
|     entry({"admin", "services", "filebrowser"}, cbi("filebrowser/settings"), | ||||
|           _("File Browser"), 2).dependent = true | ||||
|  | ||||
|     entry({"admin", "services", "filebrowser", "check"}, call("action_check")).leaf = | ||||
|         true | ||||
|     entry({"admin", "services", "filebrowser", "download"}, call("action_download")).leaf = | ||||
|         true | ||||
|     entry({"admin", "services", "filebrowser", "status"}, call("act_status")).leaf = | ||||
|         true | ||||
|     entry({"admin", "services", "filebrowser", "get_log"}, call("get_log")).leaf = | ||||
|         true | ||||
|     entry({"admin", "services", "filebrowser", "clear_log"}, call("clear_log")).leaf = | ||||
|         true | ||||
| end | ||||
|  | ||||
| local function http_write_json(content) | ||||
|     http.prepare_content("application/json") | ||||
|     http.write_json(content or {code = 1}) | ||||
| 	if not nixio.fs.access("/etc/config/filebrowser") then | ||||
| 		return | ||||
| 	end | ||||
| 	entry({"admin", "nas"}, firstchild(), _("NAS") , 45).dependent = false | ||||
| 	local page | ||||
| 	page = entry({"admin", "nas", "filebrowser"}, cbi("filebrowser"), _("文件管理器"), 100) | ||||
| 	page.dependent = true | ||||
| 	entry({"admin","nas","filebrowser","status"},call("act_status")).leaf=true | ||||
| end | ||||
|  | ||||
| function act_status() | ||||
|     local e = {} | ||||
|     e.status = luci.sys.call("ps -w | grep -v grep | grep 'filebrowser -a' >/dev/null") == 0 | ||||
|     http_write_json(e) | ||||
| 	local e={} | ||||
| 	e.running=luci.sys.call("pgrep filebrowser >/dev/null")==0 | ||||
| 	luci.http.prepare_content("application/json") | ||||
| 	luci.http.write_json(e) | ||||
| end | ||||
|  | ||||
| function action_check() | ||||
|     local json = api.to_check() | ||||
|     http_write_json(json) | ||||
| end | ||||
|  | ||||
| function action_download() | ||||
|     local json = nil | ||||
|     local task = http.formvalue("task") | ||||
|     if task == "extract" then | ||||
|         json = api.to_extract(http.formvalue("file")) | ||||
|     elseif task == "move" then | ||||
|         json = api.to_move(http.formvalue("file")) | ||||
|     else | ||||
|         json = api.to_download(http.formvalue("url")) | ||||
|     end | ||||
|     http_write_json(json) | ||||
| end | ||||
|  | ||||
| function get_log() | ||||
|     luci.http.write(luci.sys.exec("[ -f '/var/log/filebrowser.log' ] && cat /var/log/filebrowser.log")) | ||||
| end | ||||
| function clear_log() luci.sys.call("echo '' > /var/log/filebrowser.log") end | ||||
|  | ||||
							
								
								
									
										42
									
								
								luci-app-filebrowser/luasrc/model/cbi/filebrowser.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								luci-app-filebrowser/luasrc/model/cbi/filebrowser.lua
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,42 @@ | ||||
| m = Map("filebrowser", translate("文件管理器"), translate("FileBrowser是一个基于Go的在线文件管理器,助您方便的管理设备上的文件。")) | ||||
|  | ||||
| m:section(SimpleSection).template  = "filebrowser/filebrowser_status" | ||||
|  | ||||
| s = m:section(TypedSection, "filebrowser") | ||||
| s.addremove = false | ||||
| s.anonymous = true | ||||
|  | ||||
| enable = s:option(Flag, "enabled", translate("启用")) | ||||
| enable.rmempty = false | ||||
|  | ||||
| o = s:option(ListValue, "addr_type", translate("监听地址")) | ||||
| o:value("local", translate("监听本机地址")) | ||||
| o:value("lan", translate("监听局域网地址")) | ||||
| o:value("wan", translate("监听全部地址")) | ||||
| o.default = "lan" | ||||
| o.rmempty = false | ||||
|  | ||||
| o = s:option(Value, "port", translate("监听端口")) | ||||
| o.placeholder = 8989 | ||||
| o.default     = 8989 | ||||
| o.datatype    = "port" | ||||
| o.rmempty     = false | ||||
|  | ||||
| o = s:option(Value, "root_dir", translate("开放目录")) | ||||
| o.placeholder = "/" | ||||
| o.default     = "/" | ||||
| o.rmempty     = false | ||||
|  | ||||
| o = s:option(Value, "db_dir", translate("数据库目录")) | ||||
| o.placeholder = "/etc" | ||||
| o.default     = "/etc" | ||||
| o.rmempty     = false | ||||
| o.description = translate("普通用户请勿随意更改") | ||||
|  | ||||
| o = s:option(Value, "db_name", translate("数据库名")) | ||||
| o.placeholder = "filebrowser.db" | ||||
| o.default     = "filebrowser.db" | ||||
| o.rmempty     = false | ||||
| o.description = translate("普通用户请勿随意更改") | ||||
|  | ||||
| return m | ||||
| @ -1,338 +0,0 @@ | ||||
| local fs = require "nixio.fs" | ||||
| local sys = require "luci.sys" | ||||
| local uci = require"luci.model.uci".cursor() | ||||
| local util = require "luci.util" | ||||
| local i18n = require "luci.i18n" | ||||
|  | ||||
| module("luci.model.cbi.filebrowser.api", package.seeall) | ||||
|  | ||||
| local appname = "filebrowser" | ||||
| local api_url = | ||||
|     "https://api.github.com/repos/filebrowser/filebrowser/releases/latest" | ||||
|  | ||||
| local wget = "/usr/bin/wget" | ||||
| local wget_args = { | ||||
|     "--no-check-certificate", "--quiet", "--timeout=10", "--tries=2" | ||||
| } | ||||
| local command_timeout = 300 | ||||
|  | ||||
| local LEDE_BOARD = nil | ||||
| local DISTRIB_TARGET = nil | ||||
|  | ||||
| function uci_get_type(type, config, default) | ||||
|     value = uci:get_first(appname, type, config, default) or sys.exec( | ||||
|                 "echo -n `uci -q get " .. appname .. ".@" .. type .. "[0]." .. | ||||
|                     config .. "`") | ||||
|     if (value == nil or value == "") and (default and default ~= "") then | ||||
|         value = default | ||||
|     end | ||||
|     return value | ||||
| end | ||||
|  | ||||
| local function _unpack(t, i) | ||||
|     i = i or 1 | ||||
|     if t[i] ~= nil then return t[i], _unpack(t, i + 1) end | ||||
| end | ||||
|  | ||||
| local function exec(cmd, args, writer, timeout) | ||||
|     local os = require "os" | ||||
|     local nixio = require "nixio" | ||||
|  | ||||
|     local fdi, fdo = nixio.pipe() | ||||
|     local pid = nixio.fork() | ||||
|  | ||||
|     if pid > 0 then | ||||
|         fdo:close() | ||||
|  | ||||
|         if writer or timeout then | ||||
|             local starttime = os.time() | ||||
|             while true do | ||||
|                 if timeout and os.difftime(os.time(), starttime) >= timeout then | ||||
|                     nixio.kill(pid, nixio.const.SIGTERM) | ||||
|                     return 1 | ||||
|                 end | ||||
|  | ||||
|                 if writer then | ||||
|                     local buffer = fdi:read(2048) | ||||
|                     if buffer and #buffer > 0 then | ||||
|                         writer(buffer) | ||||
|                     end | ||||
|                 end | ||||
|  | ||||
|                 local wpid, stat, code = nixio.waitpid(pid, "nohang") | ||||
|  | ||||
|                 if wpid and stat == "exited" then return code end | ||||
|  | ||||
|                 if not writer and timeout then nixio.nanosleep(1) end | ||||
|             end | ||||
|         else | ||||
|             local wpid, stat, code = nixio.waitpid(pid) | ||||
|             return wpid and stat == "exited" and code | ||||
|         end | ||||
|     elseif pid == 0 then | ||||
|         nixio.dup(fdo, nixio.stdout) | ||||
|         fdi:close() | ||||
|         fdo:close() | ||||
|         nixio.exece(cmd, args, nil) | ||||
|         nixio.stdout:close() | ||||
|         os.exit(1) | ||||
|     end | ||||
| end | ||||
|  | ||||
| local function compare_versions(ver1, comp, ver2) | ||||
|     local table = table | ||||
|  | ||||
|     local av1 = util.split(ver1, "[%.%-]", nil, true) | ||||
|     local av2 = util.split(ver2, "[%.%-]", nil, true) | ||||
|  | ||||
|     local max = table.getn(av1) | ||||
|     local n2 = table.getn(av2) | ||||
|     if (max < n2) then max = n2 end | ||||
|  | ||||
|     for i = 1, max, 1 do | ||||
|         local s1 = av1[i] or "" | ||||
|         local s2 = av2[i] or "" | ||||
|  | ||||
|         if comp == "~=" and (s1 ~= s2) then return true end | ||||
|         if (comp == "<" or comp == "<=") and (s1 < s2) then return true end | ||||
|         if (comp == ">" or comp == ">=") and (s1 > s2) then return true end | ||||
|         if (s1 ~= s2) then return false end | ||||
|     end | ||||
|  | ||||
|     return not (comp == "<" or comp == ">") | ||||
| end | ||||
|  | ||||
| local function auto_get_arch() | ||||
|     local arch = nixio.uname().machine or "" | ||||
|     if fs.access("/usr/lib/os-release") then | ||||
|         LEDE_BOARD = sys.exec( | ||||
|                          "echo -n `grep 'LEDE_BOARD' /usr/lib/os-release | awk -F '[\\042\\047]' '{print $2}'`") | ||||
|     end | ||||
|     if fs.access("/etc/openwrt_release") then | ||||
|         DISTRIB_TARGET = sys.exec( | ||||
|                              "echo -n `grep 'DISTRIB_TARGET' /etc/openwrt_release | awk -F '[\\042\\047]' '{print $2}'`") | ||||
|     end | ||||
|  | ||||
|     if arch == "mips" then | ||||
|         if LEDE_BOARD and LEDE_BOARD ~= "" then | ||||
|             if string.match(LEDE_BOARD, "ramips") == "ramips" then | ||||
|                 arch = "ramips" | ||||
|             else | ||||
|                 arch = sys.exec("echo '" .. LEDE_BOARD .. | ||||
|                                     "' | grep -oE 'ramips|ar71xx'") | ||||
|             end | ||||
|         elseif DISTRIB_TARGET and DISTRIB_TARGET ~= "" then | ||||
|             if string.match(DISTRIB_TARGET, "ramips") == "ramips" then | ||||
|                 arch = "ramips" | ||||
|             else | ||||
|                 arch = sys.exec("echo '" .. DISTRIB_TARGET .. | ||||
|                                     "' | grep -oE 'ramips|ar71xx'") | ||||
|             end | ||||
|         end | ||||
|     end | ||||
|  | ||||
|     return util.trim(arch) | ||||
| end | ||||
|  | ||||
| local function get_file_info(arch) | ||||
|     local file_tree = "" | ||||
|     local sub_version = "" | ||||
|  | ||||
|     if arch == "x86_64" then | ||||
|         file_tree = "amd64" | ||||
|     elseif arch == "aarch64" then | ||||
|         file_tree = "arm64" | ||||
|     elseif arch == "ramips" then | ||||
|         file_tree = "mipsle" | ||||
|     elseif arch == "ar71xx" then | ||||
|         file_tree = "mips" | ||||
|     elseif arch:match("^i[%d]86$") then | ||||
|         file_tree = "386" | ||||
|     elseif arch:match("^armv[5-8]") then | ||||
|         file_tree = "armv" | ||||
|         sub_version = arch:match("[5-8]") | ||||
|         if LEDE_BOARD and string.match(LEDE_BOARD, "bcm53xx") == "bcm53xx" then | ||||
|             sub_version = "5" | ||||
|         elseif DISTRIB_TARGET and string.match(DISTRIB_TARGET, "bcm53xx") == | ||||
|             "bcm53xx" then | ||||
|             sub_version = "5" | ||||
|         end | ||||
|         sub_version = "5" | ||||
|     end | ||||
|  | ||||
|     return file_tree, sub_version | ||||
| end | ||||
|  | ||||
| local function get_api_json(url) | ||||
|     local jsonc = require "luci.jsonc" | ||||
|  | ||||
|     local output = {} | ||||
|     -- exec(wget, { "-O-", url, _unpack(wget_args) }, | ||||
|     --	function(chunk) output[#output + 1] = chunk end) | ||||
|     -- local json_content = util.trim(table.concat(output)) | ||||
|  | ||||
|     local json_content = luci.sys.exec(wget .. | ||||
|                                            " --no-check-certificate --timeout=10 -t 1 -O- " .. | ||||
|                                            url) | ||||
|  | ||||
|     if json_content == "" then return {} end | ||||
|  | ||||
|     return jsonc.parse(json_content) or {} | ||||
| end | ||||
|  | ||||
| function get_version() return uci_get_type("global", "version", "0") end | ||||
|  | ||||
| function to_check(arch) | ||||
|     if not arch or arch == "" then arch = auto_get_arch() end | ||||
|  | ||||
|     local file_tree, sub_version = get_file_info(arch) | ||||
|  | ||||
|     if file_tree == "" then | ||||
|         return { | ||||
|             code = 1, | ||||
|             error = i18n.translate( | ||||
|                 "Can't determine ARCH, or ARCH not supported.") | ||||
|         } | ||||
|     end | ||||
|  | ||||
|     local json = get_api_json(api_url) | ||||
|  | ||||
|     if json.tag_name == nil then | ||||
|         return { | ||||
|             code = 1, | ||||
|             error = i18n.translate("Get remote version info failed.") | ||||
|         } | ||||
|     end | ||||
|  | ||||
|     local remote_version = json.tag_name:match("[^v]+") | ||||
|  | ||||
|     local needs_update = compare_versions(get_version(), "<", remote_version) | ||||
|     local html_url, download_url | ||||
|  | ||||
|     if needs_update then | ||||
|         html_url = json.html_url | ||||
|         for _, v in ipairs(json.assets) do | ||||
|             if v.name and v.name:match("linux%-" .. file_tree .. sub_version) then | ||||
|                 download_url = v.browser_download_url | ||||
|                 break | ||||
|             end | ||||
|         end | ||||
|     end | ||||
|  | ||||
|     if needs_update and not download_url then | ||||
|         return { | ||||
|             code = 1, | ||||
|             version = remote_version, | ||||
|             html_url = html_url, | ||||
|             error = i18n.translate( | ||||
|                 "New version found, but failed to get new version download url.") | ||||
|         } | ||||
|     end | ||||
|  | ||||
|     return { | ||||
|         code = 0, | ||||
|         update = needs_update, | ||||
|         version = remote_version, | ||||
|         url = {html = html_url, download = download_url} | ||||
|     } | ||||
| end | ||||
|  | ||||
| function to_download(url) | ||||
|     if not url or url == "" then | ||||
|         return {code = 1, error = i18n.translate("Download url is required.")} | ||||
|     end | ||||
|  | ||||
|     sys.call("/bin/rm -f /tmp/filebrowser_download.*") | ||||
|  | ||||
|     local tmp_file = util.trim(util.exec( | ||||
|                                    "mktemp -u -t filebrowser_download.XXXXXX")) | ||||
|  | ||||
|     local result = exec(wget, {"-O", tmp_file, url, _unpack(wget_args)}, nil, | ||||
|                         command_timeout) == 0 | ||||
|  | ||||
|     if not result then | ||||
|         exec("/bin/rm", {"-f", tmp_file}) | ||||
|         return { | ||||
|             code = 1, | ||||
|             error = i18n.translatef("File download failed or timed out: %s", url) | ||||
|         } | ||||
|     end | ||||
|  | ||||
|     return {code = 0, file = tmp_file} | ||||
| end | ||||
|  | ||||
| function to_extract(file, subfix) | ||||
|     if not file or file == "" or not fs.access(file) then | ||||
|         return {code = 1, error = i18n.translate("File path required.")} | ||||
|     end | ||||
|  | ||||
|     sys.call("/bin/rm -rf /tmp/filebrowser_extract.*") | ||||
|     local tmp_dir = util.trim(util.exec( | ||||
|                                   "mktemp -d -t filebrowser_extract.XXXXXX")) | ||||
|  | ||||
|     local output = {} | ||||
|     exec("/bin/tar", {"-C", tmp_dir, "-zxvf", file}, | ||||
|          function(chunk) output[#output + 1] = chunk end) | ||||
|  | ||||
|     local files = util.split(table.concat(output)) | ||||
|  | ||||
|     exec("/bin/rm", {"-f", file}) | ||||
|  | ||||
|     if not new_file then | ||||
|         for _, f in pairs(files) do | ||||
|             if f:match("filebrowser") then | ||||
|                 new_file = tmp_dir .. "/" .. util.trim(f) | ||||
|                 break | ||||
|             end | ||||
|         end | ||||
|     end | ||||
|  | ||||
|     if not new_file then | ||||
|         exec("/bin/rm", {"-rf", tmp_dir}) | ||||
|         return { | ||||
|             code = 1, | ||||
|             error = i18n.translatef("Can't find client in file: %s", file) | ||||
|         } | ||||
|     end | ||||
|  | ||||
|     return {code = 0, file = new_file} | ||||
| end | ||||
|  | ||||
| function to_move(file) | ||||
|     if not file or file == "" or not fs.access(file) then | ||||
|         sys.call("/bin/rm -rf /tmp/filebrowser_extract.*") | ||||
|         return {code = 1, error = i18n.translate("Client file is required.")} | ||||
|     end | ||||
|     local executable_directory = | ||||
|         uci_get_type("global", "executable_directory", "/tmp") | ||||
|     luci.sys.exec("mkdir -p " .. executable_directory) | ||||
|     local client_path = executable_directory .. "/" .. appname | ||||
|     local client_path_bak | ||||
|  | ||||
|     if fs.access(client_path) then | ||||
|         client_path_bak = "/tmp/" .. appname .. ".bak" | ||||
|         exec("/bin/mv", {"-f", client_path, client_path_bak}) | ||||
|     end | ||||
|  | ||||
|     local result = exec("/bin/mv", {"-f", file, client_path}, nil, | ||||
|                         command_timeout) == 0 | ||||
|  | ||||
|     if not result or not fs.access(client_path) then | ||||
|         if client_path_bak then | ||||
|             exec("/bin/mv", {"-f", client_path_bak, client_path}) | ||||
|         end | ||||
|         return { | ||||
|             code = 1, | ||||
|             error = i18n.translatef("Can't move new file to path: %s", | ||||
|                                     client_path) | ||||
|         } | ||||
|     end | ||||
|  | ||||
|     exec("/bin/chmod", {"755", client_path}) | ||||
|  | ||||
|     if client_path_bak then exec("/bin/rm", {"-f", client_path_bak}) end | ||||
|  | ||||
|     sys.call("/bin/rm -rf /tmp/filebrowser_extract.*") | ||||
|  | ||||
|     return {code = 0} | ||||
| end | ||||
| @ -1,59 +0,0 @@ | ||||
| m = Map("filebrowser", translate("FileBrowser"), translate( | ||||
|             "File explorer is software that creates your own cloud that you can install on a server, point it to a path, and then access your files through a beautiful web interface. You have many features available!")) | ||||
| m:append(Template("filebrowser/status")) | ||||
|  | ||||
| s = m:section(TypedSection, "global", translate("Global Settings")) | ||||
| s.anonymous = true | ||||
| s.addremove = false | ||||
|  | ||||
| o = s:option(Flag, "enable", translate("Enable")) | ||||
| o.rmempty = false | ||||
|  | ||||
| o = s:option(Value, "address", translate("Listen address")) | ||||
| o.default = "0.0.0.0" | ||||
| o.rmempty = false | ||||
|  | ||||
| o = s:option(Value, "port", translate("Listen port")) | ||||
| o.datatype = "port" | ||||
| o.default = 8088 | ||||
| o.rmempty = false | ||||
|  | ||||
| o = s:option(Value, "database", translate("Database path")) | ||||
| o.default = "/etc/filebrowser.db" | ||||
| o.rmempty = false | ||||
|  | ||||
| o = s:option(Value, "username", translate("Initial username")) | ||||
| o.default = "admin" | ||||
| o.rmempty = false | ||||
|  | ||||
| o = s:option(Value, "password", translate("Initial password")) | ||||
| o.default = "admin" | ||||
| o.rmempty = false | ||||
|  | ||||
| o = s:option(Value, "ssl_cert", translate("SSL cert")) | ||||
| o.default = "" | ||||
|  | ||||
| o = s:option(Value, "ssl_key", translate("SSL key")) | ||||
| o.default = "" | ||||
|  | ||||
| o = s:option(Value, "root_path", translate("Root path"), translate( | ||||
|                  "Point to a path to access your files in the web interface, default is /root")) | ||||
| o.default = "/root" | ||||
| o.rmempty = false | ||||
|  | ||||
| o = s:option(Value, "executable_directory", translate("Executable directory"), | ||||
|              translate( | ||||
|                  "The file size is large, requiring at least 32M space. It is recommended to insert a usb flash drive or hard disk, or use it in the tmp directory<br />For example, /mnt/sda1<br />For example, /tmp")) | ||||
| o.default = "/tmp" | ||||
| o.rmempty = false | ||||
|  | ||||
| o = s:option(Button, "_download", translate("Manually download"), translate( | ||||
|                  "Make sure you have enough space. <br /><font style='color:red'>Be sure to fill out the executable storage directory the first time you run it, and then save the application. Then manually download, otherwise can not use!</font>")) | ||||
| o.template = "filebrowser/download" | ||||
| o.inputstyle = "apply" | ||||
| o.btnclick = "downloadClick(this);" | ||||
| o.id = "download_btn" | ||||
|  | ||||
| m:append(Template("filebrowser/log")) | ||||
|  | ||||
| return m | ||||
| @ -1,169 +0,0 @@ | ||||
| <% | ||||
| local dsp = require "luci.dispatcher" | ||||
| -%> | ||||
|  | ||||
| <script type="text/javascript">//<![CDATA[ | ||||
|   var msgInfo; | ||||
|  | ||||
|   var tokenStr = '<%=token%>'; | ||||
|   var clickToDownloadText = '<%:Click to download%>'; | ||||
|   var inProgressText = '<%:Downloading...%>'; | ||||
|   var downloadInProgressNotice = '<%:Download, are you sure to close?%>'; | ||||
|   var downloadSuccessText = '<%:Download successful%>'; | ||||
|   var unexpectedErrorText = '<%:Unexpected error%>'; | ||||
|  | ||||
|   function addPageNotice() { | ||||
|     window.onbeforeunload = function(e) { | ||||
|       e.returnValue = downloadInProgressNotice; | ||||
|       return downloadInProgressNotice; | ||||
|     }; | ||||
|   } | ||||
|  | ||||
|   function removePageNotice() { | ||||
|     window.onbeforeunload = undefined; | ||||
|   } | ||||
|  | ||||
|   function onUpdateSuccess(btn) { | ||||
|     alert(downloadSuccessText); | ||||
|  | ||||
|     if (btn) { | ||||
|       btn.value = downloadSuccessText; | ||||
|       btn.placeholder = downloadSuccessText; | ||||
|       btn.disabled = true; | ||||
|     } | ||||
|  | ||||
|     window.setTimeout(function () { | ||||
|       window.location.reload(); | ||||
|     }, 1000); | ||||
|   } | ||||
|  | ||||
|   function onRequestError(btn, errorMessage) { | ||||
|     btn.disabled = false; | ||||
|     btn.value = btn.placeholder; | ||||
|  | ||||
|     if (errorMessage) { | ||||
|       alert(errorMessage); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   function doAjaxGet(url, data, onResult) { | ||||
|     new XHR().get(url, data, function(_, json) { | ||||
|       var resultJson = json || { | ||||
|         'code': 1, | ||||
|         'error': unexpectedErrorText | ||||
|       }; | ||||
|  | ||||
|       if (typeof onResult === 'function') { | ||||
|         onResult(resultJson); | ||||
|       } | ||||
|     }) | ||||
|   } | ||||
|  | ||||
|   function downloadClick(btn) { | ||||
|       if (msgInfo === undefined) { | ||||
|         checkUpdate(btn); | ||||
|       } else { | ||||
|         doDownload(btn); | ||||
|       } | ||||
|   } | ||||
|  | ||||
|   function checkUpdate(btn) { | ||||
|     btn.disabled = true; | ||||
|     btn.value = inProgressText; | ||||
|  | ||||
|     addPageNotice(); | ||||
|  | ||||
|     var ckeckDetailElm = document.getElementById(btn.id + '-detail'); | ||||
|  | ||||
|     doAjaxGet('<%=dsp.build_url("admin/services/filebrowser/check")%>/', { | ||||
|       token: tokenStr | ||||
|     }, function (json) { | ||||
|       removePageNotice(); | ||||
|       if (json.code) { | ||||
|         eval('Info = undefined'); | ||||
|         onRequestError(btn, json.error); | ||||
|       } else { | ||||
|           eval('Info = json'); | ||||
|           btn.disabled = false; | ||||
|           btn.value = clickToDownloadText; | ||||
|           btn.placeholder = clickToDownloadText; | ||||
|       } | ||||
|  | ||||
|       if (ckeckDetailElm) { | ||||
|         var urlNode = ''; | ||||
|         if (json.version) { | ||||
|           urlNode = '<em style="color:red;"><%:The latest version:%>' + json.version + '</em>'; | ||||
|           if (json.url && json.url.html) { | ||||
|             urlNode = '<a href="' + json.url.html + '" target="_blank">' + urlNode + '</a>'; | ||||
|           } | ||||
|         } | ||||
|         ckeckDetailElm.innerHTML = urlNode; | ||||
|       } | ||||
| 	  msgInfo = json; | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   function doDownload(btn) { | ||||
|     btn.disabled = true; | ||||
|     btn.value = '<%:Downloading...%>'; | ||||
|  | ||||
|     addPageNotice(); | ||||
|  | ||||
|     var UpdateUrl = '<%=dsp.build_url("admin/services/filebrowser/download")%>'; | ||||
|     // Download file | ||||
|     doAjaxGet(UpdateUrl, { | ||||
|       token: tokenStr, | ||||
|       url: msgInfo ? msgInfo.url.download : '' | ||||
|     }, function (json) { | ||||
|       if (json.code) { | ||||
|         removePageNotice(); | ||||
|         onRequestError(btn, json.error); | ||||
|       } else { | ||||
|         btn.value = '<%:Unpacking...%>'; | ||||
|  | ||||
|         // Extract file | ||||
|         doAjaxGet(UpdateUrl, { | ||||
|           token: tokenStr, | ||||
|           task: 'extract', | ||||
|           file: json.file | ||||
|         }, function (json) { | ||||
|           if (json.code) { | ||||
|             removePageNotice(); | ||||
|             onRequestError(btn, json.error); | ||||
|           } else { | ||||
|             btn.value = '<%:Moving...%>'; | ||||
|  | ||||
|             // Move file to target dir | ||||
|             doAjaxGet(UpdateUrl, { | ||||
|               token: tokenStr, | ||||
|               task: 'move', | ||||
|               file: json.file | ||||
|             }, function (json) { | ||||
|               removePageNotice(); | ||||
|               if (json.code) { | ||||
|                 onRequestError(btn, json.error); | ||||
|               } else { | ||||
|                 onUpdateSuccess(btn); | ||||
|               } | ||||
|             }) | ||||
|           } | ||||
|         }) | ||||
|       } | ||||
|     }) | ||||
|   } | ||||
| //]]></script> | ||||
|  | ||||
| <%+cbi/valueheader%> | ||||
| 	<% if self:cfgvalue(section) ~= false then %> | ||||
| 		<input class="cbi-button cbi-input-<%=self.inputstyle or "button" %>" type="button"<%= | ||||
| 			attr("name", cbid) .. | ||||
| 			attr("id", self.id or cbid) .. | ||||
| 			attr("value", self.inputtitle or self.title) .. | ||||
| 			ifattr(self.btnclick, "onclick", self.btnclick) .. | ||||
| 			ifattr(self.placeholder, "placeholder") | ||||
| 		%> /> | ||||
| 		<span id="<%=self.id or cbid%>-detail"></span> | ||||
| 	<% else %> | ||||
| 		- | ||||
| 	<% end %> | ||||
| <%+cbi/valuefooter%> | ||||
| @ -0,0 +1,32 @@ | ||||
| <script type="text/javascript">//<![CDATA[ | ||||
| XHR.poll(1, '<%=url([[admin]], [[nas]], [[filebrowser]], [[status]])%>', null, | ||||
| 	function(x, data) { | ||||
| 		var tb = document.getElementById('filebrowser_status'); | ||||
| 		if (data && tb) { | ||||
| 			if (data.running) { | ||||
| 				var links = '<font color=green>Filebrowser <%:运行中%></font><input class="cbi-button mar-10" type="button" value="<%:打开管理界面%>" onclick="openClient();" />'; | ||||
| 				tb.innerHTML = links; | ||||
| 			} else { | ||||
| 				tb.innerHTML = '<font color=red>Filebrowser <%:未运行%></font>'; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| ); | ||||
|  | ||||
| function openClient() { | ||||
| 	var curWwwPath = window.document.location.href; | ||||
| 	var pathName = window.document.location.pathname; | ||||
| 	var pos = curWwwPath.indexOf(pathName); | ||||
| 	var localhostPath = curWwwPath.substring(0, pos); | ||||
| 	var clientPort = window.document.getElementById("cbid.filebrowser.config.port").value | ||||
| 	var url = localhostPath + ":" + clientPort; | ||||
| 	window.open(url) | ||||
| }; | ||||
| //]]> | ||||
| </script> | ||||
| <style>.mar-10 {margin-left: 50px; margin-right: 10px;}</style> | ||||
| <fieldset class="cbi-section"> | ||||
| 	<p id="filebrowser_status"> | ||||
| 		<em><%:Collecting data...%></em> | ||||
| 	</p> | ||||
| </fieldset> | ||||
| @ -1,31 +0,0 @@ | ||||
| <script type="text/javascript"> | ||||
| 	//<![CDATA[ | ||||
| 	function clear_log(btn) { | ||||
| 		XHR.get('<%=url([[admin]], [[services]], [[filebrowser]], [[clear_log]])%>', null, | ||||
| 			function(x, data) { | ||||
| 				if(x && x.status == 200) { | ||||
| 					var log_textarea = document.getElementById('log_textarea'); | ||||
| 					log_textarea.innerHTML = ""; | ||||
| 					log_textarea.scrollTop = log_textarea.scrollHeight; | ||||
| 				} | ||||
| 			} | ||||
| 		); | ||||
| 	} | ||||
| 	XHR.poll(3, '<%=url([[admin]], [[services]], [[filebrowser]], [[get_log]])%>', null, | ||||
| 		function(x, data) { | ||||
| 			if(x && x.status == 200) { | ||||
| 				var log_textarea = document.getElementById('log_textarea'); | ||||
| 				log_textarea.innerHTML = x.responseText; | ||||
| 				log_textarea.scrollTop = log_textarea.scrollHeight; | ||||
| 			} | ||||
| 		} | ||||
| 	); | ||||
| 	//]]> | ||||
| </script> | ||||
| <fieldset class="cbi-section" id="_log_fieldset"> | ||||
| 	<legend> | ||||
| 		<%:Logs%> | ||||
| 	</legend> | ||||
| 	<input class="cbi-button cbi-input-remove" type="button" onclick="clear_log()" value="<%:Clear logs%>" style="margin-left: 10px;"> | ||||
| 	<textarea id="log_textarea" class="cbi-input-textarea" style="width: calc(100% - 20px); margin: 10px;" data-update="change" rows="5" wrap="off" readonly="readonly"></textarea> | ||||
| </fieldset> | ||||
| @ -1,38 +0,0 @@ | ||||
| <% | ||||
| local dsp = require "luci.dispatcher" | ||||
| -%> | ||||
|  | ||||
| <fieldset class="cbi-section"> | ||||
| 	<legend><%:Running Status%></legend> | ||||
| 	<fieldset class="cbi-section"> | ||||
| 		<div class="cbi-value"> | ||||
| 			<label class="cbi-value-title"><%:Status%></label> | ||||
| 			<div class="cbi-value-field" id="_status"><p><span><%:Collecting data...%></span></p></div> | ||||
| 		</div> | ||||
| 	</fieldset> | ||||
| </fieldset> | ||||
|  | ||||
| <script type="text/javascript">//<![CDATA[ | ||||
| 	var _status = document.getElementById('_status'); | ||||
| 	XHR.poll(3,'<%=dsp.build_url("admin/services/filebrowser/status")%>', null, | ||||
| 		function(x, json) { | ||||
| 			if (x && x.status == 200) { | ||||
| 				if (_status) | ||||
| 					_status.innerHTML = json.status ? '<p><span style="color:green;"><%:RUNNING%></span> <input type="button" class="cbi-button cbi-input-apply" value="<%:Enter interface%>" onclick="openwebui()" /></p>' : '<p><span style="color:red;"><%:NOT RUNNING%></span></p>'; | ||||
| 			} | ||||
| 		}); | ||||
| 		 | ||||
| 	function openwebui(){ | ||||
| 		 | ||||
| 		var url = window.location.host; | ||||
| 		if (url.indexOf(':')) { | ||||
| 			url = url.split(':')[0]; | ||||
| 		} | ||||
| 		ssl_cert = "<%=luci.sys.exec("uci get filebrowser.@global[0].ssl_cert"):gsub("^%s*(.-)%s*$", "%1")%>"; | ||||
| 		ssl_key = "<%=luci.sys.exec("uci get filebrowser.@global[0].ssl_key"):gsub("^%s*(.-)%s*$", "%1")%>"; | ||||
| 		port = "<%=luci.sys.exec("uci get filebrowser.@global[0].port"):gsub("^%s*(.-)%s*$", "%1")%>"; | ||||
| 		protocol = 'http'; | ||||
| 		if (ssl_cert !== '' && ssl_key !== '') protocol = 'https'; | ||||
| 		window.open(protocol+'://'+url+':'+port,'target',''); | ||||
| 	} | ||||
| //]]></script> | ||||
| @ -1,125 +0,0 @@ | ||||
| msgid "File Browser" | ||||
| msgstr "文件浏览器" | ||||
|  | ||||
| msgid "File explorer is software that creates your own cloud that you can install on a server, point it to a path, and then access your files through a beautiful web interface. You have many features available!" | ||||
| msgstr "文件浏览器是一种创建你自己的云的软件,你可以在服务器上安装它,将它指向一个路径,然后通过一个漂亮的web界面访问你的文件。您有许多可用的特性!" | ||||
|  | ||||
| msgid "RUNNING" | ||||
| msgstr "运行中" | ||||
|  | ||||
| msgid "NOT RUNNING" | ||||
| msgstr "未运行" | ||||
|  | ||||
| msgid "Enter interface" | ||||
| msgstr "进入界面" | ||||
|  | ||||
| msgid "Global Settings" | ||||
| msgstr "全局设置" | ||||
|  | ||||
| msgid "Enable" | ||||
| msgstr "启用" | ||||
|  | ||||
| msgid "Listen address" | ||||
| msgstr "监听地址" | ||||
|  | ||||
| msgid "Listen port" | ||||
| msgstr "监听端口" | ||||
|  | ||||
| msgid "Initial username" | ||||
| msgstr "初始账户" | ||||
|  | ||||
| msgid "Initial password" | ||||
| msgstr "初始密码" | ||||
|  | ||||
| msgid "SSL cert" | ||||
| msgstr "SSL 证书" | ||||
|  | ||||
| msgid "SSL key" | ||||
| msgstr "SSL 私钥" | ||||
|  | ||||
| msgid "Database path" | ||||
| msgstr "数据库路径" | ||||
|  | ||||
| msgid "Root path" | ||||
| msgstr "指向路径" | ||||
|  | ||||
| msgid "Point to a path to access your files in the web interface, default is /root" | ||||
| msgstr "指向一个路径,可在web界面访问你的文件,默认为 /root" | ||||
|  | ||||
| msgid "Executable directory" | ||||
| msgstr "可执行文件存放目录" | ||||
|  | ||||
| msgid "The file size is large, requiring at least 32M space. It is recommended to insert a usb flash drive or hard disk, or use it in the tmp directory<br />For example, /mnt/sda1<br />For example, /tmp" | ||||
| msgstr "文件较大,至少需要32M空间。建议插入U盘或硬盘,或放入tmp目录里使用<br />例如:/mnt/sda1<br />例如:/tmp" | ||||
|  | ||||
| msgid "Manually download" | ||||
| msgstr "手动下载" | ||||
|  | ||||
| msgid "Make sure you have enough space. <br /><font style='color:red'>Be sure to fill out the executable storage directory the first time you run it, and then save the application. Then manually download, otherwise can not use!</font>" | ||||
| msgstr "请确保具有足够的空间。<br /><font style='color:red'>第一次运行务必填好项目存放目录,然后保存应用。再手动下载,否则无法使用!</font>" | ||||
|  | ||||
| msgid "Logs" | ||||
| msgstr "日志" | ||||
|  | ||||
| msgid "Clear logs" | ||||
| msgstr "清空日志" | ||||
|  | ||||
| msgid "It is the latest version" | ||||
| msgstr "已是最新版本" | ||||
|  | ||||
| msgid "Download successful" | ||||
| msgstr "下载成功" | ||||
|  | ||||
| msgid "Click to download" | ||||
| msgstr "点击下载" | ||||
|  | ||||
| msgid "Updating..." | ||||
| msgstr "更新中" | ||||
|  | ||||
| msgid "Unexpected error" | ||||
| msgstr "意外错误" | ||||
|  | ||||
| msgid "Download, are you sure to close?" | ||||
| msgstr "正在下载,你确认要关闭吗?" | ||||
|  | ||||
| msgid "Downloading..." | ||||
| msgstr "下载中" | ||||
|  | ||||
| msgid "Unpacking..." | ||||
| msgstr "解压中" | ||||
|  | ||||
| msgid "Moving..." | ||||
| msgstr "移动中" | ||||
|  | ||||
| msgid "The latest version:" | ||||
| msgstr "最新版本:" | ||||
|  | ||||
| msgid "Can't determine ARCH, or ARCH not supported." | ||||
| msgstr "无法确认ARCH架构,或是不支持。" | ||||
|  | ||||
| msgid "Get remote version info failed." | ||||
| msgstr "获取远程版本信息失败。" | ||||
|  | ||||
| msgid "New version found, but failed to get new version download url." | ||||
| msgstr "发现新版本,但未能获得新版本的下载地址。" | ||||
|  | ||||
| msgid "Download url is required." | ||||
| msgstr "请指定下载地址。" | ||||
|  | ||||
| msgid "File download failed or timed out: %s" | ||||
| msgstr "文件下载失败或超时:%s" | ||||
|  | ||||
| msgid "File path required." | ||||
| msgstr "请指定文件路径。" | ||||
|  | ||||
| msgid "Can't find client in file: %s" | ||||
| msgstr "无法在文件中找到客户端:%s" | ||||
|  | ||||
| msgid "Client file is required." | ||||
| msgstr "请指定客户端文件。" | ||||
|  | ||||
| msgid "The client file is not suitable for current device." | ||||
| msgstr "客户端文件不适合当前设备。" | ||||
|  | ||||
| msgid "Can't move new file to path: %s" | ||||
| msgstr "无法移动新文件到:%s" | ||||
| @ -1,13 +0,0 @@ | ||||
|  | ||||
| config global | ||||
| 	option address '0.0.0.0' | ||||
| 	option port '8088' | ||||
| 	option database '/etc/filebrowser.db' | ||||
| 	option username 'admin' | ||||
| 	option password 'admin' | ||||
| 	option ssl_cert '' | ||||
| 	option ssl_key '' | ||||
| 	option root_path '/root' | ||||
| 	option executable_directory '/tmp' | ||||
| 	option enable '0' | ||||
|  | ||||
| @ -1,48 +0,0 @@ | ||||
| #!/bin/sh /etc/rc.common | ||||
| # Copyright (C) 2018-2020 Lienol <lawlienol@gmail.com> | ||||
| # Improve by xiaozhuai <xiaozhuai7@gmail.com> | ||||
|  | ||||
| START=99 | ||||
|  | ||||
| LOG_PATH="/var/log/filebrowser.log" | ||||
|  | ||||
| echolog() { | ||||
| 	echo -e "$(date "+%Y-%m-%d %H:%M:%S"): $1" >> $LOG_PATH | ||||
| } | ||||
|  | ||||
| config_t_get() { | ||||
| 	local index=0 | ||||
| 	[ -n "$4" ] && index=$4 | ||||
| 	local ret=$(uci get filebrowser.@$1[$index].$2 2>/dev/null) | ||||
| 	echo ${ret:=$3} | ||||
| } | ||||
| start() { | ||||
| 	ENABLED=$(config_t_get global enable 0) | ||||
| 	[ "$ENABLED" = "0" ] && return | ||||
| 	ADDRESS=$(config_t_get global address 0.0.0.0) | ||||
| 	PORT=$(config_t_get global port 8088) | ||||
| 	DATABASE=$(config_t_get global database /etc/filebrowser.db) | ||||
| 	USERNAME=$(config_t_get global username admin) | ||||
| 	PASSWORD=$(config_t_get global password admin) | ||||
| 	SSL_CERT=$(config_t_get global ssl_cert) | ||||
| 	SSL_KEY=$(config_t_get global ssl_key) | ||||
| 	ROOT_PATH=$(config_t_get global root_path /root) | ||||
| 	executable_directory=$(config_t_get global executable_directory /tmp) | ||||
| 	[ ! -f "$executable_directory/filebrowser" ] && echolog "$executable_directory/filebrowser not exists, please download first" && exit | ||||
| 	 | ||||
| 	SSL_PARAMS="" | ||||
| 	[ -n "$SSL_CERT" ] && [ -n "$SSL_KEY" ] && SSL_PARAMS="-t $SSL_CERT -k $SSL_KEY" | ||||
| 	PASSWORD="$($executable_directory/filebrowser hash "$PASSWORD")" | ||||
| 	$executable_directory/filebrowser -a $ADDRESS -p $PORT -r $ROOT_PATH -d "$DATABASE" --username $USERNAME --password $PASSWORD $SSL_PARAMS -l $LOG_PATH >/dev/null 2>&1 & | ||||
| } | ||||
|  | ||||
| stop() { | ||||
| 	ps -w | grep -v "grep" | grep "$executable_directory/filebrowser -a" | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1 & | ||||
| 	rm -rf $LOG_PATH | ||||
| } | ||||
|  | ||||
| restart() { | ||||
| 	stop | ||||
| 	sleep 1 | ||||
| 	start | ||||
| } | ||||
							
								
								
									
										0
									
								
								luci-app-filebrowser/root/etc/uci-defaults/luci-app-filebrowser → luci-app-filebrowser/root/etc/uci-defaults/luci-filebrowser
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										0
									
								
								luci-app-filebrowser/root/etc/uci-defaults/luci-app-filebrowser → luci-app-filebrowser/root/etc/uci-defaults/luci-filebrowser
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							| @ -1,11 +0,0 @@ | ||||
| { | ||||
| 	"luci-app-filebrowser": { | ||||
| 		"description": "Grant UCI access for luci-app-filebrowser", | ||||
| 		"read": { | ||||
| 			"uci": [ "filebrowser" ] | ||||
| 		}, | ||||
| 		"write": { | ||||
| 			"uci": [ "filebrowser" ] | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @ -12,7 +12,6 @@ function index() | ||||
| 	local page | ||||
| 	page = entry({"admin", "services", "gost"}, cbi("gost"), _("Gost"), 100) | ||||
| 	page.dependent = true | ||||
| 	page.acl_depends = { "luci-app-gost" } | ||||
| 	entry({"admin", "services", "gost", "status"},call("act_status")).leaf=true | ||||
| end | ||||
|  | ||||
|  | ||||
| @ -1 +0,0 @@ | ||||
| zh_Hans | ||||
| @ -1,11 +0,0 @@ | ||||
| { | ||||
| 	"luci-app-gost": { | ||||
| 		"description": "Grant UCI access for luci-app-gost", | ||||
| 		"read": { | ||||
| 			"uci": [ "gost" ] | ||||
| 		}, | ||||
| 		"write": { | ||||
| 			"uci": [ "gost" ] | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 actions-user
					actions-user