summaryrefslogtreecommitdiffhomepage
path: root/modules/luci-mod-system/luasrc/model/cbi
diff options
context:
space:
mode:
Diffstat (limited to 'modules/luci-mod-system/luasrc/model/cbi')
-rw-r--r--modules/luci-mod-system/luasrc/model/cbi/admin_system/admin.lua122
-rw-r--r--modules/luci-mod-system/luasrc/model/cbi/admin_system/backupfiles.lua80
-rw-r--r--modules/luci-mod-system/luasrc/model/cbi/admin_system/crontab.lua32
-rw-r--r--modules/luci-mod-system/luasrc/model/cbi/admin_system/fstab.lua270
-rw-r--r--modules/luci-mod-system/luasrc/model/cbi/admin_system/fstab/mount.lua151
-rw-r--r--modules/luci-mod-system/luasrc/model/cbi/admin_system/fstab/swap.lua54
-rw-r--r--modules/luci-mod-system/luasrc/model/cbi/admin_system/ipkg.lua64
-rw-r--r--modules/luci-mod-system/luasrc/model/cbi/admin_system/leds.lua158
-rw-r--r--modules/luci-mod-system/luasrc/model/cbi/admin_system/startup.lua97
-rw-r--r--modules/luci-mod-system/luasrc/model/cbi/admin_system/system.lua224
10 files changed, 1252 insertions, 0 deletions
diff --git a/modules/luci-mod-system/luasrc/model/cbi/admin_system/admin.lua b/modules/luci-mod-system/luasrc/model/cbi/admin_system/admin.lua
new file mode 100644
index 0000000000..6c1c1235c5
--- /dev/null
+++ b/modules/luci-mod-system/luasrc/model/cbi/admin_system/admin.lua
@@ -0,0 +1,122 @@
+-- Copyright 2008 Steven Barth <steven@midlink.org>
+-- Copyright 2011 Jo-Philipp Wich <jow@openwrt.org>
+-- Licensed to the public under the Apache License 2.0.
+
+local fs = require "nixio.fs"
+
+m = Map("system", translate("Router Password"),
+ translate("Changes the administrator password for accessing the device"))
+
+s = m:section(TypedSection, "_dummy", "")
+s.addremove = false
+s.anonymous = true
+
+pw1 = s:option(Value, "pw1", translate("Password"))
+pw1.password = true
+
+pw2 = s:option(Value, "pw2", translate("Confirmation"))
+pw2.password = true
+
+function s.cfgsections()
+ return { "_pass" }
+end
+
+function m.parse(map)
+ local v1 = pw1:formvalue("_pass")
+ local v2 = pw2:formvalue("_pass")
+
+ if v1 and v2 and #v1 > 0 and #v2 > 0 then
+ if v1 == v2 then
+ if luci.sys.user.setpasswd(luci.dispatcher.context.authuser, v1) == 0 then
+ m.message = translate("Password successfully changed!")
+ else
+ m.message = translate("Unknown Error, password not changed!")
+ end
+ else
+ m.message = translate("Given password confirmation did not match, password not changed!")
+ end
+ end
+
+ Map.parse(map)
+end
+
+
+if fs.access("/etc/config/dropbear") then
+
+m2 = Map("dropbear", translate("SSH Access"),
+ translate("Dropbear offers <abbr title=\"Secure Shell\">SSH</abbr> network shell access and an integrated <abbr title=\"Secure Copy\">SCP</abbr> server"))
+
+s = m2:section(TypedSection, "dropbear", translate("Dropbear Instance"))
+s.anonymous = true
+s.addremove = true
+
+
+ni = s:option(Value, "Interface", translate("Interface"),
+ translate("Listen only on the given interface or, if unspecified, on all"))
+
+ni.template = "cbi/network_netlist"
+ni.nocreate = true
+ni.unspecified = true
+
+
+pt = s:option(Value, "Port", translate("Port"),
+ translate("Specifies the listening port of this <em>Dropbear</em> instance"))
+
+pt.datatype = "port"
+pt.default = 22
+
+
+pa = s:option(Flag, "PasswordAuth", translate("Password authentication"),
+ translate("Allow <abbr title=\"Secure Shell\">SSH</abbr> password authentication"))
+
+pa.enabled = "on"
+pa.disabled = "off"
+pa.default = pa.enabled
+pa.rmempty = false
+
+
+ra = s:option(Flag, "RootPasswordAuth", translate("Allow root logins with password"),
+ translate("Allow the <em>root</em> user to login with password"))
+
+ra.enabled = "on"
+ra.disabled = "off"
+ra.default = ra.enabled
+
+
+gp = s:option(Flag, "GatewayPorts", translate("Gateway ports"),
+ translate("Allow remote hosts to connect to local SSH forwarded ports"))
+
+gp.enabled = "on"
+gp.disabled = "off"
+gp.default = gp.disabled
+
+
+s2 = m2:section(TypedSection, "_dummy", translate("SSH-Keys"),
+ translate("Here you can paste public SSH-Keys (one per line) for SSH public-key authentication."))
+s2.addremove = false
+s2.anonymous = true
+s2.template = "cbi/tblsection"
+
+function s2.cfgsections()
+ return { "_keys" }
+end
+
+keys = s2:option(TextValue, "_data", "")
+keys.wrap = "off"
+keys.rows = 3
+
+function keys.cfgvalue()
+ return fs.readfile("/etc/dropbear/authorized_keys") or ""
+end
+
+function keys.write(self, section, value)
+ return fs.writefile("/etc/dropbear/authorized_keys", value:gsub("\r\n", "\n"))
+end
+
+function keys.remove(self, section, value)
+ return fs.writefile("/etc/dropbear/authorized_keys", "")
+end
+
+end
+
+return m, m2
diff --git a/modules/luci-mod-system/luasrc/model/cbi/admin_system/backupfiles.lua b/modules/luci-mod-system/luasrc/model/cbi/admin_system/backupfiles.lua
new file mode 100644
index 0000000000..ee2401e93d
--- /dev/null
+++ b/modules/luci-mod-system/luasrc/model/cbi/admin_system/backupfiles.lua
@@ -0,0 +1,80 @@
+-- Copyright 2008 Steven Barth <steven@midlink.org>
+-- Copyright 2011 Jo-Philipp Wich <jow@openwrt.org>
+-- Licensed to the public under the Apache License 2.0.
+
+if luci.http.formvalue("cbid.luci.1._list") then
+ luci.http.redirect(luci.dispatcher.build_url("admin/system/flashops/backupfiles") .. "?display=list")
+elseif luci.http.formvalue("cbid.luci.1._edit") then
+ luci.http.redirect(luci.dispatcher.build_url("admin/system/flashops/backupfiles") .. "?display=edit")
+ return
+end
+
+m = SimpleForm("luci", translate("Backup file list"))
+m:append(Template("admin_system/backupfiles"))
+
+if luci.http.formvalue("display") ~= "list" then
+ f = m:section(SimpleSection, nil, translate("This is a list of shell glob patterns for matching files and directories to include during sysupgrade. Modified files in /etc/config/ and certain other configurations are automatically preserved."))
+
+ l = f:option(Button, "_list", translate("Show current backup file list"))
+ l.inputtitle = translate("Open list...")
+ l.inputstyle = "apply"
+
+ c = f:option(TextValue, "_custom")
+ c.rmempty = false
+ c.cols = 70
+ c.rows = 30
+
+ c.cfgvalue = function(self, section)
+ return nixio.fs.readfile("/etc/sysupgrade.conf")
+ end
+
+ c.write = function(self, section, value)
+ value = value:gsub("\r\n?", "\n")
+ return nixio.fs.writefile("/etc/sysupgrade.conf", value)
+ end
+else
+ m.submit = false
+ m.reset = false
+
+ f = m:section(SimpleSection, nil, translate("Below is the determined list of files to backup. It consists of changed configuration files marked by opkg, essential base files and the user defined backup patterns."))
+
+ l = f:option(Button, "_edit", translate("Back to configuration"))
+ l.inputtitle = translate("Close list...")
+ l.inputstyle = "link"
+
+
+ d = f:option(DummyValue, "_detected")
+ d.rawhtml = true
+ d.cfgvalue = function(s)
+ local list = io.popen(
+ "( find $(sed -ne '/^[[:space:]]*$/d; /^#/d; p' /etc/sysupgrade.conf " ..
+ "/lib/upgrade/keep.d/* 2>/dev/null) -type f 2>/dev/null; " ..
+ "opkg list-changed-conffiles ) | sort -u"
+ )
+
+ if list then
+ local files = { "<ul>" }
+
+ while true do
+ local ln = list:read("*l")
+ if not ln then
+ break
+ else
+ files[#files+1] = "<li>"
+ files[#files+1] = luci.util.pcdata(ln)
+ files[#files+1] = "</li>"
+ end
+ end
+
+ list:close()
+ files[#files+1] = "</ul>"
+
+ return table.concat(files, "")
+ end
+
+ return "<em>" .. translate("No files found") .. "</em>"
+ end
+
+end
+
+return m
diff --git a/modules/luci-mod-system/luasrc/model/cbi/admin_system/crontab.lua b/modules/luci-mod-system/luasrc/model/cbi/admin_system/crontab.lua
new file mode 100644
index 0000000000..016a6199aa
--- /dev/null
+++ b/modules/luci-mod-system/luasrc/model/cbi/admin_system/crontab.lua
@@ -0,0 +1,32 @@
+-- Copyright 2008 Steven Barth <steven@midlink.org>
+-- Copyright 2008-2013 Jo-Philipp Wich <jow@openwrt.org>
+-- Licensed to the public under the Apache License 2.0.
+
+local fs = require "nixio.fs"
+local cronfile = "/etc/crontabs/root"
+
+f = SimpleForm("crontab", translate("Scheduled Tasks"),
+ translate("This is the system crontab in which scheduled tasks can be defined.") ..
+ translate("<br/>Note: you need to manually restart the cron service if the " ..
+ "crontab file was empty before editing."))
+
+t = f:field(TextValue, "crons")
+t.rmempty = true
+t.rows = 10
+function t.cfgvalue()
+ return fs.readfile(cronfile) or ""
+end
+
+function f.handle(self, state, data)
+ if state == FORM_VALID then
+ if data.crons then
+ fs.writefile(cronfile, data.crons:gsub("\r\n", "\n"))
+ luci.sys.call("/usr/bin/crontab %q" % cronfile)
+ else
+ fs.writefile(cronfile, "")
+ end
+ end
+ return true
+end
+
+return f
diff --git a/modules/luci-mod-system/luasrc/model/cbi/admin_system/fstab.lua b/modules/luci-mod-system/luasrc/model/cbi/admin_system/fstab.lua
new file mode 100644
index 0000000000..3ce5351bf0
--- /dev/null
+++ b/modules/luci-mod-system/luasrc/model/cbi/admin_system/fstab.lua
@@ -0,0 +1,270 @@
+-- Copyright 2008 Steven Barth <steven@midlink.org>
+-- Licensed to the public under the Apache License 2.0.
+
+require("luci.tools.webadmin")
+
+local fs = require "nixio.fs"
+local util = require "nixio.util"
+local tp = require "luci.template.parser"
+
+local block = io.popen("block info", "r")
+local ln, dev, devices = nil, nil, {}
+
+repeat
+ ln = block:read("*l")
+ dev = ln and ln:match("^/dev/(.-):")
+
+ if dev then
+ local e, s, key, val = { }
+
+ for key, val in ln:gmatch([[(%w+)="(.-)"]]) do
+ e[key:lower()] = val
+ devices[val] = e
+ end
+
+ s = tonumber((fs.readfile("/sys/class/block/%s/size" % dev)))
+
+ e.dev = "/dev/%s" % dev
+ e.size = s and math.floor(s / 2048)
+
+ devices[e.dev] = e
+ end
+until not ln
+
+block:close()
+
+m = Map("fstab", translate("Mount Points"))
+s = m:section(TypedSection, "global", translate("Global Settings"))
+s.addremove = false
+s.anonymous = true
+
+detect = s:option(Button, "block_detect", translate("Generate Config"), translate("Find all currently attached filesystems and swap and replace configuration with defaults based on what was detected"))
+detect.inputstyle = "reload"
+
+detect.write = function(self, section)
+ luci.sys.call("block detect >/etc/config/fstab")
+ luci.http.redirect(luci.dispatcher.build_url("admin/system", "fstab"))
+end
+
+o = s:option(Flag, "anon_swap", translate("Anonymous Swap"), translate("Mount swap not specifically configured"))
+o.default = o.disabled
+o.rmempty = false
+
+o = s:option(Flag, "anon_mount", translate("Anonymous Mount"), translate("Mount filesystems not specifically configured"))
+o.default = o.disabled
+o.rmempty = false
+
+o = s:option(Flag, "auto_swap", translate("Automount Swap"), translate("Automatically mount swap on hotplug"))
+o.default = o.enabled
+o.rmempty = false
+
+o = s:option(Flag, "auto_mount", translate("Automount Filesystem"), translate("Automatically mount filesystems on hotplug"))
+o.default = o.enabled
+o.rmempty = false
+
+o = s:option(Flag, "check_fs", translate("Check filesystems before mount"), translate("Automatically check filesystem for errors before mounting"))
+o.default = o.disabled
+o.rmempty = false
+
+local mounts = luci.sys.mounts()
+local non_system_mounts = {}
+for rawmount, val in pairs(mounts) do
+ if (string.find(val.mountpoint, "/tmp/.jail") == nil) then
+ repeat
+ val.umount = false
+ if (val.mountpoint == "/") then
+ break
+ elseif (val.mountpoint == "/overlay") then
+ break
+ elseif (val.mountpoint == "/rom") then
+ break
+ elseif (val.mountpoint == "/tmp") then
+ break
+ elseif (val.mountpoint == "/tmp/shm") then
+ break
+ elseif (val.mountpoint == "/tmp/upgrade") then
+ break
+ elseif (val.mountpoint == "/dev") then
+ break
+ end
+ val.umount = true
+ until true
+ non_system_mounts[rawmount] = val
+ end
+end
+
+v = m:section(Table, non_system_mounts, translate("Mounted file systems"))
+
+fs = v:option(DummyValue, "fs", translate("Filesystem"))
+
+mp = v:option(DummyValue, "mountpoint", translate("Mount Point"))
+
+avail = v:option(DummyValue, "avail", translate("Available"))
+function avail.cfgvalue(self, section)
+ return luci.tools.webadmin.byte_format(
+ ( tonumber(mounts[section].available) or 0 ) * 1024
+ ) .. " / " .. luci.tools.webadmin.byte_format(
+ ( tonumber(mounts[section].blocks) or 0 ) * 1024
+ )
+end
+
+used = v:option(DummyValue, "used", translate("Used"))
+function used.cfgvalue(self, section)
+ return ( mounts[section].percent or "0%" ) .. " (" ..
+ luci.tools.webadmin.byte_format(
+ ( tonumber(mounts[section].used) or 0 ) * 1024
+ ) .. ")"
+end
+
+unmount = v:option(Button, "unmount", translate("Unmount"))
+unmount.render = function(self, section, scope)
+ if non_system_mounts[section].umount then
+ self.title = translate("Unmount")
+ self.inputstyle = "remove"
+ Button.render(self, section, scope)
+ end
+end
+
+unmount.write = function(self, section)
+ if non_system_mounts[section].umount then
+ luci.sys.call("/bin/umount '%s'" % luci.util.shellstartsqescape(non_system_mounts[section].mountpoint))
+ return luci.http.redirect(luci.dispatcher.build_url("admin/system", "fstab"))
+ end
+end
+
+mount = m:section(TypedSection, "mount", translate("Mount Points"), translate("Mount Points define at which point a memory device will be attached to the filesystem"))
+mount.anonymous = true
+mount.addremove = true
+mount.template = "cbi/tblsection"
+mount.extedit = luci.dispatcher.build_url("admin/system/fstab/mount/%s")
+
+mount.create = function(...)
+ local sid = TypedSection.create(...)
+ if sid then
+ luci.http.redirect(mount.extedit % sid)
+ return
+ end
+end
+
+
+mount:option(Flag, "enabled", translate("Enabled")).rmempty = false
+
+dev = mount:option(DummyValue, "device", translate("Device"))
+dev.rawhtml = true
+dev.cfgvalue = function(self, section)
+ local v, e
+
+ v = m.uci:get("fstab", section, "uuid")
+ e = v and devices[v:lower()]
+ if v and e and e.size then
+ return "UUID: %s (%s, %d MB)" %{ tp.pcdata(v), e.dev, e.size }
+ elseif v and e then
+ return "UUID: %s (%s)" %{ tp.pcdata(v), e.dev }
+ elseif v then
+ return "UUID: %s (<em>%s</em>)" %{ tp.pcdata(v), translate("not present") }
+ end
+
+ v = m.uci:get("fstab", section, "label")
+ e = v and devices[v]
+ if v and e and e.size then
+ return "Label: %s (%s, %d MB)" %{ tp.pcdata(v), e.dev, e.size }
+ elseif v and e then
+ return "Label: %s (%s)" %{ tp.pcdata(v), e.dev }
+ elseif v then
+ return "Label: %s (<em>%s</em>)" %{ tp.pcdata(v), translate("not present") }
+ end
+
+ v = Value.cfgvalue(self, section) or "?"
+ e = v and devices[v]
+ if v and e and e.size then
+ return "%s (%d MB)" %{ tp.pcdata(v), e.size }
+ elseif v and e then
+ return tp.pcdata(v)
+ elseif v then
+ return "%s (<em>%s</em>)" %{ tp.pcdata(v), translate("not present") }
+ end
+end
+
+mp = mount:option(DummyValue, "target", translate("Mount Point"))
+mp.cfgvalue = function(self, section)
+ if m.uci:get("fstab", section, "is_rootfs") == "1" then
+ return "/overlay"
+ else
+ return Value.cfgvalue(self, section) or "?"
+ end
+end
+
+fs = mount:option(DummyValue, "fstype", translate("Filesystem"))
+fs.cfgvalue = function(self, section)
+ local v, e
+
+ v = m.uci:get("fstab", section, "uuid")
+ v = v and v:lower() or m.uci:get("fstab", section, "label")
+ v = v or m.uci:get("fstab", section, "device")
+
+ e = v and devices[v]
+
+ return e and e.type or m.uci:get("fstab", section, "fstype") or "?"
+end
+
+op = mount:option(DummyValue, "options", translate("Options"))
+op.cfgvalue = function(self, section)
+ return Value.cfgvalue(self, section) or "defaults"
+end
+
+rf = mount:option(DummyValue, "is_rootfs", translate("Root"))
+rf.cfgvalue = function(self, section)
+ local target = m.uci:get("fstab", section, "target")
+ if target == "/" then
+ return translate("yes")
+ elseif target == "/overlay" then
+ return translate("overlay")
+ else
+ return translate("no")
+ end
+end
+
+ck = mount:option(DummyValue, "enabled_fsck", translate("Check"))
+ck.cfgvalue = function(self, section)
+ return Value.cfgvalue(self, section) == "1"
+ and translate("yes") or translate("no")
+end
+
+
+swap = m:section(TypedSection, "swap", "SWAP", translate("If your physical memory is insufficient unused data can be temporarily swapped to a swap-device resulting in a higher amount of usable <abbr title=\"Random Access Memory\">RAM</abbr>. Be aware that swapping data is a very slow process as the swap-device cannot be accessed with the high datarates of the <abbr title=\"Random Access Memory\">RAM</abbr>."))
+swap.anonymous = true
+swap.addremove = true
+swap.template = "cbi/tblsection"
+swap.extedit = luci.dispatcher.build_url("admin/system/fstab/swap/%s")
+
+swap.create = function(...)
+ local sid = TypedSection.create(...)
+ if sid then
+ luci.http.redirect(swap.extedit % sid)
+ return
+ end
+end
+
+
+swap:option(Flag, "enabled", translate("Enabled")).rmempty = false
+
+dev = swap:option(DummyValue, "device", translate("Device"))
+dev.cfgvalue = function(self, section)
+ local v
+
+ v = m.uci:get("fstab", section, "uuid")
+ if v then return "UUID: %s" % v end
+
+ v = m.uci:get("fstab", section, "label")
+ if v then return "Label: %s" % v end
+
+ v = Value.cfgvalue(self, section) or "?"
+ e = v and devices[v]
+ if v and e and e.size then
+ return "%s (%s MB)" % {v, e.size}
+ else
+ return v
+ end
+end
+
+return m
diff --git a/modules/luci-mod-system/luasrc/model/cbi/admin_system/fstab/mount.lua b/modules/luci-mod-system/luasrc/model/cbi/admin_system/fstab/mount.lua
new file mode 100644
index 0000000000..a85872afad
--- /dev/null
+++ b/modules/luci-mod-system/luasrc/model/cbi/admin_system/fstab/mount.lua
@@ -0,0 +1,151 @@
+-- Copyright 2010 Jo-Philipp Wich <jow@openwrt.org>
+-- Licensed to the public under the Apache License 2.0.
+
+local fs = require "nixio.fs"
+local util = require "nixio.util"
+
+local has_fscheck = fs.access("/usr/sbin/e2fsck")
+
+local block = io.popen("block info", "r")
+local ln, dev, devices = nil, nil, {}
+
+repeat
+ ln = block:read("*l")
+ dev = ln and ln:match("^/dev/(.-):")
+
+ if dev then
+ local e, s, key, val = { }
+
+ for key, val in ln:gmatch([[(%w+)="(.-)"]]) do
+ e[key:lower()] = val
+ end
+
+ s = tonumber((fs.readfile("/sys/class/block/%s/size" % dev)))
+
+ e.dev = "/dev/%s" % dev
+ e.size = s and math.floor(s / 2048)
+
+ devices[#devices+1] = e
+ end
+until not ln
+
+block:close()
+
+
+m = Map("fstab", translate("Mount Points - Mount Entry"))
+m.redirect = luci.dispatcher.build_url("admin/system/fstab")
+
+if not arg[1] or m.uci:get("fstab", arg[1]) ~= "mount" then
+ luci.http.redirect(m.redirect)
+ return
+end
+
+
+
+mount = m:section(NamedSection, arg[1], "mount", translate("Mount Entry"))
+mount.anonymous = true
+mount.addremove = false
+
+mount:tab("general", translate("General Settings"))
+mount:tab("advanced", translate("Advanced Settings"))
+
+
+mount:taboption("general", Flag, "enabled", translate("Enable this mount")).rmempty = false
+
+
+o = mount:taboption("general", Value, "uuid", translate("UUID"),
+ translate("If specified, mount the device by its UUID instead of a fixed device node"))
+
+o:value("", translate("-- match by uuid --"))
+
+for i, d in ipairs(devices) do
+ if d.uuid and d.size then
+ o:value(d.uuid, "%s (%s, %d MB)" %{ d.uuid, d.dev, d.size })
+ elseif d.uuid then
+ o:value(d.uuid, "%s (%s)" %{ d.uuid, d.dev })
+ end
+end
+
+
+o = mount:taboption("general", Value, "label", translate("Label"),
+ translate("If specified, mount the device by the partition label instead of a fixed device node"))
+
+o:value("", translate("-- match by label --"))
+
+o:depends("uuid", "")
+
+for i, d in ipairs(devices) do
+ if d.label and d.size then
+ o:value(d.label, "%s (%s, %d MB)" %{ d.label, d.dev, d.size })
+ elseif d.label then
+ o:value(d.label, "%s (%s)" %{ d.label, d.dev })
+ end
+end
+
+
+o = mount:taboption("general", Value, "device", translate("Device"),
+ translate("The device file of the memory or partition (<abbr title=\"for example\">e.g.</abbr> <code>/dev/sda1</code>)"))
+
+o:value("", translate("-- match by device --"))
+
+o:depends({ uuid = "", label = "" })
+
+for i, d in ipairs(devices) do
+ if d.size then
+ o:value(d.dev, "%s (%d MB)" %{ d.dev, d.size })
+ else
+ o:value(d.dev)
+ end
+end
+
+
+o = mount:taboption("general", Value, "target", translate("Mount point"),
+ translate("Specifies the directory the device is attached to"))
+
+o:value("/", translate("Use as root filesystem (/)"))
+o:value("/overlay", translate("Use as external overlay (/overlay)"))
+
+
+o = mount:taboption("general", DummyValue, "__notice", translate("Root preparation"))
+o:depends("target", "/")
+o.rawhtml = true
+o.default = [[
+<p>%s</p><pre>mkdir -p /tmp/introot
+mkdir -p /tmp/extroot
+mount --bind / /tmp/introot
+mount /dev/sda1 /tmp/extroot
+tar -C /tmp/introot -cvf - . | tar -C /tmp/extroot -xf -
+umount /tmp/introot
+umount /tmp/extroot</pre>
+]] %{
+ translate("Make sure to clone the root filesystem using something like the commands below:"),
+
+}
+
+
+o = mount:taboption("advanced", Value, "fstype", translate("Filesystem"),
+ translate("The filesystem that was used to format the memory (<abbr title=\"for example\">e.g.</abbr> <samp><abbr title=\"Third Extended Filesystem\">ext3</abbr></samp>)"))
+
+o:value("", "auto")
+
+local fs
+for fs in io.lines("/proc/filesystems") do
+ fs = fs:match("%S+")
+ if fs ~= "nodev" then
+ o:value(fs)
+ end
+end
+
+
+o = mount:taboption("advanced", Value, "options", translate("Mount options"),
+ translate("See \"mount\" manpage for details"))
+
+o.placeholder = "defaults"
+
+
+if has_fscheck then
+ o = mount:taboption("advanced", Flag, "enabled_fsck", translate("Run filesystem check"),
+ translate("Run a filesystem check before mounting the device"))
+end
+
+return m
diff --git a/modules/luci-mod-system/luasrc/model/cbi/admin_system/fstab/swap.lua b/modules/luci-mod-system/luasrc/model/cbi/admin_system/fstab/swap.lua
new file mode 100644
index 0000000000..82468d5fcc
--- /dev/null
+++ b/modules/luci-mod-system/luasrc/model/cbi/admin_system/fstab/swap.lua
@@ -0,0 +1,54 @@
+-- Copyright 2010 Jo-Philipp Wich <jow@openwrt.org>
+-- Licensed to the public under the Apache License 2.0.
+
+local fs = require "nixio.fs"
+local util = require "nixio.util"
+
+local devices = {}
+util.consume((fs.glob("/dev/sd*")), devices)
+util.consume((fs.glob("/dev/hd*")), devices)
+util.consume((fs.glob("/dev/scd*")), devices)
+util.consume((fs.glob("/dev/mmc*")), devices)
+
+local size = {}
+for i, dev in ipairs(devices) do
+ local s = tonumber((fs.readfile("/sys/class/block/%s/size" % dev:sub(6))))
+ size[dev] = s and math.floor(s / 2048)
+end
+
+
+m = Map("fstab", translate("Mount Points - Swap Entry"))
+m.redirect = luci.dispatcher.build_url("admin/system/fstab")
+
+if not arg[1] or m.uci:get("fstab", arg[1]) ~= "swap" then
+ luci.http.redirect(m.redirect)
+ return
+end
+
+
+mount = m:section(NamedSection, arg[1], "swap", translate("Swap Entry"))
+mount.anonymous = true
+mount.addremove = false
+
+mount:tab("general", translate("General Settings"))
+mount:tab("advanced", translate("Advanced Settings"))
+
+
+mount:taboption("general", Flag, "enabled", translate("Enable this swap")).rmempty = false
+
+
+o = mount:taboption("general", Value, "device", translate("Device"),
+ translate("The device file of the memory or partition (<abbr title=\"for example\">e.g.</abbr> <code>/dev/sda1</code>)"))
+
+for i, d in ipairs(devices) do
+ o:value(d, size[d] and "%s (%s MB)" % {d, size[d]})
+end
+
+o = mount:taboption("advanced", Value, "uuid", translate("UUID"),
+ translate("If specified, mount the device by its UUID instead of a fixed device node"))
+
+o = mount:taboption("advanced", Value, "label", translate("Label"),
+ translate("If specified, mount the device by the partition label instead of a fixed device node"))
+
+
+return m
diff --git a/modules/luci-mod-system/luasrc/model/cbi/admin_system/ipkg.lua b/modules/luci-mod-system/luasrc/model/cbi/admin_system/ipkg.lua
new file mode 100644
index 0000000000..7c6d7e1c66
--- /dev/null
+++ b/modules/luci-mod-system/luasrc/model/cbi/admin_system/ipkg.lua
@@ -0,0 +1,64 @@
+-- Copyright 2008 Steven Barth <steven@midlink.org>
+-- Copyright 2008-2011 Jo-Philipp Wich <jow@openwrt.org>
+-- Licensed to the public under the Apache License 2.0.
+
+local ipkgfile = "/etc/opkg.conf"
+local distfeeds = "/etc/opkg/distfeeds.conf"
+local customfeeds = "/etc/opkg/customfeeds.conf"
+
+f = SimpleForm("ipkgconf", translate("OPKG-Configuration"), translate("General options for opkg"))
+
+f:append(Template("admin_system/ipkg"))
+
+t = f:field(TextValue, "lines")
+t.wrap = "off"
+t.rows = 10
+function t.cfgvalue()
+ return nixio.fs.readfile(ipkgfile) or ""
+end
+
+function t.write(self, section, data)
+ return nixio.fs.writefile(ipkgfile, data:gsub("\r\n", "\n"))
+end
+
+function f.handle(self, state, data)
+ return true
+end
+
+g = SimpleForm("distfeedconf", translate("Distribution feeds"),
+ translate("Build/distribution specific feed definitions. This file will NOT be preserved in any sysupgrade."))
+
+d = g:field(TextValue, "lines2")
+d.wrap = "off"
+d.rows = 10
+function d.cfgvalue()
+ return nixio.fs.readfile(distfeeds) or ""
+end
+
+function d.write(self, section, data)
+ return nixio.fs.writefile(distfeeds, data:gsub("\r\n", "\n"))
+end
+
+function g.handle(self, state, data)
+ return true
+end
+
+h = SimpleForm("customfeedconf", translate("Custom feeds"),
+ translate("Custom feed definitions, e.g. private feeds. This file can be preserved in a sysupgrade."))
+
+c = h:field(TextValue, "lines3")
+c.wrap = "off"
+c.rows = 10
+function c.cfgvalue()
+ return nixio.fs.readfile(customfeeds) or ""
+end
+
+function c.write(self, section, data)
+ return nixio.fs.writefile(customfeeds, data:gsub("\r\n", "\n"))
+end
+
+function h.handle(self, state, data)
+ return true
+end
+
+return f, g, h
diff --git a/modules/luci-mod-system/luasrc/model/cbi/admin_system/leds.lua b/modules/luci-mod-system/luasrc/model/cbi/admin_system/leds.lua
new file mode 100644
index 0000000000..2ea044e16a
--- /dev/null
+++ b/modules/luci-mod-system/luasrc/model/cbi/admin_system/leds.lua
@@ -0,0 +1,158 @@
+-- Copyright 2008 Steven Barth <steven@midlink.org>
+-- Licensed to the public under the Apache License 2.0.
+
+m = Map("system", translate("<abbr title=\"Light Emitting Diode\">LED</abbr> Configuration"), translate("Customizes the behaviour of the device <abbr title=\"Light Emitting Diode\">LED</abbr>s if possible."))
+
+local sysfs_path = "/sys/class/leds/"
+local leds = {}
+
+local fs = require "nixio.fs"
+local nu = require "nixio.util"
+local util = require "luci.util"
+
+if fs.access(sysfs_path) then
+ leds = nu.consume((fs.dir(sysfs_path)))
+end
+
+if #leds == 0 then
+ return m
+end
+
+
+s = m:section(TypedSection, "led", "")
+s.anonymous = true
+s.addremove = true
+
+function s.parse(self, ...)
+ TypedSection.parse(self, ...)
+ os.execute("/etc/init.d/led enable")
+end
+
+
+s:option(Value, "name", translate("Name"))
+
+
+sysfs = s:option(ListValue, "sysfs", translate("<abbr title=\"Light Emitting Diode\">LED</abbr> Name"))
+for k, v in ipairs(leds) do
+ sysfs:value(v)
+end
+
+s:option(Flag, "default", translate("Default state")).rmempty = false
+
+
+trigger = s:option(ListValue, "trigger", translate("Trigger"))
+
+local triggers = fs.readfile(sysfs_path .. leds[1] .. "/trigger")
+for t in triggers:gmatch("[%w-]+") do
+ trigger:value(t, translate(t:gsub("-", "")))
+end
+
+
+delayon = s:option(Value, "delayon", translate ("On-State Delay"))
+delayon:depends("trigger", "timer")
+
+delayoff = s:option(Value, "delayoff", translate ("Off-State Delay"))
+delayoff:depends("trigger", "timer")
+
+
+dev = s:option(ListValue, "_net_dev", translate("Device"))
+dev.rmempty = true
+dev:value("")
+dev:depends("trigger", "netdev")
+
+function dev.cfgvalue(self, section)
+ return m.uci:get("system", section, "dev")
+end
+
+function dev.write(self, section, value)
+ m.uci:set("system", section, "dev", value)
+end
+
+function dev.remove(self, section)
+ local t = trigger:formvalue(section)
+ if t ~= "netdev" and t ~= "usbdev" then
+ m.uci:delete("system", section, "dev")
+ end
+end
+
+for k, v in pairs(luci.sys.net.devices()) do
+ if v ~= "lo" then
+ dev:value(v)
+ end
+end
+
+
+mode = s:option(MultiValue, "mode", translate("Trigger Mode"))
+mode.rmempty = true
+mode:depends("trigger", "netdev")
+mode:value("link", translate("Link On"))
+mode:value("tx", translate("Transmit"))
+mode:value("rx", translate("Receive"))
+
+
+usbdev = s:option(ListValue, "_usb_dev", translate("USB Device"))
+usbdev:depends("trigger", "usbdev")
+usbdev.rmempty = true
+usbdev:value("")
+
+function usbdev.cfgvalue(self, section)
+ return m.uci:get("system", section, "dev")
+end
+
+function usbdev.write(self, section, value)
+ m.uci:set("system", section, "dev", value)
+end
+
+function usbdev.remove(self, section)
+ local t = trigger:formvalue(section)
+ if t ~= "netdev" and t ~= "usbdev" then
+ m.uci:delete("system", section, "dev")
+ end
+end
+
+
+usbport = s:option(MultiValue, "port", translate("USB Ports"))
+usbport:depends("trigger", "usbport")
+usbport.rmempty = true
+usbport.widget = "checkbox"
+usbport.cast = "table"
+usbport.size = 1
+
+function usbport.valuelist(self, section)
+ local port, ports = nil, {}
+ for port in util.imatch(m.uci:get("system", section, "port")) do
+ local b, n = port:match("^usb(%d+)-port(%d+)$")
+ if not (b and n) then
+ b, n = port:match("^(%d+)-(%d+)$")
+ end
+ if b and n then
+ ports[#ports+1] = "usb%u-port%u" %{ tonumber(b), tonumber(n) }
+ end
+ end
+ return ports
+end
+
+function usbport.validate(self, value)
+ return type(value) == "string" and { value } or value
+end
+
+
+for p in nixio.fs.glob("/sys/bus/usb/devices/[0-9]*/manufacturer") do
+ local id = p:match("%d+-%d+")
+ local mf = nixio.fs.readfile("/sys/bus/usb/devices/" .. id .. "/manufacturer") or "?"
+ local pr = nixio.fs.readfile("/sys/bus/usb/devices/" .. id .. "/product") or "?"
+ usbdev:value(id, "%s (%s - %s)" %{ id, mf, pr })
+end
+
+for p in nixio.fs.glob("/sys/bus/usb/devices/*/usb[0-9]*-port[0-9]*") do
+ local bus, port = p:match("usb(%d+)-port(%d+)")
+ if bus and port then
+ usbport:value("usb%u-port%u" %{ tonumber(bus), tonumber(port) },
+ "Hub %u, Port %u" %{ tonumber(bus), tonumber(port) })
+ end
+end
+
+port_mask = s:option(Value, "port_mask", translate ("Switch Port Mask"))
+port_mask:depends("trigger", "switch0")
+
+return m
diff --git a/modules/luci-mod-system/luasrc/model/cbi/admin_system/startup.lua b/modules/luci-mod-system/luasrc/model/cbi/admin_system/startup.lua
new file mode 100644
index 0000000000..9e19ac50a2
--- /dev/null
+++ b/modules/luci-mod-system/luasrc/model/cbi/admin_system/startup.lua
@@ -0,0 +1,97 @@
+-- Copyright 2008 Steven Barth <steven@midlink.org>
+-- Copyright 2010-2012 Jo-Philipp Wich <jow@openwrt.org>
+-- Copyright 2010 Manuel Munz <freifunk at somakoma dot de>
+-- Licensed to the public under the Apache License 2.0.
+
+local fs = require "nixio.fs"
+local sys = require "luci.sys"
+
+local inits = { }
+
+for _, name in ipairs(sys.init.names()) do
+ local index = sys.init.index(name)
+ local enabled = sys.init.enabled(name)
+
+ if index < 255 then
+ inits["%02i.%s" % { index, name }] = {
+ name = name,
+ index = tostring(index),
+ enabled = enabled
+ }
+ end
+end
+
+
+m = SimpleForm("initmgr", translate("Initscripts"), translate("You can enable or disable installed init scripts here. Changes will applied after a device reboot.<br /><strong>Warning: If you disable essential init scripts like \"network\", your device might become inaccessible!</strong>"))
+m.reset = false
+m.submit = false
+
+
+s = m:section(Table, inits)
+
+i = s:option(DummyValue, "index", translate("Start priority"))
+n = s:option(DummyValue, "name", translate("Initscript"))
+
+
+e = s:option(Button, "endisable", translate("Enable/Disable"))
+
+e.render = function(self, section, scope)
+ if inits[section].enabled then
+ self.title = translate("Enabled")
+ self.inputstyle = "save"
+ else
+ self.title = translate("Disabled")
+ self.inputstyle = "reset"
+ end
+
+ Button.render(self, section, scope)
+end
+
+e.write = function(self, section)
+ if inits[section].enabled then
+ inits[section].enabled = false
+ return sys.init.disable(inits[section].name)
+ else
+ inits[section].enabled = true
+ return sys.init.enable(inits[section].name)
+ end
+end
+
+
+start = s:option(Button, "start", translate("Start"))
+start.inputstyle = "apply"
+start.write = function(self, section)
+ sys.call("/etc/init.d/%s %s >/dev/null" %{ inits[section].name, self.option })
+end
+
+restart = s:option(Button, "restart", translate("Restart"))
+restart.inputstyle = "reload"
+restart.write = start.write
+
+stop = s:option(Button, "stop", translate("Stop"))
+stop.inputstyle = "remove"
+stop.write = start.write
+
+
+
+f = SimpleForm("rc", translate("Local Startup"),
+ translate("This is the content of /etc/rc.local. Insert your own commands here (in front of 'exit 0') to execute them at the end of the boot process."))
+
+t = f:field(TextValue, "rcs")
+t.rmempty = true
+t.rows = 20
+
+function t.cfgvalue()
+ return fs.readfile("/etc/rc.local") or ""
+end
+
+function f.handle(self, state, data)
+ if state == FORM_VALID then
+ if data.rcs then
+ fs.writefile("/etc/rc.local", data.rcs:gsub("\r\n", "\n"))
+ end
+ end
+ return true
+end
+
+return m, f
diff --git a/modules/luci-mod-system/luasrc/model/cbi/admin_system/system.lua b/modules/luci-mod-system/luasrc/model/cbi/admin_system/system.lua
new file mode 100644
index 0000000000..c7fdfcddba
--- /dev/null
+++ b/modules/luci-mod-system/luasrc/model/cbi/admin_system/system.lua
@@ -0,0 +1,224 @@
+-- Copyright 2008 Steven Barth <steven@midlink.org>
+-- Copyright 2011 Jo-Philipp Wich <jow@openwrt.org>
+-- Licensed to the public under the Apache License 2.0.
+
+local sys = require "luci.sys"
+local zones = require "luci.sys.zoneinfo"
+local fs = require "nixio.fs"
+local conf = require "luci.config"
+
+local m, s, o
+local has_ntpd = fs.access("/usr/sbin/ntpd")
+
+m = Map("system", translate("System"), translate("Here you can configure the basic aspects of your device like its hostname or the timezone."))
+m:chain("luci")
+
+
+s = m:section(TypedSection, "system", translate("System Properties"))
+s.anonymous = true
+s.addremove = false
+
+s:tab("general", translate("General Settings"))
+s:tab("logging", translate("Logging"))
+s:tab("language", translate("Language and Style"))
+
+
+--
+-- System Properties
+--
+
+o = s:taboption("general", DummyValue, "_systime", translate("Local Time"))
+o.template = "admin_system/clock_status"
+
+
+o = s:taboption("general", Value, "hostname", translate("Hostname"))
+o.datatype = "hostname"
+
+function o.write(self, section, value)
+ Value.write(self, section, value)
+ sys.hostname(value)
+end
+
+
+o = s:taboption("general", ListValue, "zonename", translate("Timezone"))
+o:value("UTC")
+
+for i, zone in ipairs(zones.TZ) do
+ o:value(zone[1])
+end
+
+function o.write(self, section, value)
+ local function lookup_zone(title)
+ for _, zone in ipairs(zones.TZ) do
+ if zone[1] == title then return zone[2] end
+ end
+ end
+
+ AbstractValue.write(self, section, value)
+ local timezone = lookup_zone(value) or "GMT0"
+ self.map.uci:set("system", section, "timezone", timezone)
+ fs.writefile("/etc/TZ", timezone .. "\n")
+end
+
+
+--
+-- Logging
+--
+
+o = s:taboption("logging", Value, "log_size", translate("System log buffer size"), "kiB")
+o.optional = true
+o.placeholder = 16
+o.datatype = "uinteger"
+
+o = s:taboption("logging", Value, "log_ip", translate("External system log server"))
+o.optional = true
+o.placeholder = "0.0.0.0"
+o.datatype = "ip4addr"
+
+o = s:taboption("logging", Value, "log_port", translate("External system log server port"))
+o.optional = true
+o.placeholder = 514
+o.datatype = "port"
+
+o = s:taboption("logging", ListValue, "log_proto", translate("External system log server protocol"))
+o:value("udp", "UDP")
+o:value("tcp", "TCP")
+
+o = s:taboption("logging", Value, "log_file", translate("Write system log to file"))
+o.optional = true
+o.placeholder = "/tmp/system.log"
+
+o = s:taboption("logging", ListValue, "conloglevel", translate("Log output level"))
+o:value(8, translate("Debug"))
+o:value(7, translate("Info"))
+o:value(6, translate("Notice"))
+o:value(5, translate("Warning"))
+o:value(4, translate("Error"))
+o:value(3, translate("Critical"))
+o:value(2, translate("Alert"))
+o:value(1, translate("Emergency"))
+
+o = s:taboption("logging", ListValue, "cronloglevel", translate("Cron Log Level"))
+o.default = 8
+o:value(5, translate("Debug"))
+o:value(8, translate("Normal"))
+o:value(9, translate("Warning"))
+
+
+--
+-- Langauge & Style
+--
+
+o = s:taboption("language", ListValue, "_lang", translate("Language"))
+o:value("auto")
+
+local i18ndir = luci.i18n.i18ndir .. "base."
+for k, v in luci.util.kspairs(conf.languages) do
+ local file = i18ndir .. k:gsub("_", "-")
+ if k:sub(1, 1) ~= "." and fs.access(file .. ".lmo") then
+ o:value(k, v)
+ end
+end
+
+function o.cfgvalue(...)
+ return m.uci:get("luci", "main", "lang")
+end
+
+function o.write(self, section, value)
+ m.uci:set("luci", "main", "lang", value)
+end
+
+
+o = s:taboption("language", ListValue, "_mediaurlbase", translate("Design"))
+for k, v in pairs(conf.themes) do
+ if k:sub(1, 1) ~= "." then
+ o:value(v, k)
+ end
+end
+
+function o.cfgvalue(...)
+ return m.uci:get("luci", "main", "mediaurlbase")
+end
+
+function o.write(self, section, value)
+ m.uci:set("luci", "main", "mediaurlbase", value)
+end
+
+
+--
+-- NTP
+--
+
+if has_ntpd then
+
+ -- timeserver setup was requested, create section and reload page
+ if m:formvalue("cbid.system._timeserver._enable") then
+ m.uci:section("system", "timeserver", "ntp",
+ {
+ server = { "0.openwrt.pool.ntp.org", "1.openwrt.pool.ntp.org", "2.openwrt.pool.ntp.org", "3.openwrt.pool.ntp.org" }
+ }
+ )
+
+ m.uci:save("system")
+ luci.http.redirect(luci.dispatcher.build_url("admin/system", arg[1]))
+ return
+ end
+
+ local has_section = false
+ m.uci:foreach("system", "timeserver",
+ function(s)
+ has_section = true
+ return false
+ end)
+
+ if not has_section then
+
+ s = m:section(TypedSection, "timeserver", translate("Time Synchronization"))
+ s.anonymous = true
+ s.cfgsections = function() return { "_timeserver" } end
+
+ x = s:option(Button, "_enable")
+ x.title = translate("Time Synchronization is not configured yet.")
+ x.inputtitle = translate("Set up Time Synchronization")
+ x.inputstyle = "apply"
+
+ else
+
+ s = m:section(TypedSection, "timeserver", translate("Time Synchronization"))
+ s.anonymous = true
+ s.addremove = false
+
+ o = s:option(Flag, "enable", translate("Enable NTP client"))
+ o.rmempty = false
+
+ function o.cfgvalue(self)
+ return sys.init.enabled("sysntpd")
+ and self.enabled or self.disabled
+ end
+
+ function o.write(self, section, value)
+ if value == self.enabled then
+ sys.init.enable("sysntpd")
+ sys.call("env -i /etc/init.d/sysntpd start >/dev/null")
+ else
+ sys.call("env -i /etc/init.d/sysntpd stop >/dev/null")
+ sys.init.disable("sysntpd")
+ end
+ end
+
+
+ o = s:option(Flag, "enable_server", translate("Provide NTP server"))
+ o:depends("enable", "1")
+
+
+ o = s:option(DynamicList, "server", translate("NTP server candidates"))
+ o.datatype = "host(0)"
+ o:depends("enable", "1")
+
+ -- retain server list even if disabled
+ function o.remove() end
+
+ end
+end
+
+return m