package ctcgfw: sync
This commit is contained in:
parent
e0244ad58a
commit
94655b05d3
@ -43,4 +43,4 @@ define Package/$(PKG_NAME)/install
|
||||
po2lmo ./po/pl/diskman.po $(1)/usr/lib/lua/luci/i18n/diskman.pl.lmo
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,$(PKG_NAME)))
|
||||
$(eval $(call BuildPackage,$(PKG_NAME)))
|
||||
@ -1 +1 @@
|
||||
e2fsprogs parted smartmontools blkid
|
||||
e2fsprogs parted smartmontools blkid mdadm btrfs-progs util-linux mergerfs snapraid
|
||||
@ -1,11 +1,6 @@
|
||||
--[[
|
||||
LuCI - Lua Configuration Interface
|
||||
Copyright 2019 lisaac <https://github.com/lisaac/luci-app-diskman>
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
$Id$
|
||||
]]--
|
||||
|
||||
require "luci.util"
|
||||
@ -29,6 +24,7 @@ function index()
|
||||
entry({"admin", "system", "diskman"}, alias("admin", "system", "diskman", "disks"), _("Disk Man"), 55)
|
||||
entry({"admin", "system", "diskman", "disks"}, form("diskman/disks"), nil).leaf = true
|
||||
entry({"admin", "system", "diskman", "partition"}, form("diskman/partition"), nil).leaf = true
|
||||
entry({"admin", "system", "diskman", "btrfs"}, form("diskman/btrfs"), nil).leaf = true
|
||||
entry({"admin", "system", "diskman", "get_disk_info"}, call("get_disk_info"), nil).leaf = true
|
||||
entry({"admin", "system", "diskman", "mk_p_table"}, call("mk_p_table"), nil).leaf = true
|
||||
entry({"admin", "system", "diskman", "smartdetail"}, call("smart_detail"), nil).leaf = true
|
||||
|
||||
@ -0,0 +1,210 @@
|
||||
--[[
|
||||
LuCI - Lua Configuration Interface
|
||||
Copyright 2019 lisaac <https://github.com/lisaac/luci-app-diskman>
|
||||
]]--
|
||||
|
||||
require "luci.util"
|
||||
require("luci.tools.webadmin")
|
||||
local dm = require "luci.model.diskman"
|
||||
local uuid = arg[1]
|
||||
|
||||
if not uuid then luci.http.redirect(luci.dispatcher.build_url("admin/system/diskman")) end
|
||||
|
||||
-- mount subv=/ to tempfs
|
||||
mount_point = "/tmp/.btrfs_tmp"
|
||||
nixio.fs.mkdirr(mount_point)
|
||||
luci.util.exec(dm.command.umount .. " "..mount_point .. " >/dev/null 2>&1")
|
||||
luci.util.exec(dm.command.mount .. " -t btrfs -o subvol=/ UUID="..uuid.." "..mount_point)
|
||||
|
||||
m = SimpleForm("btrfs", translate("Btrfs"), translate("Manage Btrfs"))
|
||||
m.template = "diskman/cbi/xsimpleform"
|
||||
m.redirect = luci.dispatcher.build_url("admin/system/diskman")
|
||||
m.submit = false
|
||||
m.reset = false
|
||||
|
||||
-- info
|
||||
local btrfs_info = dm.get_btrfs_info(mount_point)
|
||||
local table_btrfs_info = m:section(Table, {btrfs_info}, translate("Btrfs Info"))
|
||||
table_btrfs_info:option(DummyValue, "uuid", translate("UUID"))
|
||||
table_btrfs_info:option(DummyValue, "members", translate("Members"))
|
||||
table_btrfs_info:option(DummyValue, "data_raid_level", translate("Data"))
|
||||
table_btrfs_info:option(DummyValue, "metadata_raid_lavel", translate("Metadata"))
|
||||
table_btrfs_info:option(DummyValue, "size_formated", translate("Size"))
|
||||
table_btrfs_info:option(DummyValue, "used_formated", translate("Used"))
|
||||
table_btrfs_info:option(DummyValue, "free_formated", translate("Free Space"))
|
||||
table_btrfs_info:option(DummyValue, "usage", translate("Usage"))
|
||||
local v_btrfs_label = table_btrfs_info:option(Value, "label", translate("Label"))
|
||||
local value_btrfs_label = ""
|
||||
v_btrfs_label.write = function(self, section, value)
|
||||
value_btrfs_label = value or ""
|
||||
end
|
||||
local btn_update_label = table_btrfs_info:option(Button, "_update_label")
|
||||
btn_update_label.inputtitle = translate("Update")
|
||||
btn_update_label.inputstyle = "edit"
|
||||
btn_update_label.write = function(self, section, value)
|
||||
local cmd = dm.command.btrfs .. " filesystem label " .. mount_point .. " " .. value_btrfs_label
|
||||
local res = luci.util.exec(cmd)
|
||||
luci.http.redirect(luci.dispatcher.build_url("admin/system/diskman/btrfs/" .. uuid))
|
||||
end
|
||||
-- subvolume
|
||||
local subvolume_list = dm.get_btrfs_subv(mount_point)
|
||||
subvolume_list["_"] = { ID = 0 }
|
||||
table_subvolume = m:section(Table, subvolume_list, translate("SubVolumes"))
|
||||
table_subvolume:option(DummyValue, "id", translate("ID"))
|
||||
table_subvolume:option(DummyValue, "top_level", translate("Top Level"))
|
||||
table_subvolume:option(DummyValue, "uuid", translate("UUID"))
|
||||
table_subvolume:option(DummyValue, "otime", translate("Otime"))
|
||||
table_subvolume:option(DummyValue, "snapshots", translate("Snapshots"))
|
||||
local v_path = table_subvolume:option(Value, "path", translate("Path"))
|
||||
v_path.forcewrite = true
|
||||
v_path.render = function(self, section, scope)
|
||||
if subvolume_list[section].ID == 0 then
|
||||
self.template = "cbi/value"
|
||||
self.placeholder = "/my_subvolume"
|
||||
self.forcewrite = true
|
||||
Value.render(self, section, scope)
|
||||
else
|
||||
self.template = "cbi/dvalue"
|
||||
DummyValue.render(self, section, scope)
|
||||
end
|
||||
end
|
||||
local value_path
|
||||
v_path.write = function(self, section, value)
|
||||
value_path = value
|
||||
end
|
||||
local btn_set_default = table_subvolume:option(Button, "_subv_set_default", translate("Set Default"))
|
||||
btn_set_default.forcewrite = true
|
||||
btn_set_default.inputstyle = "edit"
|
||||
btn_set_default.template = "diskman/cbi/disabled_button"
|
||||
btn_set_default.render = function(self, section, scope)
|
||||
if subvolume_list[section].default_subvolume then
|
||||
self.view_disabled = true
|
||||
self.inputtitle = translate("Set Default")
|
||||
elseif subvolume_list[section].ID == 0 then
|
||||
self.template = "cbi/dvalue"
|
||||
else
|
||||
self.inputtitle = translate("Set Default")
|
||||
self.view_disabled = false
|
||||
end
|
||||
Button.render(self, section, scope)
|
||||
end
|
||||
btn_set_default.write = function(self, section, value)
|
||||
local cmd
|
||||
if value == translate("Set Default") then
|
||||
cmd = dm.command.btrfs .. " subvolume set-default " .. mount_point..subvolume_list[section].path
|
||||
else
|
||||
cmd = dm.command.btrfs .. " subvolume set-default " .. mount_point.."/"
|
||||
end
|
||||
local res = luci.util.exec(cmd.. " 2>&1")
|
||||
if res and (res:match("ERR") or res:match("not enough arguments")) then
|
||||
m.errmessage = res
|
||||
else
|
||||
luci.http.redirect(luci.dispatcher.build_url("admin/system/diskman/btrfs/" .. uuid))
|
||||
end
|
||||
end
|
||||
local btn_remove = table_subvolume:option(Button, "_subv_remove")
|
||||
btn_remove.template = "diskman/cbi/disabled_button"
|
||||
btn_remove.forcewrite = true
|
||||
btn_remove.render = function(self, section, scope)
|
||||
if subvolume_list[section].ID == 0 then
|
||||
btn_remove.inputtitle = translate("Create")
|
||||
btn_remove.inputstyle = "add"
|
||||
self.view_disabled = false
|
||||
elseif subvolume_list[section].path == "/" or subvolume_list[section].default_subvolume then
|
||||
btn_remove.inputtitle = translate("Delete")
|
||||
btn_remove.inputstyle = "remove"
|
||||
self.view_disabled = true
|
||||
else
|
||||
btn_remove.inputtitle = translate("Delete")
|
||||
btn_remove.inputstyle = "remove"
|
||||
self.view_disabled = false
|
||||
end
|
||||
Button.render(self, section, scope)
|
||||
end
|
||||
|
||||
btn_remove.write = function(self, section, value)
|
||||
local cmd
|
||||
if value == translate("Delete") then
|
||||
cmd = dm.command.btrfs .. " subvolume delete " .. mount_point .. subvolume_list[section].path
|
||||
elseif value == translate("Create") then
|
||||
if value_path and value_path:match("^/") then
|
||||
cmd = dm.command.btrfs .. " subvolume create " .. mount_point .. value_path
|
||||
else
|
||||
m.errmessage = translate("Please input Subvolume Path, Subvolume must start with '/'")
|
||||
return
|
||||
end
|
||||
end
|
||||
local res = luci.util.exec(cmd.. " 2>&1")
|
||||
if res and (res:match("ERR") or res:match("not enough arguments")) then
|
||||
m.errmessage = luci.util.pcdata(res)
|
||||
else
|
||||
luci.http.redirect(luci.dispatcher.build_url("admin/system/diskman/btrfs/" .. uuid))
|
||||
end
|
||||
end
|
||||
-- snapshot
|
||||
-- local snapshot_list = dm.get_btrfs_subv(mount_point, 1)
|
||||
-- table_snapshot = m:section(Table, snapshot_list, translate("Snapshots"))
|
||||
-- table_snapshot:option(DummyValue, "id", translate("ID"))
|
||||
-- table_snapshot:option(DummyValue, "top_level", translate("Top Level"))
|
||||
-- table_snapshot:option(DummyValue, "uuid", translate("UUID"))
|
||||
-- table_snapshot:option(DummyValue, "otime", translate("Otime"))
|
||||
-- table_snapshot:option(DummyValue, "path", translate("Path"))
|
||||
-- local snp_remove = table_snapshot:option(Button, "_snp_remove")
|
||||
-- snp_remove.inputtitle = translate("Delete")
|
||||
-- snp_remove.inputstyle = "remove"
|
||||
-- snp_remove.write = function(self, section, value)
|
||||
-- local cmd = dm.command.btrfs .. " subvolume delete " .. mount_point .. snapshot_list[section].path
|
||||
-- local res = luci.util.exec(cmd.. " 2>&1")
|
||||
-- if res and (res:match("ERR") or res:match("not enough arguments")) then
|
||||
-- m.errmessage = luci.util.pcdata(res)
|
||||
-- else
|
||||
-- luci.http.redirect(luci.dispatcher.build_url("admin/system/diskman/btrfs/" .. uuid))
|
||||
-- end
|
||||
-- end
|
||||
|
||||
-- new snapshots
|
||||
local s_snapshot = m:section(SimpleSection, translate("New Snapshot"))
|
||||
local value_sorce, value_dest, value_readonly
|
||||
local v_sorce = s_snapshot:option(Value, "_source", translate("Source Path"), translate("The source path for create the snapshot"))
|
||||
v_sorce.placeholder = "/data"
|
||||
v_sorce.forcewrite = true
|
||||
v_sorce.write = function(self, section, value)
|
||||
value_sorce = value
|
||||
end
|
||||
|
||||
local v_readonly = s_snapshot:option(Flag, "_readonly", translate("Readonly"), translate("The path where you want to store the snapshot"))
|
||||
v_readonly.forcewrite = true
|
||||
v_readonly.rmempty = false
|
||||
v_readonly.disabled = 0
|
||||
v_readonly.enabled = 1
|
||||
v_readonly.default = 1
|
||||
v_readonly.write = function(self, section, value)
|
||||
value_readonly = value
|
||||
end
|
||||
local v_dest = s_snapshot:option(Value, "_dest", translate("Destination Path (optional)"))
|
||||
v_dest.forcewrite = true
|
||||
v_dest.placeholder = "/.snapshot/202002051538"
|
||||
v_dest.write = function(self, section, value)
|
||||
value_dest = value
|
||||
end
|
||||
local btn_snp_create = s_snapshot:option(Button, "_snp_create")
|
||||
btn_snp_create.title = " "
|
||||
btn_snp_create.inputtitle = translate("New Snapshot")
|
||||
btn_snp_create.inputstyle = "add"
|
||||
btn_snp_create.write = function(self, section, value)
|
||||
if value_sorce and value_sorce:match("^/") then
|
||||
if not value_dest then value_dest = "/.snapshot"..value_sorce.."/"..os.date("%Y%m%d%H%M%S") end
|
||||
nixio.fs.mkdirr(mount_point..value_dest:match("(.-)[^/]+$"))
|
||||
local cmd = dm.command.btrfs .. " subvolume snapshot" .. (value_readonly == 1 and " -r " or " ") .. mount_point..value_sorce .. " " .. mount_point..value_dest
|
||||
local res = luci.util.exec(cmd .. " 2>&1")
|
||||
if res and (res:match("ERR") or res:match("not enough arguments")) then
|
||||
m.errmessage = luci.util.pcdata(res)
|
||||
else
|
||||
luci.http.redirect(luci.dispatcher.build_url("admin/system/diskman/btrfs/" .. uuid))
|
||||
end
|
||||
else
|
||||
m.errmessage = translate("Please input Source Path of snapshot, Source Path must start with '/'")
|
||||
end
|
||||
end
|
||||
|
||||
return m
|
||||
@ -1,11 +1,6 @@
|
||||
--[[
|
||||
LuCI - Lua Configuration Interface
|
||||
Copyright 2019 lisaac <https://github.com/lisaac/luci-app-diskman>
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
$Id$
|
||||
]]--
|
||||
|
||||
require "luci.util"
|
||||
@ -67,17 +62,23 @@ if dm.command.mdadm then
|
||||
r:option(DummyValue, "status", translate("Status"))
|
||||
r:option(DummyValue, "members_str", translate("Members"))
|
||||
r:option(DummyValue, "active", translate("Active"))
|
||||
-- local redit = r:option(Button, "rpartition")
|
||||
-- redit.inputstyle = "edit"
|
||||
-- redit.inputtitle = "Edit"
|
||||
-- redit.write = function(self, section)
|
||||
-- local url = luci.dispatcher.build_url("admin/system/diskman/partition")
|
||||
-- url = url .. "/" .. raid_devices[section].path:match("/dev/(.+)")
|
||||
-- luci.http.redirect(url)
|
||||
-- end
|
||||
r.extedit = luci.dispatcher.build_url("admin/system/diskman/partition/%s")
|
||||
end
|
||||
end
|
||||
|
||||
-- btrfs devices
|
||||
if dm.command.btrfs then
|
||||
btrfs_devices = dm.list_btrfs_devices()
|
||||
if next(btrfs_devices) ~= nil then
|
||||
local table_btrfs = m:section(Table, btrfs_devices, translate("Btrfs"))
|
||||
table_btrfs:option(DummyValue, "uuid", translate("UUID"))
|
||||
table_btrfs:option(DummyValue, "label", translate("Label"))
|
||||
table_btrfs:option(DummyValue, "members", translate("Members"))
|
||||
-- sieze is error, since there is RAID
|
||||
-- table_btrfs:option(DummyValue, "size_formated", translate("Size"))
|
||||
table_btrfs:option(DummyValue, "used_formated", translate("Usage"))
|
||||
table_btrfs.extedit = luci.dispatcher.build_url("admin/system/diskman/btrfs/%s")
|
||||
end
|
||||
end
|
||||
|
||||
--tabs
|
||||
@ -95,12 +96,12 @@ if dm.command.mdadm then
|
||||
local r = m:section(SimpleSection, translate("RAID Creation"))
|
||||
r.template="diskman/cbi/xnullsection"
|
||||
r.config = "raid"
|
||||
local r_name = r:option(Value, "_name", translate("Raid Name"))
|
||||
local r_name = r:option(Value, "_rname", translate("Raid Name"))
|
||||
r_name.placeholder = "/dev/md0"
|
||||
r_name.write = function(self, section, value)
|
||||
rname = value
|
||||
end
|
||||
local r_level = r:option(ListValue, "_level", translate("Raid Level"))
|
||||
local r_level = r:option(ListValue, "_rlevel", translate("Raid Level"))
|
||||
local valid_raid = luci.util.exec("lsmod | grep md_mod")
|
||||
if valid_raid:match("linear") then
|
||||
r_level:value("linear", "Linear")
|
||||
@ -121,7 +122,7 @@ if dm.command.mdadm then
|
||||
r_level.write = function(self, section, value)
|
||||
rlevel = value
|
||||
end
|
||||
local r_member = r:option(DynamicList, "_member", translate("Raid Member"))
|
||||
local r_member = r:option(DynamicList, "_rmember", translate("Raid Member"))
|
||||
for dev, info in pairs(disks) do
|
||||
if not info.inuse and #info.partitions == 0 then
|
||||
r_member:value(info.path, info.path.. " ".. info.size_formated)
|
||||
@ -135,7 +136,7 @@ if dm.command.mdadm then
|
||||
r_member.write = function(self, section, value)
|
||||
rmembers = value
|
||||
end
|
||||
local r_create = r:option(Button, "_create")
|
||||
local r_create = r:option(Button, "_rcreate")
|
||||
r_create.render = function(self, section, scope)
|
||||
self.title = " "
|
||||
self.inputtitle = translate("Create Raid")
|
||||
@ -145,8 +146,8 @@ if dm.command.mdadm then
|
||||
r_create.write = function(self, section, value)
|
||||
-- mdadm --create --verbose /dev/md0 --level=stripe --raid-devices=2 /dev/sdb6 /dev/sdc5
|
||||
local res = dm.create_raid(rname, rlevel, rmembers)
|
||||
if res:match("^ERR") then
|
||||
m.errmessage = translate(res)
|
||||
if res and res:match("^ERR") then
|
||||
m.errmessage = luci.util.pcdata(res)
|
||||
return
|
||||
end
|
||||
dm.gen_mdadm_config()
|
||||
@ -201,11 +202,17 @@ v_mount_option.render = function(self, section, scope)
|
||||
self.template = "cbi/dvalue"
|
||||
local mp = mount_point[section].mount_options
|
||||
mount_point[section].mount_options = nil
|
||||
local length = 0
|
||||
for k in mp:gmatch("([^,]+)") do
|
||||
mount_point[section].mount_options = mount_point[section].mount_options and mount_point[section].mount_options .. "," or ""
|
||||
if #mount_point[section].mount_options > 50 then mount_point[section].mount_options = mount_point[section].mount_options.. " " end
|
||||
mount_point[section].mount_options= mount_point[section].mount_options.. k
|
||||
mount_point[section].mount_options = mount_point[section].mount_options and (mount_point[section].mount_options .. ",") or ""
|
||||
if length > 20 then
|
||||
mount_point[section].mount_options = mount_point[section].mount_options.. " <br>"
|
||||
length = 0
|
||||
end
|
||||
mount_point[section].mount_options = mount_point[section].mount_options .. k
|
||||
length = length + #k
|
||||
end
|
||||
self.rawhtml = true
|
||||
-- mount_point[section].mount_options = #mount_point[section].mount_options > 50 and mount_point[section].mount_options:sub(1,50) .. "..." or mount_point[section].mount_options
|
||||
DummyValue.render(self, section, scope)
|
||||
end
|
||||
@ -244,22 +251,67 @@ btn_umount.write = function(self, section, value)
|
||||
local res
|
||||
if value == translate("Mount") then
|
||||
luci.util.exec("mkdir -p ".. _mount_point.mount_point)
|
||||
res = luci.util.exec("mount ".. _mount_point.device .. (_mount_point.fs and (" -t ".. _mount_point.fs )or "") .. (_mount_point.mount_options and (" -o " .. _mount_point.mount_options.. " ") or " ").._mount_point.mount_point .. " 2>&1")
|
||||
res = luci.util.exec(dm.command.mount .. " ".. _mount_point.device .. (_mount_point.fs and (" -t ".. _mount_point.fs )or "") .. (_mount_point.mount_options and (" -o " .. _mount_point.mount_options.. " ") or " ").._mount_point.mount_point .. " 2>&1")
|
||||
elseif value == translate("Umount") then
|
||||
res = luci.util.exec("umount "..mount_point[section].mount_point .. " 2>&1")
|
||||
res = luci.util.exec(dm.command.umount .. " "..mount_point[section].mount_point .. " 2>&1")
|
||||
end
|
||||
if res:match("^mount:") then
|
||||
if res:match("^mount:") or res:match("^umount:") then
|
||||
m.errmessage = luci.util.pcdata(res)
|
||||
else
|
||||
luci.http.redirect(luci.dispatcher.build_url("admin/system/diskman"))
|
||||
end
|
||||
end
|
||||
|
||||
-- -- btrfs
|
||||
-- btrfs
|
||||
if dm.command.btrfs then
|
||||
local blabel, bmembers, blevel
|
||||
tab_section.tabs.btrfs = translate("Btrfs")
|
||||
local btrfs_devices = {}
|
||||
local table_btrfs = m:section(Table, btrfs_devices, translate("Btrfs"))
|
||||
table_btrfs.config = "btrfs"
|
||||
local r = m:section(SimpleSection, translate("Multiple Devices Btrfs Creation"))
|
||||
r.template="diskman/cbi/xnullsection"
|
||||
r.config = "btrfs"
|
||||
local btrfs_label = r:option(Value, "_blabel", translate("Btrfs Label"))
|
||||
btrfs_label.write = function(self, section, value)
|
||||
blabel = value
|
||||
end
|
||||
local btrfs_level = r:option(ListValue, "_blevel", translate("Btrfs Raid Level"))
|
||||
btrfs_level:value("single", "Single")
|
||||
btrfs_level:value("raid0", "Raid 0")
|
||||
btrfs_level:value("raid1", "Raid 1")
|
||||
btrfs_level:value("raid10", "Raid 10")
|
||||
btrfs_level.write = function(self, section, value)
|
||||
blevel = value
|
||||
end
|
||||
|
||||
local btrfs_member = r:option(DynamicList, "_bmember", translate("Btrfs Member"))
|
||||
for dev, info in pairs(disks) do
|
||||
if not info.inuse and #info.partitions == 0 then
|
||||
btrfs_member:value(info.path, info.path.. " ".. info.size_formated)
|
||||
end
|
||||
for i, v in ipairs(info.partitions) do
|
||||
if not v.inuse then
|
||||
btrfs_member:value("/dev/".. v.name, "/dev/".. v.name .. " ".. v.size_formated)
|
||||
end
|
||||
end
|
||||
end
|
||||
btrfs_member.write = function(self, section, value)
|
||||
bmembers = value
|
||||
end
|
||||
local btrfs_create = r:option(Button, "_bcreate")
|
||||
btrfs_create.render = function(self, section, scope)
|
||||
self.title = " "
|
||||
self.inputtitle = translate("Create Btrfs")
|
||||
self.inputstyle = "add"
|
||||
Button.render(self, section, scope)
|
||||
end
|
||||
btrfs_create.write = function(self, section, value)
|
||||
-- mkfs.btrfs -L label -d blevel /dev/sda /dev/sdb
|
||||
local res = dm.create_btrfs(blabel, blevel, bmembers)
|
||||
if res and res:match("^ERR") then
|
||||
m.errmessage = luci.util.pcdata(res)
|
||||
return
|
||||
end
|
||||
luci.http.redirect(luci.dispatcher.build_url("admin/system/diskman"))
|
||||
end
|
||||
end
|
||||
|
||||
return m
|
||||
|
||||
@ -1,11 +1,6 @@
|
||||
--[[
|
||||
LuCI - Lua Configuration Interface
|
||||
Copyright 2019 lisaac <https://github.com/lisaac/luci-app-diskman>
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
$Id$
|
||||
]]--
|
||||
|
||||
require "luci.util"
|
||||
@ -37,10 +32,11 @@ s:option(DummyValue, "path", translate("Path"))
|
||||
s:option(DummyValue, "model", translate("Model"))
|
||||
s:option(DummyValue, "sn", translate("Serial Number"))
|
||||
s:option(DummyValue, "size_formated", translate("Size"))
|
||||
s:option(DummyValue, "sec_size", translate("Sector Size "))
|
||||
s:option(DummyValue, "sec_size", translate("Sector Size"))
|
||||
local dv_p_table = s:option(ListValue, "p_table", translate("Partition Table"))
|
||||
dv_p_table.render = function(self, section, scope)
|
||||
if not disk_info.p_table:match("Raid") and (#disk_info.partitions == 0 or (#disk_info.partitions == 1 and disk_info.partitions[1].number == -1)) then
|
||||
-- create table only if not used by raid and no partitions on disk
|
||||
if not disk_info.p_table:match("Raid") and (#disk_info.partitions == 0 or (#disk_info.partitions == 1 and disk_info.partitions[1].number == -1) or (disk_info.p_table:match("LOOP") and not disk_info.partitions[1].inuse)) then
|
||||
self:value(disk_info.p_table, disk_info.p_table)
|
||||
self:value("GPT", "GPT")
|
||||
self:value("MBR", "MBR")
|
||||
@ -100,7 +96,7 @@ btn_eject.forcewrite = true
|
||||
btn_eject.write = function(self, section, value)
|
||||
for i, p in ipairs(disk_info.partitions) do
|
||||
if p.mount_point ~= "-" then
|
||||
m.errmessage = p.name .. "is in use! please unmount it first!"
|
||||
m.errmessage = p.name .. translate("is in use! please unmount it first!")
|
||||
return
|
||||
end
|
||||
end
|
||||
@ -160,7 +156,9 @@ if not disk_info.p_table:match("Raid") then
|
||||
if disk_info.p_table == "MBR" then
|
||||
s_partition_table:option(DummyValue, "type", translate("Type"))
|
||||
end
|
||||
s_partition_table:option(DummyValue, "useage", translate("Useage"))
|
||||
s_partition_table:option(DummyValue, "used_formated", translate("Used"))
|
||||
s_partition_table:option(DummyValue, "free_formated", translate("Free Space"))
|
||||
s_partition_table:option(DummyValue, "usage", translate("Usage"))
|
||||
s_partition_table:option(DummyValue, "mount_point", translate("Mount Point"))
|
||||
local val_fs = s_partition_table:option(Value, "fs", translate("File System"))
|
||||
val_fs.forcewrite = true
|
||||
@ -211,18 +209,21 @@ if not disk_info.p_table:match("Raid") then
|
||||
btn_format.write = function(self, section, value)
|
||||
local partition_name = "/dev/".. disk_info.partitions[section].name
|
||||
if not nixio.fs.access(partition_name) then
|
||||
m.errmessage = "Partition NOT found!"
|
||||
m.errmessage = translate("Partition NOT found!")
|
||||
return
|
||||
end
|
||||
local fs = disk_info.partitions[section]._fs
|
||||
if not format_cmd[fs] then
|
||||
m.errmessage = "Filesystem NOT support!"
|
||||
m.errmessage = translate("Filesystem NOT support!")
|
||||
return
|
||||
end
|
||||
local cmd = format_cmd[fs].cmd .. " " .. format_cmd[fs].option .. " " .. partition_name
|
||||
-- luci.util.perror(cmd)
|
||||
local res = luci.sys.exec(cmd)
|
||||
luci.http.redirect(luci.dispatcher.build_url("admin/system/diskman/partition/" .. dev))
|
||||
local res = luci.util.exec(cmd .. " 2>&1")
|
||||
if res and res:lower():match("error+") then
|
||||
m.errmessage = luci.util.pcdata(res)
|
||||
else
|
||||
luci.http.redirect(luci.dispatcher.build_url("admin/system/diskman/partition/" .. dev))
|
||||
end
|
||||
end
|
||||
|
||||
local btn_action = s_partition_table:option(Button, "_action")
|
||||
@ -250,7 +251,6 @@ if not disk_info.p_table:match("Raid") then
|
||||
Button.render(self, section, scope)
|
||||
end
|
||||
btn_action.write = function(self, section, value)
|
||||
-- luci.util.perror(value)
|
||||
if value == translate("New") then
|
||||
local start_sec = disk_info.partitions[section]._sec_start and tonumber(disk_info.partitions[section]._sec_start) or tonumber(disk_info.partitions[section].sec_start)
|
||||
local end_sec = disk_info.partitions[section]._sec_end
|
||||
@ -267,7 +267,7 @@ if not disk_info.p_table:match("Raid") then
|
||||
start_sec = start_sec .. "s"
|
||||
end
|
||||
else
|
||||
m.errmessage = "Invalid Start Sector!"
|
||||
m.errmessage = translate("Invalid Start Sector!")
|
||||
return
|
||||
end
|
||||
-- support +size format for End sector
|
||||
@ -286,7 +286,7 @@ if not disk_info.p_table:match("Raid") then
|
||||
elseif tonumber(end_sec) then
|
||||
end_sec = end_sec .. "s"
|
||||
else
|
||||
m.errmessage = "Invalid End Sector!"
|
||||
m.errmessage = translate("Invalid End Sector!")
|
||||
return
|
||||
end
|
||||
local part_type = "primary"
|
||||
@ -305,9 +305,9 @@ if not disk_info.p_table:match("Raid") then
|
||||
|
||||
-- partiton
|
||||
local cmd = dm.command.parted .. " -s -a optimal /dev/" .. dev .. " mkpart " .. part_type .." " .. start_sec .. " " .. end_sec
|
||||
local res = luci.util.exec(cmd)
|
||||
if res:match("Error.+") then
|
||||
m.errmessage = res
|
||||
local res = luci.util.exec(cmd .. " 2>&1")
|
||||
if res and res:lower():match("error+") then
|
||||
m.errmessage = luci.util.pcdata(res)
|
||||
else
|
||||
luci.http.redirect(luci.dispatcher.build_url("admin/system/diskman/partition/" .. dev))
|
||||
end
|
||||
@ -315,13 +315,13 @@ if not disk_info.p_table:match("Raid") then
|
||||
-- remove partition
|
||||
local number = tostring(disk_info.partitions[section].number)
|
||||
if (not number) or (number == "") then
|
||||
m.errmessage = "Partition not exists!"
|
||||
m.errmessage = translate("Partition not exists!")
|
||||
return
|
||||
end
|
||||
local cmd = dm.command.parted .. " -s /dev/" .. dev .. " rm " .. number
|
||||
local res = luci.util.exec(cmd)
|
||||
if res:match("Error.+") then
|
||||
m.errmessage = res
|
||||
local res = luci.util.exec(cmd .. " 2>&1")
|
||||
if res and res:lower():match("error+") then
|
||||
m.errmessage = luci.util.pcdata(res)
|
||||
else
|
||||
luci.http.redirect(luci.dispatcher.build_url("admin/system/diskman/partition/" .. dev))
|
||||
end
|
||||
|
||||
@ -1,17 +1,12 @@
|
||||
--[[
|
||||
LuCI - Lua Configuration Interface
|
||||
Copyright 2019 lisaac <https://github.com/lisaac/luci-app-diskman>
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
$Id$
|
||||
]]--
|
||||
|
||||
require "luci.util"
|
||||
local ver = require "luci.version"
|
||||
|
||||
local CMD = {"parted", "mdadm", "blkid", "smartctl", "df", "sgdisk", "btrfs"}
|
||||
local CMD = {"parted", "mdadm", "blkid", "smartctl", "df", "sgdisk", "btrfs", "mergerfs", "snapraid"}
|
||||
|
||||
local d = {command ={}}
|
||||
for _, cmd in ipairs(CMD) do
|
||||
@ -19,6 +14,9 @@ for _, cmd in ipairs(CMD) do
|
||||
d.command[cmd] = command:match("^.+"..cmd) or nil
|
||||
end
|
||||
|
||||
d.command.mount = nixio.fs.access("/usr/bin/mount") and "/usr/bin/mount" or "/bin/mount"
|
||||
d.command.umount = nixio.fs.access("/usr/bin/umount") and "/usr/bin/umount" or "/bin/umount"
|
||||
|
||||
local mounts = nixio.fs.readfile("/proc/mounts") or ""
|
||||
local swaps = nixio.fs.readfile("/proc/swaps") or ""
|
||||
local df = luci.sys.exec(d.command.df) or ""
|
||||
@ -142,11 +140,16 @@ local get_mount_point = function(partition)
|
||||
|
||||
end
|
||||
|
||||
local get_partition_useage = function(partition)
|
||||
-- return used, free, usage
|
||||
local get_partition_usage = function(partition)
|
||||
if not nixio.fs.access("/dev/"..partition) then return false end
|
||||
local useage = df:match("\n/dev/" .. partition .. "%s+%d+%s+%d+%s+%d+%s+([0-9]+)%%%s")
|
||||
useage = useage and (useage .. "%") or false
|
||||
return useage
|
||||
local used, free, usage = df:match("\n/dev/" .. partition .. "%s+%d+%s+(%d+)%s+(%d+)%s+(%d+)%%%s-")
|
||||
|
||||
usage = usage and (usage .. "%") or "-"
|
||||
used = used and (tonumber(used) * 1024) or 0
|
||||
free = free and (tonumber(free) * 1024) or 0
|
||||
|
||||
return used, free, usage
|
||||
end
|
||||
|
||||
local get_parted_info = function(device)
|
||||
@ -195,7 +198,15 @@ local get_parted_info = function(device)
|
||||
partition_temp["sec_start"] = partition_temp["sec_start"] and partition_temp["sec_start"]:sub(1,-2)
|
||||
partition_temp["sec_end"] = partition_temp["sec_end"] and partition_temp["sec_end"]:sub(1,-2)
|
||||
partition_temp["mount_point"] = partition_temp["name"]~="-" and get_mount_point(partition_temp["name"]) or "-"
|
||||
partition_temp["useage"] = partition_temp["mount_point"]~="-" and get_partition_useage(partition_temp["name"]) or "-"
|
||||
if partition_temp["mount_point"]~="-" then
|
||||
partition_temp["used"], partition_temp["free"], partition_temp["usage"] = get_partition_usage(partition_temp["name"])
|
||||
partition_temp["used_formated"] = partition_temp["used"] and byte_format(partition_temp["used"]) or "-"
|
||||
partition_temp["free_formated"] = partition_temp["free"] and byte_format(partition_temp["free"]) or "-"
|
||||
else
|
||||
partition_temp["used"], partition_temp["free"], partition_temp["usage"] = 0,0,"-"
|
||||
partition_temp["used_formated"] = "-"
|
||||
partition_temp["free_formated"] = "-"
|
||||
end
|
||||
-- if disk_temp["p_table"] == "MBR" and (partition_temp["number"] < 4) and (partition_temp["number"] > 0) then
|
||||
-- local real_size_sec = tonumber(nixio.fs.readfile("/sys/block/"..device.."/"..partition_temp["name"].."/size")) * tonumber(disk_temp.phy_sec)
|
||||
-- if real_size_sec ~= partition_temp["size"] then
|
||||
@ -288,8 +299,8 @@ d.get_disk_info = function(device, wakeup)
|
||||
{
|
||||
path, model, sn, size, size_mounted, flags, type, temp, p_table, logic_sec, phy_sec, sec_size, sata_ver, rota_rate, status, health,
|
||||
partitions = {
|
||||
1 = { number, name, sec_start, sec_end, size, size_mounted, fs, tag_name, type, flags, mount_point, useage },
|
||||
2 = { number, name, sec_start, sec_end, size, size_mounted, fs, tag_name, type, flags, mount_point, useage },
|
||||
1 = { number, name, sec_start, sec_end, size, size_mounted, fs, tag_name, type, flags, mount_point, usage, used, free, used_formated, free_formated},
|
||||
2 = { number, name, sec_start, sec_end, size, size_mounted, fs, tag_name, type, flags, mount_point, usage, used, free, used_formated, free_formated},
|
||||
...
|
||||
}
|
||||
--raid devices only
|
||||
@ -537,4 +548,178 @@ d.gen_mdadm_config = function()
|
||||
luci.util.exec("/etc/init.d/mdadm enable")
|
||||
end
|
||||
|
||||
-- list btrfs filesystem device
|
||||
-- {uuid={uuid, label, members, size, used}...}
|
||||
d.list_btrfs_devices = function()
|
||||
local btrfs_device = {}
|
||||
if not d.command.btrfs then return btrfs_device end
|
||||
local line, _uuid
|
||||
for _, line in ipairs(luci.util.execl(d.command.btrfs .. " filesystem show -d --raw"))
|
||||
do
|
||||
local label, uuid = line:match("^Label:%s+([^%s]+)%s+uuid:%s+([^%s]+)")
|
||||
if label and uuid then
|
||||
_uuid = uuid
|
||||
local _label = label:match("^'([^']+)'")
|
||||
btrfs_device[_uuid] = {label = _label or label, uuid = uuid}
|
||||
-- table.insert(btrfs_device, {label = label, uuid = uuid})
|
||||
end
|
||||
local used = line:match("Total devices[%w%s]+used%s+(%d+)$")
|
||||
if used then
|
||||
btrfs_device[_uuid]["used"] = tonumber(used)
|
||||
btrfs_device[_uuid]["used_formated"] = byte_format(tonumber(used))
|
||||
end
|
||||
local size, device = line:match("devid[%w.%s]+size%s+(%d+)[%w.%s]+path%s+([^%s]+)$")
|
||||
if size and device then
|
||||
btrfs_device[_uuid]["size"] = btrfs_device[_uuid]["size"] and btrfs_device[_uuid]["size"] + tonumber(size) or tonumber(size)
|
||||
btrfs_device[_uuid]["size_formated"] = byte_format(btrfs_device[_uuid]["size"])
|
||||
btrfs_device[_uuid]["members"] = btrfs_device[_uuid]["members"] and btrfs_device[_uuid]["members"]..", "..device or device
|
||||
end
|
||||
end
|
||||
return btrfs_device
|
||||
end
|
||||
|
||||
d.create_btrfs = function(blabel, blevel, bmembers)
|
||||
-- mkfs.btrfs -L label -d blevel /dev/sda /dev/sdb
|
||||
if not d.command.btrfs or type(bmembers) ~= "table" or next(bmembers) == nil then return "ERR no btrfs support or no members" end
|
||||
local label = blabel and " -L " .. blabel or ""
|
||||
local cmd = "mkfs.btrfs -f " .. label .. " -d " .. blevel .. " " .. table.concat(bmembers, " ")
|
||||
return luci.util.exec(cmd)
|
||||
end
|
||||
|
||||
-- get btrfs info
|
||||
-- {uuid, label, members, data_raid_level,metadata_raid_lavel, size, used, size_formated, used_formated, free, free_formated, usage}
|
||||
d.get_btrfs_info = function(m_point)
|
||||
local btrfs_info = {}
|
||||
if not m_point or not d.command.btrfs then return btrfs_info end
|
||||
local cmd = d.command.btrfs .. " filesystem show --raw " .. m_point
|
||||
local _, line, uuid, _label, members
|
||||
for _, line in ipairs(luci.util.execl(cmd)) do
|
||||
if not uuid and not _label then
|
||||
_label, uuid = line:match("^Label:%s+([^%s]+)%s+uuid:%s+([^s]+)")
|
||||
else
|
||||
local mb = line:match("%s+devid.+path%s+([^%s]+)")
|
||||
if mb then
|
||||
members = members and (members .. ", ".. mb) or mb
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not _label or not uuid then return btrfs_info end
|
||||
local label = _label:match("^'([^']+)'")
|
||||
cmd = d.command.btrfs .. " filesystem usage -b " .. m_point
|
||||
local used, free, data_raid_level, metadata_raid_lavel
|
||||
for _, line in ipairs(luci.util.execl(cmd)) do
|
||||
if not used then
|
||||
used = line:match("^%s+Used:%s+(%d+)")
|
||||
elseif not free then
|
||||
free = line:match("^%s+Free %(estimated%):%s+(%d+)")
|
||||
elseif not data_raid_level then
|
||||
data_raid_level = line:match("^Data,%s-(%w+)")
|
||||
elseif not metadata_raid_lavel then
|
||||
metadata_raid_lavel = line:match("^Metadata,%s-(%w+)")
|
||||
end
|
||||
end
|
||||
if used and free and data_raid_level and metadata_raid_lavel then
|
||||
used = tonumber(used)
|
||||
free = tonumber(free)
|
||||
btrfs_info = {
|
||||
uuid = uuid,
|
||||
label = label,
|
||||
data_raid_level = data_raid_level,
|
||||
metadata_raid_lavel = metadata_raid_lavel,
|
||||
used = used,
|
||||
free = free,
|
||||
size = used + free,
|
||||
size_formated = byte_format(used + free),
|
||||
used_formated = byte_format(used),
|
||||
free_formated = byte_format(free),
|
||||
members = members,
|
||||
usage = string.format("%.2f",(used / (free+used) * 100)) .. "%"
|
||||
}
|
||||
end
|
||||
return btrfs_info
|
||||
end
|
||||
|
||||
-- get btrfs subvolume
|
||||
-- {id={id, gen, top_level, path, snapshots, otime, default_subvolume}...}
|
||||
d.get_btrfs_subv = function(m_point, snapshot)
|
||||
local subvolume = {}
|
||||
if not m_point or not d.command.btrfs then return subvolume end
|
||||
|
||||
-- get default subvolume
|
||||
local cmd = d.command.btrfs .. " subvolume get-default " .. m_point
|
||||
local res = luci.util.exec(cmd)
|
||||
local default_subvolume_id = res:match("^ID%s+([^%s]+)")
|
||||
|
||||
-- get the root subvolume
|
||||
if not snapshot then
|
||||
local _, line, section_snap, _uuid, _otime, _id, _snap
|
||||
cmd = d.command.btrfs .. " subvolume show ".. m_point
|
||||
for _, line in ipairs(luci.util.execl(cmd)) do
|
||||
if not section_snap then
|
||||
if not _uuid then
|
||||
_uuid = line:match("^%s-UUID:%s+([^%s]+)")
|
||||
elseif not _otime then
|
||||
_otime = line:match("^%s+Creation time:%s+(.+)")
|
||||
elseif not _id then
|
||||
_id = line:match("^%s+Subvolume ID:%s+([^%s]+)")
|
||||
elseif line:match("^%s+(Snapshot%(s%):)") then
|
||||
section_snap = true
|
||||
end
|
||||
else
|
||||
local snapshot = line:match("^%s+(.+)")
|
||||
if snapshot then
|
||||
_snap = _snap and (_snap ..", /".. snapshot) or ("/"..snapshot)
|
||||
end
|
||||
end
|
||||
end
|
||||
if _uuid and _otime and _id then
|
||||
subvolume["0".._id] = {id = _id , uuid = _uuid, otime = _otime, snapshots = _snap, path = "/"}
|
||||
if default_subvolume_id == _id then
|
||||
subvolume["0".._id].default_subvolume = 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- get subvolume of btrfs
|
||||
cmd = d.command.btrfs .. " subvolume list -gcu" .. (snapshot and "s " or " ") .. m_point
|
||||
for _, line in ipairs(luci.util.execl(cmd)) do
|
||||
-- ID 259 gen 11 top level 258 uuid 26ae0c59-199a-cc4d-bd58-644eb4f65d33 path 1a/2b'
|
||||
local id, gen, top_level, uuid, path, otime, otime2
|
||||
if snapshot then
|
||||
id, gen, top_level, otime, otime2, uuid, path = line:match("^ID%s+([^%s]+)%s+gen%s+([^%s]+)%s+cgen.-top level%s+([^%s]+)%s+otime%s+([^%s]+)%s+([^%s]+)%s+uuid%s+([^%s]+)%s+path%s+([^%s]+)%s-$")
|
||||
else
|
||||
id, gen, top_level, uuid, path = line:match("^ID%s+([^%s]+)%s+gen%s+([^%s]+)%s+cgen.-top level%s+([^%s]+)%s+uuid%s+([^%s]+)%s+path%s+([^%s]+)%s-$")
|
||||
end
|
||||
if id and gen and top_level and uuid and path then
|
||||
subvolume[id] = {id = id, gen = gen, top_level = top_level, otime = (otime and otime or "") .." ".. (otime2 and otime2 or ""), uuid = uuid, path = '/'.. path}
|
||||
if not snapshot then
|
||||
-- use btrfs subv show to get snapshots
|
||||
local show_cmd = d.command.btrfs .. " subvolume show "..m_point.."/"..path
|
||||
local __, line_show, section_snap
|
||||
for __, line_show in ipairs(luci.util.execl(show_cmd)) do
|
||||
if not section_snap then
|
||||
local create_time = line_show:match("^%s+Creation time:%s+(.+)")
|
||||
if create_time then
|
||||
subvolume[id]["otime"] = create_time
|
||||
elseif line_show:match("^%s+(Snapshot%(s%):)") then
|
||||
section_snap = "true"
|
||||
end
|
||||
else
|
||||
local snapshot = line_show:match("^%s+(.+)")
|
||||
subvolume[id]["snapshots"] = subvolume[id]["snapshots"] and (subvolume[id]["snapshots"] .. ", /".. snapshot) or ("/"..snapshot)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if subvolume[default_subvolume_id] then
|
||||
subvolume[default_subvolume_id].default_subvolume = 1
|
||||
end
|
||||
-- if m_point == "/tmp/.btrfs_tmp" then
|
||||
-- luci.util.exec("umount " .. m_point)
|
||||
-- end
|
||||
return subvolume
|
||||
end
|
||||
|
||||
return d
|
||||
|
||||
@ -61,7 +61,7 @@ msgstr "Sektor początkowy"
|
||||
msgid "End Sector"
|
||||
msgstr "Sektor końcowy"
|
||||
|
||||
msgid "Useage"
|
||||
msgid "Usage"
|
||||
msgstr "Użycie"
|
||||
|
||||
msgid "Model"
|
||||
@ -126,3 +126,66 @@ msgstr "Informacja o partycjach"
|
||||
|
||||
msgid "Default 2048 sector alignment, support +size{b,k,m,g,t} in End Sector"
|
||||
msgstr "Sektory wyrównywane są do wielokrotności 2048, sektor końcowy można podać jako rozmiar w postaci +size{b,k,m,g,t}"
|
||||
|
||||
msgid "Multiple Devices Btrfs Creation"
|
||||
msgstr "Kreator urządzeń Btrfs"
|
||||
|
||||
msgid "Label"
|
||||
msgstr "Etykieta"
|
||||
|
||||
msgid "Btrfs Label"
|
||||
msgstr "Etykieta Btrfs"
|
||||
|
||||
msgid "Btrfs Raid Level"
|
||||
msgstr "Poziom Raid Btrfs"
|
||||
|
||||
msgid "Btrfs Member"
|
||||
msgstr "Członek Btrfs"
|
||||
|
||||
msgid "Create Btrfs"
|
||||
msgstr "Utwórz Btrfs"
|
||||
|
||||
msgid "New Snapshot"
|
||||
msgstr "Nowy obraz"
|
||||
|
||||
msgid "SubVolumes"
|
||||
msgstr "SubVolumes"
|
||||
|
||||
msgid "Top Level"
|
||||
msgstr "Top Level"
|
||||
|
||||
msgid "Manage Btrfs"
|
||||
msgstr "Zarządzaj Btrfs"
|
||||
|
||||
msgid "Otime"
|
||||
msgstr "Otime"
|
||||
|
||||
msgid "Snapshots"
|
||||
msgstr "Obrazy"
|
||||
|
||||
msgid "Set Default"
|
||||
msgstr "Ustaw domyślnie"
|
||||
|
||||
msgid "Source Path"
|
||||
msgstr "Ścieżka źródłowa"
|
||||
|
||||
msgid "Readonly"
|
||||
msgstr "Tylko do odczytu"
|
||||
|
||||
msgid "Delete"
|
||||
msgstr "Usuń"
|
||||
|
||||
msgid "Create"
|
||||
msgstr "Utwórz"
|
||||
|
||||
msgid "Destination Path (optional)"
|
||||
msgstr "Ścieżka docelowa (opcjonalnie)"
|
||||
|
||||
msgid "Metadata"
|
||||
msgstr "Metadata"
|
||||
|
||||
msgid "Data"
|
||||
msgstr "Data"
|
||||
|
||||
msgid "Btrfs Info"
|
||||
msgstr "Informacja o Btrfs"
|
||||
|
||||
@ -2,7 +2,7 @@ msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=UTF-8\n"
|
||||
|
||||
msgid "DiskMan"
|
||||
msgstr "DiskMan磁盘管理"
|
||||
msgstr "DiskMan 磁盘管理"
|
||||
|
||||
msgid "Manage Disks over LuCI."
|
||||
msgstr "通过LuCI管理磁盘"
|
||||
@ -61,8 +61,14 @@ msgstr "起始扇区"
|
||||
msgid "End Sector"
|
||||
msgstr "中止扇区"
|
||||
|
||||
msgid "Useage"
|
||||
msgstr "使用情况"
|
||||
msgid "Usage"
|
||||
msgstr "用量"
|
||||
|
||||
msgid "Used"
|
||||
msgstr "已使用"
|
||||
|
||||
msgid "Free Space"
|
||||
msgstr "空闲空间"
|
||||
|
||||
msgid "Model"
|
||||
msgstr "主机型号"
|
||||
@ -126,3 +132,96 @@ msgstr "分区信息"
|
||||
|
||||
msgid "Default 2048 sector alignment, support +size{b,k,m,g,t} in End Sector"
|
||||
msgstr "默认2048扇区对齐,【中止扇区】支持 +容量{b,k,m,g,t} 格式,例:+500m +10g +1t"
|
||||
|
||||
msgid "Multiple Devices Btrfs Creation"
|
||||
msgstr "Btrfs 阵列创建"
|
||||
|
||||
msgid "Label"
|
||||
msgstr "卷标"
|
||||
|
||||
msgid "Btrfs Label"
|
||||
msgstr "Btrfs 卷标"
|
||||
|
||||
msgid "Btrfs Raid Level"
|
||||
msgstr "Btrfs Raid 级别"
|
||||
|
||||
msgid "Btrfs Member"
|
||||
msgstr "Btrfs 整列成员"
|
||||
|
||||
msgid "Create Btrfs"
|
||||
msgstr "创建 Btrfs"
|
||||
|
||||
msgid "New Snapshot"
|
||||
msgstr "新建快照"
|
||||
|
||||
msgid "SubVolumes"
|
||||
msgstr "子卷"
|
||||
|
||||
msgid "Top Level"
|
||||
msgstr "父ID"
|
||||
|
||||
msgid "Manage Btrfs"
|
||||
msgstr "Btrfs 管理"
|
||||
|
||||
msgid "Otime"
|
||||
msgstr "创建时间"
|
||||
|
||||
msgid "Snapshots"
|
||||
msgstr "快照"
|
||||
|
||||
msgid "Set Default"
|
||||
msgstr "默认子卷"
|
||||
|
||||
msgid "Source Path"
|
||||
msgstr "源目录"
|
||||
|
||||
msgid "Readonly"
|
||||
msgstr "只读"
|
||||
|
||||
msgid "Delete"
|
||||
msgstr "删除"
|
||||
|
||||
msgid "Create"
|
||||
msgstr "创建"
|
||||
|
||||
msgid "Destination Path (optional)"
|
||||
msgstr "目标目录(可选)"
|
||||
|
||||
msgid "Metadata"
|
||||
msgstr "元数据"
|
||||
|
||||
msgid "Data"
|
||||
msgstr "数据"
|
||||
|
||||
msgid "Btrfs Info"
|
||||
msgstr "Btrfs 信息"
|
||||
|
||||
msgid "The source path for create the snapshot"
|
||||
msgstr "创建快照的源数据目录"
|
||||
|
||||
msgid "The path where you want to store the snapshot"
|
||||
msgstr "存放快照数据目录"
|
||||
|
||||
msgid "Please input Source Path of snapshot, Source Path must start with '/'"
|
||||
msgstr "请输入快照源路径,源路径必须以'/'开头"
|
||||
|
||||
msgid "Please input Subvolume Path, Subvolume must start with '/'"
|
||||
msgstr "请输入子卷路径,子卷路径必须以'/'开头"
|
||||
|
||||
msgid "is in use! please unmount it first!"
|
||||
msgstr "正在被使用!请先卸载!"
|
||||
|
||||
msgid "Partition NOT found!"
|
||||
msgstr "分区未找到!"
|
||||
|
||||
msgid "Filesystem NOT support!"
|
||||
msgstr "文件系统不支持!"
|
||||
|
||||
msgid "Invalid Start Sector!"
|
||||
msgstr "无效的起始扇区!"
|
||||
|
||||
msgid "Invalid End Sector"
|
||||
msgstr "无效的终止扇区!"
|
||||
|
||||
msgid "Partition not exists!"
|
||||
msgstr "分区不存在!"
|
||||
@ -1,7 +1,7 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-dockerman
|
||||
PKG_VERSION:=v0.1.9
|
||||
PKG_VERSION:=v0.2
|
||||
PKG_RELEASE:=beta
|
||||
PKG_MAINTAINER:=lisaac <https://github.com/lisaac/luci-app-dockerman>
|
||||
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
|
||||
|
||||
@ -1,11 +1,6 @@
|
||||
--[[
|
||||
LuCI - Lua Configuration Interface
|
||||
Copyright 2019 lisaac <lisaac.cn@gmail.com>
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
$Id$
|
||||
Copyright 2019 lisaac <https://github.com/lisaac/luci-app-dockerman>
|
||||
]]--
|
||||
require "luci.util"
|
||||
local docker = require "luci.model.docker"
|
||||
|
||||
@ -1,11 +1,6 @@
|
||||
--[[
|
||||
LuCI - Lua Configuration Interface
|
||||
Copyright 2019 lisaac <lisaac.cn@gmail.com>
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
$Id$
|
||||
Copyright 2019 lisaac <https://github.com/lisaac/luci-app-dockerman>
|
||||
]]--
|
||||
|
||||
require "luci.util"
|
||||
|
||||
@ -1,11 +1,6 @@
|
||||
--[[
|
||||
LuCI - Lua Configuration Interface
|
||||
Copyright 2019 lisaac <lisaac.cn@gmail.com>
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
$Id$
|
||||
Copyright 2019 lisaac <https://github.com/lisaac/luci-app-dockerman>
|
||||
]]--
|
||||
|
||||
require "luci.util"
|
||||
@ -94,7 +89,7 @@ container_selecter.default = 0
|
||||
|
||||
container_id = c_table:option(DummyValue, "_id", translate("ID"))
|
||||
container_id.width="10%"
|
||||
container_name = c_table:option(DummyValue, "_name", translate("Name"))
|
||||
container_name = c_table:option(DummyValue, "_name", translate("Container Name"))
|
||||
container_name.width="20%"
|
||||
container_name.template="docker/cbi/dummyvalue"
|
||||
container_name.href = function (self, section)
|
||||
|
||||
@ -1,11 +1,6 @@
|
||||
--[[
|
||||
LuCI - Lua Configuration Interface
|
||||
Copyright 2019 lisaac <lisaac.cn@gmail.com>
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
$Id$
|
||||
Copyright 2019 lisaac <https://github.com/lisaac/luci-app-dockerman>
|
||||
]]--
|
||||
|
||||
require "luci.util"
|
||||
|
||||
@ -1,11 +1,6 @@
|
||||
--[[
|
||||
LuCI - Lua Configuration Interface
|
||||
Copyright 2019 lisaac <lisaac.cn@gmail.com>
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
$Id$
|
||||
Copyright 2019 lisaac <https://github.com/lisaac/luci-app-dockerman>
|
||||
]]--
|
||||
|
||||
require "luci.util"
|
||||
@ -62,7 +57,7 @@ network_selecter.render = function(self, section, scope)
|
||||
Flag.render(self, section, scope)
|
||||
end
|
||||
|
||||
network_name = network_table:option(DummyValue, "_name", translate("Name"))
|
||||
network_name = network_table:option(DummyValue, "_name", translate("Network Name"))
|
||||
network_driver = network_table:option(DummyValue, "_driver", translate("Driver"))
|
||||
network_interface = network_table:option(DummyValue, "_interface", translate("Parent Interface"))
|
||||
network_subnet = network_table:option(DummyValue, "_subnet", translate("Subnet"))
|
||||
|
||||
@ -1,11 +1,6 @@
|
||||
--[[
|
||||
LuCI - Lua Configuration Interface
|
||||
Copyright 2019 lisaac <lisaac.cn@gmail.com>
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
$Id$
|
||||
Copyright 2019 lisaac <https://github.com/lisaac/luci-app-dockerman>
|
||||
]]--
|
||||
|
||||
require "luci.util"
|
||||
@ -55,6 +50,8 @@ if cmd_line and cmd_line:match("^docker.+") then
|
||||
key = "port"
|
||||
elseif key == "e" then
|
||||
key = "env"
|
||||
elseif key == "dns" then
|
||||
key = "dns"
|
||||
elseif key == "net" then
|
||||
key = "network"
|
||||
elseif key == "cpu-shares" then
|
||||
@ -69,7 +66,7 @@ if cmd_line and cmd_line:match("^docker.+") then
|
||||
end
|
||||
--key=value
|
||||
if val then
|
||||
if key == "mount" or key == "link" or key == "env" or key == "port" or key == "device" or key == "tmpfs" then
|
||||
if key == "mount" or key == "link" or key == "env" or key == "dns" or key == "port" or key == "device" or key == "tmpfs" then
|
||||
if not default_config[key] then default_config[key] = {} end
|
||||
table.insert( default_config[key], val )
|
||||
else
|
||||
@ -81,7 +78,7 @@ if cmd_line and cmd_line:match("^docker.+") then
|
||||
cursor = 1
|
||||
-- value
|
||||
elseif key and type(key) == "string" and cursor == 1 then
|
||||
if key == "mount" or key == "link" or key == "env" or key == "port" or key == "device" or key == "tmpfs" then
|
||||
if key == "mount" or key == "link" or key == "env" or key == "dns" or key == "port" or key == "device" or key == "tmpfs" then
|
||||
if not default_config[key] then default_config[key] = {} end
|
||||
table.insert( default_config[key], w )
|
||||
else
|
||||
@ -119,6 +116,7 @@ elseif cmd_line and cmd_line:match("^duplicate/[^/]+$") then
|
||||
default_config.ip = default_config.network and default_config.network ~= "bridge" and default_config.network ~= "host" and default_config.network ~= "null" and create_body.NetworkingConfig.EndpointsConfig[default_config.network].IPAMConfig and create_body.NetworkingConfig.EndpointsConfig[default_config.network].IPAMConfig.IPv4Address or nil
|
||||
default_config.link = create_body.HostConfig.Links
|
||||
default_config.env = create_body.Env
|
||||
default_config.dns = create_body.HostConfig.Dns
|
||||
default_config.mount = create_body.HostConfig.Binds
|
||||
|
||||
if create_body.HostConfig.PortBindings and type(create_body.HostConfig.PortBindings) == "table" then
|
||||
@ -183,12 +181,6 @@ d.disabled = 0
|
||||
d.enabled = 1
|
||||
d.default = default_config.tty and 1 or 0
|
||||
|
||||
d = s:option(Flag, "_force_pull", translate("Always pull image first"))
|
||||
d.rmempty = true
|
||||
d.disabled = 0
|
||||
d.enabled = 1
|
||||
d.default = 0
|
||||
|
||||
d = s:option(Value, "image", translate("Docker Image"))
|
||||
d.rmempty = true
|
||||
d.default = default_config.image or nil
|
||||
@ -198,6 +190,12 @@ for _, v in ipairs (images) do
|
||||
end
|
||||
end
|
||||
|
||||
d = s:option(Flag, "_force_pull", translate("Always pull image first"))
|
||||
d.rmempty = true
|
||||
d.disabled = 0
|
||||
d.enabled = 1
|
||||
d.default = 0
|
||||
|
||||
d = s:option(Flag, "privileged", translate("Privileged"))
|
||||
d.rmempty = true
|
||||
d.disabled = 0
|
||||
@ -222,11 +220,6 @@ d_ip.datatype="ip4addr"
|
||||
d_ip:depends("network", "nil")
|
||||
d_ip.default = default_config.ip or nil
|
||||
|
||||
d = s:option(Value, "user", translate("User"))
|
||||
d.placeholder = "1000:1000"
|
||||
d.rmempty = true
|
||||
d.default = default_config.user or nil
|
||||
|
||||
d = s:option(DynamicList, "link", translate("Links with other containers"))
|
||||
d.template = "docker/cbi/xdynlist"
|
||||
d.placeholder = "container_name:alias"
|
||||
@ -234,19 +227,30 @@ d.rmempty = true
|
||||
d:depends("network", "bridge")
|
||||
d.default = default_config.link or nil
|
||||
|
||||
d = s:option(DynamicList, "env", translate("Environmental Variable"))
|
||||
d = s:option(DynamicList, "dns", translate("Set custom DNS servers"))
|
||||
d.template = "docker/cbi/xdynlist"
|
||||
d.placeholder = "8.8.8.8"
|
||||
d.rmempty = true
|
||||
d.default = default_config.dns or nil
|
||||
|
||||
d = s:option(Value, "user", translate("User(-u)"), translate("The user that commands are run as inside the container.(format: name|uid[:group|gid])"))
|
||||
d.placeholder = "1000:1000"
|
||||
d.rmempty = true
|
||||
d.default = default_config.user or nil
|
||||
|
||||
d = s:option(DynamicList, "env", translate("Environmental Variable(-e)"), translate("Set environment variables to inside the container"))
|
||||
d.template = "docker/cbi/xdynlist"
|
||||
d.placeholder = "TZ=Asia/Shanghai"
|
||||
d.rmempty = true
|
||||
d.default = default_config.env or nil
|
||||
|
||||
d = s:option(DynamicList, "mount", translate("Bind Mount"))
|
||||
d = s:option(DynamicList, "mount", translate("Bind Mount(-v)"), translate("Bind mount a volume"))
|
||||
d.template = "docker/cbi/xdynlist"
|
||||
d.placeholder = "/media:/media:slave"
|
||||
d.rmempty = true
|
||||
d.default = default_config.mount or nil
|
||||
|
||||
local d_ports = s:option(DynamicList, "port", translate("Exposed Ports"))
|
||||
local d_ports = s:option(DynamicList, "port", translate("Exposed Ports(-p)"), translate("Publish container's port(s) to the host"))
|
||||
d_ports.template = "docker/cbi/xdynlist"
|
||||
d_ports.placeholder = "2200:22/tcp"
|
||||
d_ports.rmempty = true
|
||||
@ -263,6 +267,20 @@ d.disabled = 0
|
||||
d.enabled = 1
|
||||
d.default = default_config.advance or 0
|
||||
|
||||
d = s:option(DynamicList, "device", translate("Device(--device)"), translate("Add host device to the container"))
|
||||
d.template = "docker/cbi/xdynlist"
|
||||
d.placeholder = "/dev/sda:/dev/xvdc:rwm"
|
||||
d.rmempty = true
|
||||
d:depends("advance", 1)
|
||||
d.default = default_config.device or nil
|
||||
|
||||
d = s:option(DynamicList, "tmpfs", translate("Tmpfs(--tmpfs)"), translate("Mount tmpfs directory"))
|
||||
d.template = "docker/cbi/xdynlist"
|
||||
d.placeholder = "/run:rw,noexec,nosuid,size=65536k"
|
||||
d.rmempty = true
|
||||
d:depends("advance", 1)
|
||||
d.default = default_config.tmpfs or nil
|
||||
|
||||
d = s:option(Value, "cpus", translate("CPUs"), translate("Number of CPUs. Number is a fractional number. 0.000 means no limit."))
|
||||
d.placeholder = "1.5"
|
||||
d.rmempty = true
|
||||
@ -270,7 +288,7 @@ d:depends("advance", 1)
|
||||
d.datatype="ufloat"
|
||||
d.default = default_config.cpus or nil
|
||||
|
||||
d = s:option(Value, "cpushares", translate("CPU Shares Weight"), translate("CPU shares (relative weight, if 0 is set, the system will ignore the value and use the default of 1024."))
|
||||
d = s:option(Value, "cpushares", translate("CPU Shares Weight"), translate("CPU shares relative weight, if 0 is set, the system will ignore the value and use the default of 1024."))
|
||||
d.placeholder = "1024"
|
||||
d.rmempty = true
|
||||
d:depends("advance", 1)
|
||||
@ -290,19 +308,6 @@ d:depends("advance", 1)
|
||||
d.datatype="uinteger"
|
||||
d.default = default_config.blkioweight or nil
|
||||
|
||||
d = s:option(DynamicList, "device", translate("Device"))
|
||||
d.template = "docker/cbi/xdynlist"
|
||||
d.placeholder = "/dev/sda:/dev/xvdc:rwm"
|
||||
d.rmempty = true
|
||||
d:depends("advance", 1)
|
||||
d.default = default_config.device or nil
|
||||
|
||||
d = s:option(DynamicList, "tmpfs", translate("Tmpfs"), translate("Mount tmpfs filesystems"))
|
||||
d.template = "docker/cbi/xdynlist"
|
||||
d.placeholder = "/run:rw,noexec,nosuid,size=65536k"
|
||||
d.rmempty = true
|
||||
d:depends("advance", 1)
|
||||
d.default = default_config.tmpfs or nil
|
||||
|
||||
for _, v in ipairs (networks) do
|
||||
if v.Name then
|
||||
@ -325,7 +330,7 @@ end
|
||||
m.handle = function(self, state, data)
|
||||
if state ~= FORM_VALID then return end
|
||||
local tmp
|
||||
local name = data.name
|
||||
local name = data.name or ("luci_" .. os.date("%Y%m%d%H%M%S"))
|
||||
local tty = type(data.tty) == "number" and (data.tty == 1 and true or false) or default_config.tty or false
|
||||
local interactive = type(data.interactive) == "number" and (data.interactive == 1 and true or false) or default_config.interactive or false
|
||||
local image = data.image
|
||||
@ -336,6 +341,7 @@ m.handle = function(self, state, data)
|
||||
local privileged = type(data.privileged) == "number" and (data.privileged == 1 and true or false) or default_config.privileged or false
|
||||
local restart = data.restart
|
||||
local env = data.env
|
||||
local dns = data.dns
|
||||
local network = data.network
|
||||
local ip = (network ~= "bridge" and network ~= "host" and network ~= "none") and data.ip or nil
|
||||
local mount = data.mount
|
||||
@ -366,12 +372,13 @@ m.handle = function(self, state, data)
|
||||
if h and c then
|
||||
t['PathOnHost'] = h
|
||||
t['PathInContainer'] = c
|
||||
t['CgroupPermissions'] = p or nil
|
||||
t['CgroupPermissions'] = p or "rwm"
|
||||
else
|
||||
local _,_, h, c = v:find("(.-):(.+)")
|
||||
if h and c then
|
||||
t['PathOnHost'] = h
|
||||
t['PathInContainer'] = c
|
||||
t['CgroupPermissions'] = "rwm"
|
||||
end
|
||||
end
|
||||
if next(t) ~= nil then
|
||||
@ -425,8 +432,8 @@ m.handle = function(self, state, data)
|
||||
create_body.Image = image
|
||||
create_body.ExposedPorts = (next(exposedports) ~= nil) and exposedports or nil
|
||||
create_body.HostConfig = create_body.HostConfig or {}
|
||||
create_body.HostConfig.Dns = dns
|
||||
create_body.HostConfig.Binds = (#mount ~= 0) and mount or nil
|
||||
create_body.HostConfig.NetworkMode = network
|
||||
create_body.HostConfig.RestartPolicy = { Name = restart, MaximumRetryCount = 0 }
|
||||
create_body.HostConfig.Privileged = privileged and true or false
|
||||
create_body.HostConfig.PortBindings = (next(portbindings) ~= nil) and portbindings or nil
|
||||
@ -434,8 +441,14 @@ m.handle = function(self, state, data)
|
||||
create_body.HostConfig.CpuShares = tonumber(cpushares)
|
||||
create_body.HostConfig.NanoCPUs = tonumber(cpus) * 10 ^ 9
|
||||
create_body.HostConfig.BlkioWeight = tonumber(blkioweight)
|
||||
if create_body.HostConfig.NetworkMode ~= network then
|
||||
-- network mode changed, need to clear duplicate config
|
||||
create_body.NetworkingConfig = nil
|
||||
end
|
||||
create_body.HostConfig.NetworkMode = network
|
||||
if ip then
|
||||
if create_body.NetworkingConfig and create_body.NetworkingConfig.EndpointsConfig and type(create_body.NetworkingConfig.EndpointsConfig) == "table" then
|
||||
-- ip + duplicate config
|
||||
for k, v in pairs (create_body.NetworkingConfig.EndpointsConfig) do
|
||||
if k == network and v.IPAMConfig and v.IPAMConfig.IPv4Address then
|
||||
v.IPAMConfig.IPv4Address = ip
|
||||
@ -445,18 +458,16 @@ m.handle = function(self, state, data)
|
||||
break
|
||||
end
|
||||
else
|
||||
-- ip + no duplicate config
|
||||
create_body.NetworkingConfig = { EndpointsConfig = { [network] = { IPAMConfig = { IPv4Address = ip } } } }
|
||||
end
|
||||
elseif not create_body.NetworkingConfig then
|
||||
-- no ip + no duplicate config
|
||||
create_body.NetworkingConfig = nil
|
||||
end
|
||||
|
||||
if next(tmpfs) ~= nil then
|
||||
create_body["HostConfig"]["Tmpfs"] = tmpfs
|
||||
end
|
||||
if next(device) ~= nil then
|
||||
create_body["HostConfig"]["Devices"] = device
|
||||
end
|
||||
create_body["HostConfig"]["Tmpfs"] = (next(tmpfs) ~= nil) and tmpfs or nil
|
||||
create_body["HostConfig"]["Devices"] = (next(device) ~= nil) and device or nil
|
||||
|
||||
if network == "bridge" and next(link) ~= nil then
|
||||
create_body["HostConfig"]["Links"] = link
|
||||
|
||||
@ -1,11 +1,6 @@
|
||||
--[[
|
||||
LuCI - Lua Configuration Interface
|
||||
Copyright 2019 lisaac <lisaac.cn@gmail.com>
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
$Id$
|
||||
Copyright 2019 lisaac <https://github.com/lisaac/luci-app-dockerman>
|
||||
]]--
|
||||
|
||||
require "luci.util"
|
||||
|
||||
@ -1,11 +1,6 @@
|
||||
--[[
|
||||
LuCI - Lua Configuration Interface
|
||||
Copyright 2019 lisaac <lisaac.cn@gmail.com>
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
$Id$
|
||||
Copyright 2019 lisaac <https://github.com/lisaac/luci-app-dockerman>
|
||||
]]--
|
||||
|
||||
require "luci.util"
|
||||
@ -87,7 +82,7 @@ s = m:section(NamedSection, "local", "section", translate("Setting"))
|
||||
|
||||
socket_path = s:option(Value, "socket_path", translate("Socket Path"))
|
||||
status_path = s:option(Value, "status_path", translate("Action Status Tempfile Path"), translate("Where you want to save the docker status file"))
|
||||
debug = s:option(Flag, "debug", translate("Enable Debug"), translate("For debug, It shows all docker API actions of luci-app-docker in Debug Tempfile Path"))
|
||||
debug = s:option(Flag, "debug", translate("Enable Debug"), translate("For debug, It shows all docker API actions of luci-app-dockerman in Debug Tempfile Path"))
|
||||
debug.enabled="true"
|
||||
debug.disabled="false"
|
||||
debug_path = s:option(Value, "debug_path", translate("Debug Tempfile Path"), translate("Where you want to save the debug tempfile"))
|
||||
|
||||
@ -1,11 +1,6 @@
|
||||
--[[
|
||||
LuCI - Lua Configuration Interface
|
||||
Copyright 2019 lisaac <lisaac.cn@gmail.com>
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
$Id$
|
||||
Copyright 2019 lisaac <https://github.com/lisaac/luci-app-dockerman>
|
||||
]]--
|
||||
|
||||
require "luci.util"
|
||||
|
||||
@ -1,11 +1,6 @@
|
||||
--[[
|
||||
LuCI - Lua Configuration Interface
|
||||
Copyright 2019 lisaac <lisaac.cn@gmail.com>
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
$Id$
|
||||
Copyright 2019 lisaac <https://github.com/lisaac/luci-app-dockerman>
|
||||
]]--
|
||||
|
||||
require "luci.util"
|
||||
@ -231,4 +226,4 @@ _docker.clear_status=function(self)
|
||||
nixio.fs.remove(self.options.status_path)
|
||||
end
|
||||
|
||||
return _docker
|
||||
return _docker
|
||||
@ -1,17 +1,3 @@
|
||||
<%#
|
||||
LuCI - Lua Configuration Interface
|
||||
Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
Copyright 2008 Jo-Philipp Wich <xm@leipzig.freifunk.net>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
$Id$
|
||||
|
||||
-%>
|
||||
<% if self.title == translate("Docker Events") then %>
|
||||
<%+header%>
|
||||
<% end %>
|
||||
|
||||
@ -81,6 +81,10 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
|
||||
|
||||
.img-con {
|
||||
margin: 1rem;
|
||||
min-width: 4rem;
|
||||
max-width: 4rem;
|
||||
min-height: 4rem;
|
||||
max-height: 4rem;
|
||||
}
|
||||
|
||||
.block h4 {
|
||||
@ -123,7 +127,7 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
|
||||
<div class="block pure-g">
|
||||
<div class="pure-u-2-5">
|
||||
<div class="img-con">
|
||||
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg role="img" viewBox="0 0 24 24">
|
||||
<title>Docker icon</title>
|
||||
<path
|
||||
d="M4.82 17.275c-.684 0-1.304-.56-1.304-1.24s.56-1.243 1.305-1.243c.748 0 1.31.56 1.31 1.242s-.622 1.24-1.305 1.24zm16.012-6.763c-.135-.992-.75-1.8-1.56-2.42l-.315-.25-.254.31c-.494.56-.69 1.553-.63 2.295.06.562.24 1.12.554 1.554-.254.13-.568.25-.81.377-.57.187-1.124.25-1.68.25H.097l-.06.37c-.12 1.182.06 2.42.562 3.54l.244.435v.06c1.5 2.483 4.17 3.6 7.078 3.6 5.594 0 10.182-2.42 12.357-7.633 1.425.062 2.864-.31 3.54-1.676l.18-.31-.3-.187c-.81-.494-1.92-.56-2.85-.31l-.018.002zm-8.008-.992h-2.428v2.42h2.43V9.518l-.002.003zm0-3.043h-2.428v2.42h2.43V6.48l-.002-.003zm0-3.104h-2.428v2.42h2.43v-2.42h-.002zm2.97 6.147H13.38v2.42h2.42V9.518l-.007.003zm-8.998 0H4.383v2.42h2.422V9.518l-.01.003zm3.03 0h-2.4v2.42H9.84V9.518l-.015.003zm-6.03 0H1.4v2.42h2.428V9.518l-.03.003zm6.03-3.043h-2.4v2.42H9.84V6.48l-.015-.003zm-3.045 0H4.387v2.42H6.8V6.48l-.016-.003z" />
|
||||
@ -145,7 +149,7 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
|
||||
<div class="block pure-g">
|
||||
<div class="pure-u-2-5">
|
||||
<div class="img-con">
|
||||
<svg id="icon-hub" viewBox="0 0 42 38" stroke-width="2" fill-rule="nonzero" width="100%" height="100%">
|
||||
<svg id="icon-hub" viewBox="0 -4 42 50" stroke-width="2" fill-rule="nonzero" width="100%" height="100%">
|
||||
<path
|
||||
d="M37.176371,36.2324812 C37.1920117,36.8041095 36.7372743,37.270685 36.1684891,37.270685 L3.74335204,37.2703476 C3.17827583,37.2703476 2.72400056,36.8091818 2.72400056,36.2397767 L2.72400056,19.6131383 C1.4312007,18.4881431 0.662551336,16.8884326 0.662551336,15.1618249 L0.664207893,14.69503 C0.63774183,14.4532127 0.650524255,14.2942438 0.711604827,14.1238231 L5.10793246,1.20935468 C5.24853286,0.797020623 5.63848594,0.511627907 6.06681069,0.511627907 L34.0728364,0.511627907 C34.5091607,0.511627907 34.889927,0.793578201 35.0316653,1.20921034 L39.4428567,14.1234095 C39.4871296,14.273204 39.5020782,14.4249444 39.4884726,14.5493649 L39.4884726,15.1505835 C39.4884726,16.9959517 38.6190601,18.6883031 37.1764746,19.7563084 L37.176371,36.2324812 Z M35.1376208,35.209311 L35.1376208,20.7057152 C34.7023924,20.8097593 34.271333,20.8633641 33.8336069,20.8633641 C32.0046019,20.8633641 30.3013756,19.9547008 29.2437221,18.4771538 C28.1860473,19.954695 26.4828515,20.8633641 24.6538444,20.8633641 C22.824803,20.8633641 21.1216155,19.9547157 20.0639591,18.4771544 C19.0062842,19.9546953 17.3030887,20.8633641 15.4740818,20.8633641 C13.6450404,20.8633641 11.9418529,19.9547157 10.8841965,18.4771544 C9.82652161,19.9546953 8.12332608,20.8633641 6.29431919,20.8633641 C5.76735555,20.8633641 5.24095778,20.7883418 4.73973398,20.644674 L4.73973398,35.209311 L35.1376208,35.209311 Z M30.2720226,15.6557626 C30.5154632,17.4501192 32.0503909,18.8018554 33.845083,18.8018554 C35.7286794,18.8018554 37.285413,17.3395134 37.4474599,15.4751932 L30.2280765,15.4751932 C30.2470638,15.532987 30.2617919,15.5932958 30.2720226,15.6557626 Z M21.0484306,15.4751932 C21.0674179,15.532987 21.0821459,15.5932958 21.0923767,15.6557626 C21.3358173,17.4501192 22.8707449,18.8018554 24.665437,18.8018554 C26.4601001,18.8018554 27.9950169,17.4501481 28.2378191,15.6611556 C28.2451225,15.5981318 28.2590045,15.5358056 28.2787375,15.4751932 L21.0484306,15.4751932 Z M11.9238102,15.6557626 C12.1672508,17.4501192 13.7021785,18.8018554 15.4968705,18.8018554 C17.2915336,18.8018554 18.8264505,17.4501481 19.0692526,15.6611556 C19.0765561,15.5981318 19.0904381,15.5358056 19.110171,15.4751932 L11.8798641,15.4751932 C11.8988514,15.532987 11.9135795,15.5932958 11.9238102,15.6557626 Z M6.31682805,18.8018317 C8.11149114,18.8018317 9.64640798,17.4501244 9.88921012,15.6611319 C9.89651357,15.5981081 9.91039559,15.5357819 9.93012856,15.4751696 L2.70318796,15.4751696 C2.86612006,17.3346852 4.42809696,18.8018317 6.31682805,18.8018317 Z M3.09670082,13.4139924 L37.04257,13.4139924 L33.3489482,2.57204736 L6.80119239,2.57204736 L3.09670082,13.4139924 Z"
|
||||
id="Fill-1"></path>
|
||||
@ -169,12 +173,7 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
|
||||
<div class="block pure-g">
|
||||
<div class="pure-u-2-5">
|
||||
<div class="img-con">
|
||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
x="0px" y="0px" width="48.723px" height="48.723px" viewBox="0 0 48.723 48.723"
|
||||
style="enable-background:new 0 0 48.723 48.723;" xml:space="preserve">
|
||||
<g>
|
||||
<g id="_x33_8_89_">
|
||||
<g>
|
||||
<svg version="1.1" x="0px" y="0px" width="100%" height="100%" viewBox="0 0 48.723 48.723" xml:space="preserve">
|
||||
<path d="M7.452,24.152h3.435v5.701h0.633c0.001,0,0.001,0,0.002,0h0.636v-5.701h3.51v-1.059h17.124v1.104h3.178v5.656h0.619
|
||||
c0,0,0,0,0.002,0h0.619v-5.656h3.736v-0.856c0-0.012,0.006-0.021,0.006-0.032c0-0.072,0-0.143,0-0.215h5.721v-1.316h-5.721
|
||||
c0-0.054,0-0.108,0-0.164c0-0.011-0.006-0.021-0.006-0.032v-0.832h-8.154v1.028h-7.911v-2.652h-0.689c-0.001,0-0.001,0-0.002,0
|
||||
@ -188,10 +187,6 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
|
||||
<path
|
||||
d="M29.491,30.994v12.684h6.895v2.611h5.205v-2.611h7.133V30.994H29.491z M46.774,41.729H31.44v-8.783h15.334V41.729z" />
|
||||
<rect x="33.584" y="46.338" width="10.809" height="0.537" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
@ -210,8 +205,7 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
|
||||
<div class="block pure-g">
|
||||
<div class="pure-u-2-5">
|
||||
<div class="img-con">
|
||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
x="0px" y="0px" viewBox="0 0 55 55" style="enable-background:new 0 0 55 55;" xml:space="preserve">
|
||||
<svg x="0px" y="0px" viewBox="0 0 55 55" style="enable-background:new 0 0 55 55;" xml:space="preserve">
|
||||
<path
|
||||
d="M52.354,8.51C51.196,4.22,42.577,0,27.5,0C12.423,0,3.803,4.22,2.646,8.51C2.562,8.657,2.5,8.818,2.5,9v0.5V21v0.5V22v11
|
||||
v0.5V34v12c0,0.162,0.043,0.315,0.117,0.451C3.798,51.346,14.364,55,27.5,55c13.106,0,23.655-3.639,24.875-8.516
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
function resolv_container(op) {
|
||||
let s = document.getElementById(op + '-status');
|
||||
if (!s) return;
|
||||
let cmd_line = prompt("Plese input <docker create/run> command line:", "");
|
||||
let cmd_line = prompt("<%:Plese input <docker create/run> command line:%>", "");
|
||||
if (cmd_line == null || cmd_line == "") {
|
||||
s.innerHTML = "<font color='red'>Canceled</font>";
|
||||
return;
|
||||
@ -12,12 +12,9 @@
|
||||
s.innerHTML = "<font color='red'>Command line Error</font>";
|
||||
return;
|
||||
}
|
||||
let re = /\/admin\/docker\/newcontainer\//
|
||||
let p = window.location.href
|
||||
let path = p.split(re)
|
||||
window.location.href = path[0] + "/admin/docker/newcontainer/" + encodeURI(cmd_line)
|
||||
window.location.href = "/cgi-bin/luci/admin/docker/newcontainer/" + encodeURI(cmd_line)
|
||||
}
|
||||
</script>
|
||||
<input type="button" class="cbi-button cbi-button-apply" value="Command line" onclick="resolv_container('<%=self.option%>')" />
|
||||
<input type="button" class="cbi-button cbi-button-apply" value="<%:Command line%>" onclick="resolv_container('<%=self.option%>')" />
|
||||
<span id="<%=self.option%>-status"></span>
|
||||
<%+cbi/valuefooter%>
|
||||
@ -58,8 +58,8 @@ msgstr "重启策略"
|
||||
msgid "Update"
|
||||
msgstr "更新"
|
||||
|
||||
msgid "Device"
|
||||
msgstr "设备"
|
||||
msgid "Device(--device)"
|
||||
msgstr "设备(--device)"
|
||||
|
||||
msgid "Mount/Volume"
|
||||
msgstr "挂载/存储卷"
|
||||
@ -103,26 +103,20 @@ msgstr "CPU数量,数字是小数,0.000表示没有限制。"
|
||||
msgid "CPU Shares Weight"
|
||||
msgstr "CPU份额权重"
|
||||
|
||||
msgid ""
|
||||
"CPU shares relative weight, if 0 is set, the system will ignore the value and use the default of 1024."
|
||||
msgstr ""
|
||||
"CPU份额相对权重,如果设置为0,则系统将忽略该值,并使用默认值1024。"
|
||||
msgid "CPU shares relative weight, if 0 is set, the system will ignore the value and use the default of 1024."
|
||||
msgstr "CPU份额相对权重,如果设置为0,则系统将忽略该值,并使用默认值1024。"
|
||||
|
||||
msgid "Memory"
|
||||
msgstr "内存"
|
||||
|
||||
msgid ""
|
||||
"Memory limit (format: <number>[<unit>]). Number is a positive integer. Unit can be one of b, k, m, or g. Minimum is 4M."
|
||||
msgstr ""
|
||||
"内存限制 (格式: <容量>[<单位>]). 数字是一个正整数。单位可以是b,k,m或g之一。最小为4M。"
|
||||
msgid "Memory limit (format: <number>[<unit>]). Number is a positive integer. Unit can be one of b, k, m, or g. Minimum is 4M."
|
||||
msgstr "内存限制 (格式: <容量>[<单位>]). 数字是一个正整数。单位可以是b,k,m或g之一。最小为4M。"
|
||||
|
||||
msgid "Block IO Weight"
|
||||
msgstr "IO 权重"
|
||||
|
||||
msgid ""
|
||||
"Block IO weight (relative weight) accepts a weight value between 10 and 1000."
|
||||
msgstr ""
|
||||
"IO 权重(相对权重)接受10到1000之间的权重值。"
|
||||
msgid "Block IO weight (relative weight) accepts a weight value between 10 and 1000."
|
||||
msgstr "IO 权重 (相对权重) 接受10到1000之间的权重值。"
|
||||
|
||||
msgid "Container Logs"
|
||||
msgstr "容器日志"
|
||||
@ -151,8 +145,8 @@ msgstr "解析命令行"
|
||||
msgid "Docker Image"
|
||||
msgstr "Docker 镜像"
|
||||
|
||||
msgid "User"
|
||||
msgstr "用户"
|
||||
msgid "User(-u)"
|
||||
msgstr "用户(-u)"
|
||||
|
||||
msgid "New Container"
|
||||
msgstr "新容器"
|
||||
@ -167,22 +161,22 @@ msgid "Always pull image first"
|
||||
msgstr "始终先拉取镜像"
|
||||
|
||||
msgid "Privileged"
|
||||
msgstr "特权模式(Privileged)"
|
||||
msgstr "特权模式(--privileged)"
|
||||
|
||||
msgid "IPv4 Address"
|
||||
msgstr "IPv4 地址"
|
||||
|
||||
msgid "Links with other containers"
|
||||
msgstr "与其他容器的链接(Links)"
|
||||
msgstr "与其他容器的链接(--link)"
|
||||
|
||||
msgid "Environmental Variable"
|
||||
msgstr "环境变量(Env)"
|
||||
msgid "Environmental Variable(-e)"
|
||||
msgstr "环境变量(-e)"
|
||||
|
||||
msgid "Bind Mount"
|
||||
msgid "Bind Mount(-v)"
|
||||
msgstr "挂载(-v)"
|
||||
|
||||
msgid "Exposed Ports"
|
||||
msgstr "暴露端口"
|
||||
msgid "Exposed Ports(-p)"
|
||||
msgstr "暴露端口(-p)"
|
||||
|
||||
msgid "Run command"
|
||||
msgstr "运行命令"
|
||||
@ -190,8 +184,8 @@ msgstr "运行命令"
|
||||
msgid "Advance"
|
||||
msgstr "高级"
|
||||
|
||||
msgid "Mount tmpfs filesystems"
|
||||
msgstr "挂载tmpfs文件系统"
|
||||
msgid "Mount tmpfs directory"
|
||||
msgstr "挂载tmpfs到容器内部目录"
|
||||
|
||||
msgid "New Network"
|
||||
msgstr "新网络"
|
||||
@ -259,8 +253,8 @@ msgstr "保存docker status文件的位置"
|
||||
msgid "Enable Debug"
|
||||
msgstr "启用调试"
|
||||
|
||||
msgid "For debug, It shows all docker API actions of luci-app-docker in Debug Tempfile Path"
|
||||
msgstr "用于调试,它在调试临时文件路径中显示luci-app-docker的所有docker API操作"
|
||||
msgid "For debug, It shows all docker API actions of luci-app-dockermab in Debug Tempfile Path"
|
||||
msgstr "用于调试,它在调试临时文件路径中显示 luci-app-dockermab 的所有docker API操作"
|
||||
|
||||
msgid "Debug Tempfile Path"
|
||||
msgstr "调试临时文件路径"
|
||||
@ -296,4 +290,37 @@ msgid "Pull Image"
|
||||
msgstr "拉取镜像"
|
||||
|
||||
msgid "Pull"
|
||||
msgstr "拉取"
|
||||
msgstr "拉取"
|
||||
|
||||
msgid "Command line"
|
||||
msgstr "输入命令行"
|
||||
|
||||
msgid "Plese input <docker create/run> command line:"
|
||||
msgstr "请输入 docker run/create ... 命令行:"
|
||||
|
||||
msgid "Network Name"
|
||||
msgstr "网络名"
|
||||
|
||||
msgid "Set custom DNS servers"
|
||||
msgstr "自定义 DNS 服务器"
|
||||
|
||||
msgid "The user that commands are run as inside the container.(format: name|uid[:group|gid])"
|
||||
msgstr "容器内部执行命令的用户(组), 格式: UID:GID"
|
||||
|
||||
msgid "Set environment variables to inside the container"
|
||||
msgstr "容器内部环境变量"
|
||||
|
||||
msgid "Bind mount a volume"
|
||||
msgstr "绑定挂载"
|
||||
|
||||
msgid "Publish container's port(s) to the host"
|
||||
msgstr "将容器的端口发布到宿主"
|
||||
|
||||
msgid "Add host device to the container"
|
||||
msgstr "添加宿主设备到容器内部"
|
||||
|
||||
msgid "Device"
|
||||
msgstr "设备"
|
||||
|
||||
msgid "Finish Time"
|
||||
msgstr "结束时间"
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-openclash
|
||||
PKG_VERSION:=0.36.2
|
||||
PKG_VERSION:=0.36.4
|
||||
PKG_RELEASE:=beta
|
||||
PKG_MAINTAINER:=vernesong <https://github.com/vernesong/OpenClash>
|
||||
|
||||
@ -14,7 +14,7 @@ define Package/$(PKG_NAME)
|
||||
SUBMENU:=3. Applications
|
||||
TITLE:=LuCI support for clash
|
||||
PKGARCH:=all
|
||||
DEPENDS:=+iptables +dnsmasq-full +coreutils +coreutils-nohup +bash +wget
|
||||
DEPENDS:=+iptables +dnsmasq-full +coreutils +coreutils-nohup +bash +curl +jsonfilter +ca-certificates
|
||||
MAINTAINER:=vernesong
|
||||
endef
|
||||
|
||||
@ -48,6 +48,7 @@ if [ -f "/etc/config/openclash" ]; then
|
||||
cp "/etc/config/openclash_custom_rules.list" "/tmp/openclash_custom_rules.list.bak" >/dev/null 2>&1
|
||||
cp "/etc/config/openclash_custom_hosts.list" "/tmp/openclash_custom_hosts.list.bak" >/dev/null 2>&1
|
||||
cp "/etc/config/openclash_custom_fake_black.conf" "/tmp/openclash_custom_fake_black.conf.bak" >/dev/null 2>&1
|
||||
cp "/etc/openclash/history" "/tmp/openclash_history.bak" >/dev/null 2>&1
|
||||
fi
|
||||
if [ -f "/etc/openclash/custom/openclash_custom_rules.list" ]; then
|
||||
cp "/etc/openclash/custom/openclash_custom_rules.list" "/tmp/openclash_custom_rules.list.bak" >/dev/null 2>&1
|
||||
@ -76,6 +77,7 @@ if [ -f "/tmp/openclash.bak" ]; then
|
||||
mv "/tmp/openclash_custom_rules.list.bak" "/etc/openclash/custom/openclash_custom_rules.list" >/dev/null 2>&1
|
||||
mv "/tmp/openclash_custom_hosts.list.bak" "/etc/openclash/custom/openclash_custom_hosts.list" >/dev/null 2>&1
|
||||
mv "/tmp/openclash_custom_fake_black.conf.bak" "/etc/openclash/custom/openclash_custom_fake_black.conf" >/dev/null 2>&1
|
||||
mv "/tmp/openclash_history.bak" "/etc/openclash/history" >/dev/null 2>&1
|
||||
fi
|
||||
if [ -f "/tmp/config.yaml" ]; then
|
||||
mv "/tmp/config.yaml" "/etc/openclash/config/config.yaml" >/dev/null 2>&1
|
||||
@ -113,6 +115,7 @@ fi
|
||||
mv "/etc/openclash/config" "/tmp/openclash_config" >/dev/null 2>&1
|
||||
mv "/etc/openclash/proxy_provider" "/tmp/openclash_proxy_provider" >/dev/null 2>&1
|
||||
mv "/etc/openclash/game_rules" "/tmp/openclash_game_rules" >/dev/null 2>&1
|
||||
mv "/etc/openclash/history" "/tmp/openclash_history.bak" >/dev/null 2>&1
|
||||
cp "/etc/config/openclash" "/tmp/openclash.bak" >/dev/null 2>&1
|
||||
cp "/etc/config/openclash_custom_rules.list" "/tmp/openclash_custom_rules.list.bak" >/dev/null 2>&1
|
||||
cp "/etc/config/openclash_custom_hosts.list" "/tmp/openclash_custom_hosts.list.bak" >/dev/null 2>&1
|
||||
@ -129,6 +132,7 @@ if [ -f "/etc/openclash/clash" ]; then
|
||||
rm -rf /etc/openclash/backup >/dev/null 2>&1
|
||||
rm -rf /etc/openclash/proxy_provider >/dev/null 2>&1
|
||||
rm -rf /etc/openclash/game_rules >/dev/null 2>&1
|
||||
rm -rf /etc/openclash/history >/dev/null 2>&1
|
||||
else
|
||||
rm -rf /etc/openclash >/dev/null 2>&1
|
||||
fi
|
||||
|
||||
@ -165,7 +165,7 @@ yml_check()
|
||||
awk '/^proxy-provider:/,/^Proxy Group:/{print}' "$3" | sed '/^Proxy Group:/d' >/tmp/backprovider.yaml 2>/dev/null
|
||||
sed -i '/^Proxy Group:/i\proxy-provider-tag' "$3" 2>/dev/null
|
||||
sed -i '/^proxy-provider:/,/proxy-provider-tag/d' "$3" 2>/dev/null
|
||||
sed -i '/^Rule:/i\proxy-provider:' "$3" 2>/dev/null
|
||||
sed -i '/^Proxy:/i\proxy-provider:' "$3" 2>/dev/null
|
||||
sed -i '/^proxy-provider:/d' /tmp/backprovider.yaml 2>/dev/null
|
||||
sed -i '/proxy-provider:/r/tmp/backprovider.yaml' "$3" 2>/dev/null
|
||||
rm -rf /tmp/backprovider.yaml 2>/dev/null
|
||||
@ -506,11 +506,16 @@ yml_game_rule_get()
|
||||
local section="$1"
|
||||
config_get_bool "enabled" "$section" "enabled" "1"
|
||||
config_get "group" "$section" "group" ""
|
||||
config_get "config" "$section" "config" ""
|
||||
|
||||
if [ "$enabled" = "0" ]; then
|
||||
return
|
||||
fi
|
||||
|
||||
if [ ! -z "$config" ] && [ "$config" != "$CONFIG_NAME" ] && [ "$config" != "all" ]; then
|
||||
return
|
||||
fi
|
||||
|
||||
if [ -z "$group" ]; then
|
||||
return
|
||||
fi
|
||||
@ -523,18 +528,21 @@ yml_game_group_get()
|
||||
local section="$1"
|
||||
config_get_bool "enabled" "$section" "enabled" "1"
|
||||
config_get "group" "$section" "group" ""
|
||||
config_get "config" "$section" "config" ""
|
||||
|
||||
if [ "$enabled" = "0" ]; then
|
||||
return
|
||||
fi
|
||||
|
||||
if [ ! -z "$config" ] && [ "$config" != "$CONFIG_NAME" ] && [ "$config" != "all" ]; then
|
||||
return
|
||||
fi
|
||||
|
||||
if [ -z "$group" ]; then
|
||||
return
|
||||
fi
|
||||
|
||||
if [ -z "$(grep "^ \{0,\}- name: $group" "$GROUP_FILE")" ]; then
|
||||
/usr/share/openclash/yml_groups_set.sh "$group"
|
||||
fi
|
||||
/usr/share/openclash/yml_groups_set.sh "$group"
|
||||
}
|
||||
|
||||
yml_game_custom()
|
||||
@ -611,6 +619,7 @@ else
|
||||
cp $BACKUP_FILE $CONFIG_FILE
|
||||
fi
|
||||
fi
|
||||
CONFIG_NAME=$(echo $CONFIG_FILE |awk -F '/' '{print $5}' 2>/dev/null)
|
||||
|
||||
enable=$(uci get openclash.config.enable 2>/dev/null)
|
||||
LOGTIME=$(date "+%Y-%m-%d %H:%M:%S")
|
||||
@ -628,6 +637,10 @@ if [ "$enable" -eq 1 ] && [ -f "$CONFIG_FILE" ]; then
|
||||
en_mode_tun="1"
|
||||
en_mode="fake-ip"
|
||||
fi
|
||||
if [ "$en_mode" = "redir-host-tun" ]; then
|
||||
en_mode_tun="1"
|
||||
en_mode="redir-host"
|
||||
fi
|
||||
if [ "$en_mode" = "redir-host-vpn" ]; then
|
||||
en_mode_tun="2"
|
||||
en_mode="redir-host"
|
||||
@ -647,6 +660,7 @@ if [ "$enable" -eq 1 ] && [ -f "$CONFIG_FILE" ]; then
|
||||
socks_port=$(uci get openclash.config.socks_port 2>/dev/null)
|
||||
enable_redirect_dns=$(uci get openclash.config.enable_redirect_dns 2>/dev/null)
|
||||
lan_ip=$(uci get network.lan.ipaddr 2>/dev/null |awk -F '/' '{print $1}' 2>/dev/null)
|
||||
wan_ip4=$(ubus call network.interface.wan status 2>/dev/null | grep \"address\" | grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' 2>/dev/null)
|
||||
lan_ip6=$(uci get network.lan.ip6addr 2>/dev/null)
|
||||
direct_dns=$(uci get openclash.config.direct_dns 2>/dev/null)
|
||||
disable_masq_cache=$(uci get openclash.config.disable_masq_cache 2>/dev/null)
|
||||
@ -688,13 +702,14 @@ if [ "$enable" -eq 1 ] && [ -f "$CONFIG_FILE" ]; then
|
||||
nohup $CLASH -d "$CLASH_CONFIG" -f "$CONFIG_FILE" >> $LOG_FILE 2>&1 &
|
||||
|
||||
#检测proxy_provider配置文件状态
|
||||
echo "第六步: 等待主程序下载代理集..." >$START_LOG
|
||||
yml_proxy_provider_check "$PROXY_PROVIDER_FILE"
|
||||
rm -rf /tmp/yaml_* 2>/dev/null
|
||||
|
||||
echo "第六步: 设置控制面板..." >$START_LOG
|
||||
echo "第七步: 设置控制面板..." >$START_LOG
|
||||
ln -s /usr/share/openclash/yacd /www/openclash 2>/dev/null
|
||||
|
||||
echo "第七步: 设置 OpenClash 防火墙规则..." >$START_LOG
|
||||
echo "第八步: 设置 OpenClash 防火墙规则..." >$START_LOG
|
||||
if [ -z "$(uci get firewall.openclash 2>/dev/null)" ] || [ -z "$(uci get ucitrack.@openclash[-1].init 2>/dev/null)" ]; then
|
||||
uci delete ucitrack.@openclash[-1] >/dev/null 2>&1
|
||||
uci add ucitrack openclash >/dev/null 2>&1
|
||||
@ -717,13 +732,8 @@ mkdir -p /var/etc
|
||||
cat > "/var/etc/openclash.include" <<-EOF
|
||||
/etc/init.d/openclash restart
|
||||
EOF
|
||||
if [ "$en_mode_tun" != "2" ]; then
|
||||
if [ -z "$en_mode_tun" ]; then
|
||||
iptables -t nat -N openclash
|
||||
|
||||
if [ "$en_mode_tun" = "1" ]; then
|
||||
iptables -t nat -A openclash -d 198.18.0.0/16 -j RETURN
|
||||
fi
|
||||
|
||||
iptables -t nat -A openclash -d 0.0.0.0/8 -j RETURN
|
||||
iptables -t nat -A openclash -d 10.0.0.0/8 -j RETURN
|
||||
iptables -t nat -A openclash -d 127.0.0.0/8 -j RETURN
|
||||
@ -732,29 +742,21 @@ EOF
|
||||
iptables -t nat -A openclash -d 192.168.0.0/16 -j RETURN
|
||||
iptables -t nat -A openclash -d 224.0.0.0/4 -j RETURN
|
||||
iptables -t nat -A openclash -d 240.0.0.0/4 -j RETURN
|
||||
if [ ! -z "$wan_ip4" ]; then
|
||||
iptables -t nat -A openclash -d "$wan_ip4" -j RETURN
|
||||
fi
|
||||
iptables -t nat -A openclash -p tcp -j REDIRECT --to-ports "$proxy_port"
|
||||
|
||||
if [ -z "$(iptables -nvL zone_lan_prerouting -t nat)" ]; then
|
||||
iptables -t nat -A PREROUTING -p tcp -j openclash
|
||||
else
|
||||
iptables -t nat -A zone_lan_prerouting -p tcp -j openclash
|
||||
fi
|
||||
iptables -t nat -A PREROUTING -p tcp -j openclash
|
||||
iptables -t nat -A OUTPUT -p tcp -d 198.18.0.0/16 -j REDIRECT --to-ports "$proxy_port"
|
||||
|
||||
if [ "$en_mode_tun" != 1 ]; then
|
||||
iptables -t nat -A OUTPUT -p tcp -d 198.18.0.0/16 -j REDIRECT --to-ports "$proxy_port"
|
||||
fi
|
||||
|
||||
if [ "$ipv6_enable" -eq 1 ]; then
|
||||
ip6tables -t nat -N openclash
|
||||
ip6tables -t nat -A openclash -p tcp -j REDIRECT --to-ports "$proxy_port"
|
||||
if [ -z "$(ip6tables -nvL zone_lan_prerouting -t nat)" ]; then
|
||||
ip6tables -t nat -A PREROUTING -p tcp -j openclash
|
||||
else
|
||||
ip6tables -t nat -A zone_lan_prerouting -p tcp -j openclash
|
||||
fi
|
||||
ip6tables -t nat -A PREROUTING -p tcp -j openclash
|
||||
fi
|
||||
else
|
||||
#TUN2模式
|
||||
#TUN模式
|
||||
ipset create localnetwork hash:net
|
||||
ipset add localnetwork 127.0.0.0/8
|
||||
ipset add localnetwork 10.0.0.0/8
|
||||
@ -763,10 +765,15 @@ EOF
|
||||
ipset add localnetwork 224.0.0.0/4
|
||||
ipset add localnetwork 240.0.0.0/4
|
||||
ipset add localnetwork 172.16.0.0/12
|
||||
ipset add localnetwork "$wan_ip4"
|
||||
#启动TUN
|
||||
if [ "$en_mode_tun" = "2" ]; then
|
||||
ip tuntap add user root mode tun clash0
|
||||
ip link set clash0 up
|
||||
ip route replace default dev clash0 table "$PROXY_ROUTE_TABLE"
|
||||
elif [ "$en_mode_tun" = "1" ]; then
|
||||
ip route replace default dev utun table "$PROXY_ROUTE_TABLE"
|
||||
fi
|
||||
ip rule add fwmark "$PROXY_FWMARK" table "$PROXY_ROUTE_TABLE"
|
||||
#设置防火墙
|
||||
iptables -t mangle -N openclash
|
||||
@ -776,10 +783,12 @@ EOF
|
||||
iptables -t mangle -I OUTPUT -j openclash
|
||||
iptables -t mangle -I PREROUTING -m set ! --match-set localnetwork dst -j MARK --set-mark "$PROXY_FWMARK"
|
||||
#ipv6
|
||||
ip6tables -t mangle -I PREROUTING -j MARK --set-mark "$PROXY_FWMARK"
|
||||
if [ "$ipv6_enable" -eq 1 ]; then
|
||||
ip6tables -t mangle -I PREROUTING -j MARK --set-mark "$PROXY_FWMARK"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "第八步: 重启 Dnsmasq 程序..." >$START_LOG
|
||||
echo "第九步: 重启 Dnsmasq 程序..." >$START_LOG
|
||||
if [ "$(iptables -t nat -nL PREROUTING --line-number |grep dpt:53 |wc -l)" -gt 2 ]; then
|
||||
echo "发现53端口被劫持,如连接异常请将OpenClash设置为劫持53端口程序的上游DNS服务器!" >$START_LOG
|
||||
echo "${LOGTIME} Warring: OpenClash May Can Not Take Over DNS, Please Use OpenClash for Upstream DNS Resolve Server" >> $LOG_FILE
|
||||
@ -789,15 +798,17 @@ EOF
|
||||
fake_block "$en_mode" "$direct_dns"
|
||||
/etc/init.d/dnsmasq restart >/dev/null 2>&1
|
||||
if pidof clash >/dev/null; then
|
||||
echo "第九步: 添加 OpenClash 计划任务,启动进程守护程序..." >$START_LOG
|
||||
echo "第十步: 添加 OpenClash 计划任务,启动进程守护程序..." >$START_LOG
|
||||
add_cron
|
||||
if [ -z "$(uci get dhcp.lan.dhcpv6 2>/dev/null)" ]; then
|
||||
echo "OpenClash 启动成功,请等待服务器上线!" >$START_LOG
|
||||
echo "${LOGTIME} OpenClash Start Successful" >> $LOG_FILE
|
||||
/usr/share/openclash/openclash_history_set.sh
|
||||
sleep 5
|
||||
else
|
||||
echo "OpenClash 启动成功,检测到您启用了IPV6的DHCP服务,可能会造成连接异常!" >$START_LOG
|
||||
echo "${LOGTIME} OpenClash Start Successful, Please Note That Network May Abnormal With IPV6's DHCP Server" >> $LOG_FILE
|
||||
/usr/share/openclash/openclash_history_set.sh
|
||||
sleep 10
|
||||
fi
|
||||
echo "" >$START_LOG
|
||||
@ -817,12 +828,14 @@ EOF
|
||||
if [ -z "$(uci get dhcp.lan.dhcpv6 2>/dev/null)" ]; then
|
||||
echo "OpenClash 使用备份规则启动成功,请更新、检查变动的规则后重试!" >$START_LOG
|
||||
echo "${LOGTIME} OpenClash Start Successful With Backup Rules Config, Please Check Or Update Other Rules And Retry" >> $LOG_FILE
|
||||
/usr/share/openclash/openclash_history_set.sh
|
||||
sleep 10
|
||||
else
|
||||
echo "OpenClash 使用备份规则启动成功,请更新、检查变动的规则后重试!" >$START_LOG
|
||||
echo "${LOGTIME} OpenClash Start Successful With Backup Rules Config, Please Check Or Update Other Rules And Retry" >> $LOG_FILE
|
||||
sleep 10
|
||||
echo "OpenClash 启动成功,检测到您启用了IPV6的DHCP服务,可能会造成连接异常!" >$START_LOG
|
||||
/usr/share/openclash/openclash_history_set.sh
|
||||
sleep 5
|
||||
echo "检测到您启用了IPV6的DHCP服务,可能会造成连接异常!" >$START_LOG
|
||||
echo "${LOGTIME} OpenClash Start Successful, Please Note That Network May Abnormal With IPV6's DHCP Server" >> $LOG_FILE
|
||||
sleep 10
|
||||
fi
|
||||
@ -871,12 +884,14 @@ fi
|
||||
stop()
|
||||
{
|
||||
echo "OpenClash 开始关闭..." >$START_LOG
|
||||
echo "第一步: 删除 OpenClash 防火墙规则..." >$START_LOG
|
||||
echo "第一步: 备份当前节点状态..." >$START_LOG
|
||||
/usr/share/openclash/openclash_history_get.sh
|
||||
|
||||
echo "第二步: 删除 OpenClash 防火墙规则..." >$START_LOG
|
||||
rm -rf /var/etc/openclash.include 2>/dev/null
|
||||
#ipv4
|
||||
iptables -t nat -F openclash >/dev/null 2>&1
|
||||
iptables -t nat -D PREROUTING -p tcp -j openclash >/dev/null 2>&1
|
||||
iptables -t nat -D zone_lan_prerouting -p tcp -j openclash >/dev/null 2>&1
|
||||
iptables -t nat -X openclash >/dev/null 2>&1
|
||||
|
||||
out_lines=$(iptables -nvL OUTPUT -t nat |sed 1,2d |sed -n '/198.18.0.0\/16/=' 2>/dev/null |sort -rn)
|
||||
@ -887,13 +902,13 @@ stop()
|
||||
#ipv6
|
||||
ip6tables -t nat -F openclash >/dev/null 2>&1
|
||||
ip6tables -t nat -D PREROUTING -p tcp -j openclash >/dev/null 2>&1
|
||||
ip6tables -t nat -D zone_lan_prerouting -p tcp -j openclash >/dev/null 2>&1
|
||||
ip6tables -t nat -X openclash >/dev/null 2>&1
|
||||
|
||||
#TUN
|
||||
ip link set dev clash0 down >/dev/null 2>&1
|
||||
ip tuntap del clash0 mode tun >/dev/null 2>&1
|
||||
ip route del default dev clash0 table "$PROXY_ROUTE_TABLE" >/dev/null 2>&1
|
||||
ip route del default dev utun table "$PROXY_ROUTE_TABLE" >/dev/null 2>&1
|
||||
ip rule del fwmark "$PROXY_FWMARK" table "$PROXY_ROUTE_TABLE" >/dev/null 2>&1
|
||||
|
||||
iptables -t mangle -D OUTPUT -j openclash >/dev/null 2>&1
|
||||
@ -903,23 +918,23 @@ stop()
|
||||
iptables -t mangle -X openclash >/dev/null 2>&1
|
||||
ipset destroy localnetwork >/dev/null 2>&1
|
||||
|
||||
echo "第二步: 关闭 OpenClash 守护程序..." >$START_LOG
|
||||
echo "第三步: 关闭 OpenClash 守护程序..." >$START_LOG
|
||||
watchdog_pids=$(ps |grep openclash_watchdog.sh |grep -v grep |awk '{print $1}' 2>/dev/null)
|
||||
for watchdog_pid in $watchdog_pids; do
|
||||
kill -9 "$watchdog_pid" >/dev/null 2>&1
|
||||
done
|
||||
|
||||
echo "第三步: 关闭 Clash 主程序..." >$START_LOG
|
||||
echo "第四步: 关闭 Clash 主程序..." >$START_LOG
|
||||
kill -9 "$(pidof clash|sed 's/$//g')" 2>/dev/null
|
||||
|
||||
echo "第四步: 重启 Dnsmasq 程序..." >$START_LOG
|
||||
echo "第五步: 重启 Dnsmasq 程序..." >$START_LOG
|
||||
dns_port=$(uci get openclash.config.dns_port 2>/dev/null)
|
||||
redirect_dns=$(uci get openclash.config.redirect_dns 2>/dev/null)
|
||||
masq_cache=$(uci get openclash.config.masq_cache 2>/dev/null)
|
||||
revert_dns "$redirect_dns" "$masq_cache" "$dns_port"
|
||||
/etc/init.d/dnsmasq restart >/dev/null 2>&1
|
||||
|
||||
echo "第五步:删除 OpenClash 残留文件..." >$START_LOG
|
||||
echo "第六步:删除 OpenClash 残留文件..." >$START_LOG
|
||||
enable=$(uci get openclash.config.enable 2>/dev/null)
|
||||
if [ "$enable" -eq 0 ]; then
|
||||
rm -rf $LOG_FILE 2>/dev/null
|
||||
@ -943,4 +958,4 @@ restart()
|
||||
{
|
||||
stop
|
||||
start
|
||||
}
|
||||
}
|
||||
@ -460,8 +460,7 @@ Rule:
|
||||
|
||||
# (HKMTMedia)
|
||||
# > 愛奇藝台灣站
|
||||
- DOMAIN-SUFFIX,iqiyi.com,HKMTMedia
|
||||
- DOMAIN-SUFFIX,71.am,HKMTMedia
|
||||
- DOMAIN,cache.video.iqiyi.com,HKMTMedia
|
||||
# > bilibili
|
||||
- DOMAIN-SUFFIX,bilibili.com,HKMTMedia
|
||||
- DOMAIN,upos-hz-mirrorakam.akamaized.net,HKMTMedia
|
||||
|
||||
Binary file not shown.
File diff suppressed because one or more lines are too long
@ -11,7 +11,14 @@ local uci = require "luci.model.uci".cursor()
|
||||
|
||||
m = Map(openclash, translate("Game Rules and Groups"))
|
||||
m.pageaction = false
|
||||
m.description=translate("注意事项:<br/>游戏模式为测试功能,不保证可用性。使用的内核由comzyh修改<br/>项目地址:https://github.com/comzyh/clash <br/>使用步骤:<br/>1、在《服务器与策略组管理》页面创建您准备使用的游戏策略组和游戏节点(节点添加时必须选择要加入的策略组),策略组类型建议:FallBack,游戏节点必须支持UDP<br/>2、在此页面的游戏规则列表下载您要使用的游戏规则<br/>3、在此页面上方设置您已下载的游戏规则的对应策略组并保存设置<br/>4、替换内核,下载地址:(https://github.com/vernesong/OpenClash/releases/tag/TUN)<br/>5、在《全局设置》-《常规设置》-《运行模式》中选择游戏模式并启动")
|
||||
m.description=translate("注意事项:<br/>游戏代理为测试功能,不保证可用性。其中游戏模式使用的内核由comzyh修改 \
|
||||
<br/>项目地址:https://github.com/comzyh/clash <br/>使用步骤: \
|
||||
<br/>1、在《服务器与策略组管理》页面创建您准备使用的游戏策略组和游戏节点(节点添加时必须选择要加入的策略组),策略组类型建议:FallBack,游戏节点必须支持UDP \
|
||||
<br/>2、在此页面的游戏规则列表下载您要使用的游戏规则 \
|
||||
<br/>3、在此页面上方设置您已下载的游戏规则的对应策略组并保存设置 \
|
||||
<br/>4、替换内核一,下载地址:https://github.com/Dreamacro/clash/releases/tag/TUN \
|
||||
<br/>或替换内核二,下载地址:https://github.com/vernesong/OpenClash/releases/tag/TUN \
|
||||
<br/>5、在《全局设置》-《常规设置》-《运行模式》中选择TUN模式(内核一)或者游戏模式(内核二)并启动")
|
||||
|
||||
|
||||
function IsRuleFile(e)
|
||||
@ -20,7 +27,21 @@ local e=string.lower(string.sub(e,-6,-1))
|
||||
return e==".rules"
|
||||
end
|
||||
|
||||
SYS.call("awk -F ',' '{print $1}' /etc/openclash/game_rules.list > /tmp/rules_name 2>/dev/null")
|
||||
function IsYamlFile(e)
|
||||
e=e or""
|
||||
local e=string.lower(string.sub(e,-5,-1))
|
||||
return e == ".yaml"
|
||||
end
|
||||
|
||||
function IsYmlFile(e)
|
||||
e=e or""
|
||||
local e=string.lower(string.sub(e,-4,-1))
|
||||
return e == ".yml"
|
||||
end
|
||||
|
||||
if not NXFS.access("/tmp/rules_name") then
|
||||
SYS.call("awk -F ',' '{print $1}' /etc/openclash/game_rules.list > /tmp/rules_name 2>/dev/null")
|
||||
end
|
||||
file = io.open("/tmp/rules_name", "r");
|
||||
|
||||
-- [[ Edit Game Rule ]] --
|
||||
@ -39,6 +60,21 @@ o.cfgvalue = function(...)
|
||||
return Flag.cfgvalue(...) or "1"
|
||||
end
|
||||
|
||||
---- config
|
||||
o = s:option(ListValue, "config", translate("Config File"))
|
||||
o:value("all", translate("Use For All Config File"))
|
||||
local e,a={}
|
||||
for t,f in ipairs(fs.glob("/etc/openclash/config/*"))do
|
||||
a=fs.stat(f)
|
||||
if a then
|
||||
e[t]={}
|
||||
e[t].name=fs.basename(f)
|
||||
if IsYamlFile(e[t].name) or IsYmlFile(e[t].name) then
|
||||
o:value(e[t].name)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---- rule name
|
||||
o = s:option(DynamicList, "rule_name", translate("Game Rule's Name"))
|
||||
local e,a={}
|
||||
@ -69,9 +105,8 @@ o:value("REJECT")
|
||||
o.rmempty = true
|
||||
|
||||
---- Rules List
|
||||
local e={},a,o,t
|
||||
a=nixio.fs.access("/tmp/rules_name")
|
||||
if a then
|
||||
local e={},o,t
|
||||
if NXFS.access("/tmp/rules_name") then
|
||||
for o in file:lines() do
|
||||
table.insert(e,o)
|
||||
end
|
||||
|
||||
@ -48,6 +48,7 @@ o = s:taboption("settings", ListValue, "en_mode", font_red..bold_on..translate("
|
||||
o.description = translate("Select Mode For OpenClash Work, Network Error Try Flush DNS Cache")
|
||||
o:value("redir-host", translate("redir-host"))
|
||||
o:value("fake-ip", translate("fake-ip"))
|
||||
o:value("redir-host-tun", translate("redir-host(tun mode)"))
|
||||
o:value("fake-ip-tun", translate("fake-ip(tun mode)"))
|
||||
o:value("redir-host-vpn", translate("redir-host-vpn(game mode)"))
|
||||
o:value("fake-ip-vpn", translate("fake-ip-vpn(game mode)"))
|
||||
|
||||
@ -132,9 +132,6 @@
|
||||
<div style="display: flex;">
|
||||
<div style="width: 51%">
|
||||
<h3>IP 地址</h3>
|
||||
<p>
|
||||
<span class="ip-title">IP 登录设备:</span><span class="ip-result" id="ip-webrtc"></span> <span class="ip-geo" id="ip-webrtc-cz88"></span>
|
||||
</p>
|
||||
<p>
|
||||
<span class="ip-title">IPIP 国内:</span><span class="ip-result" id="ip-ipipnet"></span> <span class="ip-geo" id="ip-ipipnet-geo"></span>
|
||||
</p>
|
||||
@ -159,9 +156,6 @@
|
||||
<p>
|
||||
<span class="ip-state_title">GitHub:</span><span id="http-github"></span>
|
||||
</p>
|
||||
<p>
|
||||
<span class="ip-state_title">Facebook:</span><span id="http-facebook"></span>
|
||||
</p>
|
||||
<p>
|
||||
<span class="ip-state_title">YouTube:</span><span id="http-youtube"></span>
|
||||
</p>
|
||||
@ -180,7 +174,6 @@
|
||||
window.open(url2);
|
||||
}
|
||||
const $$ = document;
|
||||
$$.getElementById('ip-webrtc').innerHTML = '查询中...';
|
||||
$$.getElementById('ip-pcol').innerHTML = '查询中...';
|
||||
$$.getElementById('ip-ipify').innerHTML = '查询中...';
|
||||
$$.getElementById('ip-ipipnet').innerHTML = '查询中...';
|
||||
@ -220,23 +213,6 @@
|
||||
//$$.getElementById(elID).innerHTML = `${resp.data.country} ${resp.data.regionName} ${resp.data.city} ${resp.data.isp}`;
|
||||
})
|
||||
},
|
||||
getWebrtcIP: () => {
|
||||
window.RTCPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection;
|
||||
let pc = new RTCPeerConnection({ iceServers: [] }),
|
||||
noop = () => { };
|
||||
pc.createDataChannel('');
|
||||
pc.createOffer(pc.setLocalDescription.bind(pc), noop);
|
||||
pc.onicecandidate = (ice) => {
|
||||
if (!ice || !ice.candidate || !ice.candidate.candidate) {
|
||||
$$.getElementById('ip-webrtc').innerHTML = '没有查询到 IP';
|
||||
return;
|
||||
}
|
||||
let ip = /([0-9]{1,3}(\.[0-9]{1,3}){3}|[a-f0-9]{1,4}(:[a-f0-9]{1,4}){7})/.exec(ice.candidate.candidate)[1];
|
||||
$$.getElementById('ip-webrtc').innerHTML = ip;
|
||||
IP.parseIPIpip(ip, 'ip-webrtc-cz88');
|
||||
pc.onicecandidate = noop;
|
||||
};
|
||||
},
|
||||
getIpipnetIP: () => {
|
||||
IP.get(`https://myip.ipip.net/?z=${random}`, 'text')
|
||||
.then((resp) => {
|
||||
@ -267,7 +243,6 @@
|
||||
$$.getElementById('http-baidu').innerHTML = '<span class="ip-checking">检测中...</span>';
|
||||
$$.getElementById('http-163').innerHTML = '<span class="ip-checking">检测中...</span>';
|
||||
$$.getElementById('http-github').innerHTML = '<span class="ip-checking">检测中...</span>';
|
||||
$$.getElementById('http-facebook').innerHTML = '<span class="ip-checking">检测中...</span>';
|
||||
$$.getElementById('http-youtube').innerHTML = '<span class="ip-checking">检测中...</span>';
|
||||
let HTTP = {
|
||||
checker: (domain, cbElID) => {
|
||||
@ -293,7 +268,6 @@
|
||||
HTTP.checker('www.baidu.com', 'http-baidu');
|
||||
HTTP.checker('s1.music.126.net/style', 'http-163');
|
||||
HTTP.checker('github.com', 'http-github');
|
||||
HTTP.checker('www.facebook.com', 'http-facebook');
|
||||
HTTP.checker('www.youtube.com', 'http-youtube');
|
||||
}
|
||||
};
|
||||
@ -301,7 +275,6 @@
|
||||
HTTP.runcheck();
|
||||
IP.getIpipnetIP();
|
||||
IP.getIpifyIP();
|
||||
IP.getWebrtcIP();
|
||||
|
||||
function getPcolIP(data){
|
||||
let pcisp = data.addr.split(' ');
|
||||
@ -334,7 +307,6 @@
|
||||
HTTP.runcheck();
|
||||
IP.getIpipnetIP();
|
||||
IP.getIpifyIP();
|
||||
IP.getWebrtcIP();
|
||||
|
||||
function getPcolIP(data){
|
||||
let pcisp = data.addr.split(' ');
|
||||
|
||||
@ -55,6 +55,10 @@
|
||||
{
|
||||
mode.innerHTML = status.clash ? "<b><font color=green><%: Redir-Host(兼容)模式 %></font></b>" : '<b><font color=red><%:NOT RUNNING%></font></b>';
|
||||
}
|
||||
else if ( status.mode == "redir-host-tun\n" )
|
||||
{
|
||||
mode.innerHTML = status.clash ? "<b><font color=green><%: Redir-Host(TUN)模式 %></font></b>" : '<b><font color=red><%:NOT RUNNING%></font></b>';
|
||||
}
|
||||
else if ( status.mode == "fake-ip-tun\n" )
|
||||
{
|
||||
mode.innerHTML = status.clash ? "<b><font color=green><%: Fake-IP(TUN)模式 %></font></b>" : '<b><font color=red><%:NOT RUNNING%></font></b>';
|
||||
@ -86,6 +90,10 @@
|
||||
{
|
||||
mode.innerHTML = status.clash ? "<b><font color=green><%: Redir-Host(兼容)模式 %></font></b>" : '<b><font color=red><%:NOT RUNNING%></font></b>';
|
||||
}
|
||||
else if ( status.mode == "redir-host-tun\n" )
|
||||
{
|
||||
mode.innerHTML = status.clash ? "<b><font color=green><%: Redir-Host(TUN)模式 %></font></b>" : '<b><font color=red><%:NOT RUNNING%></font></b>';
|
||||
}
|
||||
else if ( status.mode == "fake-ip-tun\n" )
|
||||
{
|
||||
mode.innerHTML = status.clash ? "<b><font color=green><%: Fake-IP(TUN)模式 %></font></b>" : '<b><font color=red><%:NOT RUNNING%></font></b>';
|
||||
|
||||
@ -3,7 +3,7 @@ CKTIME=$(date "+%Y-%m-%d-%H")
|
||||
LAST_OPVER="/tmp/clash_last_version"
|
||||
version_url="https://raw.githubusercontent.com/vernesong/OpenClash/master/core_version"
|
||||
if [ "$CKTIME" != "$(grep "CheckTime" $LAST_OPVER 2>/dev/null |awk -F ':' '{print $2}')" ]; then
|
||||
wget-ssl --no-check-certificate --quiet --timeout=10 --tries=2 "$version_url" -O $LAST_OPVER
|
||||
curl -sL -m 10 --retry 2 "$version_url" -o $LAST_OPVER >/dev/null 2>&1
|
||||
if [ "$?" -eq "0" ] && [ "$(ls -l $LAST_OPVER 2>/dev/null |awk '{print int($5)}')" -gt 0 ]; then
|
||||
echo "CheckTime:$CKTIME" >>$LAST_OPVER
|
||||
else
|
||||
|
||||
@ -16,12 +16,12 @@ config_download()
|
||||
{
|
||||
if [ "$URL_TYPE" == "v2rayn" ]; then
|
||||
subscribe_url=`echo $subscribe_url |sed 's/{/%7B/g;s/}/%7D/g;s/:/%3A/g;s/\"/%22/g;s/,/%2C/g;s/?/%3F/g;s/=/%3D/g;s/&/%26/g;s/\//%2F/g'`
|
||||
wget-ssl --no-check-certificate --quiet --timeout=10 --tries=2 https://tgbot.lbyczf.com/v2rayn2clash?url="$subscribe_url" -O /tmp/config.yaml
|
||||
curl -sL -m 10 --retry 2 https://tgbot.lbyczf.com/v2rayn2clash?url="$subscribe_url" -o /tmp/config.yaml >/dev/null 2>&1
|
||||
elif [ "$URL_TYPE" == "surge" ]; then
|
||||
subscribe_url=`echo $subscribe_url |sed 's/{/%7B/g;s/}/%7D/g;s/:/%3A/g;s/\"/%22/g;s/,/%2C/g;s/?/%3F/g;s/=/%3D/g;s/&/%26/g;s/\//%2F/g'`
|
||||
wget-ssl --no-check-certificate --quiet --timeout=10 --tries=2 https://tgbot.lbyczf.com/surge2clash?url="$subscribe_url" -O /tmp/config.yaml
|
||||
curl -sL -m 10 --retry 2 https://tgbot.lbyczf.com/surge2clash?url="$subscribe_url" -o /tmp/config.yaml >/dev/null 2>&1
|
||||
else
|
||||
wget-ssl --no-check-certificate --quiet --timeout=10 --tries=2 "$subscribe_url" -O /tmp/config.yaml
|
||||
curl -sL -m 10 --retry 2 "$subscribe_url" -o /tmp/config.yaml >/dev/null 2>&1
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
@ -11,7 +11,7 @@ CPU_MODEL=$(uci get openclash.config.core_version 2>/dev/null)
|
||||
if [ "$(/etc/openclash/clash -v 2>/dev/null |awk -F ' ' '{print $2}')" != "$(sed -n 1p /tmp/clash_last_version 2>/dev/null)" ] || [ -z "$(/etc/openclash/clash -v 2>/dev/null |awk -F ' ' '{print $2}')" ] || [ ! -f /etc/openclash/clash ]; then
|
||||
if [ "$CPU_MODEL" != 0 ]; then
|
||||
echo "开始下载 OpenClash 内核..." >$START_LOG
|
||||
wget-ssl --no-check-certificate --quiet --timeout=10 --tries=5 https://github.com/vernesong/OpenClash/releases/download/Clash/clash-"$CPU_MODEL".tar.gz -O /tmp/clash.tar.gz
|
||||
curl -sL -m 10 --retry 2 https://github.com/vernesong/OpenClash/releases/download/Clash/clash-"$CPU_MODEL".tar.gz -o /tmp/clash.tar.gz >/dev/null 2>&1
|
||||
if [ "$?" -eq "0" ] && [ "$(ls -l /tmp/clash.tar.gz |awk '{print int($5/1024)}')" -ne 0 ]; then
|
||||
tar zxvf /tmp/clash.tar.gz -C /tmp >/dev/null 2>&1\
|
||||
&& rm -rf /tmp/clash.tar.gz >/dev/null 2>&1\
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
LOGTIME=$(date "+%Y-%m-%d %H:%M:%S")
|
||||
LOG_FILE="/tmp/openclash.log"
|
||||
echo "开始下载【$RULE_FILE_NAME】规则..." >$START_LOG
|
||||
wget-ssl --no-check-certificate --quiet --timeout=10 --tries=2 https://raw.githubusercontent.com/FQrabbit/SSTap-Rule/master/rules/"$DOWNLOAD_PATH" -O "$TMP_RULE_DIR"
|
||||
curl -sL -m 10 --retry 2 https://raw.githubusercontent.com/FQrabbit/SSTap-Rule/master/rules/"$DOWNLOAD_PATH" -o "$TMP_RULE_DIR" >/dev/null 2>&1
|
||||
if [ "$?" -eq "0" ] && [ "$(ls -l $TMP_RULE_DIR |awk '{print $5}')" -ne 0 ]; then
|
||||
echo "【$RULE_FILE_NAME】规则下载成功,检查规则版本是否更新..." >$START_LOG
|
||||
cmp -s $TMP_RULE_DIR $RULE_FILE_DIR
|
||||
|
||||
@ -0,0 +1,17 @@
|
||||
#!/bin/sh
|
||||
|
||||
CURL_GROUP_CACHE="/tmp/openclash_history_gorup.json"
|
||||
CURL_NOW_CACHE="/tmp/openclash_history_now.json"
|
||||
CURL_CACHE="/tmp/openclash_history_curl.json"
|
||||
HISTORY_PATH="/etc/openclash/history"
|
||||
SECRET=$(uci get openclash.config.dashboard_password 2>/dev/null)
|
||||
LAN_IP=$(uci get network.lan.ipaddr 2>/dev/null |awk -F '/' '{print $1}' 2>/dev/null)
|
||||
PORT=$(uci get openclash.config.cn_port 2>/dev/null)
|
||||
|
||||
curl -w %{http_code}"\n" -H "Authorization: Bearer ${SECRET}" -H "Content-Type:application/json" -X GET http://"$LAN_IP":"$PORT"/proxies > "$CURL_CACHE" 2>/dev/null
|
||||
if [ "$(sed -n '$p' "$CURL_CACHE")" -eq "200" ]; then
|
||||
cat "$CURL_CACHE" |jsonfilter -e '@["proxies"][@.type="Selector"]["name"]' > "$CURL_GROUP_CACHE" 2>/dev/null
|
||||
cat "$CURL_CACHE" |jsonfilter -e '@["proxies"][@.type="Selector"]["now"]' > "$CURL_NOW_CACHE" 2>/dev/null
|
||||
awk 'NR==FNR{a[i]=$0;i++}NR>FNR{print a[j]"#*#"$0;j++}' "$CURL_GROUP_CACHE" "$CURL_NOW_CACHE" > "$HISTORY_PATH" 2>/dev/null
|
||||
fi
|
||||
rm -rf /tmp/openclash_history_* 2>/dev/null
|
||||
@ -0,0 +1,15 @@
|
||||
#!/bin/sh
|
||||
|
||||
HISTORY_PATH="/etc/openclash/history"
|
||||
SECRET=$(uci get openclash.config.dashboard_password 2>/dev/null)
|
||||
LAN_IP=$(uci get network.lan.ipaddr 2>/dev/null |awk -F '/' '{print $1}' 2>/dev/null)
|
||||
PORT=$(uci get openclash.config.cn_port 2>/dev/null)
|
||||
|
||||
if [ ! -z "$(grep "#*#" "$HISTORY_PATH")" ]; then
|
||||
cat $HISTORY_PATH |while read line
|
||||
do
|
||||
GORUP_NAME=$(echo $line |awk -F '#*#' '{print $1}')
|
||||
NOW_NAME=$(echo $line |awk -F '#*#' '{print $3}')
|
||||
curl -H "Authorization: Bearer ${SECRET}" -H "Content-Type:application/json" -X PUT -d '{"name":"'"$NOW_NAME"'"}' http://"$LAN_IP":"$PORT"/proxies/"$GORUP_NAME" >/dev/null 2>&1
|
||||
done
|
||||
fi
|
||||
@ -3,7 +3,7 @@
|
||||
LOGTIME=$(date "+%Y-%m-%d %H:%M:%S")
|
||||
LOG_FILE="/tmp/openclash.log"
|
||||
echo "开始下载 GEOIP 数据库..." >$START_LOG
|
||||
wget-ssl --no-check-certificate --quiet --timeout=10 --tries=2 https://static.clash.to/GeoIP2/GeoIP2-Country.mmdb -O /tmp/Country.mmdb
|
||||
curl -sL -m 10 --retry 2 https://static.clash.to/GeoIP2/GeoIP2-Country.mmdb -o /tmp/Country.mmdb >/dev/null 2>&1
|
||||
if [ "$?" -eq "0" ] && [ "$(ls -l /tmp/Country.mmdb |awk '{print int($5/1024)}')" -ne 0 ]; then
|
||||
echo "GEOIP 数据库下载成功,检查数据库版本是否更新..." >$START_LOG
|
||||
cmp -s /tmp/Country.mmdb /etc/openclash/Country.mmdb
|
||||
|
||||
@ -6,13 +6,13 @@
|
||||
rule_source=$(uci get openclash.config.rule_source 2>/dev/null)
|
||||
echo "开始下载使用中的第三方规则..." >$START_LOG
|
||||
if [ "$rule_source" = "lhie1" ]; then
|
||||
wget-ssl --no-check-certificate --quiet --timeout=10 --tries=2 https://raw.githubusercontent.com/lhie1/Rules/master/Clash/Rule.yml -O /tmp/rules.yaml
|
||||
curl -sL -m 10 --retry 2 https://raw.githubusercontent.com/lhie1/Rules/master/Clash/Rule.yml -o /tmp/rules.yaml >/dev/null 2>&1
|
||||
sed -i '1i Rule:' /tmp/rules.yaml
|
||||
elif [ "$rule_source" = "ConnersHua" ]; then
|
||||
wget-ssl --no-check-certificate --quiet --timeout=10 --tries=2 https://raw.githubusercontent.com/ConnersHua/Profiles/master/Clash/Pro.yaml -O /tmp/rules.yaml
|
||||
curl -sL -m 10 --retry 2 https://raw.githubusercontent.com/ConnersHua/Profiles/master/Clash/Pro.yaml -o /tmp/rules.yaml >/dev/null 2>&1
|
||||
sed -i -n '/^Rule:/,$p' /tmp/rules.yaml
|
||||
elif [ "$rule_source" = "ConnersHua_return" ]; then
|
||||
wget-ssl --no-check-certificate --quiet --timeout=10 --tries=2 https://raw.githubusercontent.com/ConnersHua/Profiles/master/Clash/BacktoCN.yaml -O /tmp/rules.yaml
|
||||
curl -sL -m 10 --retry 2 https://raw.githubusercontent.com/ConnersHua/Profiles/master/Clash/BacktoCN.yaml -o /tmp/rules.yaml >/dev/null 2>&1
|
||||
sed -i -n '/^Rule:/,$p' /tmp/rules.yaml
|
||||
fi
|
||||
if [ "$?" -eq "0" ] && [ "$rule_source" != 0 ] && [ "$(ls -l /tmp/rules.yaml |awk '{print int($5/1024)}')" -ne 0 ]; then
|
||||
|
||||
@ -10,7 +10,7 @@ LAST_OPVER="/tmp/openclash_last_version"
|
||||
LAST_VER=$(sed -n 1p "$LAST_OPVER" 2>/dev/null |sed "s/^v//g")
|
||||
if [ "$(sed -n 1p /etc/openclash/openclash_version 2>/dev/null)" != "$(sed -n 1p $LAST_OPVER 2>/dev/null)" ] && [ -f "$LAST_OPVER" ]; then
|
||||
echo "开始下载 OpenClash-$LAST_VER ..." >$START_LOG
|
||||
wget-ssl --no-check-certificate --quiet --timeout=10 --tries=5 https://github.com/vernesong/OpenClash/releases/download/v"$LAST_VER"/luci-app-openclash_"$LAST_VER"_all.ipk -O /tmp/openclash.ipk
|
||||
curl -sL -m 10 --retry 5 https://github.com/vernesong/OpenClash/releases/download/v"$LAST_VER"/luci-app-openclash_"$LAST_VER"_all.ipk -o /tmp/openclash.ipk >/dev/null 2>&1
|
||||
if [ "$?" -eq "0" ] && [ "$(ls -l /tmp/openclash.ipk |awk '{print int($5/1024)}')" -ne 0 ]; then
|
||||
echo "OpenClash-$LAST_VER 下载成功,开始更新,更新过程请不要刷新页面和进行其他操作..." >$START_LOG
|
||||
cat > /tmp/openclash_update.sh <<"EOF"
|
||||
|
||||
@ -3,7 +3,7 @@ CKTIME=$(date "+%Y-%m-%d-%H")
|
||||
LAST_OPVER="/tmp/openclash_last_version"
|
||||
version_url="https://raw.githubusercontent.com/vernesong/OpenClash/master/version"
|
||||
if [ "$CKTIME" != "$(grep "CheckTime" $LAST_OPVER 2>/dev/null |awk -F ':' '{print $2}')" ]; then
|
||||
wget-ssl --no-check-certificate --quiet --timeout=10 --tries=2 "$version_url" -O $LAST_OPVER
|
||||
curl -sL -m 10 --retry 2 "$version_url" -o $LAST_OPVER >/dev/null 2>&1
|
||||
if [ "$?" -eq "0" ] && [ "$(ls -l $LAST_OPVER 2>/dev/null |awk '{print int($5)}')" -gt 0 ]; then
|
||||
if [ "$(sed -n 1p /etc/openclash/openclash_version 2>/dev/null)" = "$(sed -n 1p $LAST_OPVER 2>/dev/null)" ]; then
|
||||
sed -i "/^https:/i\CheckTime:${CKTIME}" "$LAST_OPVER" 2>/dev/null
|
||||
|
||||
@ -19,6 +19,8 @@ if [ "$enable" -eq 1 ]; then
|
||||
CONFIG_FILE=$(uci get openclash.config.config_path 2>/dev/null)
|
||||
echo "${LOGTIME} Watchdog: Clash Core Problem, Restart." >> $LOG_FILE
|
||||
nohup $CLASH -d "$CLASH_CONFIG" -f "$CONFIG_FILE" >> $LOG_FILE 2>&1 &
|
||||
sleep 3
|
||||
/usr/share/openclash/openclash_history_set.sh
|
||||
else
|
||||
echo "${LOGTIME} Watchdog: Already Restart 3 Times With Clash Core Problem, Auto-Exit." >> $LOG_FILE
|
||||
exit 0
|
||||
@ -28,11 +30,23 @@ if [ "$enable" -eq 1 ]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
## Porxy history
|
||||
/usr/share/openclash/openclash_history_get.sh
|
||||
|
||||
## Log File Size Manage:
|
||||
LOGSIZE=`ls -l /tmp/openclash.log |awk '{print int($5/1024)}'`
|
||||
if [ "$LOGSIZE" -gt 90 ]; then
|
||||
echo "$LOGTIME Watchdog: Size Limit, Clean Up All Log Records." > $LOG_FILE
|
||||
fi
|
||||
|
||||
## 端口转发重启
|
||||
last_line=$(iptables -t nat -nL PREROUTING --line-number |awk '{print $1}' 2>/dev/null |awk 'END {print}' |sed -n '$p')
|
||||
op_line=$(iptables -t nat -nL PREROUTING --line-number |grep "openclash" 2>/dev/null |awk '{print $1}' 2>/dev/null |head -1)
|
||||
if [ "$last_line" -ne "$op_line" ]; then
|
||||
iptables -t nat -D PREROUTING -p tcp -j openclash
|
||||
iptables -t nat -A PREROUTING -p tcp -j openclash
|
||||
echo "$LOGTIME Watchdog: Reset Firewall For Enabling Redirect." >>$LOG_FILE
|
||||
fi
|
||||
|
||||
## DNS转发劫持
|
||||
if [ "$enable_redirect_dns" != "0" ]; then
|
||||
|
||||
@ -6,6 +6,7 @@ status=$(ps|grep -c /usr/share/openclash/yml_groups_set.sh)
|
||||
|
||||
START_LOG="/tmp/openclash_start.log"
|
||||
GROUP_FILE="/tmp/yaml_groups.yaml"
|
||||
CONFIG_GROUP_FILE="/tmp/yaml_group.yaml"
|
||||
CFG_FILE="/etc/config/openclash"
|
||||
servers_update=$(uci get openclash.config.servers_update 2>/dev/null)
|
||||
CONFIG_FILE=$(uci get openclash.config.config_path 2>/dev/null)
|
||||
@ -35,6 +36,7 @@ yml_servers_add()
|
||||
local section="$1"
|
||||
config_get_bool "enabled" "$section" "enabled" "1"
|
||||
config_get "config" "$section" "config" ""
|
||||
config_get "name" "$section" "name" ""
|
||||
|
||||
if [ ! -z "$config" ] && [ "$config" != "$CONFIG_NAME" ] && [ "$config" != "all" ]; then
|
||||
return
|
||||
@ -43,8 +45,9 @@ yml_servers_add()
|
||||
if [ "$enabled" = "0" ]; then
|
||||
return
|
||||
else
|
||||
config_get "name" "$section" "name" ""
|
||||
config_list_foreach "$section" "groups" set_groups "$name" "$2"
|
||||
if [ -z "$3" ]; then
|
||||
config_list_foreach "$section" "groups" set_groups "$name" "$2"
|
||||
fi
|
||||
|
||||
if [ ! -z "$if_game_group" ] && [ -z "$(grep -F $name /tmp/yaml_proxy.yaml)" ]; then
|
||||
/usr/share/openclash/yml_proxys_set.sh "$name" "proxy"
|
||||
@ -83,6 +86,7 @@ set_proxy_provider()
|
||||
local section="$1"
|
||||
config_get_bool "enabled" "$section" "enabled" "1"
|
||||
config_get "config" "$section" "config" ""
|
||||
config_get "name" "$section" "name" ""
|
||||
|
||||
if [ ! -z "$config" ] && [ "$config" != "$CONFIG_NAME" ] && [ "$config" != "all" ]; then
|
||||
return
|
||||
@ -91,8 +95,9 @@ set_proxy_provider()
|
||||
if [ "$enabled" = "0" ]; then
|
||||
return
|
||||
else
|
||||
config_get "name" "$section" "name" ""
|
||||
config_list_foreach "$section" "groups" set_provider_groups "$name" "$2"
|
||||
if [ -z "$3" ]; then
|
||||
config_list_foreach "$section" "groups" set_provider_groups "$name" "$2"
|
||||
fi
|
||||
|
||||
if [ ! -z "$if_game_group" ] && [ -z "$(grep "^ \{0,\}$name" /tmp/yaml_proxy_provider.yaml)" ]; then
|
||||
/usr/share/openclash/yml_proxys_set.sh "$name" "proxy-provider"
|
||||
@ -146,6 +151,13 @@ yml_groups_set()
|
||||
return
|
||||
fi
|
||||
|
||||
#游戏策略组存在时判断节点是否存在
|
||||
if [ ! -z "$if_game_group" ] && [ ! -z "$(grep "^ \{0,\}- name: $if_game_group" "$CONFIG_GROUP_FILE")" ]; then
|
||||
config_foreach yml_servers_add "servers" "$name" "check" #加入服务器节点
|
||||
config_foreach set_proxy_provider "proxy-provider" "$group_name" "check" #加入代理集
|
||||
return
|
||||
fi
|
||||
|
||||
echo "正在写入【$type】-【$name】策略组到配置文件【$CONFIG_NAME】..." >$START_LOG
|
||||
|
||||
echo "- name: $name" >>$GROUP_FILE
|
||||
@ -168,9 +180,8 @@ yml_groups_set()
|
||||
config_foreach yml_servers_add "servers" "$name" #加入服务器节点
|
||||
|
||||
echo " use: $group_name" >>$GROUP_FILE
|
||||
|
||||
config_foreach set_proxy_provider "proxy-provider" "$group_name" #加入代理集
|
||||
|
||||
|
||||
if [ "$set_group" -eq 1 ]; then
|
||||
sed -i "/^ \{0,\}proxies: ${group_name}/c\ proxies:" $GROUP_FILE
|
||||
else
|
||||
@ -184,10 +195,10 @@ yml_groups_set()
|
||||
fi
|
||||
|
||||
[ ! -z "$test_url" ] && {
|
||||
echo " url: $test_url" >>$GROUP_FILE
|
||||
echo " url: $test_url" >>$GROUP_FILE
|
||||
}
|
||||
[ ! -z "$test_interval" ] && {
|
||||
echo " interval: \"$test_interval\"" >>$GROUP_FILE
|
||||
echo " interval: \"$test_interval\"" >>$GROUP_FILE
|
||||
}
|
||||
}
|
||||
|
||||
@ -208,6 +219,7 @@ if [ "$create_config" = "0" ] || [ "$servers_if_update" = "1" ] || [ ! -z "$if_g
|
||||
echo "Proxy Group:" >$GROUP_FILE
|
||||
else
|
||||
echo "开始加入游戏策略组【$if_game_group】的信息..." >$START_LOG
|
||||
rm -rf $GROUP_FILE
|
||||
fi
|
||||
config_load "openclash"
|
||||
config_foreach yml_groups_set "groups"
|
||||
|
||||
@ -301,7 +301,7 @@ rm -rf /tmp/Proxy_Provider
|
||||
config_load "openclash"
|
||||
config_foreach yml_proxy_provider_set "proxy-provider"
|
||||
sed -i "s/^ \{0,\}/ - /" /tmp/Proxy_Provider 2>/dev/null #添加参数
|
||||
if [ "$(grep "-" /tmp/Proxy_Provider |wc -l)" -eq 0 ]; then
|
||||
if [ "$(grep "-" /tmp/Proxy_Provider 2>/dev/null |wc -l)" -eq 0 ]; then
|
||||
rm -rf $PROXY_PROVIDER_FILE
|
||||
rm -rf /tmp/Proxy_Provider
|
||||
fi
|
||||
@ -665,9 +665,9 @@ echo "" >$START_LOG
|
||||
if [ -z "$if_game_proxy" ]; then
|
||||
rm -rf $SERVER_FILE 2>/dev/null
|
||||
rm -rf $PROXY_PROVIDER_FILE 2>/dev/null
|
||||
rm -rf /tmp/yaml_groups.yaml 2>/dev/null
|
||||
fi
|
||||
rm -rf /tmp/Proxy_Server 2>/dev/null
|
||||
rm -rf /tmp/yaml_groups.yaml 2>/dev/null
|
||||
rm -rf /tmp/Proxy_Provider 2>/dev/null
|
||||
uci set openclash.config.enable=1 2>/dev/null
|
||||
[ "$(uci get openclash.config.servers_if_update)" == "0" ] && [ -z "$if_game_proxy" ] && /etc/init.d/openclash restart >/dev/null 2>&1
|
||||
|
||||
@ -95,6 +95,9 @@ msgstr "Redir-Host(兼容)模式"
|
||||
msgid "fake-ip"
|
||||
msgstr "Fake-IP(增强)模式"
|
||||
|
||||
msgid "redir-host(tun mode)"
|
||||
msgstr "Redir-Host(TUN)模式【依赖kmod-tun】"
|
||||
|
||||
msgid "fake-ip(tun mode)"
|
||||
msgstr "Fake-IP(TUN)模式【依赖kmod-tun】"
|
||||
|
||||
|
||||
@ -11,14 +11,16 @@ PKG_CONFIG_DEPENDS:= CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks \
|
||||
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Server \
|
||||
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Socks \
|
||||
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Socks \
|
||||
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_ipt2socks \
|
||||
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_dnscrypt_proxy \
|
||||
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_dnsforwarder \
|
||||
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_ChinaDNS \
|
||||
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_haproxy \
|
||||
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_udpspeeder \
|
||||
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_udp2raw-tunnel \
|
||||
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_privoxy \
|
||||
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_simple-obfs\
|
||||
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_simple-obfs-server\
|
||||
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_ipt2socks\
|
||||
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_GoQuiet-client\
|
||||
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_GoQuiet-server\
|
||||
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_v2ray-plugin
|
||||
@ -33,10 +35,10 @@ config PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks
|
||||
config PACKAGE_$(PKG_NAME)_INCLUDE_V2ray
|
||||
bool "Include V2ray"
|
||||
default y
|
||||
|
||||
|
||||
config PACKAGE_$(PKG_NAME)_INCLUDE_Trojan
|
||||
bool "Include Trojan"
|
||||
default n
|
||||
default y
|
||||
|
||||
config PACKAGE_$(PKG_NAME)_INCLUDE_Kcptun
|
||||
bool "Include Kcptun"
|
||||
@ -48,7 +50,7 @@ config PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Server
|
||||
|
||||
config PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Server
|
||||
bool "Include Shadowsocks Server"
|
||||
default n
|
||||
default y
|
||||
|
||||
config PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Socks
|
||||
bool "Include ShadowsocksR Socks and Tunnel"
|
||||
@ -56,51 +58,59 @@ config PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Socks
|
||||
|
||||
config PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Socks
|
||||
bool "Include Shadowsocks Socks and Tunnel"
|
||||
default n
|
||||
|
||||
config PACKAGE_$(PKG_NAME)_INCLUDE_dnscrypt_proxy
|
||||
bool "dnscrypt-proxy-full"
|
||||
default n
|
||||
|
||||
config PACKAGE_$(PKG_NAME)_INCLUDE_dnsforwarder
|
||||
bool "dnsforwarder"
|
||||
default n
|
||||
|
||||
config PACKAGE_$(PKG_NAME)_INCLUDE_ChinaDNS
|
||||
bool "chinadns"
|
||||
default n
|
||||
|
||||
config PACKAGE_$(PKG_NAME)_INCLUDE_haproxy
|
||||
bool "haproxy"
|
||||
default n
|
||||
|
||||
config PACKAGE_$(PKG_NAME)_INCLUDE_privoxy
|
||||
bool "privoxy http local"
|
||||
default n
|
||||
|
||||
config PACKAGE_$(PKG_NAME)_INCLUDE_simple-obfs
|
||||
bool "simple-obfs-local"
|
||||
default n
|
||||
|
||||
config PACKAGE_$(PKG_NAME)_INCLUDE_simple-obfs-server
|
||||
bool "simple-obfs-server"
|
||||
default n
|
||||
default y
|
||||
|
||||
config PACKAGE_$(PKG_NAME)_INCLUDE_ipt2socks
|
||||
bool "Include ipt2socks"
|
||||
default n
|
||||
default y
|
||||
|
||||
config PACKAGE_$(PKG_NAME)_INCLUDE_dnscrypt_proxy
|
||||
bool "Include dnscrypt-proxy-full"
|
||||
default y
|
||||
|
||||
config PACKAGE_$(PKG_NAME)_INCLUDE_dnsforwarder
|
||||
bool "Include dnsforwarder"
|
||||
default y
|
||||
|
||||
config PACKAGE_$(PKG_NAME)_INCLUDE_ChinaDNS
|
||||
bool "Include chinadns"
|
||||
default y
|
||||
|
||||
config PACKAGE_$(PKG_NAME)_INCLUDE_haproxy
|
||||
bool "Include haproxy"
|
||||
default y
|
||||
|
||||
config PACKAGE_$(PKG_NAME)_INCLUDE_privoxy
|
||||
bool "Include privoxy http local"
|
||||
default y
|
||||
|
||||
config PACKAGE_$(PKG_NAME)_INCLUDE_simple-obfs
|
||||
bool "Include simple-obfsl"
|
||||
default y
|
||||
|
||||
config PACKAGE_$(PKG_NAME)_INCLUDE_simple-obfs-server
|
||||
bool "Include simple-obfs-server"
|
||||
default y
|
||||
|
||||
config PACKAGE_$(PKG_NAME)_INCLUDE_udpspeeder
|
||||
bool "Include udpspeeder"
|
||||
default y
|
||||
|
||||
config PACKAGE_$(PKG_NAME)_INCLUDE_udp2raw-tunnel
|
||||
bool "Include udp2raw-tunnel"
|
||||
default y
|
||||
|
||||
config PACKAGE_$(PKG_NAME)_INCLUDE_GoQuiet-client
|
||||
bool "GoQuiet-client"
|
||||
default n
|
||||
|
||||
bool "Include GoQuiet-client"
|
||||
default y
|
||||
|
||||
config PACKAGE_$(PKG_NAME)_INCLUDE_GoQuiet-server
|
||||
bool "GoQuiet-server"
|
||||
default n
|
||||
bool "Include GoQuiet-server"
|
||||
default y
|
||||
|
||||
config PACKAGE_$(PKG_NAME)_INCLUDE_v2ray-plugin
|
||||
bool "v2ray-plugin"
|
||||
default n
|
||||
bool "Include v2ray-plugin"
|
||||
default y
|
||||
endef
|
||||
|
||||
define Package/luci-app-ssr-plus-Jo
|
||||
@ -112,20 +122,22 @@ define Package/luci-app-ssr-plus-Jo
|
||||
DEPENDS:=+shadowsocksr-libev-alt +ipset +ip-full +iptables-mod-tproxy +dnsmasq-full +coreutils +coreutils-base64 +bash +pdnsd-alt +curl +wget +unzip \
|
||||
+PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks:shadowsocks-libev-ss-redir \
|
||||
+PACKAGE_$(PKG_NAME)_INCLUDE_V2ray:v2ray \
|
||||
+PACKAGE_$(PKG_NAME)_INCLUDE_Trojan:trojan \
|
||||
+PACKAGE_$(PKG_NAME)_INCLUDE_Trojan:trojan \
|
||||
+PACKAGE_$(PKG_NAME)_INCLUDE_Kcptun:kcptun-client \
|
||||
+PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Server:shadowsocksr-libev-server \
|
||||
+PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Server:shadowsocks-libev-ss-server \
|
||||
+PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Socks:shadowsocksr-libev-ssr-local \
|
||||
+PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Socks:shadowsocks-libev-ss-local \
|
||||
+PACKAGE_$(PKG_NAME)_INCLUDE_ipt2socks:ipt2socks \
|
||||
+PACKAGE_$(PKG_NAME)_INCLUDE_dnscrypt_proxy:dnscrypt-proxy-full \
|
||||
+PACKAGE_$(PKG_NAME)_INCLUDE_dnsforwarder:dnsforwarder \
|
||||
+PACKAGE_$(PKG_NAME)_INCLUDE_ChinaDNS:openwrt_chinadns \
|
||||
+PACKAGE_$(PKG_NAME)_INCLUDE_haproxy:haproxy \
|
||||
+PACKAGE_$(PKG_NAME)_INCLUDE_privoxy:privoxy \
|
||||
+PACKAGE_$(PKG_NAME)_INCLUDE_udpspeeder:speederv2-tunnel \
|
||||
+PACKAGE_$(PKG_NAME)_INCLUDE_udp2raw-tunnel:udp2raw-tunnel \
|
||||
+PACKAGE_$(PKG_NAME)_INCLUDE_simple-obfs:simple-obfs \
|
||||
+PACKAGE_$(PKG_NAME)_INCLUDE_simple-obfs-server:simple-obfs-server \
|
||||
+PACKAGE_$(PKG_NAME)_INCLUDE_ipt2socks:ipt2socks \
|
||||
+PACKAGE_$(PKG_NAME)_INCLUDE_GoQuiet-client:gq-client \
|
||||
+PACKAGE_$(PKG_NAME)_INCLUDE_GoQuiet-server:gq-server \
|
||||
+PACKAGE_$(PKG_NAME)_INCLUDE_v2ray-plugin:v2ray-plugin
|
||||
|
||||
@ -11,8 +11,8 @@ LUCI_TITLE:=LuCI support for UnblockNeteaseMusic
|
||||
LUCI_DEPENDS:=+bash +busybox +coreutils-nohup +curl +dnsmasq-full +ipset +libopenssl +node
|
||||
LUCI_PKGARCH:=all
|
||||
PKG_NAME:=luci-app-unblockneteasemusic
|
||||
PKG_VERSION:=2.6
|
||||
PKG_RELEASE:=3
|
||||
PKG_VERSION:=2.7
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_MAINTAINER:=[CTCGFW]Project-OpenWrt
|
||||
|
||||
|
||||
@ -12,10 +12,11 @@ function index()
|
||||
entry({"admin", "services", "unblockneteasemusic"},firstchild(), _("解除网易云音乐播放限制"), 50).dependent = false
|
||||
|
||||
entry({"admin", "services", "unblockneteasemusic", "general"},cbi("unblockneteasemusic"), _("基本设定"), 1)
|
||||
entry({"admin", "services", "unblockneteasemusic", "upgrade_core"},form("unblockneteasemusic_upcore"), _("更新核心"), 2).leaf = true
|
||||
entry({"admin", "services", "unblockneteasemusic", "upgrade"},form("unblockneteasemusic_upgrade"), _("更新组件"), 2).leaf = true
|
||||
entry({"admin", "services", "unblockneteasemusic", "log"},form("unblockneteasemusiclog"), _("日志"), 3)
|
||||
|
||||
entry({"admin", "services", "unblockneteasemusic", "status"},call("act_status")).leaf=true
|
||||
entry({"admin", "services", "unblockneteasemusic", "update_luci"},call("act_update_luci"))
|
||||
entry({"admin", "services", "unblockneteasemusic", "update_core"},call("act_update_core"))
|
||||
end
|
||||
|
||||
@ -26,21 +27,49 @@ function act_status()
|
||||
luci.http.write_json(e)
|
||||
end
|
||||
|
||||
function update_core()
|
||||
cloud_ver=luci.sys.exec("curl -s 'https://github.com/nondanee/UnblockNeteaseMusic/commits/master' |tr -d '\n' |grep -Eo 'commit\/[0-9a-z]+' |sed -n 1p |sed 's#commit/##g'")
|
||||
cloud_ver_mini=luci.sys.exec("curl -s 'https://github.com/nondanee/UnblockNeteaseMusic/commits/master' |tr -d '\n' |grep -Eo 'BtnGroup-item.> [0-9a-z]+' |sed -n 1p |sed 's#BtnGroup-item.> ##g'")
|
||||
if not cloud_ver or not cloud_ver_mini then
|
||||
function update_luci()
|
||||
luci_cloud_ver=luci.sys.exec("curl -s 'https://github.com/project-openwrt/luci-app-unblockneteasemusic/releases/latest'| grep -Eo '[0-9\.]+\-[0-9]+'")
|
||||
if not luci_cloud_ver then
|
||||
return "1"
|
||||
else
|
||||
local_ver=luci.sys.exec("cat '/usr/share/unblockneteasemusic/local_ver'")
|
||||
if not local_ver or (local_ver ~= cloud_ver) then
|
||||
luci.sys.call("rm -f /usr/share/unblockneteasemusic/update_successfully")
|
||||
luci.sys.call("/bin/bash /usr/share/unblockneteasemusic/update_core.sh luci_update")
|
||||
if not nixio.fs.access("/usr/share/unblockneteasemusic/update_successfully") then
|
||||
luci_local_ver=luci.sys.exec("opkg info 'luci-app-unblockneteasemusic' |sed -n '2p' |tr -d 'Version: '")
|
||||
if not luci_local_ver or (luci_local_ver ~= luci_cloud_ver) then
|
||||
luci.sys.call("rm -f /usr/share/unblockneteasemusic/update_luci_successfully")
|
||||
luci.sys.call("/bin/bash /usr/share/unblockneteasemusic/update.sh update_luci")
|
||||
if not nixio.fs.access("/usr/share/unblockneteasemusic/update_luci_successfully") then
|
||||
return "2"
|
||||
else
|
||||
luci.sys.call("rm -f /usr/share/unblockneteasemusic/update_successfully")
|
||||
return cloud_ver_mini
|
||||
luci.sys.call("rm -f /usr/share/unblockneteasemusic/update_luci_successfully")
|
||||
return luci_cloud_ver
|
||||
end
|
||||
else
|
||||
return "0"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function act_update_luci()
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json({
|
||||
ret = update_luci();
|
||||
})
|
||||
end
|
||||
|
||||
function update_core()
|
||||
core_cloud_ver=luci.sys.exec("curl -s 'https://github.com/nondanee/UnblockNeteaseMusic/commits/master' |tr -d '\n' |grep -Eo 'commit\/[0-9a-z]+' |sed -n 1p |sed 's#commit/##g'")
|
||||
core_cloud_ver_mini=luci.sys.exec("curl -s 'https://github.com/nondanee/UnblockNeteaseMusic/commits/master' |tr -d '\n' |grep -Eo 'BtnGroup-item.> [0-9a-z]+' |sed -n 1p |sed 's#BtnGroup-item.> ##g'")
|
||||
if not core_cloud_ver or not core_cloud_ver_mini then
|
||||
return "1"
|
||||
else
|
||||
core_local_ver=luci.sys.exec("cat '/usr/share/unblockneteasemusic/core_local_ver'")
|
||||
if not core_local_ver or (core_local_ver ~= core_cloud_ver) then
|
||||
luci.sys.call("rm -f /usr/share/unblockneteasemusic/update_core_successfully")
|
||||
luci.sys.call("/bin/bash /usr/share/unblockneteasemusic/update.sh update_core_from_luci")
|
||||
if not nixio.fs.access("/usr/share/unblockneteasemusic/update_core_successfully") then
|
||||
return "2"
|
||||
else
|
||||
luci.sys.call("rm -f /usr/share/unblockneteasemusic/update_core_successfully")
|
||||
return core_cloud_ver_mini
|
||||
end
|
||||
else
|
||||
return "0"
|
||||
@ -53,4 +82,4 @@ function act_update_core()
|
||||
luci.http.write_json({
|
||||
ret = update_core();
|
||||
})
|
||||
end
|
||||
end
|
||||
@ -48,7 +48,7 @@ hijack = s:option(ListValue, "hijack_ways", translate("劫持方法"))
|
||||
hijack:value("dont_hijack", translate("不开启劫持"))
|
||||
hijack:value("use_ipset", translate("使用IPSet劫持"))
|
||||
hijack:value("use_hosts", translate("使用Hosts劫持"))
|
||||
hijack.description = translate("如果使用Hosts劫持,主实例的HTTP/HTTPS端口将被锁定为80/443")
|
||||
hijack.description = translate("如果使用Hosts劫持,程序监听的HTTP/HTTPS端口将被锁定为80/443")
|
||||
hijack.default = "dont_hijack"
|
||||
hijack.rmempty = false
|
||||
|
||||
@ -103,7 +103,7 @@ pub_access.rmempty = false
|
||||
pub_access:depends("advanced_mode", 1)
|
||||
|
||||
strict_mode = s:option(Flag, "strict_mode", translate("启用严格模式"))
|
||||
strict_mode.description = translate("若将服务部署到公网,则强烈建议使用严格模式,此模式下仅放行网易云音乐所属域名的请求;注意:该模式下只能使用PAC方式进行代理")
|
||||
strict_mode.description = translate("若将服务部署到公网,则强烈建议使用严格模式,此模式下仅放行网易云音乐所属域名的请求;注意:该模式下不能使用全局代理")
|
||||
strict_mode.default = 0
|
||||
strict_mode.rmempty = false
|
||||
strict_mode:depends("advanced_mode", 1)
|
||||
@ -112,7 +112,6 @@ netease_server_ip = s:option(Value, "netease_server_ip", translate("网易云服
|
||||
netease_server_ip.description = translate("通过 ping music.163.com 即可获得IP地址,仅限填写一个")
|
||||
netease_server_ip.placeholder = "59.111.181.38"
|
||||
netease_server_ip.datatype = "ipaddr"
|
||||
netease_server_ip:depends("set_netease_server_ip", 1)
|
||||
netease_server_ip:depends("advanced_mode", 1)
|
||||
|
||||
proxy_server_ip = s:option(Value, "proxy_server_ip", translate("代理服务器地址"))
|
||||
@ -121,4 +120,16 @@ proxy_server_ip.placeholder = "http(s)://host:port"
|
||||
proxy_server_ip.datatype = "string"
|
||||
proxy_server_ip:depends("advanced_mode", 1)
|
||||
|
||||
self_issue_cert_crt = s:option(Value, "self_issue_cert_crt", translate("自签发证书公钥位置"))
|
||||
self_issue_cert_crt.description = translate("[公钥] 默认使用UnblockNeteaseMusic项目提供的CA证书,您可以指定为您自己的证书")
|
||||
self_issue_cert_crt.placeholder = "/usr/share/unblockneteasemusic/core/server.crt"
|
||||
self_issue_cert_crt.datatype = "file"
|
||||
self_issue_cert_crt:depends("advanced_mode", 1)
|
||||
|
||||
self_issue_cert_key = s:option(Value, "self_issue_cert_key", translate("自签发证书私钥位置"))
|
||||
self_issue_cert_key.description = translate("[私钥] 默认使用UnblockNeteaseMusic项目提供的CA证书,您可以指定为您自己的证书")
|
||||
self_issue_cert_key.placeholder = "/usr/share/unblockneteasemusic/core/server.key"
|
||||
self_issue_cert_key.datatype = "file"
|
||||
self_issue_cert_key:depends("advanced_mode", 1)
|
||||
|
||||
return mp
|
||||
|
||||
@ -4,6 +4,12 @@ m = SimpleForm("Version")
|
||||
m.reset = false
|
||||
m.submit = false
|
||||
|
||||
up_core=m:field(DummyValue,"update_luci",translate("更新LuCI"))
|
||||
up_core.rawhtml = true
|
||||
up_core.template = "unblockneteasemusic/update_luci"
|
||||
up_core.value = translate("未检查")
|
||||
up_core.description = "更新完毕后请手动刷新该界面"
|
||||
|
||||
up_core=m:field(DummyValue,"update_core",translate("更新主程序"))
|
||||
up_core.rawhtml = true
|
||||
up_core.template = "unblockneteasemusic/update_core"
|
||||
@ -0,0 +1,36 @@
|
||||
<%+cbi/valueheader%>
|
||||
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
function act_update_luci(btn,dataname)
|
||||
{
|
||||
btn.disabled = true;
|
||||
btn.value = '<%:正在更新LuCI...%> ';
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "services", "unblockneteasemusic","update_luci")%>',
|
||||
status.ret,
|
||||
function(x,status)
|
||||
{
|
||||
var s = document.getElementById(dataname+'-status');
|
||||
if (s)
|
||||
{
|
||||
if(status.ret=="0")
|
||||
s.innerHTML ="<font color='green'>"+"<%:当前已是最新版本%>"+"</font>";
|
||||
else if (status.ret=="1")
|
||||
s.innerHTML ="<font color='red'>"+"<%:无法检测最新版本%>"+"</font>";
|
||||
else if(status.ret=="2")
|
||||
s.innerHTML ="<font color='red'>"+"<%:更新失败,请稍后重试%>"+"</font>";
|
||||
else
|
||||
s.innerHTML ="<font color='green'>"+"<%:更新成功,当前版本号:%>"+status.ret+"</font>";
|
||||
}
|
||||
btn.disabled = false;
|
||||
btn.value = '<%:点此更新LuCI%>';
|
||||
}
|
||||
);
|
||||
return false;
|
||||
}
|
||||
//]]></script>
|
||||
|
||||
|
||||
<input type="button" class="cbi-button cbi-input-reload" value="<%:点此更新LuCI%> " onclick="return act_update_luci(this,'<%=self.option%>')" />
|
||||
<span id="<%=self.option%>-status"><em><%=self.value%></em></span>
|
||||
|
||||
<%+cbi/valuefooter%>
|
||||
@ -17,3 +17,5 @@ config unblockneteasemusic
|
||||
option strict_mode '0'
|
||||
option netease_server_ip '59.111.181.38'
|
||||
option proxy_server_ip ''
|
||||
option self_issue_cert_crt '/usr/share/unblockneteasemusic/core/server.crt'
|
||||
option self_issue_cert_key '/usr/share/unblockneteasemusic/core/server.key'
|
||||
|
||||
@ -31,46 +31,49 @@ netease_server_ip="$(uci get unblockneteasemusic.@unblockneteasemusic[0].netease
|
||||
proxy_server_ip="$(uci get unblockneteasemusic.@unblockneteasemusic[0].proxy_server_ip 2>"/dev/null")"
|
||||
[ -n "${proxy_server_ip}" ] && proxy_server_ip="-u ${proxy_server_ip}"
|
||||
|
||||
self_issue_cert_crt="$(uci get unblockneteasemusic.@unblockneteasemusic[0].self_issue_cert_crt 2>"/dev/null")"
|
||||
self_issue_cert_key="$(uci get unblockneteasemusic.@unblockneteasemusic[0].self_issue_cert_key 2>"/dev/null")"
|
||||
|
||||
set_ipset(){
|
||||
if [ "${set_type}" = "start" ]; then
|
||||
mkdir -p "/tmp/dnsmasq.d"
|
||||
rm -f "/tmp/dnsmasq.d/dnsmasq-unblockneteasemusic.conf"
|
||||
cat <<-EOF > "/tmp/dnsmasq.d/dnsmasq-unblockneteasemusic.conf"
|
||||
dhcp-option=252,http://${lan_addr}:${http_port}/proxy.pac
|
||||
ipset=/.music.163.com/music
|
||||
ipset=/interface.music.163.com/music
|
||||
ipset=/interface3.music.163.com/music
|
||||
ipset=/apm.music.163.com/music
|
||||
ipset=/apm3.music.163.com/music
|
||||
ipset=/.music.163.com/neteasemusic
|
||||
ipset=/interface.music.163.com/neteasemusic
|
||||
ipset=/interface3.music.163.com/neteasemusic
|
||||
ipset=/apm.music.163.com/neteasemusic
|
||||
ipset=/apm3.music.163.com/neteasemusic
|
||||
EOF
|
||||
/etc/init.d/dnsmasq restart > "/dev/null" 2>&1
|
||||
/etc/init.d/dnsmasq reload > "/dev/null" 2>&1
|
||||
|
||||
if ! ipset list music > "/dev/null"; then ipset create music hash:ip; fi
|
||||
if ! ipset list "neteasemusic" > "/dev/null"; then ipset create "neteasemusic" hash:ip; fi
|
||||
curl -s "http://httpdns.n.netease.com/httpdns/v2/d?domain=music.163.com,interface.music.163.com,interface3.music.163.com,apm.music.163.com,apm3.music.163.com,clientlog.music.163.com,clientlog3.music.163.com" |grep -Eo '[0-9]+?\.[0-9]+?\.[0-9]+?\.[0-9]+?' |sort |uniq |awk '{print "ipset add music "$1}' |bash > "/dev/null" 2>&1
|
||||
iptables -t nat -N cloud_music
|
||||
iptables -t nat -A cloud_music -d 0.0.0.0/8 -j RETURN
|
||||
iptables -t nat -A cloud_music -d 10.0.0.0/8 -j RETURN
|
||||
iptables -t nat -A cloud_music -d 127.0.0.0/8 -j RETURN
|
||||
iptables -t nat -A cloud_music -d 169.254.0.0/16 -j RETURN
|
||||
iptables -t nat -A cloud_music -d 172.16.0.0/12 -j RETURN
|
||||
iptables -t nat -A cloud_music -d 192.168.0.0/16 -j RETURN
|
||||
iptables -t nat -A cloud_music -d 224.0.0.0/4 -j RETURN
|
||||
iptables -t nat -A cloud_music -d 240.0.0.0/4 -j RETURN
|
||||
iptables -t nat -A cloud_music -p tcp --dport 80 -j REDIRECT --to-ports "${http_port}"
|
||||
iptables -t nat -A cloud_music -p tcp --dport 443 -j REDIRECT --to-ports "${https_port}"
|
||||
iptables -t nat -I PREROUTING -p tcp -m set --match-set music dst -j cloud_music
|
||||
iptables -t nat -N "netease_cloud_music"
|
||||
iptables -t nat -A "netease_cloud_music" -d "0.0.0.0/8" -j RETURN
|
||||
iptables -t nat -A "netease_cloud_music" -d "10.0.0.0/8" -j RETURN
|
||||
iptables -t nat -A "netease_cloud_music" -d "127.0.0.0/8" -j RETURN
|
||||
iptables -t nat -A "netease_cloud_music" -d "169.254.0.0/16" -j RETURN
|
||||
iptables -t nat -A "netease_cloud_music" -d "172.16.0.0/12" -j RETURN
|
||||
iptables -t nat -A "netease_cloud_music" -d "192.168.0.0/16" -j RETURN
|
||||
iptables -t nat -A "netease_cloud_music" -d "224.0.0.0/4" -j RETURN
|
||||
iptables -t nat -A "netease_cloud_music" -d "240.0.0.0/4" -j RETURN
|
||||
iptables -t nat -A "netease_cloud_music" -p tcp --dport 80 -j REDIRECT --to-ports "${http_port}"
|
||||
iptables -t nat -A "netease_cloud_music" -p tcp --dport 443 -j REDIRECT --to-ports "${https_port}"
|
||||
iptables -t nat -I PREROUTING -p tcp -m set --match-set "neteasemusic" dst -j "netease_cloud_music"
|
||||
|
||||
mkdir -p /var/etc
|
||||
mkdir -p "/var/etc/"
|
||||
echo -e "/etc/init.d/unblockneteasemusic restart" > "/var/etc/unblockneteasemusic.include"
|
||||
elif [ "${set_type}" = "stop" ]; then
|
||||
iptables -t nat -D PREROUTING -p tcp -m set --match-set music dst -j cloud_music
|
||||
iptables -t nat -F cloud_music
|
||||
iptables -t nat -X cloud_music
|
||||
ipset destroy music
|
||||
iptables -t nat -D PREROUTING -p tcp -m set --match-set "neteasemusic" dst -j "netease_cloud_music"
|
||||
iptables -t nat -F "netease_cloud_music"
|
||||
iptables -t nat -X "netease_cloud_music"
|
||||
ipset destroy "neteasemusic"
|
||||
|
||||
echo "" > "/var/etc/unblockneteasemusic.include"
|
||||
rm -f "/tmp/dnsmasq.d/dnsmasq-unblockneteasemusic.conf"
|
||||
/etc/init.d/dnsmasq restart > "/dev/null" 2>&1
|
||||
/etc/init.d/dnsmasq reload > "/dev/null" 2>&1
|
||||
fi
|
||||
}
|
||||
|
||||
@ -87,14 +90,14 @@ address=/apm.music.163.com/${lan_addr}
|
||||
address=/apm3.music.163.com/${lan_addr}
|
||||
address=/music.httpdns.c.163.com/0.0.0.0
|
||||
EOF
|
||||
/etc/init.d/dnsmasq restart > "/dev/null" 2>&1
|
||||
/etc/init.d/dnsmasq reload > "/dev/null" 2>&1
|
||||
|
||||
ip route add 223.252.199.10 dev lo
|
||||
ip route add "223.252.199.10" dev lo
|
||||
elif [ "${set_type}" = "stop" ]; then
|
||||
rm -f "/tmp/dnsmasq.d/dnsmasq-unblockneteasemusic.conf"
|
||||
/etc/init.d/dnsmasq restart > "/dev/null" 2>&1
|
||||
/etc/init.d/dnsmasq reload > "/dev/null" 2>&1
|
||||
|
||||
ip route del 223.252.199.10
|
||||
ip route del "223.252.199.10"
|
||||
fi
|
||||
}
|
||||
|
||||
@ -103,7 +106,7 @@ set_ports(){
|
||||
iptables -I INPUT -p tcp --dport "${http_port}" -j ACCEPT
|
||||
iptables -I INPUT -p tcp --dport "${https_port}" -j ACCEPT
|
||||
|
||||
mkdir -p /var/etc
|
||||
mkdir -p "/var/etc/"
|
||||
echo -e "/etc/init.d/unblockneteasemusic restart" > "/var/etc/unblockneteasemusic.include"
|
||||
elif [ "${set_type}" = "stop" ]; then
|
||||
iptables -D INPUT -p tcp --dport "${http_port}" -j ACCEPT
|
||||
@ -119,7 +122,7 @@ start()
|
||||
|
||||
[ "${enable}" -ne "1" ] && exit 0
|
||||
|
||||
[ ! -e "/usr/share/unblockneteasemusic/core/app.js" ] && rm -f "/usr/share/unblockneteasemusic/local_ver" && bash "/usr/share/unblockneteasemusic/update_core.sh"
|
||||
[ ! -e "/usr/share/unblockneteasemusic/core/app.js" ] && rm -f "/usr/share/unblockneteasemusic/local_ver" && bash "/usr/share/unblockneteasemusic/update.sh" "update_core_non_restart"
|
||||
[ ! -e "/usr/share/unblockneteasemusic/core/app.js" ] && echo "Core Not Found, please download it before starting." >> "/tmp/unblockneteasemusic.log" && exit 1
|
||||
|
||||
if [ "${music_source}" = "qq" ];then
|
||||
@ -133,6 +136,9 @@ start()
|
||||
sed -i -e "1i const key = '${youtube_key}'" "/usr/share/unblockneteasemusic/core/provider/youtube.js"
|
||||
fi
|
||||
|
||||
[ -f "${self_issue_cert_crt}" ] && { [ "${self_issue_cert_crt}" != "/usr/share/unblockneteasemusic/core/server.crt" ] && ln -sf "${self_issue_cert_crt}" "/usr/share/unblockneteasemusic/core/server.crt"; }
|
||||
[ -f "${self_issue_cert_key}" ] && { [ "${self_issue_cert_key}" != "/usr/share/unblockneteasemusic/core/server.key" ] && ln -sf "${self_issue_cert_key}" "/usr/share/unblockneteasemusic/core/server.key"; }
|
||||
|
||||
[ "${hijack_ways}" = "use_hosts" ] && { http_port="80"; https_port="443"; }
|
||||
if [ "${music_source}" = "default" ]; then
|
||||
nohup node "/usr/share/unblockneteasemusic/core/app.js" -a "${addr}" -p "${http_port}":"${https_port}" -e "${endpoint_url}" ${netease_server_ip} ${proxy_server_ip} ${strict_mode} >> "/tmp/unblockneteasemusic.log" 2>&1 &
|
||||
@ -150,7 +156,7 @@ start()
|
||||
[ "*$(uci get unblockneteasemusic.@unblockneteasemusic[0].pub_access 2>"/dev/null")*" = "*1*" ] && set_ports > "/dev/null" 2>&1
|
||||
|
||||
sed -i '/unblockneteasemusic/d' /etc/crontabs/root
|
||||
[ "${auto_update}" -eq "1" ] && echo "0 ${update_time} * * * /usr/share/unblockneteasemusic/update_core.sh" >> "/etc/crontabs/root"
|
||||
[ "${auto_update}" -eq "1" ] && echo "0 ${update_time} * * * /usr/share/unblockneteasemusic/update.sh update_core" >> "/etc/crontabs/root"
|
||||
echo "*/5 * * * * /usr/share/unblockneteasemusic/log_check.sh" >> "/etc/crontabs/root"
|
||||
/etc/init.d/cron restart > "/dev/null" 2>&1
|
||||
}
|
||||
@ -163,7 +169,7 @@ stop()
|
||||
/etc/init.d/cron restart > "/dev/null" 2>&1
|
||||
|
||||
sed -i '/unblockneteasemusic/d' "/etc/sysupgrade.conf"
|
||||
[ "${keep_core_when_upgrade}" -eq 1 ] && { echo "/usr/share/unblockneteasemusic/core/" >> "/etc/sysupgrade.conf"; echo "/usr/share/unblockneteasemusic/local_ver" >> "/etc/sysupgrade.conf"; }
|
||||
[ "${keep_core_when_upgrade}" -eq "1" ] && { echo "/usr/share/unblockneteasemusic/core/" >> "/etc/sysupgrade.conf"; echo "/usr/share/unblockneteasemusic/local_ver" >> "/etc/sysupgrade.conf"; }
|
||||
|
||||
rm -f "/tmp/unblockneteasemusic.log"
|
||||
|
||||
|
||||
@ -0,0 +1,120 @@
|
||||
#!/bin/bash
|
||||
# Created By [CTCGFW]Project OpenWRT
|
||||
# https://github.com/project-openwrt
|
||||
|
||||
function check_core_if_already_running(){
|
||||
running_tasks="$(ps |grep "unblockneteasemusic" |grep "update" |grep "core" |grep -v "grep" |awk '{print $1}' |wc -l)"
|
||||
[ "${running_tasks}" -gt "2" ] && echo -e "\nA task is already running." >>/tmp/unblockneteasemusic.log && exit 2
|
||||
}
|
||||
|
||||
function check_luci_if_already_running(){
|
||||
running_tasks="$(ps |grep "unblockneteasemusic" |grep "update" |grep "update_luci" |grep -v "grep" |awk '{print $1}' |wc -l)"
|
||||
[ "${running_tasks}" -gt "2" ] && echo -e "\nA task is already running." >>/tmp/unblockneteasemusic.log && exit 2
|
||||
}
|
||||
|
||||
function clean_log(){
|
||||
echo "" > /tmp/unblockneteasemusic.log
|
||||
}
|
||||
|
||||
function check_luci_latest_version(){
|
||||
luci_latest_ver="$(curl -s 'https://github.com/project-openwrt/luci-app-unblockneteasemusic/releases/latest'| grep -Eo '[0-9\.]+\-[0-9]+')"
|
||||
[ -z "${luci_latest_ver}" ] && echo -e "\nFailed to check latest LuCI version, please try again later." >>/tmp/unblockneteasemusic.log && exit 1
|
||||
if [ "$(opkg info 'luci-app-unblockneteasemusic' |sed -n '2p' |tr -d 'Version: ')" != "${luci_latest_ver}" ]; then
|
||||
clean_log
|
||||
echo -e "Local LuCI version: $(opkg info 'luci-app-unblockneteasemusic' |sed -n '2p' |tr -d 'Version: '), cloud LuCI version: ${luci_latest_ver}." >>/tmp/unblockneteasemusic.log
|
||||
update_luci
|
||||
else
|
||||
echo -e "\nLocal LuCI version: $(opkg info 'luci-app-unblockneteasemusic' |sed -n '2p' |tr -d 'Version: '), cloud LuCI version: ${luci_latest_ver}." >>/tmp/unblockneteasemusic.log
|
||||
echo -e "You're already using the latest LuCI version." >>/tmp/unblockneteasemusic.log
|
||||
exit 3
|
||||
fi
|
||||
}
|
||||
|
||||
function update_luci(){
|
||||
echo -e "Updating LuCI..." >>/tmp/unblockneteasemusic.log
|
||||
|
||||
mkdir -p "/tmp" >/dev/null 2>&1
|
||||
|
||||
curl -sL "https://github.com/project-openwrt/luci-app-unblockneteasemusic/releases/download/v${luci_latest_ver}/luci-app-unblockneteasemusic_${luci_latest_ver}_all.ipk" -o "/tmp/luci-app-unblockneteasemusic_${luci_latest_ver}_all.ipk" >/dev/null 2>&1
|
||||
opkg install "/tmp/luci-app-unblockneteasemusic_${luci_latest_ver}_all.ipk"
|
||||
rm -f "/tmp/luci-app-unblockneteasemusic_${luci_latest_ver}_all.ipk"
|
||||
rm -rf "/tmp/luci-indexcache" "/tmp/luci-modulecache"
|
||||
|
||||
if [ "$(opkg info 'luci-app-unblockneteasemusic' |sed -n '2p' |tr -d 'Version: ')" != "$1" ]; then
|
||||
echo -e "Failed to update LuCI." >>/tmp/unblockneteasemusic.log
|
||||
exit 1
|
||||
else
|
||||
touch "/usr/share/unblockneteasemusic/update_luci_successfully"
|
||||
fi
|
||||
|
||||
echo -e "Succeeded in updating LuCI." >/tmp/unblockneteasemusic.log
|
||||
echo -e "Current LuCI version: ${luci_latest_ver}.\n" >>/tmp/unblockneteasemusic.log
|
||||
}
|
||||
|
||||
function check_core_latest_version(){
|
||||
core_latest_ver="$(curl -s https://github.com/nondanee/UnblockNeteaseMusic/commits/master |tr -d '\n' |grep -Eo 'commit\/[0-9a-z]+' |sed -n 1p |sed 's#commit/##g')"
|
||||
[ -z "${core_latest_ver}" ] && echo -e "\nFailed to check latest core version, please try again later." >>/tmp/unblockneteasemusic.log && exit 1
|
||||
if [ ! -e "/usr/share/unblockneteasemusic/core_local_ver" ]; then
|
||||
clean_log
|
||||
echo -e "Local version: NOT FOUND, cloud version: ${core_latest_ver}." >>/tmp/unblockneteasemusic.log
|
||||
update_core
|
||||
else
|
||||
if [ "$(cat /usr/share/unblockneteasemusic/core_local_ver)" != "${core_latest_ver}" ]; then
|
||||
clean_log
|
||||
echo -e "Local core version: $(cat /usr/share/unblockneteasemusic/core_local_ver 2>/dev/null), cloud core version: ${core_latest_ver}." >>/tmp/unblockneteasemusic.log
|
||||
update_core
|
||||
else
|
||||
echo -e "\nLocal core version: $(cat /usr/share/unblockneteasemusic/core_local_ver 2>/dev/null), cloud core version: ${core_latest_ver}." >>/tmp/unblockneteasemusic.log
|
||||
echo -e "You're already using the latest core version." >>/tmp/unblockneteasemusic.log
|
||||
exit 3
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
function update_core(){
|
||||
echo -e "Updating core..." >>/tmp/unblockneteasemusic.log
|
||||
|
||||
mkdir -p "/usr/share/unblockneteasemusic/core" >/dev/null 2>&1
|
||||
rm -rf /usr/share/unblockneteasemusic/core/* >/dev/null 2>&1
|
||||
|
||||
curl -sL "https://github.com/nondanee/UnblockNeteaseMusic/archive/master.tar.gz" -o "/usr/share/unblockneteasemusic/core/core.tar.gz" >/dev/null 2>&1
|
||||
tar -zxf "/usr/share/unblockneteasemusic/core/core.tar.gz" -C "/usr/share/unblockneteasemusic/core/" >/dev/null 2>&1
|
||||
mv /usr/share/unblockneteasemusic/core/UnblockNeteaseMusic-master/* "/usr/share/unblockneteasemusic/core/"
|
||||
rm -rf "/usr/share/unblockneteasemusic/core/core.tar.gz" "/usr/share/unblockneteasemusic/core/UnblockNeteaseMusic-master" >/dev/null 2>&1
|
||||
|
||||
if [ ! -e "/usr/share/unblockneteasemusic/core/app.js" ]; then
|
||||
echo -e "Failed to download core." >>/tmp/unblockneteasemusic.log
|
||||
exit 1
|
||||
else
|
||||
[ "${update_core_from_luci}" == "y" ] && touch "/usr/share/unblockneteasemusic/update_core_successfully"
|
||||
echo -e "${core_latest_ver}" > /usr/share/unblockneteasemusic/core_local_ver
|
||||
[ "${non_restart}" != "y" ] && /etc/init.d/unblockneteasemusic restart
|
||||
fi
|
||||
|
||||
echo -e "Succeeded in updating core." >/tmp/unblockneteasemusic.log
|
||||
echo -e "Current core version: ${core_latest_ver}.\n" >>/tmp/unblockneteasemusic.log
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
"update_luci")
|
||||
check_luci_if_already_running
|
||||
check_luci_latest_version
|
||||
;;
|
||||
"update_core")
|
||||
check_core_if_already_running
|
||||
check_core_latest_version
|
||||
;;
|
||||
"update_core_non_restart")
|
||||
non_restart="y"
|
||||
check_core_if_already_running
|
||||
check_core_latest_version
|
||||
;;
|
||||
"update_core_from_luci")
|
||||
update_core_from_luci="y"
|
||||
check_core_if_already_running
|
||||
check_core_latest_version
|
||||
;;
|
||||
*)
|
||||
echo -e "Usage: ./update.sh {update_luci|update_core}"
|
||||
;;
|
||||
esac
|
||||
@ -1,64 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Created By [CTCGFW]Project OpenWRT
|
||||
# https://github.com/project-openwrt
|
||||
|
||||
function check_if_already_running(){
|
||||
running_tasks="$(ps |grep "unblockneteasemusic" |grep "update_core" |grep -v "grep" |awk '{print $1}' |wc -l)"
|
||||
[ "${running_tasks}" -gt "2" ] && echo -e "\nA task is already running." >>/tmp/unblockneteasemusic.log && exit 2
|
||||
}
|
||||
|
||||
function clean_log(){
|
||||
echo "" > /tmp/unblockneteasemusic.log
|
||||
}
|
||||
|
||||
function check_latest_version(){
|
||||
latest_ver="$(curl -s https://github.com/nondanee/UnblockNeteaseMusic/commits/master |tr -d '\n' |grep -Eo 'commit\/[0-9a-z]+' |sed -n 1p |sed 's#commit/##g')"
|
||||
[ -z "${latest_ver}" ] && echo -e "\nFailed to check latest version, please try again later." >>/tmp/unblockneteasemusic.log && exit 1
|
||||
if [ ! -e "/usr/share/unblockneteasemusic/local_ver" ]; then
|
||||
clean_log
|
||||
echo -e "Local version: NOT FOUND, cloud version: ${latest_ver}." >>/tmp/unblockneteasemusic.log
|
||||
update_core
|
||||
else
|
||||
if [ "$(cat /usr/share/unblockneteasemusic/local_ver)" != "${latest_ver}" ]; then
|
||||
clean_log
|
||||
echo -e "Local version: $(cat /usr/share/unblockneteasemusic/local_ver 2>/dev/null), cloud version: ${latest_ver}." >>/tmp/unblockneteasemusic.log
|
||||
update_core
|
||||
else
|
||||
echo -e "\nLocal version: $(cat /usr/share/unblockneteasemusic/local_ver 2>/dev/null), cloud version: ${latest_ver}." >>/tmp/unblockneteasemusic.log
|
||||
echo -e "You're already using the latest version." >>/tmp/unblockneteasemusic.log
|
||||
exit 3
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
function update_core(){
|
||||
echo -e "Updating core..." >>/tmp/unblockneteasemusic.log
|
||||
|
||||
mkdir -p "/usr/share/unblockneteasemusic/core" >/dev/null 2>&1
|
||||
rm -rf /usr/share/unblockneteasemusic/core/* >/dev/null 2>&1
|
||||
|
||||
curl -L "https://github.com/nondanee/UnblockNeteaseMusic/archive/master.tar.gz" -o "/usr/share/unblockneteasemusic/core/core.tar.gz" >/dev/null 2>&1
|
||||
tar -zxf "/usr/share/unblockneteasemusic/core/core.tar.gz" -C "/usr/share/unblockneteasemusic/core/" >/dev/null 2>&1
|
||||
mv /usr/share/unblockneteasemusic/core/UnblockNeteaseMusic-master/* "/usr/share/unblockneteasemusic/core/"
|
||||
rm -rf "/usr/share/unblockneteasemusic/core/core.tar.gz" "/usr/share/unblockneteasemusic/core/UnblockNeteaseMusic-master" >/dev/null 2>&1
|
||||
|
||||
if [ ! -e "/usr/share/unblockneteasemusic/core/app.js" ]; then
|
||||
echo -e "Failed to download core." >>/tmp/unblockneteasemusic.log
|
||||
exit 1
|
||||
else
|
||||
[ "${luci_update}" == "y" ] && touch "/usr/share/unblockneteasemusic/update_successfully"
|
||||
echo -e "${latest_ver}" > /usr/share/unblockneteasemusic/local_ver
|
||||
/etc/init.d/unblockneteasemusic restart
|
||||
fi
|
||||
|
||||
echo -e "Succeeded in updating core." >/tmp/unblockneteasemusic.log
|
||||
echo -e "Current version: ${latest_ver}.\n" >>/tmp/unblockneteasemusic.log
|
||||
}
|
||||
|
||||
function main(){
|
||||
check_if_already_running
|
||||
check_latest_version
|
||||
}
|
||||
|
||||
[ "$1" == "luci_update" ] && luci_update="y"
|
||||
main
|
||||
@ -8,8 +8,8 @@ include $(TOPDIR)/rules.mk
|
||||
|
||||
LUCI_TITLE:=Argon Theme
|
||||
LUCI_DEPENDS:=
|
||||
PKG_VERSION:=2.0
|
||||
PKG_RELEASE:=20200131
|
||||
PKG_VERSION:=2.1
|
||||
PKG_RELEASE:=20200206
|
||||
|
||||
include $(TOPDIR)/feeds/luci/luci.mk
|
||||
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
*/
|
||||
@import url("custom.css?v=1");
|
||||
/*
|
||||
* Icon Css and Fonts
|
||||
* Icon Css and Fonts
|
||||
*/
|
||||
@font-face {
|
||||
font-family: 'argon';
|
||||
@ -356,9 +356,10 @@ button,
|
||||
select,
|
||||
input,
|
||||
.cbi-dropdown {
|
||||
line-height: 1.5rem;
|
||||
height: 2.5rem;
|
||||
padding: 0.625rem 0.75rem;
|
||||
margin: 0.25rem 0;
|
||||
margin: 0.25rem 0.1rem;
|
||||
color: #8898aa;
|
||||
border: 1px solid #dee2e6;
|
||||
border-radius: 0.25rem;
|
||||
@ -607,11 +608,23 @@ header .fill .status * {
|
||||
margin-bottom: 1em;
|
||||
padding: 1rem;
|
||||
border: 0;
|
||||
border-radius: 0 !important;
|
||||
border-radius: 0.375rem !important;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16), 0 0 2px 0 rgba(0, 0, 0, 0.12);
|
||||
text-shadow: 1px 1px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
.alert.error,
|
||||
.alert-message.error {
|
||||
background-color: #ffd600;
|
||||
}
|
||||
.alert h4,
|
||||
.alert-message h4 {
|
||||
padding: 0rem 1.5rem 0.75rem 0rem;
|
||||
}
|
||||
.alert .btn,
|
||||
.alert-message .btn {
|
||||
height: auto;
|
||||
}
|
||||
.alert-message > h4 {
|
||||
font-size: 110%;
|
||||
font-weight: bold;
|
||||
@ -1532,10 +1545,13 @@ body:not(.Interfaces) .cbi-rowstyle-2:first-child {
|
||||
.cbi-dropdown > ul.preview {
|
||||
display: none;
|
||||
}
|
||||
.cbi-dropdown > ul.preview li {
|
||||
.cbi-button-apply > ul.preview {
|
||||
display: none;
|
||||
}
|
||||
.cbi-button-apply > ul.preview li {
|
||||
color: #fff;
|
||||
}
|
||||
.cbi-dropdown > ul:first-child li {
|
||||
.cbi-button-apply > ul:first-child li {
|
||||
color: #fff;
|
||||
}
|
||||
.cbi-dropdown > .open {
|
||||
@ -2264,18 +2280,24 @@ input[name="nslookup"] {
|
||||
.node-main-login .main .main-right #maincontent .container .alert-message.error {
|
||||
position: absolute;
|
||||
color: #fff;
|
||||
width: calc(100% - 4rem);
|
||||
width: calc(100% - 2rem);
|
||||
background-color: #f0ad4e;
|
||||
border-color: #eea236;
|
||||
box-sizing: border-box;
|
||||
margin-top: 8rem;
|
||||
border-radius: 5px;
|
||||
padding: 1rem 2rem;
|
||||
margin-top: -7rem;
|
||||
border-radius: 5px !important;
|
||||
padding: 1rem 2rem 0.5rem 2rem;
|
||||
text-align: center;
|
||||
}
|
||||
.node-main-login .main .main-right #maincontent .container .alert-message.error p {
|
||||
color: #fff;
|
||||
}
|
||||
.node-main-login .main .main-right #maincontent .container .alert-message.error h4 {
|
||||
font-size: 1rem;
|
||||
}
|
||||
.node-main-login .main .main-right #maincontent .container .alert-message.error .btn {
|
||||
height: auto;
|
||||
}
|
||||
.node-main-login .main .main-right #maincontent .container .cbi-map h2 {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
|
||||
File diff suppressed because one or more lines are too long
@ -29,7 +29,7 @@
|
||||
@import url("custom.css?v=1");
|
||||
|
||||
/*
|
||||
* Icon Css and Fonts
|
||||
* Icon Css and Fonts
|
||||
*/
|
||||
@font-face {
|
||||
font-family: 'argon';
|
||||
@ -417,9 +417,10 @@ button,
|
||||
select,
|
||||
input,
|
||||
.cbi-dropdown {
|
||||
line-height: 1.5rem;
|
||||
height: 2.5rem;
|
||||
padding: .625rem .75rem;
|
||||
margin: 0.25rem 0;
|
||||
margin: 0.25rem 0.1rem;
|
||||
color: #8898aa;
|
||||
border: 1px solid #dee2e6;
|
||||
|
||||
@ -714,10 +715,22 @@ header {
|
||||
margin-bottom: 1em;
|
||||
padding: 1rem;
|
||||
border: 0;
|
||||
border-radius: 0 !important;
|
||||
border-radius: 0.375rem !important;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .16), 0 0 2px 0 rgba(0, 0, 0, .12);
|
||||
text-shadow: 1px 1px rgba(0, 0, 0, .1);
|
||||
|
||||
&.error{
|
||||
background-color: #ffd600;
|
||||
}
|
||||
|
||||
h4{
|
||||
padding: 0rem 1.5rem 0.75rem 0rem;
|
||||
}
|
||||
|
||||
.btn{
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.alert-message>h4 {
|
||||
@ -1809,13 +1822,17 @@ body:not(.Interfaces) .cbi-rowstyle-2:first-child {
|
||||
.cbi-dropdown>ul.preview {
|
||||
display: none;
|
||||
|
||||
}
|
||||
.cbi-button-apply>ul.preview {
|
||||
display: none;
|
||||
|
||||
li {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.cbi-dropdown>ul:first-child {
|
||||
.cbi-button-apply>ul:first-child {
|
||||
li {
|
||||
color: #fff;
|
||||
}
|
||||
@ -2679,17 +2696,23 @@ input[name="nslookup"] {
|
||||
&.error {
|
||||
position: absolute;
|
||||
color: #fff;
|
||||
width: calc(100% - 4rem);
|
||||
width: calc(100% - 2rem);
|
||||
background-color: #f0ad4e;
|
||||
border-color: #eea236;
|
||||
box-sizing: border-box;
|
||||
margin-top: 8rem;
|
||||
border-radius: 5px;
|
||||
padding: 1rem 2rem;
|
||||
margin-top: -7rem;
|
||||
border-radius: 5px !important;
|
||||
padding: 1rem 2rem 0.5rem 2rem;
|
||||
text-align: center;
|
||||
p{
|
||||
color: #fff;
|
||||
}
|
||||
h4{
|
||||
font-size: 1rem;
|
||||
}
|
||||
.btn{
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,21 +1,24 @@
|
||||
/**
|
||||
* Material is a clean HTML5 theme for LuCI. It is based on luci-theme-bootstrap and MUI
|
||||
* Argon is a clean HTML5 theme for LuCI. It is based on luci-theme-material and Argon Template
|
||||
*
|
||||
* luci-theme-material
|
||||
* Copyright 2015 Lutty Yang <lutty@wcan.in>
|
||||
* luci-theme-argon
|
||||
* Copyright 2019 Jerrykuku <jerrykuku@qq.com>
|
||||
*
|
||||
* Have a bug? Please create an issue here on GitHub!
|
||||
* https://github.com/LuttyYang/luci-theme-material/issues
|
||||
* Have a bug? Please create an issue here on GitHub!
|
||||
* https://github.com/jerrykuku/luci-theme-argon/issues
|
||||
*
|
||||
* luci-theme-bootstrap:
|
||||
* Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
* Copyright 2008 Jo-Philipp Wich <jow@openwrt.org>
|
||||
* Copyright 2012 David Menting <david@nut-bolt.nl>
|
||||
* luci-theme-material:
|
||||
* Copyright 2015 Lutty Yang <lutty@wcan.in>
|
||||
* https://github.com/LuttyYang/luci-theme-material/
|
||||
*
|
||||
* MUI:
|
||||
* https://github.com/muicss/mui
|
||||
* Agron Theme
|
||||
* https://demos.creative-tim.com/argon-dashboard/index.html
|
||||
*
|
||||
* Licensed to the public under the Apache License 2.0
|
||||
* Login background
|
||||
* https://unsplash.com/
|
||||
* Font generate by Icomoon<icomoon.io>
|
||||
*
|
||||
* Licensed to the public under the Apache License 2.0
|
||||
*/
|
||||
|
||||
document.addEventListener('luci-loaded', function(ev) {
|
||||
|
||||
@ -16,27 +16,11 @@
|
||||
Licensed to the public under the Apache License 2.0
|
||||
-%>
|
||||
|
||||
<%
|
||||
local ver = require "luci.version"
|
||||
local disp = require "luci.dispatcher"
|
||||
local request = disp.context.path
|
||||
local category = request[1]
|
||||
local tree = disp.node()
|
||||
local categories = disp.node_childs(tree)
|
||||
%>
|
||||
<% local ver = require "luci.version" %>
|
||||
</div>
|
||||
<footer class="mobile-hide">
|
||||
<a href="https://github.com/openwrt/luci">Powered by <%= ver.luciname %> (<%= ver.luciversion %>)</a> / <%= ver.distversion %>
|
||||
<% if #categories > 1 then %>
|
||||
<ul class="breadcrumb pull-right" id="modemenu">
|
||||
<% for i, r in ipairs(categories) do %>
|
||||
<li<% if request[1] == r then %> class="active"<%end%>>
|
||||
<a href="<%=controller%>/<%=r%>/"><%=striptags(translate(tree.nodes[r].title))%></a>
|
||||
<span class="divider">|</span>
|
||||
</li>
|
||||
<% end %>
|
||||
</ul>
|
||||
<% end %>
|
||||
<ul class="breadcrumb pull-right" id="modemenu" style="display:none"></ul>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
@ -44,8 +28,8 @@
|
||||
// thanks for Jo-Philipp Wich <jow@openwrt.org>
|
||||
var luciLocation = <%= luci.http.write_json(luci.dispatcher.context.path) %>;
|
||||
</script>
|
||||
<script src="<%=media%>/js/jquery.min.js?v=git-20.029.45734-adbbd5c"></script>
|
||||
<script src="<%=media%>/js/script.js?v=git-20.029.45734-adbbd5c"></script>
|
||||
<script src="<%=media%>/js/jquery.min.js"></script>
|
||||
<script src="<%=media%>/js/script.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@ -17,146 +17,24 @@
|
||||
-%>
|
||||
|
||||
<%
|
||||
local sys = require "luci.sys"
|
||||
local sys = require "luci.sys"
|
||||
local util = require "luci.util"
|
||||
local http = require "luci.http"
|
||||
local disp = require "luci.dispatcher"
|
||||
local fs = require "nixio.fs"
|
||||
local nutil = require "nixio.util"
|
||||
|
||||
local boardinfo = util.ubus("system", "board")
|
||||
|
||||
local request = disp.context.path
|
||||
local request2 = disp.context.request
|
||||
|
||||
local category = request[1]
|
||||
local cattree = category and disp.node(category)
|
||||
|
||||
local leaf = request2[#request2]
|
||||
|
||||
local tree = disp.node()
|
||||
local node = disp.context.dispatched
|
||||
|
||||
local categories = disp.node_childs(tree)
|
||||
|
||||
local c = tree
|
||||
local i, r
|
||||
|
||||
-- tag all nodes leading to this page
|
||||
for i, r in ipairs(request) do
|
||||
if c.nodes and c.nodes[r] then
|
||||
c = c.nodes[r]
|
||||
c._menu_selected = true
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local fs = require "nixio.fs"
|
||||
local nutil = require "nixio.util"
|
||||
|
||||
|
||||
|
||||
-- send as HTML5
|
||||
http.prepare_content("text/html")
|
||||
|
||||
local function nodeurl(prefix, name, query)
|
||||
local u = url(prefix, name)
|
||||
if query then
|
||||
u = u .. http.build_querystring(query)
|
||||
end
|
||||
return pcdata(u)
|
||||
end
|
||||
|
||||
local function render_tabmenu(prefix, node, level)
|
||||
if not level then
|
||||
level = 1
|
||||
end
|
||||
|
||||
local childs = disp.node_childs(node)
|
||||
if #childs > 0 then
|
||||
if level > 2 then
|
||||
write('<ul class="tabs">')
|
||||
end
|
||||
|
||||
local selected_node
|
||||
local selected_name
|
||||
local i, v
|
||||
|
||||
for i, v in ipairs(childs) do
|
||||
local nnode = node.nodes[v]
|
||||
if nnode._menu_selected then
|
||||
selected_node = nnode
|
||||
selected_name = v
|
||||
end
|
||||
|
||||
if level > 2 then
|
||||
write('<li class="tabmenu-item-%s %s"><a href="%s">%s</a></li>' %{
|
||||
v, (nnode._menu_selected or (node.leaf and v == leaf)) and 'active' or '',
|
||||
nodeurl(prefix, v, nnode.query),
|
||||
striptags(translate(nnode.title))
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
if level > 2 then
|
||||
write('</ul>')
|
||||
end
|
||||
|
||||
if selected_node then
|
||||
render_tabmenu(prefix .. "/" .. selected_name, selected_node, level + 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function render_submenu(prefix, node)
|
||||
local childs = disp.node_childs(node)
|
||||
if #childs > 0 then
|
||||
write('<ul class="slide-menu">')
|
||||
|
||||
for i, r in ipairs(childs) do
|
||||
local nnode = node.nodes[r]
|
||||
local title = striptags(translate(nnode.title))
|
||||
|
||||
write('<li><a data-title="%s" href="%s">%s</a></li>' %{
|
||||
title,
|
||||
nodeurl(prefix, r, nnode.query),
|
||||
title
|
||||
})
|
||||
end
|
||||
|
||||
write('</ul>')
|
||||
end
|
||||
end
|
||||
|
||||
local function render_topmenu()
|
||||
local childs = disp.node_childs(cattree)
|
||||
if #childs > 0 then
|
||||
write('<ul class="nav">')
|
||||
|
||||
for i, r in ipairs(childs) do
|
||||
local nnode = cattree.nodes[r]
|
||||
local grandchildren = disp.node_childs(nnode)
|
||||
|
||||
if #grandchildren > 0 then
|
||||
local title = striptags(translate(nnode.title))
|
||||
local en_title = pcdata(striptags(string.gsub(nnode.title," ","_")))
|
||||
write('<li class="slide"><a class="menu" data-title="%s" href="#">%s</a>' %{
|
||||
en_title,
|
||||
title
|
||||
})
|
||||
|
||||
render_submenu(category .. "/" .. r, nnode)
|
||||
write('</li>')
|
||||
else
|
||||
local title = striptags(translate(nnode.title))
|
||||
local en_title = pcdata(striptags(nnode.title))
|
||||
write('<li class="lg"><a class="logout" data-title="%s" href="%s">%s</a></li>' %{
|
||||
en_title,
|
||||
nodeurl(category, r, nnode.query),
|
||||
title
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
write('</ul>')
|
||||
end
|
||||
end
|
||||
|
||||
math.randomseed(os.time())
|
||||
|
||||
math.randomseed(os.time())
|
||||
function glob(...)
|
||||
local iter, code, msg = fs.glob(...)
|
||||
if iter then
|
||||
@ -167,16 +45,21 @@
|
||||
end
|
||||
|
||||
local bgcount = 0
|
||||
for f in ipairs(glob("/www/luci-static/material/img/*")) do
|
||||
for f in ipairs(glob("/www/luci-static/argon/img/*")) do
|
||||
bgcount = bgcount + 1
|
||||
end
|
||||
|
||||
|
||||
-%>
|
||||
<!DOCTYPE html>
|
||||
<html lang="<%=luci.i18n.context.lang%>">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title><%=striptags( (boardinfo.hostname or "?") .. ( (node and node.title) and ' - ' .. translate(node.title) or '')) %> - LuCI</title>
|
||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport"/>
|
||||
<title>
|
||||
<%=striptags( (boardinfo.hostname or "?") .. ( (node and node.title) and ' - ' .. translate(node.title) or '')) %>
|
||||
- LuCI</title>
|
||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport" />
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="mobile-web-app-capable" content="yes">
|
||||
<meta name="theme-color" content="#09c">
|
||||
@ -184,82 +67,219 @@
|
||||
<meta name="msapplication-TileColor" content="#09c">
|
||||
<meta name="application-name" content="<%=striptags( (boardinfo.hostname or "?") ) %> - LuCI">
|
||||
<meta name="apple-mobile-web-app-title" content="<%=striptags( (boardinfo.hostname or "?") ) %> - LuCI">
|
||||
<meta name="msapplication-TileImage" content="<%=media%>/logo.png"/>
|
||||
<link rel="icon" href="<%=media%>/logo.png" sizes="144x144">
|
||||
<link rel="apple-touch-icon-precomposed" href="<%=media%>/logo.png" sizes="144x144">
|
||||
<link rel="stylesheet" href="<%=media%>/cascade.css?v=<%=math.random(1,100000)%>">
|
||||
<meta name="msapplication-TileImage" content="<%=media%>/logo.png" />
|
||||
<link rel="icon" href="<%=media%>/logo.png" sizes="144x144">
|
||||
<link rel="apple-touch-icon-precomposed" href="<%=media%>/logo.png" sizes="144x144">
|
||||
<link rel="stylesheet" href="<%=media%>/cascade.css">
|
||||
<link rel="shortcut icon" href="<%=media%>/favicon.ico">
|
||||
<% if node and node.css then %>
|
||||
<link rel="stylesheet" href="<%=resource%>/<%=node.css%>">
|
||||
<link rel="stylesheet" href="<%=resource%>/<%=node.css%>">
|
||||
<% end -%>
|
||||
<% if css then %>
|
||||
<style title="text/css"><%= css %></style>
|
||||
<style title="text/css">
|
||||
<%=css %>
|
||||
</style>
|
||||
<% end -%>
|
||||
<script src="<%=url('admin/translations', luci.i18n.context.lang)%>?v=git-20.029.45734-adbbd5c"></script>
|
||||
<script src="<%=resource%>/cbi.js?v=git-20.029.45734-adbbd5c"></script>
|
||||
<script src="<%=resource%>/xhr.js?v=git-20.029.45734-adbbd5c"></script>
|
||||
</head>
|
||||
<body class="lang_<%=luci.i18n.context.lang%> <% if node then %><%= striptags( node.title ) %><% end %> <% if luci.dispatcher.context.authsession then %>logged-in<% end %>" data-page="<%= table.concat(disp.context.requestpath, "-") %>">
|
||||
<script src="<%=url('admin/translations', luci.i18n.context.lang)%><%# ?v=PKG_VERSION %>"></script>
|
||||
<script src="<%=resource%>/cbi.js"></script>
|
||||
<script src="<%=resource%>/xhr.js"></script>
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
(function () {
|
||||
function get_children(node) {
|
||||
var children = [];
|
||||
|
||||
<div class="main">
|
||||
<div style="" class="loading">
|
||||
<div class="sk-folding-cube">
|
||||
<div class="sk-cube1 sk-cube"></div>
|
||||
<div class="sk-cube2 sk-cube"></div>
|
||||
<div class="sk-cube4 sk-cube"></div>
|
||||
<div class="sk-cube3 sk-cube"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="main-left">
|
||||
<div class="sidenav-header d-flex align-items-center">
|
||||
<a class="brand" href="#"><%=boardinfo.hostname or "?"%> ™</a>
|
||||
<div class="ml-auto">
|
||||
<!-- Sidenav toggler -->
|
||||
<div class="sidenav-toggler d-none d-xl-block active" data-action="sidenav-unpin" data-target="#sidenav-main">
|
||||
<div class="sidenav-toggler-inner">
|
||||
<i class="sidenav-toggler-line"></i>
|
||||
<i class="sidenav-toggler-line"></i>
|
||||
<i class="sidenav-toggler-line"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% render_topmenu() %>
|
||||
</div>
|
||||
<div class="main-right">
|
||||
<header class="bg-primary">
|
||||
<div class="fill">
|
||||
<div class="container">
|
||||
<a class="showSide"></a>
|
||||
<a class="brand" href="#"><%=boardinfo.hostname or "?"%> ™</a>
|
||||
<div class="pull-right">
|
||||
<span id="xhr_poll_status" style="display:none" onclick="XHR.running() ? XHR.halt() : XHR.run()">
|
||||
<span class="label success" id="xhr_poll_status_on"><span class="mobile-hide"><%:Auto Refresh%></span> <%:on%></span>
|
||||
<span class="label" id="xhr_poll_status_off" style="display:none"><span class="mobile-hide"><%:Auto Refresh%></span> <%:off%></span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<div class="darkMask"></div>
|
||||
<div class="login-bg" style="background-image:url(<%=media%>/img/bg<%=math.random(1,bgcount)%>.jpg)"></div>
|
||||
<div id="maincontent">
|
||||
<div class="container">
|
||||
<%- if luci.sys.process.info("uid") == 0 and luci.sys.user.getuser("root") and not luci.sys.user.getpasswd("root") then -%>
|
||||
<div class="alert-message warning">
|
||||
for (var k in node.children) {
|
||||
if (!node.children.hasOwnProperty(k))
|
||||
continue;
|
||||
|
||||
if (!node.children[k].satisfied)
|
||||
continue;
|
||||
|
||||
if (!node.children[k].hasOwnProperty('title'))
|
||||
continue;
|
||||
|
||||
children.push(Object.assign(node.children[k], { name: k }));
|
||||
}
|
||||
|
||||
return children.sort(function (a, b) {
|
||||
return ((a.order || 1000) - (b.order || 1000));
|
||||
});
|
||||
}
|
||||
|
||||
function render_mainmenu(tree, url, level) {
|
||||
var l = (level || 0) + 1,
|
||||
ul = E('ul', { 'class': level ? 'slide-menu' : 'nav' }),
|
||||
children = get_children(tree);
|
||||
if (children.length == 0 || l > 2)
|
||||
return E([]);
|
||||
|
||||
for (var i = 0; i < children.length; i++) {
|
||||
var submenu = render_mainmenu(children[i], url + '/' + children[i].name, l),
|
||||
hasChildren = submenu.children.length;
|
||||
isLogout = (children[i].name == 'logout');
|
||||
ul.appendChild(E('li', { 'class': hasChildren ? 'slide' : isLogout ? 'lg' : null }, [
|
||||
E('a', {
|
||||
'href': hasChildren ? '#' : L.url(url, children[i].name),
|
||||
'class': hasChildren ? 'menu' : isLogout?"logout":null,
|
||||
'data-title': children[i].title,
|
||||
}, [_(children[i].title)]),
|
||||
submenu
|
||||
]));
|
||||
}
|
||||
|
||||
if (l == 1) {
|
||||
var container = document.querySelector('#mainmenu');
|
||||
|
||||
container.appendChild(ul);
|
||||
container.style.display = '';
|
||||
}
|
||||
|
||||
return ul;
|
||||
}
|
||||
|
||||
function render_modemenu(tree) {
|
||||
var ul = document.querySelector('#modemenu'),
|
||||
children = get_children(tree);
|
||||
|
||||
for (var i = 0; i < children.length; i++) {
|
||||
var isActive = (L.env.requestpath.length ? children[i].name == L.env.requestpath[0] : i == 0);
|
||||
|
||||
ul.appendChild(E('li', {}, [
|
||||
E('a', {
|
||||
'href': L.url(children[i].name),
|
||||
'class': isActive ? 'active' : null
|
||||
}, [_(children[i].title)])
|
||||
]));
|
||||
|
||||
if (isActive)
|
||||
render_mainmenu(children[i], children[i].name);
|
||||
}
|
||||
|
||||
if (ul.children.length > 1)
|
||||
ul.style.display = '';
|
||||
}
|
||||
|
||||
function render_tabmenu(tree, url, level) {
|
||||
var container = document.querySelector('#tabmenu'),
|
||||
l = (level || 0) + 1,
|
||||
ul = E('ul', { 'class': 'tabs' }),
|
||||
children = get_children(tree),
|
||||
activeNode = null;
|
||||
|
||||
if (children.length == 0)
|
||||
return E([]);
|
||||
|
||||
for (var i = 0; i < children.length; i++) {
|
||||
var isActive = (L.env.dispatchpath[l + 2] == children[i].name),
|
||||
activeClass = isActive ? ' active' : '',
|
||||
className = 'tabmenu-item-%s %s'.format(children[i].name, activeClass);
|
||||
|
||||
ul.appendChild(E('li', { 'class': className }, [
|
||||
E('a', { 'href': L.url(url, children[i].name) }, [_(children[i].title)])
|
||||
]));
|
||||
|
||||
if (isActive)
|
||||
activeNode = children[i];
|
||||
}
|
||||
|
||||
container.appendChild(ul);
|
||||
container.style.display = '';
|
||||
|
||||
if (activeNode)
|
||||
container.appendChild(render_tabmenu(activeNode, url + '/' + activeNode.name, l));
|
||||
|
||||
return ul;
|
||||
}
|
||||
|
||||
document.addEventListener('luci-loaded', function (ev) {
|
||||
var tree = <%= luci.http.write_json(luci.dispatcher.menu_json() or { }) %>,
|
||||
node = tree,
|
||||
url = '';
|
||||
|
||||
render_modemenu(tree);
|
||||
|
||||
if (L.env.dispatchpath.length >= 3) {
|
||||
for (var i = 0; i < 3 && node; i++) {
|
||||
node = node.children[L.env.dispatchpath[i]];
|
||||
url = url + (url ? '/' : '') + L.env.dispatchpath[i];
|
||||
}
|
||||
|
||||
if (node)
|
||||
render_tabmenu(node, url);
|
||||
}
|
||||
});
|
||||
}) ();
|
||||
//]]></script>
|
||||
</head>
|
||||
|
||||
<body
|
||||
class="lang_<%=luci.i18n.context.lang%> <% if node then %><%= striptags( node.title ) %><% end %> <% if luci.dispatcher.context.authsession then %>logged-in<% end %>"
|
||||
data-page="<%= table.concat(disp.context.requestpath, "-") %>">
|
||||
|
||||
<div class="main">
|
||||
<div style="" class="loading">
|
||||
<div class="sk-folding-cube">
|
||||
<div class="sk-cube1 sk-cube"></div>
|
||||
<div class="sk-cube2 sk-cube"></div>
|
||||
<div class="sk-cube4 sk-cube"></div>
|
||||
<div class="sk-cube3 sk-cube"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="main-left" id="mainmenu" style="display:none">
|
||||
<div class="sidenav-header d-flex align-items-center">
|
||||
<a class="brand" href="#"><%=boardinfo.hostname or "?"%> ™</a>
|
||||
<div class="ml-auto">
|
||||
<!-- Sidenav toggler -->
|
||||
<div class="sidenav-toggler d-none d-xl-block active" data-action="sidenav-unpin"
|
||||
data-target="#sidenav-main">
|
||||
<div class="sidenav-toggler-inner">
|
||||
<i class="sidenav-toggler-line"></i>
|
||||
<i class="sidenav-toggler-line"></i>
|
||||
<i class="sidenav-toggler-line"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="main-right">
|
||||
<header class="bg-primary">
|
||||
<div class="fill">
|
||||
<div class="container">
|
||||
<a class="showSide"></a>
|
||||
<a class="brand" href="#"><%=boardinfo.hostname or "?"%> ™</a>
|
||||
<div class="pull-right">
|
||||
<span id="xhr_poll_status" style="display:none"
|
||||
onclick="XHR.running() ? XHR.halt() : XHR.run()">
|
||||
<span class="label success" id="xhr_poll_status_on"><span
|
||||
class="mobile-hide"><%:Auto Refresh%></span> <%:on%></span>
|
||||
<span class="label" id="xhr_poll_status_off" style="display:none"><span
|
||||
class="mobile-hide"><%:Auto Refresh%></span> <%:off%></span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<div class="darkMask"></div>
|
||||
<div class="login-bg" style="background-image:url(<%=media%>/img/bg<%=math.random(1,bgcount)%>.jpg)"></div>
|
||||
<div id="maincontent">
|
||||
<div class="container">
|
||||
<%- if luci.sys.process.info("uid") == 0 and luci.sys.user.getuser("root") and not luci.sys.user.getpasswd("root") then -%>
|
||||
<div class="alert-message error">
|
||||
<h4><%:No password set!%></h4>
|
||||
<p><%:There is no password set on this router. Please configure a root password to protect the web interface and enable SSH.%></p>
|
||||
<p><%:There is no password set on this router. Please configure a root password to protect the web interface and enable SSH.%>
|
||||
</p>
|
||||
<% if disp.lookup("admin/system/admin") then %>
|
||||
<div class="right"><a class="btn" href="<%=url("admin/system/admin")%>"><%:Go to password configuration...%></a></div>
|
||||
<div class="right"><a class="btn"
|
||||
href="<%=url("admin/system/admin")%>"><%:Go to password configuration...%></a></div>
|
||||
<% end %>
|
||||
</div>
|
||||
<%- end -%>
|
||||
<%- end -%>
|
||||
|
||||
<noscript>
|
||||
<div class="alert-message warning">
|
||||
<h4><%:JavaScript required!%></h4>
|
||||
<p><%:You must enable JavaScript in your browser or LuCI will not work properly.%></p>
|
||||
</div>
|
||||
</noscript>
|
||||
<noscript>
|
||||
<div class="alert-message error">
|
||||
<h4><%:JavaScript required!%></h4>
|
||||
<p><%:You must enable JavaScript in your browser or LuCI will not work properly.%></p>
|
||||
</div>
|
||||
</noscript>
|
||||
|
||||
<% if category then render_tabmenu(category, cattree) end %>
|
||||
<div id="tabmenu" style="display:none"></div>
|
||||
@ -52,6 +52,7 @@ endef
|
||||
define Package/speederv2-tunnel/install
|
||||
$(INSTALL_DIR) $(1)/usr/bin
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/speederv2_cross $(1)/usr/bin/speederv2
|
||||
( cd $(1)/usr/bin; $(LN) speederv2 udpspeeder; )
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,speederv2-tunnel))
|
||||
|
||||
Loading…
Reference in New Issue
Block a user