summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--module/admin-core/Makefile36
-rw-r--r--module/admin-core/contrib/ffluci-flash88
-rw-r--r--module/admin-core/contrib/init.d/luci_fw121
-rw-r--r--module/admin-core/contrib/uci/luci_fw2
-rw-r--r--module/admin-core/src/controller/admin/index.lua1
-rw-r--r--module/admin-core/src/controller/admin/network.lua1
-rw-r--r--module/admin-core/src/controller/admin/services.lua1
-rw-r--r--module/admin-core/src/controller/admin/status.lua1
-rw-r--r--module/admin-core/src/controller/admin/system.lua202
-rw-r--r--module/admin-core/src/controller/admin/uci.lua59
-rw-r--r--module/admin-core/src/controller/admin/wifi.lua1
-rw-r--r--module/admin-core/src/view/admin_index/index.htm5
-rw-r--r--module/admin-core/src/view/admin_mesh/index.htm2
-rw-r--r--module/admin-core/src/view/admin_network/index.htm2
-rw-r--r--module/admin-core/src/view/admin_services/index.htm2
-rw-r--r--module/admin-core/src/view/admin_status/index.htm2
-rw-r--r--module/admin-core/src/view/admin_status/system.htm2
-rw-r--r--module/admin-core/src/view/admin_system/editor.htm14
-rw-r--r--module/admin-core/src/view/admin_system/index.htm2
-rw-r--r--module/admin-core/src/view/admin_system/ipkg.htm23
-rw-r--r--module/admin-core/src/view/admin_system/packages.htm77
-rw-r--r--module/admin-core/src/view/admin_system/passwd.htm34
-rw-r--r--module/admin-core/src/view/admin_system/reboot.htm10
-rw-r--r--module/admin-core/src/view/admin_system/sshkeys.htm23
-rw-r--r--module/admin-core/src/view/admin_system/upgrade.htm32
-rw-r--r--module/admin-core/src/view/admin_uci/apply.htm6
-rw-r--r--module/admin-core/src/view/admin_uci/changes.htm11
-rw-r--r--module/admin-core/src/view/admin_uci/revert.htm5
-rw-r--r--module/admin-core/src/view/admin_wifi/index.htm2
-rw-r--r--module/public-core/Makefile36
-rw-r--r--module/public-core/src/controller/public/index.lua1
-rw-r--r--module/public-core/src/view/public_index/contact.htm12
-rw-r--r--module/public-core/src/view/public_index/index.htm5
-rw-r--r--themes/fledermaus/contrib/media/cascade.css256
-rw-r--r--themes/fledermaus/contrib/media/cbi.js36
-rw-r--r--themes/fledermaus/contrib/media/logo.pngbin0 -> 4002 bytes
36 files changed, 1113 insertions, 0 deletions
diff --git a/module/admin-core/Makefile b/module/admin-core/Makefile
new file mode 100644
index 0000000000..9b57451399
--- /dev/null
+++ b/module/admin-core/Makefile
@@ -0,0 +1,36 @@
+LUAC = luac
+LUAC_OPTIONS = -s
+
+FILES = i18n/* view/*/*.htm
+
+CFILES = controller/*/*.lua model/cbi/*/*.lua model/menu/*.lua
+
+DIRECTORIES = model/cbi model/menu controller i18n view
+
+
+INFILES = $(CFILES:%=src/%)
+OUTDIRS = $(DIRECTORIES:%=dist/%)
+CPFILES = $(FILES:%=src/%)
+
+.PHONY: all compile source clean depends
+
+all: compile
+
+
+depends:
+ mkdir -p $(OUTDIRS)
+ for i in $(CPFILES); do [ -f "$$i" ] && (i=$$(echo $$i | cut -d/ -f2-); \
+ mkdir -p dist/$$(dirname $$i); cp src/$$i dist/$$i); done
+
+compile: depends
+ for i in $(INFILES); do [ -f "$$i" ] && (i=$$(echo $$i | cut -d/ -f2-); \
+ mkdir -p dist/$$(dirname $$i); $(LUAC) $(LUAC_OPTIONS) -o dist/$$i src/$$i); done
+
+
+source: depends
+ for i in $(INFILES); do [ -f "$$i" ] && (i=$$(echo $$i | cut -d/ -f2-); \
+ mkdir -p dist/$$(dirname $$i); cp src/$$i dist/$$i); done
+
+
+clean:
+ rm dist -rf
diff --git a/module/admin-core/contrib/ffluci-flash b/module/admin-core/contrib/ffluci-flash
new file mode 100644
index 0000000000..3ff478f0f5
--- /dev/null
+++ b/module/admin-core/contrib/ffluci-flash
@@ -0,0 +1,88 @@
+#!/bin/sh
+. /etc/functions.sh
+
+# initialize defaults
+RAMFS_COPY_BIN="" # extra programs for temporary ramfs root
+RAMFS_COPY_DATA="" # extra data files
+export KEEP_PATTERN=""
+export VERBOSE=1
+
+# parse options
+while [ -n "$1" ]; do
+ case "$1" in
+ -k)
+ shift
+ export KEEP_PATTERN="$1"
+ ;;
+ -*)
+ echo "Invalid option: $1"
+ exit 1
+ ;;
+ *) break;;
+ esac
+ shift;
+done
+
+export CONFFILES=/tmp/sysupgrade.conffiles
+export CONF_TAR=/tmp/sysupgrade.tgz
+
+[ -f $CONFFILES ] && rm $CONFFILES
+[ -f $CONF_TAR ] && rm $CONF_TAR
+
+export ARGV="$*"
+export ARGC="$#"
+
+[ -z "$ARGV" ] && {
+ cat <<EOF
+Usage: $0 [options] <image file or URL>
+
+Options:
+ -k <"file 1, file 2, ..."> Files to be kept
+EOF
+ exit 1
+}
+
+add_pattern_conffiles() {
+ local file="$1"
+ find $KEEP_PATTERN >> "$file" 2>/dev/null
+ return 0
+}
+
+# hooks
+sysupgrade_image_check="platform_check_image"
+sysupgrade_init_conffiles=""
+
+[ -n "$KEEP_PATTERN" ] && append sysupgrade_init_conffiles "add_pattern_conffiles"
+
+include /lib/upgrade
+
+do_save_conffiles() {
+ [ -z "$(rootfs_type)" ] && {
+ echo "Cannot save config while running from ramdisk."
+ exit 3
+ return 0
+ }
+ run_hooks "$CONFFILES" $sysupgrade_init_conffiles
+
+ v "Saving config files..."
+ [ "$VERBOSE" -gt 1 ] && TAR_V="v" || TAR_V=""
+ tar c${TAR_V}zf "$CONF_TAR" -T "$CONFFILES" 2>/dev/null
+}
+
+type platform_check_image >/dev/null 2>/dev/null || {
+ echo "Firmware upgrade is not implemented for this platform."
+ exit 1
+}
+
+for check in $sysupgrade_image_check; do
+ ( eval "$check \"\$ARGV\"" ) || {
+ echo "Image check '$check' failed."
+ exit 2
+ }
+done
+
+[ -n "$sysupgrade_init_conffiles" ] && do_save_conffiles
+run_hooks "" $sysupgrade_pre_upgrade
+
+v "Switching to ramdisk..."
+run_ramfs '. /etc/functions.sh; include /lib/upgrade; do_upgrade' \ No newline at end of file
diff --git a/module/admin-core/contrib/init.d/luci_fw b/module/admin-core/contrib/init.d/luci_fw
new file mode 100644
index 0000000000..880c87dbe3
--- /dev/null
+++ b/module/admin-core/contrib/init.d/luci_fw
@@ -0,0 +1,121 @@
+#!/bin/sh /etc/rc.common
+START=46
+
+apply_portfw() {
+ local cfg="$1"
+ config_get proto "$cfg" proto
+ config_get dport "$cfg" dport
+ config_get iface "$cfg" iface
+ config_get to "$cfg" to
+
+ ports=$(echo $to | cut -sd: -f2)
+ if [ -n "$ports" ]; then
+ ports="--dport $(echo $ports | sed -e 's/-/:/')"
+ else
+ ports="--dport $dport"
+ fi
+
+ ip=$(echo $to | cut -d: -f1)
+
+ if ([ "$proto" == "tcpudp" ] || [ "$proto" == "tcp" ]); then
+ iptables -t nat -A luci_prerouting -i "$iface" -p tcp --dport "$dport" -j DNAT --to "$to"
+ iptables -A luci_forward -i "$iface" -p tcp -d "$ip" $ports -j ACCEPT
+ fi
+
+ if ([ "$proto" == "tcpudp" ] || [ "$proto" == "udp" ]); then
+ iptables -t nat -A luci_prerouting -i "$iface" -p udp --dport "$dport" -j DNAT --to "$to"
+ iptables -A luci_forward -i "$iface" -p udp -d "$ip" $ports -j ACCEPT
+ fi
+}
+
+apply_rule() {
+ local cfg="$1"
+ local cmd=""
+
+ config_get chain "$cfg" chain
+ [ -n "$chain" ] || return 0
+ [ "$chain" == "forward" ] && cmd="$cmd -A luci_forward"
+ [ "$chain" == "input" ] && cmd="$cmd -A luci_input"
+ [ "$chain" == "output" ] && cmd="$cmd -A luci_output"
+ [ "$chain" == "prerouting" ] && cmd="$cmd -t nat -A luci_prerouting"
+ [ "$chain" == "postrouting" ] && cmd="$cmd -t nat -A luci_postrouting"
+
+ config_get iface "$cfg" iface
+ [ -n "$iface" ] && cmd="$cmd -i $iface"
+
+ config_get oface "$cfg" oface
+ [ -n "$oface" ] && cmd="$cmd -o $oface"
+
+ config_get proto "$cfg" proto
+ [ -n "$proto" ] && cmd="$cmd -p $proto"
+
+ config_get source "$cfg" source
+ [ -n "$source" ] && cmd="$cmd -s $source"
+
+ config_get destination "$cfg" destination
+ [ -n "$destination" ] && cmd="$cmd -d $destination"
+
+ config_get sport "$cfg" sport
+ [ -n "$sport" ] && cmd="$cmd --sport $sport"
+
+ config_get dport "$cfg" dport
+ [ -n "$dport" ] && cmd="$cmd --dport $dport"
+
+ config_get todest "$cfg" todest
+ [ -n "$todest" ] && cmd="$cmd --to-destination $todest"
+
+ config_get tosrc "$cfg" tosrc
+ [ -n "$tosrc" ] && cmd="$cmd --to-source $tosrc"
+
+ config_get jump "$cfg" jump
+ [ -n "$jump" ] && cmd="$cmd -j $jump"
+
+ config_get command "$cfg" command
+ [ -n "$command" ] && cmd="$cmd $command"
+
+ iptables $cmd
+}
+
+start() {
+ ### Create subchains
+ iptables -N luci_input
+ iptables -N luci_output
+ iptables -N luci_forward
+ iptables -t nat -N luci_prerouting
+ iptables -t nat -N luci_postrouting
+
+ ### Hook in the chains
+ iptables -A input_rule -j luci_input
+ iptables -A output_rule -j luci_output
+ iptables -A forwarding_rule -j luci_forward
+ iptables -t nat -A prerouting_rule -j luci_prerouting
+ iptables -t nat -A postrouting_rule -j luci_postrouting
+
+ ### Read chains from config
+ config_load luci_fw
+ config_foreach apply_portfw portfw
+ config_foreach apply_rule rule
+}
+
+stop() {
+ ### Hook out the chains
+ iptables -D input_rule -j luci_input
+ iptables -D output_rule -j luci_output
+ iptables -D forwarding_rule -j luci_forward
+ iptables -t nat -D prerouting_rule -j luci_prerouting
+ iptables -t nat -D postrouting_rule -j luci_postrouting
+
+ ### Clear subchains
+ iptables -F luci_input
+ iptables -F luci_output
+ iptables -F luci_forward
+ iptables -t nat -F luci_prerouting
+ iptables -t nat -F luci_postrouting
+
+ ### Delete subchains
+ iptables -X luci_input
+ iptables -X luci_output
+ iptables -X luci_forward
+ iptables -t nat -X luci_prerouting
+ iptables -t nat -X luci_postrouting
+}
diff --git a/module/admin-core/contrib/uci/luci_fw b/module/admin-core/contrib/uci/luci_fw
new file mode 100644
index 0000000000..c7dec7f2c5
--- /dev/null
+++ b/module/admin-core/contrib/uci/luci_fw
@@ -0,0 +1,2 @@
+
+ \ No newline at end of file
diff --git a/module/admin-core/src/controller/admin/index.lua b/module/admin-core/src/controller/admin/index.lua
new file mode 100644
index 0000000000..b4a7720f8b
--- /dev/null
+++ b/module/admin-core/src/controller/admin/index.lua
@@ -0,0 +1 @@
+module("ffluci.controller.admin.index", package.seeall) \ No newline at end of file
diff --git a/module/admin-core/src/controller/admin/network.lua b/module/admin-core/src/controller/admin/network.lua
new file mode 100644
index 0000000000..4f8160a4c9
--- /dev/null
+++ b/module/admin-core/src/controller/admin/network.lua
@@ -0,0 +1 @@
+module(..., package.seeall) \ No newline at end of file
diff --git a/module/admin-core/src/controller/admin/services.lua b/module/admin-core/src/controller/admin/services.lua
new file mode 100644
index 0000000000..42181212bd
--- /dev/null
+++ b/module/admin-core/src/controller/admin/services.lua
@@ -0,0 +1 @@
+module("ffluci.controller.admin.services", package.seeall) \ No newline at end of file
diff --git a/module/admin-core/src/controller/admin/status.lua b/module/admin-core/src/controller/admin/status.lua
new file mode 100644
index 0000000000..bdd51d4629
--- /dev/null
+++ b/module/admin-core/src/controller/admin/status.lua
@@ -0,0 +1 @@
+module("ffluci.controller.admin.status", package.seeall) \ No newline at end of file
diff --git a/module/admin-core/src/controller/admin/system.lua b/module/admin-core/src/controller/admin/system.lua
new file mode 100644
index 0000000000..b0763d8afe
--- /dev/null
+++ b/module/admin-core/src/controller/admin/system.lua
@@ -0,0 +1,202 @@
+module("ffluci.controller.admin.system", package.seeall)
+
+require("ffluci.sys")
+require("ffluci.http")
+require("ffluci.util")
+require("ffluci.fs")
+require("ffluci.model.ipkg")
+require("ffluci.model.uci")
+
+function action_editor()
+ local file = ffluci.http.formvalue("file", "")
+ local data = ffluci.http.formvalue("data")
+ local err = nil
+ local msg = nil
+ local stat = true
+
+ if file and data then
+ stat, err = ffluci.fs.writefile(file, data)
+ end
+
+ if not stat then
+ err = ffluci.util.split(err, " ")
+ table.remove(err, 1)
+ msg = table.concat(err, " ")
+ end
+
+ local cnt, err = ffluci.fs.readfile(file)
+ if cnt then
+ cnt = ffluci.util.pcdata(cnt)
+ end
+ ffluci.template.render("admin_system/editor", {fn=file, cnt=cnt, msg=msg})
+end
+
+function action_ipkg()
+ local file = "/etc/ipkg.conf"
+ local data = ffluci.http.formvalue("data")
+ local stat = nil
+ local err = nil
+
+ if data then
+ stat, err = ffluci.fs.writefile(file, data)
+ end
+
+ local cnt = ffluci.fs.readfile(file)
+ if cnt then
+ cnt = ffluci.util.pcdata(cnt)
+ end
+
+ ffluci.template.render("admin_system/ipkg", {cnt=cnt, msg=err})
+end
+
+function action_packages()
+ local ipkg = ffluci.model.ipkg
+ local void = nil
+ local submit = ffluci.http.formvalue("submit")
+
+
+ -- Search query
+ local query = ffluci.http.formvalue("query")
+ query = (query ~= '') and query or nil
+
+
+ -- Packets to be installed
+ local install = ffluci.http.formvalue("install")
+ install = (type(install) == "table" and submit) and install or nil
+
+ -- Install from URL
+ local url = ffluci.http.formvalue("url")
+ if url and url ~= '' and submit then
+ if not install then
+ install = {}
+ end
+ install[url] = 1
+ end
+
+ -- Do install
+ if install then
+ for k, v in pairs(install) do
+ void, install[k] = ipkg.install(k)
+ end
+ end
+
+
+ -- Remove packets
+ local remove = ffluci.http.formvalue("remove")
+ remove = (type(remove) == "table" and submit) and remove or nil
+ if remove then
+ for k, v in pairs(remove) do
+ void, remove[k] = ipkg.remove(k)
+ end
+ end
+
+
+ -- Update all packets
+ local update = ffluci.http.formvalue("update")
+ if update then
+ void, update = ipkg.update()
+ end
+
+
+ -- Upgrade all packets
+ local upgrade = ffluci.http.formvalue("upgrade")
+ if upgrade then
+ void, upgrade = ipkg.upgrade()
+ end
+
+
+ -- Package info
+ local info = ffluci.model.ipkg.info(query)
+ info = info or {}
+ local pkgs = {}
+
+ -- Sort after status and name
+ for k, v in pairs(info) do
+ local x = 0
+ for i, j in pairs(pkgs) do
+ local vins = (v.Status and v.Status.installed)
+ local jins = (j.Status and j.Status.installed)
+ if vins ~= jins then
+ if vins then
+ break
+ end
+ else
+ if j.Package > v.Package then
+ break
+ end
+ end
+ x = i
+ end
+ table.insert(pkgs, x+1, v)
+ end
+
+ ffluci.template.render("admin_system/packages", {pkgs=pkgs, query=query,
+ install=install, remove=remove, update=update, upgrade=upgrade})
+end
+
+function action_passwd()
+ local p1 = ffluci.http.formvalue("pwd1")
+ local p2 = ffluci.http.formvalue("pwd2")
+ local stat = nil
+
+ if p1 or p2 then
+ if p1 == p2 then
+ stat = ffluci.sys.user.setpasswd("root", p1)
+ else
+ stat = 10
+ end
+ end
+
+ ffluci.template.render("admin_system/passwd", {stat=stat})
+end
+
+function action_reboot()
+ local reboot = ffluci.http.formvalue("reboot")
+ ffluci.template.render("admin_system/reboot", {reboot=reboot})
+ if reboot then
+ ffluci.sys.reboot()
+ end
+end
+
+function action_sshkeys()
+ local file = "/etc/dropbear/authorized_keys"
+ local data = ffluci.http.formvalue("data")
+ local stat = nil
+ local err = nil
+
+ if data then
+ stat, err = ffluci.fs.writefile(file, data)
+ end
+
+ local cnt = ffluci.fs.readfile(file)
+ if cnt then
+ cnt = ffluci.util.pcdata(cnt)
+ end
+
+ ffluci.template.render("admin_system/sshkeys", {cnt=cnt, msg=err})
+end
+
+function action_upgrade()
+ local ret = nil
+ local plat = ffluci.fs.mtime("/lib/upgrade/platform.sh")
+
+ local image = ffluci.http.formvalue("image")
+ local imgname = ffluci.http.formvalue("image_name")
+ local keepcfg = ffluci.http.formvalue("keepcfg")
+
+ if plat and imgname then
+ local kpattern = nil
+ if keepcfg then
+ local files = ffluci.model.uci.show("luci", "flash_keep")
+ if files.luci and files.luci.flash_keep then
+ kpattern = ""
+ for k,v in pairs(files.luci.flash_keep) do
+ kpattern = kpattern .. " " .. v
+ end
+ end
+ end
+ ret = ffluci.sys.flash(image, kpattern)
+ end
+
+ ffluci.template.render("admin_system/upgrade", {sysupgrade=plat, ret=ret})
+end \ No newline at end of file
diff --git a/module/admin-core/src/controller/admin/uci.lua b/module/admin-core/src/controller/admin/uci.lua
new file mode 100644
index 0000000000..3c9fc87395
--- /dev/null
+++ b/module/admin-core/src/controller/admin/uci.lua
@@ -0,0 +1,59 @@
+module("ffluci.controller.admin.uci", package.seeall)
+require("ffluci.util")
+require("ffluci.sys")
+
+-- This function has a higher priority than the admin_uci/apply template
+function action_apply()
+ local changes = ffluci.model.uci.changes()
+ local output = ""
+
+ if changes then
+ local apply = {}
+
+ -- Collect files to be applied
+ for i, line in ipairs(ffluci.util.split(changes)) do
+ local r = line:match("^-?([^.]+)")
+ if r then
+ apply[r] = true
+ end
+ end
+
+ -- Commit changes
+ ffluci.model.uci.commit()
+
+ -- Search for post-commit commands
+ if ffluci.config.uci_oncommit then
+ for k, v in pairs(apply) do
+ local cmd = ffluci.config.uci_oncommit[k]
+ if cmd then
+ output = output .. cmd .. ":" .. ffluci.sys.exec(cmd)
+ end
+ end
+ end
+ end
+
+ ffluci.template.render("admin_uci/apply", {changes=changes, output=output})
+end
+
+
+function action_revert()
+ local changes = ffluci.model.uci.changes()
+ if changes then
+ local revert = {}
+
+ -- Collect files to be reverted
+ for i, line in ipairs(ffluci.util.split(changes)) do
+ local r = line:match("^-?([^.]+)")
+ if r then
+ revert[r] = true
+ end
+ end
+
+ -- Revert them
+ for k, v in pairs(revert) do
+ ffluci.model.uci.revert(k)
+ end
+ end
+
+ ffluci.template.render("admin_uci/revert", {changes=changes})
+end \ No newline at end of file
diff --git a/module/admin-core/src/controller/admin/wifi.lua b/module/admin-core/src/controller/admin/wifi.lua
new file mode 100644
index 0000000000..bc1040c715
--- /dev/null
+++ b/module/admin-core/src/controller/admin/wifi.lua
@@ -0,0 +1 @@
+module("ffluci.controller.admin.wifi", package.seeall) \ No newline at end of file
diff --git a/module/admin-core/src/view/admin_index/index.htm b/module/admin-core/src/view/admin_index/index.htm
new file mode 100644
index 0000000000..1f06e344cf
--- /dev/null
+++ b/module/admin-core/src/view/admin_index/index.htm
@@ -0,0 +1,5 @@
+<%+header%>
+<h1><%:hello Hallo!%></h1>
+<p><%:admin1 Dies ist der Administrationsbereich. %>
+<p><em>ToDo: Intelligenter Einleitungstext</em></p>
+<%+footer%> \ No newline at end of file
diff --git a/module/admin-core/src/view/admin_mesh/index.htm b/module/admin-core/src/view/admin_mesh/index.htm
new file mode 100644
index 0000000000..75aa026582
--- /dev/null
+++ b/module/admin-core/src/view/admin_mesh/index.htm
@@ -0,0 +1,2 @@
+<%+header%>
+<%+footer%> \ No newline at end of file
diff --git a/module/admin-core/src/view/admin_network/index.htm b/module/admin-core/src/view/admin_network/index.htm
new file mode 100644
index 0000000000..75aa026582
--- /dev/null
+++ b/module/admin-core/src/view/admin_network/index.htm
@@ -0,0 +1,2 @@
+<%+header%>
+<%+footer%> \ No newline at end of file
diff --git a/module/admin-core/src/view/admin_services/index.htm b/module/admin-core/src/view/admin_services/index.htm
new file mode 100644
index 0000000000..75aa026582
--- /dev/null
+++ b/module/admin-core/src/view/admin_services/index.htm
@@ -0,0 +1,2 @@
+<%+header%>
+<%+footer%> \ No newline at end of file
diff --git a/module/admin-core/src/view/admin_status/index.htm b/module/admin-core/src/view/admin_status/index.htm
new file mode 100644
index 0000000000..75aa026582
--- /dev/null
+++ b/module/admin-core/src/view/admin_status/index.htm
@@ -0,0 +1,2 @@
+<%+header%>
+<%+footer%> \ No newline at end of file
diff --git a/module/admin-core/src/view/admin_status/system.htm b/module/admin-core/src/view/admin_status/system.htm
new file mode 100644
index 0000000000..75aa026582
--- /dev/null
+++ b/module/admin-core/src/view/admin_status/system.htm
@@ -0,0 +1,2 @@
+<%+header%>
+<%+footer%> \ No newline at end of file
diff --git a/module/admin-core/src/view/admin_system/editor.htm b/module/admin-core/src/view/admin_system/editor.htm
new file mode 100644
index 0000000000..0215c91dff
--- /dev/null
+++ b/module/admin-core/src/view/admin_system/editor.htm
@@ -0,0 +1,14 @@
+<%+header%>
+<h1><%:texteditor Texteditor%></h1>
+<form method="post" action="<%=controller%>/admin/system/editor">
+<div><%:file Datei%>: <input type="text" name="file" size="30" value="<%=(fn or '')%>" />
+<% if msg then %><span class="error"><%:error Fehler%>: <%=msg%></span><% end %></div>
+<br />
+<div><textarea style="width: 100%" rows="20" name="data"><%=(cnt or '')%></textarea></div>
+<br />
+<div>
+ <input type="submit" value="<%:save Speichern%>" />
+ <input type="reset" value="<%:reset Zurücksetzen%>" />
+</div>
+</form>
+<%+footer%> \ No newline at end of file
diff --git a/module/admin-core/src/view/admin_system/index.htm b/module/admin-core/src/view/admin_system/index.htm
new file mode 100644
index 0000000000..75aa026582
--- /dev/null
+++ b/module/admin-core/src/view/admin_system/index.htm
@@ -0,0 +1,2 @@
+<%+header%>
+<%+footer%> \ No newline at end of file
diff --git a/module/admin-core/src/view/admin_system/ipkg.htm b/module/admin-core/src/view/admin_system/ipkg.htm
new file mode 100644
index 0000000000..bbe7f3bc6e
--- /dev/null
+++ b/module/admin-core/src/view/admin_system/ipkg.htm
@@ -0,0 +1,23 @@
+<%+header%>
+<h1><%:system System%></h1>
+<h2><%:ipkg IPKG-Konfiguration%></h2>
+
+<br />
+
+<div><strong><%:ipkg_pkglists Paketlisten%>:</strong><code>src <em>Name</em> <em>URL</em></code></div>
+<div><strong><%:ipkg_targets Installationsziele%>:</strong><code>dest <em>Name</em> <em>Pfad</em></code></div>
+
+<br />
+
+<form method="post" action="<%=controller%>/admin/system/ipkg">
+ <fieldset class="cbi-section-node">
+ <div><textarea style="width: 100%" rows="10" name="data"><%=(cnt or '')%></textarea></div>
+ <br />
+ <div>
+ <input type="submit" value="<%:save Speichern%>" />
+ <input type="reset" value="<%:reset Zurücksetzen%>" />
+ </div>
+ <% if msg then %><br /><div class="error"><%:error Fehler%>: <%=msg%></div><% end %>
+ </fieldset>
+</form>
+<%+footer%> \ No newline at end of file
diff --git a/module/admin-core/src/view/admin_system/packages.htm b/module/admin-core/src/view/admin_system/packages.htm
new file mode 100644
index 0000000000..d9cdb4dd0e
--- /dev/null
+++ b/module/admin-core/src/view/admin_system/packages.htm
@@ -0,0 +1,77 @@
+<%+header%>
+<h1><%:system System%></h1>
+<h2><%:packages Paketverwaltung%></h2>
+
+<br />
+
+<% if install or remove or update or upgrade then %>
+<div class="code"><strong><%:status Status%>:</strong><br />
+<% if update then %>
+ <%:packages_update Paketlisten aktualisieren%>: <% if update == 0 then %><span class="ok"><%:ok OK%></span><% else %><span class="error"><%:error Fehler%> (<%:code Code%> <%=update%>)</span><% end %><br />
+<% end %>
+<% if upgrade then%>
+ <%:packages_upgrade Installierte Pakete aktualisieren%>: <% if upgrade == 0 then %><span class="ok"><%:ok OK%></span><% else %><span class="error"><%:error Fehler%> (<%:code Code%> <%=upgrade%>)</span><% end %><br />
+<% end %>
+<% if install then for k,v in pairs(install) do %>
+ <%:packages_install Installation von%> '<%=k%>': <% if v == 0 then %><span class="ok"><%:ok OK%></span><% else %><span class="error"><%:error Fehler%> (<%:code Code%> <%=v%>)</span><% end %><br />
+<% end end %>
+<% if remove then for k,v in pairs(remove) do %>
+ <%:packages_remove Deinstallation von%> '<%=k%>': <% if v == 0 then %><span class="ok"><%:ok OK%></span><% else %><span class="error"><%:error Fehler%> (<%:code Code%> <%=v%>)</span><% end %><br />
+<% end end %>
+</div>
+<br />
+<% end %>
+
+<div>
+<a href="<%=controller%>/admin/system/ipkg"><%:packages_ipkg Paketlisten und Installationsziele bearbeiten%></a><br />
+<a href="<%=controller%>/admin/system/packages?update=1"><%:packages_updatelist Paketlisten aktualisieren%></a><br />
+<a href="<%=controller%>/admin/system/packages?upgrade=1"><%:packages_upgrade Installierte Pakete aktualisieren%></a>
+</div>
+
+<br />
+<br />
+
+<form method="post" action="<%=controller%>/admin/system/packages">
+ <div>
+ <span class="bold"><%:packages_installurl Paket herunterladen und installieren%>:</span><br />
+ <input type="text" name="url" size="30" value="" />
+ <input type="submit" name="submit" value="<%:ok OK%>" />
+ </div>
+
+ <br />
+ <br />
+
+ <div>
+ <span class="bold"><%:filter Filter%>:</span>
+ <input type="text" name="query" size="20" value="<%=(query or '')%>" />
+ <input type="submit" name="search" value="<%:packages_search Paket suchen%>" />
+ <input type="submit" name="submit" value="<%:packages_do Aktionen ausführen%>" />
+ </div>
+
+ <br />
+ <br />
+
+ <div>
+ <table style="font-size: 0.8em">
+ <tr>
+ <th><%:packages_name Paketname%></th>
+ <th><%:version Version%></th>
+ <th><%:install Installieren%></th>
+ <th><%:delete Löschen%></th>
+ <th><%:descr Beschreibung%></th>
+ </tr>
+ <% for k, pkg in pairs(pkgs) do %>
+ <tr>
+ <td><%=pkg.Package%></td>
+ <td><%=(pkg.Version or '')%></td>
+ <td><% if not pkg.Status or not pkg.Status.installed then %><input type="checkbox" name="install.<%=pkg.Package%>" value="1" /><% else %><%:installed installiert%><% end %></td>
+ <td><% if pkg.Status and pkg.Status.installed then %><input type="checkbox" name="remove.<%=pkg.Package%>" value="1" /><% else %><%:notinstalled nicht installiert%><% end %></td>
+ <td><%=(pkg.Description or '')%></td>
+ </tr>
+ <% end %>
+ </table>
+ </div>
+ <br />
+ <input type="submit" name="submit" value="<%:packages_do Aktionen ausführen%>" />
+</form>
+<%+footer%> \ No newline at end of file
diff --git a/module/admin-core/src/view/admin_system/passwd.htm b/module/admin-core/src/view/admin_system/passwd.htm
new file mode 100644
index 0000000000..441753d839
--- /dev/null
+++ b/module/admin-core/src/view/admin_system/passwd.htm
@@ -0,0 +1,34 @@
+<%+header%>
+<h1><%:system System%></h1>
+<h2><%:passwd Passwort ändern%></h2>
+<div><br />
+<% if stat then %>
+ <% if stat == 0 then %>
+ <code><%:password_changed Passwort erfolgreich geändert!%></code>
+ <% elseif stat == 10 then %>
+ <code class="error"><%:password_nomatch Passwörter stimmen nicht überein! %></code>
+ <% else %>
+ <code class="error"><%:unknown_error Unbekannter Fehler!%></code>
+ <% end %>
+<% end %>
+<% if not stat or stat == 10 then %>
+ <form method="post" action="<%=controller%>/admin/system/passwd">
+ <fieldset class="cbi-section-node">
+ <div class="cbi-value clear">
+ <div class="cbi-value-title left"><%:password Passwort%></div>
+ <div class="cbi-value-field"><input type="password" name="pwd1" /></div>
+ </div>
+ <div class="cbi-value clear">
+ <div class="cbi-value-title left"><%:confirmation Bestätigung%></div>
+ <div class="cbi-value-field"><input type="password" name="pwd2" /></div>
+ </div>
+ <br />
+ <div>
+ <input type="submit" value="<%:save Speichern%>" />
+ <input type="reset" value="<%:reset Zurücksetzen%>" />
+ </div>
+ </fieldset>
+ </form>
+<% end %>
+</div>
+<%+footer%> \ No newline at end of file
diff --git a/module/admin-core/src/view/admin_system/reboot.htm b/module/admin-core/src/view/admin_system/reboot.htm
new file mode 100644
index 0000000000..365c330781
--- /dev/null
+++ b/module/admin-core/src/view/admin_system/reboot.htm
@@ -0,0 +1,10 @@
+<%+header%>
+<h1><%:system System%></h1>
+<h2><%:reboot Neu starten%></h2>
+<% if not reboot then %>
+<p><a href="<%=controller%>/admin/system/reboot?reboot=1"><%:reboot_do Neustart durchführen%></a></p>
+<% else %>
+<p><%:reboot_running Bitte warten: Neustart wird durchgeführt...%></p>
+<script type="text/javascript">setTimeout("location='<%=controller%>/admin'", 30000)</script>
+<% end %>
+<%+footer%> \ No newline at end of file
diff --git a/module/admin-core/src/view/admin_system/sshkeys.htm b/module/admin-core/src/view/admin_system/sshkeys.htm
new file mode 100644
index 0000000000..1e1cc24ce1
--- /dev/null
+++ b/module/admin-core/src/view/admin_system/sshkeys.htm
@@ -0,0 +1,23 @@
+<%+header%>
+<h1><%:system System%></h1>
+<h2><%:sshkeys SSH-Schlüssel%></h2>
+
+<br />
+
+<div><%:sshkeys_descr Hier können öffentliche SSH-Schlüssel (einer pro Zeile)
+ zur Authentifizierung abgelegt werden.%></div>
+
+<br />
+
+<form method="post" action="<%=controller%>/admin/system/sshkeys">
+ <fieldset class="cbi-section-node">
+ <div><textarea style="width: 100%" rows="10" name="data"><%=(cnt or '')%></textarea></div>
+ <br />
+ <div>
+ <input type="submit" value="<%:save Speichern%>" />
+ <input type="reset" value="<%:reset Zurücksetzen%>" />
+ </div>
+ <% if msg then %><br /><div class="error"><%:error Fehler%>: <%=msg%></div><% end %>
+ </fieldset>
+</form>
+<%+footer%> \ No newline at end of file
diff --git a/module/admin-core/src/view/admin_system/upgrade.htm b/module/admin-core/src/view/admin_system/upgrade.htm
new file mode 100644
index 0000000000..d91d169a4a
--- /dev/null
+++ b/module/admin-core/src/view/admin_system/upgrade.htm
@@ -0,0 +1,32 @@
+<%+header%>
+<h1><%:system System%></h1>
+<h2><%:upgrade Upgrade%></h2>
+<br />
+<% if sysupgrade and not ret then %>
+<form method="post" action="<%=controller%>-upload/admin/system/upgrade" enctype="multipart/form-data">
+ <fieldset class="cbi-section-node">
+ <div class="cbi-value clear">
+ <div class="cbi-value-title left"><%:fwimage Firmwareimage%></div>
+ <div class="cbi-value-field"><input type="file" size="30" name="image" /></div>
+ </div>
+ <br />
+ <div class="cbi-value clear">
+ <input type="checkbox" name="keepcfg" value="1" checked="checked" />
+ <span class="bold"><%:keepcfg Konfigurationsdateien übernehmen%></span>
+ </div>
+ <br />
+ <div>
+ <input type="submit" value="<%:fwupgrade Firmware aktualisieren%>" />
+ </div>
+ </fieldset>
+</form>
+<% elseif ret then %>
+ <% if ret == 0 then %>
+<div class="ok"><%:flashed Flashvorgang erfolgreich. Router startet neu...%></div>
+ <% else %>
+<div class="error"><%:flasherr Flashvorgang fehlgeschlagen!%> (<%:code Code%> <%=ret%>)</div>
+ <% end %>
+<% else %>
+<div class="error"><%:notimplemented Diese Funktion steht leider (noch) nicht zur Verfügung.%></div>
+<% end %>
+<%+footer%> \ No newline at end of file
diff --git a/module/admin-core/src/view/admin_uci/apply.htm b/module/admin-core/src/view/admin_uci/apply.htm
new file mode 100644
index 0000000000..43777c6c6d
--- /dev/null
+++ b/module/admin-core/src/view/admin_uci/apply.htm
@@ -0,0 +1,6 @@
+<%+header%>
+<h1><%:config Konfiguration%></h1>
+<p><%:uci_applied Die folgenden Änderungen wurden übernommen:%></p>
+<code><%=(changes or "-")%>
+<%=output%></code>
+<%+footer%> \ No newline at end of file
diff --git a/module/admin-core/src/view/admin_uci/changes.htm b/module/admin-core/src/view/admin_uci/changes.htm
new file mode 100644
index 0000000000..3bbcd0e5fb
--- /dev/null
+++ b/module/admin-core/src/view/admin_uci/changes.htm
@@ -0,0 +1,11 @@
+<%+header%>
+<h1><%:config Konfiguration%></h1>
+<h2><%:changes Änderungen%></h2>
+<code><%=(ffluci.model.uci.changes() or "-")%></code>
+<form class="inline" method="get" action="<%=controller%>/admin/uci/apply">
+ <input type="submit" value="<%:apply Anwenden%>" />
+</form>
+<form class="inline" method="get" action="<%=controller%>/admin/uci/revert">
+ <input type="submit" value="<%:revert Verwerfen%>" />
+</form>
+<%+footer%> \ No newline at end of file
diff --git a/module/admin-core/src/view/admin_uci/revert.htm b/module/admin-core/src/view/admin_uci/revert.htm
new file mode 100644
index 0000000000..f5eabc71b7
--- /dev/null
+++ b/module/admin-core/src/view/admin_uci/revert.htm
@@ -0,0 +1,5 @@
+<%+header%>
+<h1><%:config Konfiguration%></h1>
+<p><%:uci_reverted Die folgenden Änderungen wurden verworfen:%></p>
+<code><%=(changes or "-")%></code>
+<%+footer%> \ No newline at end of file
diff --git a/module/admin-core/src/view/admin_wifi/index.htm b/module/admin-core/src/view/admin_wifi/index.htm
new file mode 100644
index 0000000000..75aa026582
--- /dev/null
+++ b/module/admin-core/src/view/admin_wifi/index.htm
@@ -0,0 +1,2 @@
+<%+header%>
+<%+footer%> \ No newline at end of file
diff --git a/module/public-core/Makefile b/module/public-core/Makefile
new file mode 100644
index 0000000000..9b57451399
--- /dev/null
+++ b/module/public-core/Makefile
@@ -0,0 +1,36 @@
+LUAC = luac
+LUAC_OPTIONS = -s
+
+FILES = i18n/* view/*/*.htm
+
+CFILES = controller/*/*.lua model/cbi/*/*.lua model/menu/*.lua
+
+DIRECTORIES = model/cbi model/menu controller i18n view
+
+
+INFILES = $(CFILES:%=src/%)
+OUTDIRS = $(DIRECTORIES:%=dist/%)
+CPFILES = $(FILES:%=src/%)
+
+.PHONY: all compile source clean depends
+
+all: compile
+
+
+depends:
+ mkdir -p $(OUTDIRS)
+ for i in $(CPFILES); do [ -f "$$i" ] && (i=$$(echo $$i | cut -d/ -f2-); \
+ mkdir -p dist/$$(dirname $$i); cp src/$$i dist/$$i); done
+
+compile: depends
+ for i in $(INFILES); do [ -f "$$i" ] && (i=$$(echo $$i | cut -d/ -f2-); \
+ mkdir -p dist/$$(dirname $$i); $(LUAC) $(LUAC_OPTIONS) -o dist/$$i src/$$i); done
+
+
+source: depends
+ for i in $(INFILES); do [ -f "$$i" ] && (i=$$(echo $$i | cut -d/ -f2-); \
+ mkdir -p dist/$$(dirname $$i); cp src/$$i dist/$$i); done
+
+
+clean:
+ rm dist -rf
diff --git a/module/public-core/src/controller/public/index.lua b/module/public-core/src/controller/public/index.lua
new file mode 100644
index 0000000000..4f8160a4c9
--- /dev/null
+++ b/module/public-core/src/controller/public/index.lua
@@ -0,0 +1 @@
+module(..., package.seeall) \ No newline at end of file
diff --git a/module/public-core/src/view/public_index/contact.htm b/module/public-core/src/view/public_index/contact.htm
new file mode 100644
index 0000000000..ded0a94af0
--- /dev/null
+++ b/module/public-core/src/view/public_index/contact.htm
@@ -0,0 +1,12 @@
+<%+header%>
+<h1><%:contact Kontakt%></h1>
+<table class="contact">
+ <tr><th><%:nickname Pseudonym%>:</th><td><%~luci.contact.nickname%></td></tr>
+ <tr><th><%:name Name%>:</th><td><%~luci.contact.name%></td></tr>
+ <tr><th><%:mail E-Mail%>:</th><td><%~luci.contact.mail%></td></tr>
+ <tr><th><%:phone Telefon%>:</th><td><%~luci.contact.phone%></td></tr>
+ <tr><th><%:location Standort%>:</th><td><%~luci.contact.location%></td></tr>
+ <tr><th><%:geocoord Geokoordinaten%>:</th><td><%~luci.contact.geo%></td></tr>
+ <tr><th><%:note Notiz%>:</th><td><%~luci.contact.note%></td></tr>
+</table>
+<%+footer%> \ No newline at end of file
diff --git a/module/public-core/src/view/public_index/index.htm b/module/public-core/src/view/public_index/index.htm
new file mode 100644
index 0000000000..1f06e344cf
--- /dev/null
+++ b/module/public-core/src/view/public_index/index.htm
@@ -0,0 +1,5 @@
+<%+header%>
+<h1><%:hello Hallo!%></h1>
+<p><%:admin1 Dies ist der Administrationsbereich. %>
+<p><em>ToDo: Intelligenter Einleitungstext</em></p>
+<%+footer%> \ No newline at end of file
diff --git a/themes/fledermaus/contrib/media/cascade.css b/themes/fledermaus/contrib/media/cascade.css
new file mode 100644
index 0000000000..d09ab7477c
--- /dev/null
+++ b/themes/fledermaus/contrib/media/cascade.css
@@ -0,0 +1,256 @@
+@charset "utf-8";
+
+body {
+ font-family: Verdana, Arial, sans-serif;
+ background-color: #aaaaaa;
+}
+
+h1 {
+ margin: 0%;
+ font-size: 1.4em;
+ font-weight: bold;
+ margin-bottom: 0.5em;
+}
+
+h2 {
+ margin: 0%;
+ font-size: 1.2em;
+ font-weight: bold;
+}
+
+h3 {
+ margin: 0%;
+}
+
+#header {
+ padding: 0.2em;
+ height: 4.5em;
+ background-color: #262626;
+}
+
+#columns {
+ border-left: 10.1em solid #262626;
+ border-right: 10.1em solid #262626;
+ display: block;
+ background-color: white;
+ padding: 0.1em;
+}
+
+#columnswrapper {
+ display: block;
+ margin-left: -10em;
+ margin-right: -10em;
+}
+
+#content {
+ margin-left: 14em;
+ margin-right: 14em;
+ display: block;
+ position: relative;
+ padding: 2px;
+ font-size: 0.8em;
+}
+
+.headerlogo {
+ height: 4em;
+ padding: 5px;
+}
+
+.headerlogo img {
+ height: 100%;
+}
+
+.headertitle {
+ font-size: 2.4em;
+ color: gray;
+ letter-spacing: 0.5em;
+ text-transform: lowercase;
+}
+
+.separator {
+ padding-left: 0.25em;
+ font-weight: bold;
+ font-size: 0.8em;
+ line-height: 1.4em;
+}
+
+.whitetext {
+ color: white;
+}
+
+.yellowtext {
+ color: #ffcb05;
+}
+
+.magentatext {
+ color: #dc0065;
+}
+
+.inheritcolor {
+ color: inherit;
+}
+
+.smalltext {
+ font-size: 0.8em;
+}
+
+.yellow {
+ background-color: #ffcb05;
+}
+
+.magenta {
+ background-color: #dc0065;
+}
+
+.nodeco {
+ text-decoration: none;
+}
+
+.redhover:hover {
+ color: red;
+}
+
+.bold {
+ font-weight: bold;
+}
+
+.sidebar {
+ position: relative;
+ padding: 0.25em;
+ color: gray;
+ width: 9em;
+ font-weight: bold;
+}
+
+.separator a, .sidebar a {
+ color: inherit;
+ text-decoration: inherit;
+}
+
+.separator a:hover, .sidebar a:hover {
+ color: red;
+}
+
+.sidebar div {
+ padding-bottom: 0.5em;
+}
+
+.sidebar ul {
+ font-size: 0.8em;
+ color: white;
+ list-style-type: none;
+ padding-left: 1em;
+ margin-top: 0%;
+}
+
+.left {
+ float: left;
+ text-align: left;
+}
+
+.right {
+ float: right;
+ text-align: right;
+}
+
+.clear {
+ clear: both;
+}
+
+.hidden {
+ display: none;
+}
+
+.inline {
+ display: inline;
+}
+
+.code {
+ background: #f7f7f7;
+ border: 1px solid #d7d7d7;
+ margin: 1em 1.75em;
+ padding: 1em;
+}
+
+code {
+ display: block;
+ background: #f7f7f7;
+ border: 1px solid #d7d7d7;
+ margin: 1em 1.75em;
+ padding: 1em;
+ overflow: auto;
+ white-space: pre;
+}
+
+.cbi-section {
+ margin-top: 1em;
+}
+
+.cbi-section-remove {
+ text-align: right;
+}
+
+.cbi-value-title {
+ line-height: 1.75em;
+ width: 15em;
+ font-weight: bold;
+}
+
+.cbi-value-field {
+ text-align: left;
+ line-height: 1.75em;
+}
+
+.cbi-value-field input, .cbi-value-field select,
+.cbi-optionals select, .cbi-optionals input,
+.cbi-section-remove input, .cbi-section-create input {
+ font-size: 0.8em;
+ margin: 0%;
+}
+
+.cbi-value-description {
+ font-style: italic;
+ font-size: 0.8em;
+ margin-bottom: 0.5em;
+}
+
+.cbi-form-separator {
+ margin-top: 1em;
+}
+
+.cbi-section-node {
+ display: block;
+ background: #f7f7f7;
+ border: 1px solid #d7d7d7;
+ overflow: auto;
+ margn-bottom: 0%;
+}
+
+.cbi-section-node h3 {
+ margin-bottom: 0.5em;
+}
+
+.cbi-error {
+ color: red;
+ font-weight: bold;
+ font-size: 0.8em;
+ margin-bottom: 0.75em;
+}
+
+.cbi-optionals {
+ margin-top: 1em;
+}
+
+.cbi-optionals option {
+ font-size: 0.8em;
+}
+
+.error {
+ color: red;
+ font-weight: bold;
+}
+
+.ok {
+ color: green;
+ font-weight: bold;
+} \ No newline at end of file
diff --git a/themes/fledermaus/contrib/media/cbi.js b/themes/fledermaus/contrib/media/cbi.js
new file mode 100644
index 0000000000..f9e463bca1
--- /dev/null
+++ b/themes/fledermaus/contrib/media/cbi.js
@@ -0,0 +1,36 @@
+var cbi_d = {};
+
+function cbi_d_add(field, target, value) {
+ if (!cbi_d[target]) {
+ cbi_d[target] = {};
+ }
+ if (!cbi_d[target][value]) {
+ cbi_d[target][value] = [];
+ }
+ cbi_d[target][value].push(field);
+}
+
+function cbi_d_update(target) {
+ if (!cbi_d[target]) {
+ return;
+ }
+
+ for (var x in cbi_d[target]) {
+ for (var i=0; i<cbi_d[target][x].length; i++) {
+ document.getElementById(cbi_d[target][x][i]).style.display = "none";
+ }
+ }
+
+ var t = document.getElementById(target);
+ if (t && t.value && cbi_d[target][t.value]) {
+ for (var i=0; i<cbi_d[target][t.value].length; i++) {
+ document.getElementById(cbi_d[target][t.value][i]).style.display = "block";
+ }
+ }
+}
+
+function cbi_d_init() {
+ for (var x in cbi_d) {
+ cbi_d_update(x);
+ }
+} \ No newline at end of file
diff --git a/themes/fledermaus/contrib/media/logo.png b/themes/fledermaus/contrib/media/logo.png
new file mode 100644
index 0000000000..d4c5dd9a3f
--- /dev/null
+++ b/themes/fledermaus/contrib/media/logo.png
Binary files differ